diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
new file mode 100644
index 0000000000..5e94a83a3a
--- /dev/null
+++ b/.builds/freebsd.yml
@@ -0,0 +1,43 @@
+image: freebsd/latest
+packages:
+ - cmake
+ - ninja
+ - llvm70
+sources:
+ - https://github.com/ziglang/zig
+tasks:
+ - build: |
+ cd zig && mkdir build && cd build
+ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
+ ninja install
+ - test: |
+ cd zig/build
+ bin/zig test ../test/stage1/behavior.zig
+ bin/zig test ../std/special/compiler_rt/index.zig
+
+ bin/zig test ../test/stage1/behavior.zig --library c
+ bin/zig test ../std/special/compiler_rt/index.zig --library c
+
+ bin/zig test ../test/stage1/behavior.zig --release-fast
+ bin/zig test ../std/special/compiler_rt/index.zig --release-fast
+
+ bin/zig test ../test/stage1/behavior.zig --release-fast --library c
+ bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c
+
+ bin/zig test ../test/stage1/behavior.zig --release-small --library c
+ bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c
+
+ bin/zig test ../test/stage1/behavior.zig --release-small
+ bin/zig test ../std/special/compiler_rt/index.zig --release-small
+
+ bin/zig test ../test/stage1/behavior.zig --release-safe
+ bin/zig test ../std/special/compiler_rt/index.zig --release-safe
+
+ bin/zig test ../test/stage1/behavior.zig --release-safe --library c
+ bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c
+ # TODO enable all tests
+ #bin/zig build --build-file ../build.zig test
+ # TODO integrate with the download page updater and make a
+ # static build available to download for FreeBSD.
+ # This will require setting up a cache of LLVM/Clang built
+ # statically.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0817c09f2a..b633e01978 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -429,6 +429,7 @@ set(BLAKE_SOURCES
)
set(ZIG_CPP_SOURCES
"${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
+ "${CMAKE_SOURCE_DIR}/src/zig_clang.cpp"
"${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
)
@@ -454,10 +455,10 @@ set(ZIG_STD_FILES
"crypto/hmac.zig"
"crypto/index.zig"
"crypto/md5.zig"
+ "crypto/poly1305.zig"
"crypto/sha1.zig"
"crypto/sha2.zig"
"crypto/sha3.zig"
- "crypto/poly1305.zig"
"crypto/x25519.zig"
"cstr.zig"
"debug/failing_allocator.zig"
@@ -482,6 +483,7 @@ set(ZIG_STD_FILES
"fmt/errol/index.zig"
"fmt/errol/lookup.zig"
"fmt/index.zig"
+ "fmt/parse_float.zig"
"hash/adler.zig"
"hash/crc.zig"
"hash/fnv.zig"
@@ -566,9 +568,9 @@ set(ZIG_STD_FILES
"math/tan.zig"
"math/tanh.zig"
"math/trunc.zig"
+ "mem.zig"
"meta/index.zig"
"meta/trait.zig"
- "mem.zig"
"mutex.zig"
"net.zig"
"os/child_process.zig"
@@ -576,20 +578,19 @@ set(ZIG_STD_FILES
"os/darwin/errno.zig"
"os/epoch.zig"
"os/file.zig"
+ "os/freebsd/errno.zig"
+ "os/freebsd/index.zig"
"os/get_app_data_dir.zig"
"os/get_user_id.zig"
"os/index.zig"
+ "os/linux/arm64.zig"
"os/linux/errno.zig"
"os/linux/index.zig"
"os/linux/vdso.zig"
"os/linux/x86_64.zig"
- "os/linux/arm64.zig"
- "os/freebsd/errno.zig"
- "os/freebsd/index.zig"
- "os/freebsd/syscall.zig"
- "os/freebsd/x86_64.zig"
"os/path.zig"
"os/time.zig"
+ "os/uefi.zig"
"os/windows/advapi32.zig"
"os/windows/error.zig"
"os/windows/index.zig"
@@ -597,6 +598,7 @@ set(ZIG_STD_FILES
"os/windows/ntdll.zig"
"os/windows/ole32.zig"
"os/windows/shell32.zig"
+ "os/windows/tls.zig"
"os/windows/util.zig"
"os/zen.zig"
"pdb.zig"
@@ -608,11 +610,22 @@ set(ZIG_STD_FILES
"special/bootstrap_lib.zig"
"special/build_runner.zig"
"special/builtin.zig"
+ "special/compiler_rt/addXf3.zig"
"special/compiler_rt/aulldiv.zig"
"special/compiler_rt/aullrem.zig"
"special/compiler_rt/comparetf2.zig"
"special/compiler_rt/divti3.zig"
"special/compiler_rt/extendXfYf2.zig"
+ "special/compiler_rt/fixdfdi.zig"
+ "special/compiler_rt/fixdfsi.zig"
+ "special/compiler_rt/fixdfti.zig"
+ "special/compiler_rt/fixint.zig"
+ "special/compiler_rt/fixsfdi.zig"
+ "special/compiler_rt/fixsfsi.zig"
+ "special/compiler_rt/fixsfti.zig"
+ "special/compiler_rt/fixtfdi.zig"
+ "special/compiler_rt/fixtfsi.zig"
+ "special/compiler_rt/fixtfti.zig"
"special/compiler_rt/fixuint.zig"
"special/compiler_rt/fixunsdfdi.zig"
"special/compiler_rt/fixunsdfsi.zig"
@@ -640,6 +653,7 @@ set(ZIG_STD_FILES
"special/compiler_rt/udivmodti4.zig"
"special/compiler_rt/udivti3.zig"
"special/compiler_rt/umodti3.zig"
+ "special/fmt_runner.zig"
"special/init-exe/build.zig"
"special/init-exe/src/main.zig"
"special/init-lib/build.zig"
@@ -647,6 +661,8 @@ set(ZIG_STD_FILES
"special/panic.zig"
"special/test_runner.zig"
"spinlock.zig"
+ "statically_initialized_mutex.zig"
+ "testing.zig"
"unicode.zig"
"zig/ast.zig"
"zig/index.zig"
@@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES})
get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
endforeach()
+
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
diff --git a/README.md b/README.md
index a19e9eb67a..3ac4f429f2 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
A programming language designed for robustness, optimality, and
clarity.
-[ziglang.org](https://ziglang.org)
+[Download & Documentation](https://ziglang.org/download/)
## Feature Highlights
@@ -84,29 +84,32 @@ clarity.
* LLVM may have the target as an experimental target, which means that you
need to use Zig-provided binaries for the target to be available, or
build LLVM from source with special configure flags.
+ * This target may be considered deprecated by an official party,
+ [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which
+ case this target will remain forever stuck in Tier 4.
#### Support Table
-| | freestanding | linux | macosx | windows | freebsd | other |
-|--------|--------------|--------|--------|---------|---------|--------|
-|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |
-|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |
-|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
-|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
-|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
-|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
+| | freestanding | linux | macosx | windows | freebsd | UEFI | other |
+|--------|--------------|--------|--------|---------|---------|--------|--------|
+|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |
+|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |
+|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
+|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
+|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
+|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
+|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
+|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
## Community
@@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
Stage 1 compiler for now.*
-Dependencies are the same as Stage 1, except now you have a working zig compiler.
+Dependencies are the same as Stage 1, except now you can use stage 1 to compile
+Zig code.
```
bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
@@ -183,11 +187,13 @@ binary.
### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
-This is the actual compiler binary that we will install to the system.
-
*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
not yet supported.*
+Once the self-hosted compiler can build itself, this will be the actual
+compiler binary that we will install to the system. Until then, users should
+use stage 1.
+
#### Debug / Development Build
```
diff --git a/build.zig b/build.zig
index e411ae8b21..5c7c5b8a18 100644
--- a/build.zig
+++ b/build.zig
@@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void {
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
- const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable;
+ const langref_out_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, "langref.html" },
+ ) catch unreachable;
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
docgen_exe.getOutputPath(),
rel_zig_exe,
@@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void {
}
const modes = chosen_modes[0..chosen_mode_index];
- test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));
+ test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
@@ -125,13 +128,19 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
for (dep.libdirs.toSliceConst()) |lib_dir| {
lib_exe_obj.addLibPath(lib_dir);
}
- const lib_dir = os.path.join(b.allocator, dep.prefix, "lib") catch unreachable;
+ const lib_dir = os.path.join(
+ b.allocator,
+ [][]const u8{ dep.prefix, "lib" },
+ ) catch unreachable;
for (dep.system_libs.toSliceConst()) |lib| {
const static_bare_name = if (mem.eql(u8, lib, "curses"))
([]const u8)("libncurses.a")
else
b.fmt("lib{}.a", lib);
- const static_lib_name = os.path.join(b.allocator, lib_dir, static_bare_name) catch unreachable;
+ const static_lib_name = os.path.join(
+ b.allocator,
+ [][]const u8{ lib_dir, static_bare_name },
+ ) catch unreachable;
const have_static = fileExists(static_lib_name) catch unreachable;
if (have_static) {
lib_exe_obj.addObjectFile(static_lib_name);
@@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool {
fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
- lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
+ lib_exe_obj.addObjectFile(os.path.join(b.allocator, [][]const u8{
+ cmake_binary_dir,
+ "zig_cpp",
+ b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt()),
+ }) catch unreachable);
}
const LibraryDep = struct {
@@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
var result = LibraryDep{
- .prefix = mem.split(prefix_output, " \r\n").next().?,
+ .prefix = mem.tokenize(prefix_output, " \r\n").next().?,
.libs = ArrayList([]const u8).init(b.allocator),
.system_libs = ArrayList([]const u8).init(b.allocator),
.includes = ArrayList([]const u8).init(b.allocator),
.libdirs = ArrayList([]const u8).init(b.allocator),
};
{
- var it = mem.split(libs_output, " \r\n");
+ var it = mem.tokenize(libs_output, " \r\n");
while (it.next()) |lib_arg| {
if (mem.startsWith(u8, lib_arg, "-l")) {
try result.system_libs.append(lib_arg[2..]);
@@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
}
}
{
- var it = mem.split(includes_output, " \r\n");
+ var it = mem.tokenize(includes_output, " \r\n");
while (it.next()) |include_arg| {
if (mem.startsWith(u8, include_arg, "-I")) {
try result.includes.append(include_arg[2..]);
@@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
}
}
{
- var it = mem.split(libdir_output, " \r\n");
+ var it = mem.tokenize(libdir_output, " \r\n");
while (it.next()) |libdir| {
if (mem.startsWith(u8, libdir, "-L")) {
try result.libdirs.append(libdir[2..]);
@@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
}
pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
- var it = mem.split(stdlib_files, ";");
+ var it = mem.tokenize(stdlib_files, ";");
while (it.next()) |stdlib_file| {
- const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;
- const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable;
+ const src_path = os.path.join(b.allocator, [][]const u8{ "std", stdlib_file }) catch unreachable;
+ const dest_path = os.path.join(
+ b.allocator,
+ [][]const u8{ "lib", "zig", "std", stdlib_file },
+ ) catch unreachable;
b.installFile(src_path, dest_path);
}
}
pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {
- var it = mem.split(c_header_files, ";");
+ var it = mem.tokenize(c_header_files, ";");
while (it.next()) |c_header_file| {
- const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;
- const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable;
+ const src_path = os.path.join(b.allocator, [][]const u8{ "c_headers", c_header_file }) catch unreachable;
+ const dest_path = os.path.join(
+ b.allocator,
+ [][]const u8{ "lib", "zig", "include", c_header_file },
+ ) catch unreachable;
b.installFile(src_path, dest_path);
}
}
@@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
if (ctx.lld_include_dir.len != 0) {
exe.addIncludeDir(ctx.lld_include_dir);
- var it = mem.split(ctx.lld_libraries, ";");
+ var it = mem.tokenize(ctx.lld_libraries, ";");
while (it.next()) |lib| {
exe.addObjectFile(lib);
}
@@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
\\Unable to determine path to libstdc++.a
\\On Fedora, install libstdc++-static and try again.
- \\
);
exe.linkSystemLibrary("pthread");
- } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) {
+ } else if (exe.target.isFreeBSD()) {
+ try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
+ exe.linkSystemLibrary("pthread");
+ } else if (exe.target.isDarwin()) {
if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
// Compiler is GCC.
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
@@ -332,7 +353,7 @@ fn addCxxKnownPath(
ctx.cxx_compiler,
b.fmt("-print-file-name={}", objname),
});
- const path_unpadded = mem.split(path_padded, "\r\n").next().?;
+ const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
if (mem.eql(u8, path_unpadded, objname)) {
if (errtxt) |msg| {
warn("{}", msg);
diff --git a/ci/azure/windows_install b/ci/azure/windows_install
index 952e9f78cb..8a279210ff 100755
--- a/ci/azure/windows_install
+++ b/ci/azure/windows_install
@@ -3,6 +3,7 @@
set -x
set -e
+pacman -Su --needed --noconfirm
pacman -S --needed --noconfirm wget p7zip python3-pip
pip install s3cmd
wget -nv "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz"
diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake
index b847813682..2f0afa09b7 100644
--- a/cmake/Findllvm.cmake
+++ b/cmake/Findllvm.cmake
@@ -15,6 +15,51 @@ find_program(LLVM_CONFIG_EXE
"c:/msys64/mingw64/bin"
"C:/Libraries/llvm-7.0.0/bin")
+if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")
+ message(FATAL_ERROR "unable to find llvm-config")
+endif()
+
+execute_process(
+ COMMAND ${LLVM_CONFIG_EXE} --version
+ OUTPUT_VARIABLE LLVM_CONFIG_VERSION
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if("${LLVM_CONFIG_VERSION}" VERSION_LESS 7)
+ message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
+endif()
+if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 8)
+ message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
+endif()
+if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 8)
+ message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
+endif()
+
+execute_process(
+ COMMAND ${LLVM_CONFIG_EXE} --targets-built
+ OUTPUT_VARIABLE LLVM_TARGETS_BUILT_SPACES
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT_SPACES}")
+function(NEED_TARGET TARGET_NAME)
+ list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)
+ if (${_index} EQUAL -1)
+ message(FATAL_ERROR "LLVM is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
+ endif()
+endfunction(NEED_TARGET)
+NEED_TARGET("AArch64")
+NEED_TARGET("AMDGPU")
+NEED_TARGET("ARM")
+NEED_TARGET("BPF")
+NEED_TARGET("Hexagon")
+NEED_TARGET("Lanai")
+NEED_TARGET("Mips")
+NEED_TARGET("MSP430")
+NEED_TARGET("NVPTX")
+NEED_TARGET("PowerPC")
+NEED_TARGET("Sparc")
+NEED_TARGET("SystemZ")
+NEED_TARGET("X86")
+NEED_TARGET("XCore")
+
if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC)
execute_process(
COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static
diff --git a/doc/docgen.zig b/doc/docgen.zig
index 2489e034bc..082f308a57 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -4,7 +4,7 @@ const io = std.io;
const os = std.os;
const warn = std.debug.warn;
const mem = std.mem;
-const assert = std.debug.assert;
+const testing = std.testing;
const max_doc_file_size = 10 * 1024 * 1024;
@@ -620,7 +620,7 @@ const TermState = enum {
test "term color" {
const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";
const result = try termColor(std.debug.global_allocator, input_bytes);
- assert(mem.eql(u8, result, "AgreenB"));
+ testing.expectEqualSlices(u8, "AgreenB", result);
}
fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
@@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
std.zig.Token.Id.Keyword_suspend,
std.zig.Token.Id.Keyword_switch,
std.zig.Token.Id.Keyword_test,
+ std.zig.Token.Id.Keyword_threadlocal,
std.zig.Token.Id.Keyword_try,
std.zig.Token.Id.Keyword_union,
std.zig.Token.Id.Keyword_unreachable,
@@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
std.zig.Token.Id.Tilde,
std.zig.Token.Id.BracketStarBracket,
+ std.zig.Token.Id.BracketStarCBracket,
=> try writeEscaped(out, src[token.start..token.end]),
std.zig.Token.Id.Invalid => return parseError(
@@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try tokenizeAndPrint(tokenizer, out, code.source_token);
try out.write("");
const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
- const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
+ const tmp_source_file_name = try os.path.join(
+ allocator,
+ [][]const u8{ tmp_dir_name, name_plus_ext },
+ );
try io.writeFile(tmp_source_file_name, trimmed_raw_source);
switch (code.id) {
Code.Id.Exe => |expected_outcome| {
const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
- const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
+ const tmp_bin_file_name = try os.path.join(
+ allocator,
+ [][]const u8{ tmp_dir_name, name_plus_bin_ext },
+ );
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
try build_args.appendSlice([][]const u8{
@@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
for (code.link_objects) |link_object| {
const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
- const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext);
+ const full_path_object = try os.path.join(
+ allocator,
+ [][]const u8{ tmp_dir_name, name_with_ext },
+ );
try build_args.append("--object");
try build_args.append(full_path_object);
try out.print(" --object {}", name_with_ext);
@@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
Code.Id.Obj => |maybe_error_match| {
const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
- const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext);
+ const tmp_obj_file_name = try os.path.join(
+ allocator,
+ [][]const u8{ tmp_dir_name, name_plus_obj_ext },
+ );
var build_args = std.ArrayList([]const u8).init(allocator);
defer build_args.deinit();
const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);
- const output_h_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_h_ext);
+ const output_h_file_name = try os.path.join(
+ allocator,
+ [][]const u8{ tmp_dir_name, name_plus_h_ext },
+ );
try build_args.appendSlice([][]const u8{
zig_exe,
diff --git a/doc/langref.html.in b/doc/langref.html.in
index a1903331a4..1341bf1be5 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -165,7 +165,7 @@ const std = @import("std");
pub fn main() !void {
// If this program is run without stdout attached, exit with an error.
- var stdout_file = try std.io.getStdOut();
+ const stdout_file = try std.io.getStdOut();
// If this program encounters pipe failure when printing to stdout, exit
// with an error.
try stdout_file.write("Hello, world!\n");
@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {
{#code_end#}
{#see_also|for|Slices#}
{#header_close#}
+
+ {#header_open|Vectors#}
+
+ A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on
+ in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin
+ function {#link|@Vector#}.
+
+
+ TODO talk about C ABI interop
+
+ {#header_open|SIMD#}
+
+ TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the
+ docs with:
+ * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector?
+ * How to convert to/from vectors/arrays
+ * How to access individual elements from vectors, how to loop over the elements
+ * "shuffle"
+ * Advice on writing high perf software, how to abstract the best way
+
+ {#header_close#}
+ {#header_close#}
+
{#header_open|Pointers#}
Zig has two kinds of pointers:
@@ -1671,7 +1694,7 @@ test "comptime @intToPtr" {
}
}
{#code_end#}
- {#see_also|Optional Pointers#}
+ {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
{#header_open|volatile#}
Loads and stores are assumed to not have side effects. If a given load or store
should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
@@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
}
{#code_end#}
{#header_close#}
+ {#see_also|C Pointers#}
{#header_close#}
+
{#header_open|Slices#}
{#code_begin|test_safety|index out of bounds#}
const assert = @import("std").debug.assert;
@@ -3169,7 +3194,16 @@ fn foo() void { }
{#code_end#}
{#header_open|Pass-by-value Parameters#}
- In Zig, structs, unions, and enums with payloads can be passed directly to a function:
+ Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters
+ are copied, and then the copy is available in the function body. This is called "passing by value".
+ Copying a primitive type is essentially free and typically involves nothing more than
+ setting a register.
+
+
+ Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy
+ could be arbitrarily expensive depending on the size. When these types are passed
+ as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way
+ Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.
{#code_begin|test#}
const Point = struct {
@@ -3178,20 +3212,20 @@ const Point = struct {
};
fn foo(point: Point) i32 {
+ // Here, `point` could be a reference, or a copy. The function body
+ // can ignore the difference and treat it as a value. Be very careful
+ // taking the address of the parameter - it should be treated as if
+ // the address will become invalid when the function returns.
return point.x + point.y;
}
const assert = @import("std").debug.assert;
-test "pass aggregate type by non-copy value to function" {
+test "pass struct to function" {
assert(foo(Point{ .x = 1, .y = 2 }) == 3);
}
{#code_end#}
- 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#}
@@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
{#code_end#}
Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,
- and the transformation is guaranteed to be safe.
+ and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}.
{#header_open|Implicit Cast: Stricter Qualification#}
@@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
For example, if we were to introduce another function to the above snippet:
- {#code_begin|test_err|unable to evaluate constant expression#}
+ {#code_begin|test_err|values of type 'type' must be comptime known#}
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
@@ -4595,7 +4629,7 @@ test "fibonacci" {
What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line?
- {#code_begin|test_err|encountered @panic at compile-time#}
+ {#code_begin|test_err|unable to evaluate constant expression#}
const assert = @import("std").debug.assert;
fn fibonacci(index: i32) i32 {
@@ -5169,6 +5203,34 @@ fn seq(c: u8) void {
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
{#header_close#}
+ {#header_open|@alignCast#}
+ {#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}
+
+ {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
+ {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
+ except with the alignment adjusted to the new value.
+
+ A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
+ to the generated code to make sure the pointer is aligned as promised.
+
+ {#header_close#}
+ {#header_open|@alignOf#}
+ {#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}
+
+ This function returns the number of bytes that this type should be aligned to
+ for the current target to match the C ABI. When the child type of a pointer has
+ this alignment, the alignment can be omitted from the type.
+
+ {#syntax#}const assert = @import("std").debug.assert;
+comptime {
+ assert(*u32 == *align(@alignOf(u32)) u32);
+}{#endsyntax#}
+
+ The result is a target-specific compile time constant. It is guaranteed to be
+ less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
+
+ {#see_also|Alignment#}
+ {#header_close#}
{#header_open|@ArgType#}
{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}
@@ -5241,6 +5303,7 @@ fn seq(c: u8) void {
Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
{#header_close#}
+
{#header_open|@bitOffsetOf#}
{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
@@ -5253,52 +5316,6 @@ fn seq(c: u8) void {
{#see_also|@byteOffsetOf#}
{#header_close#}
- {#header_open|@breakpoint#}
- {#syntax#}@breakpoint(){#endsyntax#}
-
- This function inserts a platform-specific debug trap instruction which causes
- debuggers to break there.
-
-
- This function is only valid within function scope.
-
-
- {#header_close#}
- {#header_open|@byteOffsetOf#}
- {#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
-
- Returns the byte offset of a field relative to its containing struct.
-
- {#see_also|@bitOffsetOf#}
- {#header_close#}
- {#header_open|@alignCast#}
- {#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}
-
- {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
- {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
- except with the alignment adjusted to the new value.
-
- A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
- to the generated code to make sure the pointer is aligned as promised.
-
- {#header_close#}
- {#header_open|@alignOf#}
- {#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}
-
- This function returns the number of bytes that this type should be aligned to
- for the current target to match the C ABI. When the child type of a pointer has
- this alignment, the alignment can be omitted from the type.
-
- {#syntax#}const assert = @import("std").debug.assert;
-comptime {
- assert(*u32 == *align(@alignOf(u32)) u32);
-}{#endsyntax#}
-
- The result is a target-specific compile time constant. It is guaranteed to be
- less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
-
- {#see_also|Alignment#}
- {#header_close#}
{#header_open|@boolToInt#}
{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}
@@ -5312,6 +5329,47 @@ comptime {
{#header_close#}
+ {#header_open|@breakpoint#}
+ {#syntax#}@breakpoint(){#endsyntax#}
+
+ This function inserts a platform-specific debug trap instruction which causes
+ debuggers to break there.
+
+
+ This function is only valid within function scope.
+
+
+ {#header_close#}
+
+ {#header_open|@bswap#}
+ {#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.
+
+ Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
+ and converts a little endian integer to a big endian integer.
+
+ {#header_close#}
+
+ {#header_open|@bitreverse#}
+ {#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}
+ {#syntax#}T{#endsyntax#} accepts any integer type.
+
+ Reverses the bitpattern of an integer value, including the sign bit if applicable.
+
+
+ For example 0b10110110 ({#syntax#}u8 = 182{#endsyntax#}, {#syntax#}i8 = -74{#endsyntax#})
+ becomes 0b01101101 ({#syntax#}u8 = 109{#endsyntax#}, {#syntax#}i8 = 109{#endsyntax#}).
+
+ {#header_close#}
+
+ {#header_open|@byteOffsetOf#}
+ {#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}
+
+ Returns the byte offset of a field relative to its containing struct.
+
+ {#see_also|@bitOffsetOf#}
+ {#header_close#}
+
{#header_open|@bytesToSlice#}
{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}
@@ -5378,17 +5436,7 @@ comptime {
{#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
{#header_close#}
- {#header_open|@cUndef#}
- {#syntax#}@cUndef(comptime name: []u8){#endsyntax#}
-
- This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
-
-
- This appends #undef $name to the {#syntax#}@cImport{#endsyntax#}
- temporary buffer.
-
- {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
- {#header_close#}
+
{#header_open|@clz#}
{#syntax#}@clz(x: T) U{#endsyntax#}
@@ -5404,6 +5452,7 @@ comptime {
{#see_also|@ctz|@popCount#}
{#header_close#}
+
{#header_open|@cmpxchgStrong#}
{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}
@@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}
{#see_also|Compile Variables|cmpxchgStrong#}
{#header_close#}
+
{#header_open|@compileError#}
{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}
@@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
and {#syntax#}comptime{#endsyntax#} functions.
{#header_close#}
+
{#header_open|@compileLog#}
{#syntax#}@compileLog(args: ...){#endsyntax#}
@@ -5525,6 +5576,7 @@ test "main" {
}
{#code_end#}
{#header_close#}
+
{#header_open|@ctz#}
{#syntax#}@ctz(x: T) U{#endsyntax#}
@@ -5540,6 +5592,19 @@ test "main" {
{#see_also|@clz|@popCount#}
{#header_close#}
+
+ {#header_open|@cUndef#}
+ {#syntax#}@cUndef(comptime name: []u8){#endsyntax#}
+
+ This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
+
+
+ This appends #undef $name to the {#syntax#}@cImport{#endsyntax#}
+ temporary buffer.
+
+ {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
+ {#header_close#}
+
{#header_open|@divExact#}
{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}
@@ -5606,14 +5671,6 @@ test "main" {
{#see_also|@intToEnum#}
{#header_close#}
- {#header_open|@errSetCast#}
-
{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}
-
- Converts an error value from one error set to another error set. Attempting to convert an error
- which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
-
- {#header_close#}
-
{#header_open|@errorName#}
{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}
@@ -5656,6 +5713,14 @@ test "main" {
{#see_also|@intToError#}
{#header_close#}
+ {#header_open|@errSetCast#}
+
{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}
+
+ Converts an error value from one error set to another error set. Attempting to convert an error
+ which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
+
+ {#header_close#}
+
{#header_open|@export#}
{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}
@@ -5724,6 +5789,7 @@ test "main" {
This function is only valid within function scope.
{#header_close#}
+
{#header_open|@handle#}
{#syntax#}@handle(){#endsyntax#}
@@ -5734,6 +5800,7 @@ test "main" {
This function is only valid within an async function scope.
{#header_close#}
+
{#header_open|@import#}
{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}
@@ -5754,6 +5821,7 @@ test "main" {
{#see_also|Compile Variables|@embedFile#}
{#header_close#}
+
{#header_open|@inlineCall#}
{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}
@@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
bit count for an integer type is {#syntax#}65535{#endsyntax#}.
{#header_close#}
+
{#header_open|@memberCount#}
{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}
@@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}
Returns the field type of a struct or union.
{#header_close#}
+
{#header_open|@memcpy#}
{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}
@@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; }
This function is a low level intrinsic with no safety mechanisms. Most code
should not use this function, instead using something like this:
- {#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}
+ {#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}
The optimizer is intelligent enough to turn the above snippet into a memcpy.
There is also a standard library function for this:
{#syntax#}const mem = @import("std").mem;
-mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}
+mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}
{#header_close#}
+
{#header_open|@memset#}
{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}
@@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}
This function is a low level intrinsic with no safety mechanisms. Most
code should not use this function, instead using something like this:
- {#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}
+ {#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}
The optimizer is intelligent enough to turn the above snippet into a memset.
@@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}
{#syntax#}const mem = @import("std").mem;
mem.set(u8, dest, c);{#endsyntax#}
{#header_close#}
+
{#header_open|@mod#}
{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}
@@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}
For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.
{#see_also|@rem#}
{#header_close#}
+
{#header_open|@mulWithOverflow#}
{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}
@@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
{#header_close#}
+
{#header_open|@newStackCall#}
{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}
@@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize {
}
{#code_end#}
{#header_close#}
+
{#header_open|@noInlineCall#}
{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}
@@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 {
{#see_also|@inlineCall#}
{#header_close#}
+
{#header_open|@OpaqueType#}
{#syntax#}@OpaqueType() type{#endsyntax#}
@@ -5996,6 +6072,7 @@ test "call foo" {
}
{#code_end#}
{#header_close#}
+
{#header_open|@panic#}
{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}
@@ -6012,6 +6089,7 @@ test "call foo" {
{#see_also|Root Source File#}
{#header_close#}
+
{#header_open|@popCount#}
{#syntax#}@popCount(integer: var) var{#endsyntax#}
Counts the number of bits set in an integer.
@@ -6022,12 +6100,18 @@ test "call foo" {
{#see_also|@ctz|@clz#}
{#header_close#}
+
{#header_open|@ptrCast#}
{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}
Converts a pointer of one type to a pointer of another type.
+
+ {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
+ to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
+
{#header_close#}
+
{#header_open|@ptrToInt#}
{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}
@@ -6042,6 +6126,7 @@ test "call foo" {
To convert the other way, use {#link|@intToPtr#}
{#header_close#}
+
{#header_open|@rem#}
{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}
@@ -6055,6 +6140,7 @@ test "call foo" {
For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.
{#see_also|@mod#}
{#header_close#}
+
{#header_open|@returnAddress#}
{#syntax#}@returnAddress(){#endsyntax#}
@@ -6075,19 +6161,14 @@ test "call foo" {
Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
{#header_close#}
+
{#header_open|@setCold#}
{#syntax#}@setCold(is_cold: bool){#endsyntax#}
Tells the optimizer that a function is rarely called.
{#header_close#}
- {#header_open|@setRuntimeSafety#}
- {#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}
-
- Sets whether runtime safety checks are on for the scope that contains the function call.
-
- {#header_close#}
{#header_open|@setEvalBranchQuota#}
{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}
@@ -6122,6 +6203,7 @@ test "foo" {
{#see_also|comptime#}
{#header_close#}
+
{#header_open|@setFloatMode#}
{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}
@@ -6156,6 +6238,7 @@ pub const FloatMode = enum {
{#see_also|Floating Point Operations#}
{#header_close#}
+
{#header_open|@setGlobalLinkage#}
{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}
@@ -6163,6 +6246,15 @@ pub const FloatMode = enum {
{#see_also|Compile Variables#}
{#header_close#}
+
+ {#header_open|@setRuntimeSafety#}
+ {#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}
+
+ Sets whether runtime safety checks are on for the scope that contains the function call.
+
+
+ {#header_close#}
+
{#header_open|@shlExact#}
{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}
@@ -6175,6 +6267,7 @@ pub const FloatMode = enum {
{#see_also|@shrExact|@shlWithOverflow#}
{#header_close#}
+
{#header_open|@shlWithOverflow#}
{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}
@@ -6188,6 +6281,7 @@ pub const FloatMode = enum {
{#see_also|@shlExact|@shrExact#}
{#header_close#}
+
{#header_open|@shrExact#}
{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}
@@ -6205,10 +6299,15 @@ pub const FloatMode = enum {
{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}
This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory.
-
-
The result is a target-specific compile time constant.
+
+ This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset
+ in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#},
+ consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or
+ {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}.
+
+ {#see_also|@typeInfo#}
{#header_close#}
{#header_open|@sliceToBytes#}
@@ -6229,6 +6328,7 @@ pub const FloatMode = enum {
This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
{#header_close#}
+
{#header_open|@subWithOverflow#}
{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}
@@ -6237,12 +6337,14 @@ pub const FloatMode = enum {
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
{#header_close#}
+
{#header_open|@tagName#}
{#syntax#}@tagName(value: var) []const u8{#endsyntax#}
Converts an enum value or union value to a slice of bytes representing the name.
{#header_close#}
+
{#header_open|@TagType#}
{#syntax#}@TagType(T: type) type{#endsyntax#}
@@ -6252,6 +6354,7 @@ pub const FloatMode = enum {
For a union, returns the enum type that is used to store the tag value.
{#header_close#}
+
{#header_open|@This#}
{#syntax#}@This() type{#endsyntax#}
@@ -6287,15 +6390,16 @@ fn List(comptime T: type) type {
#1047 for details.
{#header_close#}
+
{#header_open|@truncate#}
- {#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}
+ {#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}
This function truncates bits from an integer type, resulting in a smaller
integer type.
- The following produces a crash in debug mode and undefined behavior in
- release mode:
+ The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
+ {#link|ReleaseFast#} mode:
{#syntax#}const a: u16 = 0xabcd;
const b: u8 = u8(a);{#endsyntax#}
@@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a);
This function always truncates the significant bits of the integer, regardless
of endianness on the target platform.
-
+
+ If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
+ then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}.
+
{#header_close#}
+
{#header_open|@typeId#}
{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}
@@ -6345,6 +6453,7 @@ pub const TypeId = enum {
};
{#code_end#}
{#header_close#}
+
{#header_open|@typeInfo#}
{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}
@@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) {
};
{#code_end#}
{#header_close#}
+
{#header_open|@typeName#}
-
{#syntax#}@typeName(T: type) []u8{#endsyntax#}
+ {#syntax#}@typeName(T: type) [N]u8{#endsyntax#}
- This function returns the string representation of a type.
+ This function returns the string representation of a type, as
+ an array. It is equivalent to a string literal of the type name.
{#header_close#}
+
{#header_open|@typeOf#}
{#syntax#}@typeOf(expression) type{#endsyntax#}
@@ -6542,7 +6654,19 @@ pub const TypeInfo = union(TypeId) {
{#header_close#}
+
+ {#header_open|@Vector#}
+ {#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}
+
+ This function returns a vector type for {#link|SIMD#}.
+
+
+ {#syntax#}ElemType{#endsyntax#} must be an {#link|integer|Integers#}, a {#link|float|Floats#}, or a
+ {#link|pointer|Pointers#}.
+
{#header_close#}
+ {#header_close#}
+
{#header_open|Build Mode#}
Zig has four build modes:
@@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void {
{#header_close#}
{#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
{#header_close#}
+
+ {#header_open|Single Threaded Builds#}
+
Zig has a compile option --single-threaded which has the following effects:
+
+ - {#link|@atomicLoad#} is emitted as a normal load.
+ - {#link|@atomicRmw#} is emitted as a normal memory load, modify, store.
+ - {#link|@fence#} becomes a no-op.
+ - Variables which have Thread Local Storage instead become globals. TODO thread local variables
+ are not implemented yet.
+ - The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
+ TODO: please note this will not be implemented until the upcoming Coroutine Rewrite
+ - The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
+ and therefore various userland APIs which read this variable become more efficient.
+ For example {#syntax#}std.Mutex{#endsyntax#} becomes
+ an empty data structure and all of its functions become no-ops.
+
+
+ {#header_close#}
+
{#header_open|Undefined Behavior#}
Zig has many instances of undefined behavior. If undefined behavior is
@@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void {
{#code_end#}
{#header_close#}
- {#header_open|Out of Bounds Float To Integer Cast#}
+ {#header_open|Out of Bounds Float to Integer Cast#}
TODO
{#header_close#}
+ {#header_open|Pointer Cast Invalid Null#}
+ At compile-time:
+ {#code_begin|test_err|null pointer casted to type#}
+comptime {
+ const opt_ptr: ?*i32 = null;
+ const ptr = @ptrCast(*i32, opt_ptr);
+}
+ {#code_end#}
+ At runtime:
+ {#code_begin|exe_err#}
+pub fn main() void {
+ var opt_ptr: ?*i32 = null;
+ var ptr = @ptrCast(*i32, opt_ptr);
+}
+ {#code_end#}
+ {#header_close#}
+
{#header_close#}
{#header_open|Memory#}
TODO: explain no default allocator in zig
@@ -7307,6 +7467,7 @@ pub fn main() void {
{#code_end#}
{#see_also|String Literals#}
{#header_close#}
+
{#header_open|Import from C Header File#}
The {#syntax#}@cImport{#endsyntax#} builtin function can be used
@@ -7345,6 +7506,36 @@ const c = @cImport({
{#code_end#}
{#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
{#header_close#}
+
+ {#header_open|C Pointers#}
+
+ This type is to be avoided whenever possible. The only valid reason for using a C pointer is in
+ auto-generated code from translating C code.
+
+
+ When importing C header files, it is ambiguous whether pointers should be translated as
+ single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
+ C pointers are a compromise so that Zig code can utilize translated header files directly.
+
+ {#syntax#}[*c]T{#endsyntax#} - C pointer.
+
+ - Supports all the syntax of the other two pointer types.
+ - Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
+ When a C pointer is implicitly casted to a non-optional pointer, safety-checked
+ {#link|Undefined Behavior#} occurs if the address is 0.
+
+ - Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
+ {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of
+ null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
+ is unnecessary as one can use normal {#link|Optional Pointers#}.
+
+ - Supports {#link|implicit casting|Implicit Casts#} to and from integers.
+ - Supports comparison with integers.
+ - Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
+ please!
+
+ {#header_close#}
+
{#header_open|Exporting a C Library#}
One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages
@@ -7741,7 +7932,7 @@ TopLevelComptime <- KEYWORD_comptime BlockExpr
TopLevelDecl
<- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
- / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl
+ / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
/ KEYWORD_use Expr SEMICOLON
FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
@@ -8032,7 +8223,8 @@ ArrayTypeStart <- LBRACKET Expr? RBRACKET
PtrTypeStart
<- ASTERISK
/ ASTERISK2
- / LBRACKET ASTERISK RBRACKET
+ / PTRUNKNOWN
+ / PTRC
# ContainerDecl specific
ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
@@ -8130,7 +8322,7 @@ LARROW2 <- '<<' ![=] skip
LARROW2EQUAL <- '<<=' skip
LARROWEQUAL <- '<=' skip
LBRACE <- '{' skip
-LBRACKET <- '[' skip
+LBRACKET <- '[' ![*] skip
LPAREN <- '(' skip
MINUS <- '-' ![%=>] skip
MINUSEQUAL <- '-=' skip
@@ -8147,6 +8339,8 @@ PLUS2 <- '++' skip
PLUSEQUAL <- '+=' skip
PLUSPERCENT <- '+%' ![=] skip
PLUSPERCENTEQUAL <- '+%=' skip
+PTRC <- '[*c]' skip
+PTRUNKNOWN <- '[*]' skip
QUESTIONMARK <- '?' skip
RARROW <- '>' ![>=] skip
RARROW2 <- '>>' ![=] skip
@@ -8201,6 +8395,7 @@ KEYWORD_struct <- 'struct' end_of_word
KEYWORD_suspend <- 'suspend' end_of_word
KEYWORD_switch <- 'switch' end_of_word
KEYWORD_test <- 'test' end_of_word
+KEYWORD_threadlocal <- 'threadlocal' end_of_word
KEYWORD_true <- 'true' end_of_word
KEYWORD_try <- 'try' end_of_word
KEYWORD_undefined <- 'undefined' end_of_word
@@ -8221,7 +8416,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm
/ KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
/ KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
/ KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
- / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try
+ / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
/ KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
/ KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while
{#header_close#}
diff --git a/doc/targets.md b/doc/targets.md
deleted file mode 100644
index e5c6ab5534..0000000000
--- a/doc/targets.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# How to Add Support For More Targets
-
-Create bootstrap code in std/bootstrap.zig and add conditional compilation
-logic. This code is responsible for the real executable entry point, calling
-main() and making the exit syscall when main returns.
-
-How to pass a byvalue struct parameter in the C calling convention is
-target-specific. Add logic for how to do function prototypes and function calls
-for the target when an exported or external function has a byvalue struct.
-
-Write the target-specific code in the standard library.
-
-Update the C integer types to be the correct size for the target.
-
-Make sure that `c_longdouble` codegens the correct floating point value.
diff --git a/example/guess_number/main.zig b/example/guess_number/main.zig
index 66264666bc..b4eb1c292a 100644
--- a/example/guess_number/main.zig
+++ b/example/guess_number/main.zig
@@ -15,7 +15,7 @@ pub fn main() !void {
std.debug.warn("unable to seed random number generator: {}", err);
return err;
};
- const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
+ const seed = std.mem.readIntNative(u64, &seed_bytes);
var prng = std.rand.DefaultPrng.init(seed);
const answer = prng.random.range(u8, 0, 100) + 1;
diff --git a/example/hello_world/hello.zig b/example/hello_world/hello.zig
index 8e65e06a96..cb7d5ef157 100644
--- a/example/hello_world/hello.zig
+++ b/example/hello_world/hello.zig
@@ -2,7 +2,7 @@ const std = @import("std");
pub fn main() !void {
// If this program is run without stdout attached, exit with an error.
- var stdout_file = try std.io.getStdOut();
+ const stdout_file = try std.io.getStdOut();
// If this program encounters pipe failure when printing to stdout, exit
// with an error.
try stdout_file.write("Hello, world!\n");
diff --git a/src-self-hosted/arg.zig b/src-self-hosted/arg.zig
index 99e6ecc17a..7bbd233a75 100644
--- a/src-self-hosted/arg.zig
+++ b/src-self-hosted/arg.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const debug = std.debug;
+const testing = std.testing;
const mem = std.mem;
const Allocator = mem.Allocator;
@@ -272,21 +273,21 @@ test "parse arguments" {
var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);
- debug.assert(args.present("help"));
- debug.assert(!args.present("help2"));
- debug.assert(!args.present("init"));
+ testing.expect(args.present("help"));
+ testing.expect(!args.present("help2"));
+ testing.expect(!args.present("init"));
- debug.assert(mem.eql(u8, args.single("build-file").?, "build.zig"));
- debug.assert(mem.eql(u8, args.single("color").?, "on"));
+ testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig"));
+ testing.expect(mem.eql(u8, args.single("color").?, "on"));
const objects = args.many("object").?;
- debug.assert(mem.eql(u8, objects[0], "obj1"));
- debug.assert(mem.eql(u8, objects[1], "obj2"));
+ testing.expect(mem.eql(u8, objects[0], "obj1"));
+ testing.expect(mem.eql(u8, objects[1], "obj2"));
- debug.assert(mem.eql(u8, args.single("library").?, "lib2"));
+ testing.expect(mem.eql(u8, args.single("library").?, "lib2"));
const pos = args.positionals.toSliceConst();
- debug.assert(mem.eql(u8, pos[0], "build"));
- debug.assert(mem.eql(u8, pos[1], "pos1"));
- debug.assert(mem.eql(u8, pos[2], "pos2"));
+ testing.expect(mem.eql(u8, pos[0], "build"));
+ testing.expect(mem.eql(u8, pos[1], "pos1"));
+ testing.expect(mem.eql(u8, pos[2], "pos2"));
}
diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig
index 45cfa98942..1c671b61e2 100644
--- a/src-self-hosted/codegen.zig
+++ b/src-self-hosted/codegen.zig
@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
pub const ObjectFile = struct {
comp: *Compilation,
- module: llvm.ModuleRef,
- builder: llvm.BuilderRef,
+ module: *llvm.Module,
+ builder: *llvm.Builder,
dibuilder: *llvm.DIBuilder,
- context: llvm.ContextRef,
+ context: *llvm.Context,
lock: event.Lock,
arena: *std.mem.Allocator,
@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
fn addLLVMAttr(
ofile: *ObjectFile,
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
) !void {
@@ -335,7 +335,7 @@ fn addLLVMAttr(
fn addLLVMAttrStr(
ofile: *ObjectFile,
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
attr_val: []const u8,
@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
}
fn addLLVMAttrInt(
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
attr_val: u64,
@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
}
-fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {
+fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void {
return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
}
-fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {
+fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void {
return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
}
-fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {
+fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void {
return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
}
fn renderLoadUntyped(
ofile: *ObjectFile,
- ptr: llvm.ValueRef,
+ ptr: *llvm.Value,
alignment: Type.Pointer.Align,
vol: Type.Pointer.Vol,
name: [*]const u8,
-) !llvm.ValueRef {
+) !*llvm.Value {
const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
switch (vol) {
Type.Pointer.Vol.Non => {},
@@ -390,11 +390,11 @@ fn renderLoadUntyped(
return result;
}
-fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef {
+fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
}
-pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef {
+pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value {
const child_type = ptr_type.key.child_type;
if (!child_type.hasBits()) {
return null;
@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
pub fn renderStoreUntyped(
ofile: *ObjectFile,
- value: llvm.ValueRef,
- ptr: llvm.ValueRef,
+ value: *llvm.Value,
+ ptr: *llvm.Value,
alignment: Type.Pointer.Align,
vol: Type.Pointer.Vol,
-) !llvm.ValueRef {
+) !*llvm.Value {
const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
switch (vol) {
Type.Pointer.Vol.Non => {},
@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
pub fn renderStore(
ofile: *ObjectFile,
- value: llvm.ValueRef,
- ptr: llvm.ValueRef,
+ value: *llvm.Value,
+ ptr: *llvm.Value,
ptr_type: *Type.Pointer,
-) !llvm.ValueRef {
+) !*llvm.Value {
return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
}
@@ -435,7 +435,7 @@ pub fn renderAlloca(
var_type: *Type,
name: []const u8,
alignment: Type.Pointer.Align,
-) !llvm.ValueRef {
+) !*llvm.Value {
const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
@@ -443,7 +443,7 @@ pub fn renderAlloca(
return result;
}
-pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 {
+pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
return switch (alignment) {
Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
Type.Pointer.Align.Override => |a| a,
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
index a8c3e13e33..de956f1525 100644
--- a/src-self-hosted/compilation.zig
+++ b/src-self-hosted/compilation.zig
@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
/// Data that is local to the event loop.
pub const ZigCompiler = struct {
loop: *event.Loop,
- llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
+ llvm_handle_pool: std.atomic.Stack(*llvm.Context),
lld_lock: event.Lock,
/// TODO pool these so that it doesn't have to lock
@@ -55,12 +55,12 @@ pub const ZigCompiler = struct {
var seed_bytes: [@sizeOf(u64)]u8 = undefined;
try std.os.getRandomBytes(seed_bytes[0..]);
- const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
+ const seed = mem.readIntNative(u64, &seed_bytes);
return ZigCompiler{
.loop = loop,
.lld_lock = event.Lock.init(loop),
- .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
+ .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
.prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
.native_libc = event.Future(LibCInstallation).init(loop),
};
@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
fn deinit(self: *ZigCompiler) void {
self.lld_lock.deinit();
while (self.llvm_handle_pool.pop()) |node| {
- c.LLVMContextDispose(node.data);
+ llvm.ContextDispose(node.data);
self.loop.allocator.destroy(node);
}
}
@@ -80,13 +80,14 @@ pub const ZigCompiler = struct {
pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
- const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
- errdefer c.LLVMContextDispose(context_ref);
+ const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
+ errdefer llvm.ContextDispose(context_ref);
- const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
+ const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
+ node.* = std.atomic.Stack(*llvm.Context).Node{
.next = undefined,
.data = context_ref,
- });
+ };
errdefer self.loop.allocator.destroy(node);
return LlvmHandle{ .node = node };
@@ -113,7 +114,7 @@ pub const ZigCompiler = struct {
};
pub const LlvmHandle = struct {
- node: *std.atomic.Stack(llvm.ContextRef).Node,
+ node: *std.atomic.Stack(*llvm.Context).Node,
pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
zig_compiler.llvm_handle_pool.push(self.node);
@@ -127,7 +128,7 @@ pub const Compilation = struct {
llvm_triple: Buffer,
root_src_path: ?[]const u8,
target: Target,
- llvm_target: llvm.TargetRef,
+ llvm_target: *llvm.Target,
build_mode: builtin.Mode,
zig_lib_dir: []const u8,
zig_std_dir: []const u8,
@@ -211,8 +212,8 @@ pub const Compilation = struct {
false_value: *Value.Bool,
noreturn_value: *Value.NoReturn,
- target_machine: llvm.TargetMachineRef,
- target_data_ref: llvm.TargetDataRef,
+ target_machine: *llvm.TargetMachine,
+ target_data_ref: *llvm.TargetData,
target_layout_str: [*]u8,
target_ptr_bits: u32,
@@ -300,6 +301,7 @@ pub const Compilation = struct {
UserResourceLimitReached,
InvalidUtf8,
BadPathName,
+ DeviceBusy,
};
pub const Event = union(enum) {
@@ -485,7 +487,7 @@ pub const Compilation = struct {
comp.name = try Buffer.init(comp.arena(), name);
comp.llvm_triple = try target.getTriple(comp.arena());
comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
- comp.zig_std_dir = try std.os.path.join(comp.arena(), zig_lib_dir, "std");
+ comp.zig_std_dir = try std.os.path.join(comp.arena(), [][]const u8{ zig_lib_dir, "std" });
const opt_level = switch (build_mode) {
builtin.Mode.Debug => llvm.CodeGenLevelNone,
@@ -595,7 +597,8 @@ pub const Compilation = struct {
}
fn initTypes(comp: *Compilation) !void {
- comp.meta_type = try comp.arena().create(Type.MetaType{
+ comp.meta_type = try comp.arena().create(Type.MetaType);
+ comp.meta_type.* = Type.MetaType{
.base = Type{
.name = "type",
.base = Value{
@@ -607,12 +610,13 @@ pub const Compilation = struct {
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
.value = undefined,
- });
+ };
comp.meta_type.value = &comp.meta_type.base;
comp.meta_type.base.base.typ = &comp.meta_type.base;
assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);
- comp.void_type = try comp.arena().create(Type.Void{
+ comp.void_type = try comp.arena().create(Type.Void);
+ comp.void_type.* = Type.Void{
.base = Type{
.name = "void",
.base = Value{
@@ -623,10 +627,11 @@ pub const Compilation = struct {
.id = builtin.TypeId.Void,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
- });
+ };
assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
- comp.noreturn_type = try comp.arena().create(Type.NoReturn{
+ comp.noreturn_type = try comp.arena().create(Type.NoReturn);
+ comp.noreturn_type.* = Type.NoReturn{
.base = Type{
.name = "noreturn",
.base = Value{
@@ -637,10 +642,11 @@ pub const Compilation = struct {
.id = builtin.TypeId.NoReturn,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
- });
+ };
assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
- comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt{
+ comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt);
+ comp.comptime_int_type.* = Type.ComptimeInt{
.base = Type{
.name = "comptime_int",
.base = Value{
@@ -651,10 +657,11 @@ pub const Compilation = struct {
.id = builtin.TypeId.ComptimeInt,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
- });
+ };
assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
- comp.bool_type = try comp.arena().create(Type.Bool{
+ comp.bool_type = try comp.arena().create(Type.Bool);
+ comp.bool_type.* = Type.Bool{
.base = Type{
.name = "bool",
.base = Value{
@@ -665,45 +672,50 @@ pub const Compilation = struct {
.id = builtin.TypeId.Bool,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
- });
+ };
assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
- comp.void_value = try comp.arena().create(Value.Void{
+ comp.void_value = try comp.arena().create(Value.Void);
+ comp.void_value.* = Value.Void{
.base = Value{
.id = Value.Id.Void,
.typ = &Type.Void.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
- });
+ };
- comp.true_value = try comp.arena().create(Value.Bool{
+ comp.true_value = try comp.arena().create(Value.Bool);
+ comp.true_value.* = Value.Bool{
.base = Value{
.id = Value.Id.Bool,
.typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.x = true,
- });
+ };
- comp.false_value = try comp.arena().create(Value.Bool{
+ comp.false_value = try comp.arena().create(Value.Bool);
+ comp.false_value.* = Value.Bool{
.base = Value{
.id = Value.Id.Bool,
.typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.x = false,
- });
+ };
- comp.noreturn_value = try comp.arena().create(Value.NoReturn{
+ comp.noreturn_value = try comp.arena().create(Value.NoReturn);
+ comp.noreturn_value.* = Value.NoReturn{
.base = Value{
.id = Value.Id.NoReturn,
.typ = &Type.NoReturn.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
- });
+ };
for (CInt.list) |cint, i| {
- const c_int_type = try comp.arena().create(Type.Int{
+ const c_int_type = try comp.arena().create(Type.Int);
+ c_int_type.* = Type.Int{
.base = Type{
.name = cint.zig_name,
.base = Value{
@@ -719,11 +731,12 @@ pub const Compilation = struct {
.bit_count = comp.target.cIntTypeSizeInBits(cint.id),
},
.garbage_node = undefined,
- });
+ };
comp.c_int_types[i] = c_int_type;
assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
}
- comp.u8_type = try comp.arena().create(Type.Int{
+ comp.u8_type = try comp.arena().create(Type.Int);
+ comp.u8_type.* = Type.Int{
.base = Type{
.name = "u8",
.base = Value{
@@ -739,7 +752,7 @@ pub const Compilation = struct {
.bit_count = 8,
},
.garbage_node = undefined,
- });
+ };
assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);
}
@@ -828,7 +841,7 @@ pub const Compilation = struct {
};
errdefer self.gpa().free(source_code);
- const tree = try self.gpa().createOne(ast.Tree);
+ const tree = try self.gpa().create(ast.Tree);
tree.* = try std.zig.parse(self.gpa(), source_code);
errdefer {
tree.deinit();
@@ -924,7 +937,8 @@ pub const Compilation = struct {
}
} else {
// add new decl
- const fn_decl = try self.gpa().create(Decl.Fn{
+ const fn_decl = try self.gpa().create(Decl.Fn);
+ fn_decl.* = Decl.Fn{
.base = Decl{
.id = Decl.Id.Fn,
.name = name,
@@ -935,7 +949,7 @@ pub const Compilation = struct {
},
.value = Decl.Fn.Val{ .Unresolved = {} },
.fn_proto = fn_proto,
- });
+ };
tree_scope.base.ref();
errdefer self.gpa().destroy(fn_decl);
@@ -1139,12 +1153,13 @@ pub const Compilation = struct {
}
}
- const link_lib = try self.gpa().create(LinkLib{
+ const link_lib = try self.gpa().create(LinkLib);
+ link_lib.* = LinkLib{
.name = name,
.path = null,
.provided_explicitly = provided_explicitly,
.symbols = ArrayList([]u8).init(self.gpa()),
- });
+ };
try self.link_libs_list.append(link_lib);
if (is_libc) {
self.libc_link_lib = link_lib;
@@ -1183,7 +1198,7 @@ pub const Compilation = struct {
const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
defer self.gpa().free(file_name);
- const full_path = try os.path.join(self.gpa(), tmp_dir, file_name[0..]);
+ const full_path = try os.path.join(self.gpa(), [][]const u8{ tmp_dir, file_name[0..] });
errdefer self.gpa().free(full_path);
return Buffer.fromOwnedSlice(self.gpa(), full_path);
@@ -1204,7 +1219,7 @@ pub const Compilation = struct {
const zig_dir_path = try getZigDir(self.gpa());
defer self.gpa().free(zig_dir_path);
- const tmp_dir = try os.path.join(self.arena(), zig_dir_path, comp_dir_name[0..]);
+ const tmp_dir = try os.path.join(self.arena(), [][]const u8{ zig_dir_path, comp_dir_name[0..] });
try os.makePath(self.gpa(), tmp_dir);
return tmp_dir;
}
diff --git a/src-self-hosted/errmsg.zig b/src-self-hosted/errmsg.zig
index 0e552fde7e..fc49fad410 100644
--- a/src-self-hosted/errmsg.zig
+++ b/src-self-hosted/errmsg.zig
@@ -118,7 +118,8 @@ pub const Msg = struct {
const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
errdefer comp.gpa().free(realpath);
- const msg = try comp.gpa().create(Msg{
+ const msg = try comp.gpa().create(Msg);
+ msg.* = Msg{
.text = text,
.realpath = realpath,
.data = Data{
@@ -128,7 +129,7 @@ pub const Msg = struct {
.span = span,
},
},
- });
+ };
tree_scope.base.ref();
return msg;
}
@@ -139,13 +140,14 @@ pub const Msg = struct {
const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);
errdefer comp.gpa().free(realpath_copy);
- const msg = try comp.gpa().create(Msg{
+ const msg = try comp.gpa().create(Msg);
+ msg.* = Msg{
.text = text,
.realpath = realpath_copy,
.data = Data{
.Cli = Cli{ .allocator = comp.gpa() },
},
- });
+ };
return msg;
}
@@ -164,7 +166,8 @@ pub const Msg = struct {
var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
try parse_error.render(&tree_scope.tree.tokens, out_stream);
- const msg = try comp.gpa().create(Msg{
+ const msg = try comp.gpa().create(Msg);
+ msg.* = Msg{
.text = undefined,
.realpath = realpath_copy,
.data = Data{
@@ -177,7 +180,7 @@ pub const Msg = struct {
},
},
},
- });
+ };
tree_scope.base.ref();
msg.text = text_buf.toOwnedSlice();
return msg;
@@ -203,7 +206,8 @@ pub const Msg = struct {
var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
try parse_error.render(&tree.tokens, out_stream);
- const msg = try allocator.create(Msg{
+ const msg = try allocator.create(Msg);
+ msg.* = Msg{
.text = undefined,
.realpath = realpath_copy,
.data = Data{
@@ -216,7 +220,7 @@ pub const Msg = struct {
},
},
},
- });
+ };
msg.text = text_buf.toOwnedSlice();
errdefer allocator.destroy(msg);
diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig
index d41f82f755..0a7f63b4f1 100644
--- a/src-self-hosted/introspect.zig
+++ b/src-self-hosted/introspect.zig
@@ -8,10 +8,10 @@ const warn = std.debug.warn;
/// Caller must free result
pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
- const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
+ const test_zig_dir = try os.path.join(allocator, [][]const u8{ test_path, "lib", "zig" });
errdefer allocator.free(test_zig_dir);
- const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig");
+ const test_index_file = try os.path.join(allocator, [][]const u8{ test_zig_dir, "std", "index.zig" });
defer allocator.free(test_index_file);
var file = try os.File.openRead(test_index_file);
diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig
index 562765b354..dc1b0dc943 100644
--- a/src-self-hosted/ir.zig
+++ b/src-self-hosted/ir.zig
@@ -67,7 +67,7 @@ pub const Inst = struct {
parent: ?*Inst,
/// populated durign codegen
- llvm_value: ?llvm.ValueRef,
+ llvm_value: ?*llvm.Value,
pub fn cast(base: *Inst, comptime T: type) ?*T {
if (base.id == comptime typeToId(T)) {
@@ -129,7 +129,7 @@ pub const Inst = struct {
}
}
- pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) {
+ pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) {
Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
@@ -313,10 +313,10 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const fn_ref = self.params.fn_ref.llvm_value.?;
- const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len);
+ const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len);
for (self.params.args) |arg, i| {
args[i] = arg.llvm_value.?;
}
@@ -360,7 +360,7 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
return self.base.val.KnownValue.getLlvmConst(ofile);
}
};
@@ -392,7 +392,7 @@ pub const Inst = struct {
return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
}
- pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const value = self.params.return_value.llvm_value;
const return_type = self.params.return_value.getKnownType();
@@ -540,7 +540,7 @@ pub const Inst = struct {
}
}
- pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef {
+ pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
switch (self.params.var_scope.data) {
Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
Scope.Var.Data.Param => |param| return param.llvm_value,
@@ -596,7 +596,7 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const child_type = self.base.getKnownType();
if (!child_type.hasBits()) {
return null;
@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
ref_instruction: ?*Inst,
/// for codegen
- llvm_block: llvm.BasicBlockRef,
- llvm_exit_block: llvm.BasicBlockRef,
+ llvm_block: *llvm.BasicBlock,
+ llvm_exit_block: *llvm.BasicBlock,
/// the basic block that is derived from this one in analysis
child: ?*BasicBlock,
@@ -1021,12 +1021,13 @@ pub const Builder = struct {
pub const Error = Analyze.Error;
pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {
- const code = try comp.gpa().create(Code{
+ const code = try comp.gpa().create(Code);
+ code.* = Code{
.basic_block_list = undefined,
.arena = std.heap.ArenaAllocator.init(comp.gpa()),
.return_type = null,
.tree_scope = tree_scope,
- });
+ };
code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
errdefer code.destroy(comp.gpa());
@@ -1052,7 +1053,8 @@ pub const Builder = struct {
/// No need to clean up resources thanks to the arena allocator.
pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
- const basic_block = try self.arena().create(BasicBlock{
+ const basic_block = try self.arena().create(BasicBlock);
+ basic_block.* = BasicBlock{
.ref_count = 0,
.name_hint = name_hint,
.debug_id = self.next_debug_id,
@@ -1063,7 +1065,7 @@ pub const Builder = struct {
.ref_instruction = null,
.llvm_block = undefined,
.llvm_exit_block = undefined,
- });
+ };
self.next_debug_id += 1;
return basic_block;
}
@@ -1774,7 +1776,8 @@ pub const Builder = struct {
params: I.Params,
is_generated: bool,
) !*Inst {
- const inst = try self.arena().create(I{
+ const inst = try self.arena().create(I);
+ inst.* = I{
.base = Inst{
.id = Inst.typeToId(I),
.is_generated = is_generated,
@@ -1793,7 +1796,7 @@ pub const Builder = struct {
.owner_bb = self.current_basic_block,
},
.params = params,
- });
+ };
// Look at the params and ref() other instructions
comptime var i = 0;
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index 1c5d111c5a..d3a461bcd9 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {
const contents = try std.io.readFileAlloc(allocator, libc_file);
defer allocator.free(contents);
- var it = std.mem.split(contents, "\n");
+ var it = std.mem.tokenize(contents, "\n");
while (it.next()) |line| {
if (line.len == 0 or line[0] == '#') continue;
- var line_it = std.mem.split(line, "=");
+ var line_it = std.mem.separate(line, "=");
const name = line_it.next() orelse {
try stderr.print("missing equal sign after field name\n");
return error.ParseError;
@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
c.ZigFindWindowsSdkError.None => {
windows_sdk = sdk;
- if (sdk.msvc_lib_dir_ptr) |ptr| {
- self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);
+ if (sdk.msvc_lib_dir_ptr != 0) {
+ self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
}
try group.call(findNativeKernel32LibDir, self, loop, sdk);
try group.call(findNativeIncludeDirWindows, self, loop, sdk);
@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {
},
}
- var it = std.mem.split(exec_result.stderr, "\n\r");
+ var it = std.mem.tokenize(exec_result.stderr, "\n\r");
var search_paths = std.ArrayList([]const u8).init(loop.allocator);
defer search_paths.deinit();
while (it.next()) |line| {
@@ -230,7 +230,7 @@ pub const LibCInstallation = struct {
while (path_i < search_paths.len) : (path_i += 1) {
const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
- const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h");
+ const stdlib_path = try std.os.path.join(loop.allocator, [][]const u8{ search_path, "stdlib.h" });
defer loop.allocator.free(stdlib_path);
if (try fileExists(stdlib_path)) {
@@ -254,7 +254,10 @@ pub const LibCInstallation = struct {
const stream = &std.io.BufferOutStream.init(&result_buf).stream;
try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);
- const stdlib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "stdlib.h");
+ const stdlib_path = try std.os.path.join(
+ loop.allocator,
+ [][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
+ );
defer loop.allocator.free(stdlib_path);
if (try fileExists(stdlib_path)) {
@@ -283,7 +286,10 @@ pub const LibCInstallation = struct {
builtin.Arch.aarch64v8 => try stream.write("arm"),
else => return error.UnsupportedArchitecture,
}
- const ucrt_lib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "ucrt.lib");
+ const ucrt_lib_path = try std.os.path.join(
+ loop.allocator,
+ [][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
+ );
defer loop.allocator.free(ucrt_lib_path);
if (try fileExists(ucrt_lib_path)) {
self.lib_dir = result_buf.toOwnedSlice();
@@ -358,7 +364,10 @@ pub const LibCInstallation = struct {
builtin.Arch.aarch64v8 => try stream.write("arm\\"),
else => return error.UnsupportedArchitecture,
}
- const kernel32_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "kernel32.lib");
+ const kernel32_path = try std.os.path.join(
+ loop.allocator,
+ [][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
+ );
defer loop.allocator.free(kernel32_path);
if (try fileExists(kernel32_path)) {
self.kernel32_lib_dir = result_buf.toOwnedSlice();
@@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
return error.CCompilerCrashed;
},
}
- var it = std.mem.split(exec_result.stdout, "\n\r");
+ var it = std.mem.tokenize(exec_result.stdout, "\n\r");
const line = it.next() orelse return error.LibCRuntimeNotFound;
const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;
@@ -428,20 +437,20 @@ const Search = struct {
fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
var search_end: usize = 0;
- if (sdk.path10_ptr) |path10_ptr| {
- if (sdk.version10_ptr) |ver10_ptr| {
+ if (sdk.path10_ptr != 0) {
+ if (sdk.version10_ptr != 0) {
search_buf[search_end] = Search{
- .path = path10_ptr[0..sdk.path10_len],
- .version = ver10_ptr[0..sdk.version10_len],
+ .path = sdk.path10_ptr[0..sdk.path10_len],
+ .version = sdk.version10_ptr[0..sdk.version10_len],
};
search_end += 1;
}
}
- if (sdk.path81_ptr) |path81_ptr| {
- if (sdk.version81_ptr) |ver81_ptr| {
+ if (sdk.path81_ptr != 0) {
+ if (sdk.version81_ptr != 0) {
search_buf[search_end] = Search{
- .path = path81_ptr[0..sdk.path81_len],
- .version = ver81_ptr[0..sdk.version81_len],
+ .path = sdk.path81_ptr[0..sdk.path81_len],
+ .version = sdk.version81_ptr[0..sdk.version81_len],
};
search_end += 1;
}
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig
index 1b32533ebc..fadc9b0189 100644
--- a/src-self-hosted/link.zig
+++ b/src-self-hosted/link.zig
@@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
}
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
- const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename);
+ const full_path = try std.os.path.join(&ctx.arena.allocator, [][]const u8{ dirname, basename });
const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
try ctx.args.append(full_path_with_null.ptr);
}
diff --git a/src-self-hosted/llvm.zig b/src-self-hosted/llvm.zig
index 778d3fae07..5cb95682ab 100644
--- a/src-self-hosted/llvm.zig
+++ b/src-self-hosted/llvm.zig
@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
pub const AttributeIndex = c_uint;
pub const Bool = c_int;
-pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
-pub const ContextRef = removeNullability(c.LLVMContextRef);
-pub const ModuleRef = removeNullability(c.LLVMModuleRef);
-pub const ValueRef = removeNullability(c.LLVMValueRef);
-pub const TypeRef = removeNullability(c.LLVMTypeRef);
-pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
-pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
-pub const TargetRef = removeNullability(c.LLVMTargetRef);
-pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);
-pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);
+pub const Builder = c.LLVMBuilderRef.Child.Child;
+pub const Context = c.LLVMContextRef.Child.Child;
+pub const Module = c.LLVMModuleRef.Child.Child;
+pub const Value = c.LLVMValueRef.Child.Child;
+pub const Type = c.LLVMTypeRef.Child.Child;
+pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
+pub const Attribute = c.LLVMAttributeRef.Child.Child;
+pub const Target = c.LLVMTargetRef.Child.Child;
+pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
+pub const TargetData = c.LLVMTargetDataRef.Child.Child;
pub const DIBuilder = c.ZigLLVMDIBuilder;
+pub const DIFile = c.ZigLLVMDIFile;
+pub const DICompileUnit = c.ZigLLVMDICompileUnit;
pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
-pub const AddFunction = c.LLVMAddFunction;
-pub const AddGlobal = c.LLVMAddGlobal;
pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
-pub const ArrayType = c.LLVMArrayType;
-pub const BuildLoad = c.LLVMBuildLoad;
pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
pub const ConstAllOnes = c.LLVMConstAllOnes;
pub const ConstArray = c.LLVMConstArray;
pub const ConstBitCast = c.LLVMConstBitCast;
-pub const ConstInt = c.LLVMConstInt;
pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
pub const ConstNeg = c.LLVMConstNeg;
-pub const ConstNull = c.LLVMConstNull;
-pub const ConstStringInContext = c.LLVMConstStringInContext;
pub const ConstStructInContext = c.LLVMConstStructInContext;
-pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData;
-pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
-pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit;
-pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder;
-pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
-pub const CreateFile = c.ZigLLVMCreateFile;
-pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
-pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout;
-pub const CreateTargetMachine = c.LLVMCreateTargetMachine;
pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
pub const DisposeBuilder = c.LLVMDisposeBuilder;
pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
-pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
-pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
pub const GetUndef = c.LLVMGetUndef;
pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
-pub const IntTypeInContext = c.LLVMIntTypeInContext;
pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
pub const MDNodeInContext = c.LLVMMDNodeInContext;
pub const MDStringInContext = c.LLVMMDStringInContext;
pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
-pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
-pub const PointerType = c.LLVMPointerType;
pub const SetAlignment = c.LLVMSetAlignment;
pub const SetDataLayout = c.LLVMSetDataLayout;
pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
pub const SetVolatile = c.LLVMSetVolatile;
pub const StructTypeInContext = c.LLVMStructTypeInContext;
pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
-pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
+pub const AddGlobal = LLVMAddGlobal;
+extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
+
+pub const ConstStringInContext = LLVMConstStringInContext;
+extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
+
+pub const ConstInt = LLVMConstInt;
+extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
+
+pub const BuildLoad = LLVMBuildLoad;
+extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
+
+pub const ConstNull = LLVMConstNull;
+extern fn LLVMConstNull(Ty: *Type) ?*Value;
+
+pub const CreateStringAttribute = LLVMCreateStringAttribute;
+extern fn LLVMCreateStringAttribute(
+ C: *Context,
+ K: [*]const u8,
+ KLength: c_uint,
+ V: [*]const u8,
+ VLength: c_uint,
+) ?*Attribute;
+
+pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
+extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
+
+pub const AddFunction = LLVMAddFunction;
+extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
+
+pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
+extern fn ZigLLVMCreateCompileUnit(
+ dibuilder: *DIBuilder,
+ lang: c_uint,
+ difile: *DIFile,
+ producer: [*]const u8,
+ is_optimized: bool,
+ flags: [*]const u8,
+ runtime_version: c_uint,
+ split_name: [*]const u8,
+ dwo_id: u64,
+ emit_debug_info: bool,
+) ?*DICompileUnit;
+
+pub const CreateFile = ZigLLVMCreateFile;
+extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
+
+pub const ArrayType = LLVMArrayType;
+extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
+
+pub const CreateDIBuilder = ZigLLVMCreateDIBuilder;
+extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder;
+
+pub const PointerType = LLVMPointerType;
+extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type;
+
+pub const CreateBuilderInContext = LLVMCreateBuilderInContext;
+extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder;
+
+pub const IntTypeInContext = LLVMIntTypeInContext;
+extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
+
+pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
+extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
+
+pub const VoidTypeInContext = LLVMVoidTypeInContext;
+extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
+
+pub const ContextCreate = LLVMContextCreate;
+extern fn LLVMContextCreate() ?*Context;
+
+pub const ContextDispose = LLVMContextDispose;
+extern fn LLVMContextDispose(C: *Context) void;
+
+pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
+extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
+
+pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
+extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
+
+pub const CreateTargetMachine = LLVMCreateTargetMachine;
+extern fn LLVMCreateTargetMachine(
+ T: *Target,
+ Triple: [*]const u8,
+ CPU: [*]const u8,
+ Features: [*]const u8,
+ Level: CodeGenOptLevel,
+ Reloc: RelocMode,
+ CodeModel: CodeModel,
+) ?*TargetMachine;
+
+pub const GetHostCPUName = LLVMGetHostCPUName;
+extern fn LLVMGetHostCPUName() ?[*]u8;
+
+pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
+extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
+
pub const GetElementType = LLVMGetElementType;
-extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;
+extern fn LLVMGetElementType(Ty: *Type) *Type;
pub const TypeOf = LLVMTypeOf;
-extern fn LLVMTypeOf(Val: ValueRef) TypeRef;
+extern fn LLVMTypeOf(Val: *Value) *Type;
pub const BuildStore = LLVMBuildStore;
-extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;
+extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
pub const BuildAlloca = LLVMBuildAlloca;
-extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef;
+extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
-pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef;
+pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
-extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool;
+extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
pub const VerifyModule = LLVMVerifyModule;
-extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
+extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
pub const GetInsertBlock = LLVMGetInsertBlock;
-extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
+extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
pub const FunctionType = LLVMFunctionType;
extern fn LLVMFunctionType(
- ReturnType: TypeRef,
- ParamTypes: [*]TypeRef,
+ ReturnType: *Type,
+ ParamTypes: [*]*Type,
ParamCount: c_uint,
IsVarArg: Bool,
-) ?TypeRef;
+) ?*Type;
pub const GetParam = LLVMGetParam;
-extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
+extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
-extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;
+extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
-extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
+extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
};
fn removeNullability(comptime T: type) type {
- comptime assert(@typeId(T) == builtin.TypeId.Optional);
- return T.Child;
+ comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
+ return *T.Child;
}
pub const BuildRet = LLVMBuildRet;
-extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;
+extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
extern fn ZigLLVMTargetMachineEmitToFile(
- targ_machine_ref: TargetMachineRef,
- module_ref: ModuleRef,
+ targ_machine_ref: *TargetMachine,
+ module_ref: *Module,
filename: [*]const u8,
output_type: EmitOutputType,
error_message: *[*]u8,
@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
) bool;
pub const BuildCall = ZigLLVMBuildCall;
-extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef;
+extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index 0742cbfe65..42556beaed 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
var stderr: *io.OutStream(os.File.WriteError) = undefined;
var stdout: *io.OutStream(os.File.WriteError) = undefined;
-const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
+pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
const usage =
\\usage: zig [command] [options]
@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
const root_name = if (provided_name) |n| n else blk: {
if (root_source_file) |file| {
const basename = os.path.basename(file);
- var it = mem.split(basename, ".");
+ var it = mem.separate(basename, ".");
break :blk it.next() orelse basename;
} else {
try stderr.write("--name [name] not provided and unable to infer\n");
@@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Compilation.Kind.Obj);
}
-const usage_fmt =
+pub const usage_fmt =
\\usage: zig fmt [file]...
\\
\\ Formats the input files and modifies them in-place.
@@ -527,7 +527,7 @@ const usage_fmt =
\\
;
-const args_fmt_spec = []Flag{
+pub const args_fmt_spec = []Flag{
Flag.Bool("--help"),
Flag.Bool("--check"),
Flag.Option("--color", []const []const u8{
@@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
var group = event.Group(FmtError!void).init(fmt.loop);
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(fmt.loop.allocator, file_path, entry.name);
+ const full_path = try os.path.join(fmt.loop.allocator, [][]const u8{ file_path, entry.name });
try group.call(fmtPath, fmt, full_path, check_mode);
}
}
@@ -944,12 +944,13 @@ const CliPkg = struct {
parent: ?*CliPkg,
pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
- var pkg = try allocator.create(CliPkg{
+ var pkg = try allocator.create(CliPkg);
+ pkg.* = CliPkg{
.name = name,
.path = path,
.children = ArrayList(*CliPkg).init(allocator),
.parent = parent,
- });
+ };
return pkg;
}
diff --git a/src-self-hosted/package.zig b/src-self-hosted/package.zig
index 720b279651..0d31731b55 100644
--- a/src-self-hosted/package.zig
+++ b/src-self-hosted/package.zig
@@ -15,11 +15,13 @@ pub const Package = struct {
/// makes internal copies of root_src_dir and root_src_path
/// allocator should be an arena allocator because Package never frees anything
pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {
- return allocator.create(Package{
+ const ptr = try allocator.create(Package);
+ ptr.* = Package{
.root_src_dir = try Buffer.init(allocator, root_src_dir),
.root_src_path = try Buffer.init(allocator, root_src_path),
.table = Table.init(allocator),
- });
+ };
+ return ptr;
}
pub fn add(self: *Package, name: []const u8, package: *Package) !void {
diff --git a/src-self-hosted/scope.zig b/src-self-hosted/scope.zig
index 43d3b5a784..9a84ad256e 100644
--- a/src-self-hosted/scope.zig
+++ b/src-self-hosted/scope.zig
@@ -120,7 +120,7 @@ pub const Scope = struct {
/// Creates a Root scope with 1 reference
/// Takes ownership of realpath
pub fn create(comp: *Compilation, realpath: []u8) !*Root {
- const self = try comp.gpa().createOne(Root);
+ const self = try comp.gpa().create(Root);
self.* = Root{
.base = Scope{
.id = Id.Root,
@@ -150,7 +150,7 @@ pub const Scope = struct {
/// Creates a scope with 1 reference
/// Takes ownership of tree, will deinit and destroy when done.
pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {
- const self = try comp.gpa().createOne(AstTree);
+ const self = try comp.gpa().create(AstTree);
self.* = AstTree{
.base = undefined,
.tree = tree,
@@ -182,7 +182,7 @@ pub const Scope = struct {
/// Creates a Decls scope with 1 reference
pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
- const self = try comp.gpa().createOne(Decls);
+ const self = try comp.gpa().create(Decls);
self.* = Decls{
.base = undefined,
.table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
@@ -235,7 +235,7 @@ pub const Scope = struct {
/// Creates a Block scope with 1 reference
pub fn create(comp: *Compilation, parent: *Scope) !*Block {
- const self = try comp.gpa().createOne(Block);
+ const self = try comp.gpa().create(Block);
self.* = Block{
.base = undefined,
.incoming_values = undefined,
@@ -262,7 +262,7 @@ pub const Scope = struct {
/// Creates a FnDef scope with 1 reference
/// Must set the fn_val later
pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
- const self = try comp.gpa().createOne(FnDef);
+ const self = try comp.gpa().create(FnDef);
self.* = FnDef{
.base = undefined,
.fn_val = null,
@@ -281,7 +281,7 @@ pub const Scope = struct {
/// Creates a CompTime scope with 1 reference
pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
- const self = try comp.gpa().createOne(CompTime);
+ const self = try comp.gpa().create(CompTime);
self.* = CompTime{ .base = undefined };
self.base.init(Id.CompTime, parent);
return self;
@@ -309,7 +309,7 @@ pub const Scope = struct {
kind: Kind,
defer_expr_scope: *DeferExpr,
) !*Defer {
- const self = try comp.gpa().createOne(Defer);
+ const self = try comp.gpa().create(Defer);
self.* = Defer{
.base = undefined,
.defer_expr_scope = defer_expr_scope,
@@ -333,7 +333,7 @@ pub const Scope = struct {
/// Creates a DeferExpr scope with 1 reference
pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {
- const self = try comp.gpa().createOne(DeferExpr);
+ const self = try comp.gpa().create(DeferExpr);
self.* = DeferExpr{
.base = undefined,
.expr_node = expr_node,
@@ -362,7 +362,7 @@ pub const Scope = struct {
pub const Param = struct {
index: usize,
typ: *Type,
- llvm_value: llvm.ValueRef,
+ llvm_value: *llvm.Value,
};
pub fn createParam(
@@ -398,7 +398,7 @@ pub const Scope = struct {
}
fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
- const self = try comp.gpa().createOne(Var);
+ const self = try comp.gpa().create(Var);
self.* = Var{
.base = undefined,
.name = name,
diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig
index 218353c9d7..121242b505 100644
--- a/src-self-hosted/target.zig
+++ b/src-self-hosted/target.zig
@@ -457,8 +457,8 @@ pub const Target = union(enum) {
}
}
- pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
- var result: llvm.TargetRef = undefined;
+ pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
+ var result: *llvm.Target = undefined;
var err_msg: [*]u8 = undefined;
if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
@@ -520,7 +520,7 @@ pub const Target = union(enum) {
=> return 64,
},
- builtin.Os.windows => switch (id) {
+ builtin.Os.windows, builtin.Os.uefi => switch (id) {
CInt.Id.Short,
CInt.Id.UShort,
=> return 16,
diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig
index ff5b96df84..4be6d53932 100644
--- a/src-self-hosted/test.zig
+++ b/src-self-hosted/test.zig
@@ -4,7 +4,7 @@ const builtin = @import("builtin");
const Target = @import("target.zig").Target;
const Compilation = @import("compilation.zig").Compilation;
const introspect = @import("introspect.zig");
-const assertOrPanic = std.debug.assertOrPanic;
+const testing = std.testing;
const errmsg = @import("errmsg.zig");
const ZigCompiler = @import("compilation.zig").ZigCompiler;
@@ -87,7 +87,7 @@ pub const TestContext = struct {
) !void {
var file_index_buf: [20]u8 = undefined;
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
- const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);
+ const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
if (std.os.path.dirname(file1_path)) |dirname| {
try std.os.makePath(allocator, dirname);
@@ -120,7 +120,7 @@ pub const TestContext = struct {
) !void {
var file_index_buf: [20]u8 = undefined;
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
- const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);
+ const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
if (std.os.path.dirname(file1_path)) |dirname| {
@@ -210,7 +210,7 @@ pub const TestContext = struct {
@panic("build incorrectly failed");
},
Compilation.Event.Fail => |msgs| {
- assertOrPanic(msgs.len != 0);
+ testing.expect(msgs.len != 0);
for (msgs) |msg| {
if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {
const span = msg.getSpan();
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
index aa00bb876d..7d611bb787 100644
--- a/src-self-hosted/type.zig
+++ b/src-self-hosted/type.zig
@@ -44,14 +44,15 @@ pub const Type = struct {
Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
+ Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
}
}
pub fn getLlvmType(
base: *Type,
allocator: *Allocator,
- llvm_context: llvm.ContextRef,
- ) (error{OutOfMemory}!llvm.TypeRef) {
+ llvm_context: *llvm.Context,
+ ) (error{OutOfMemory}!*llvm.Type) {
switch (base.id) {
Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
@@ -77,6 +78,7 @@ pub const Type = struct {
Id.ArgTuple => unreachable,
Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
+ Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
}
}
@@ -103,6 +105,7 @@ pub const Type = struct {
Id.Enum,
Id.Fn,
Id.Promise,
+ Id.Vector,
=> return false,
Id.Struct => @panic("TODO"),
@@ -135,6 +138,7 @@ pub const Type = struct {
Id.Float,
Id.Fn,
Id.Promise,
+ Id.Vector,
=> return true,
Id.Pointer => {
@@ -192,7 +196,7 @@ pub const Type = struct {
}
/// If you have an llvm conext handy, you can use it here.
- pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
+ pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
@@ -201,7 +205,7 @@ pub const Type = struct {
}
/// Lower level function that does the work. See getAbiAlignment.
- async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
+ async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
}
@@ -214,7 +218,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -409,7 +413,7 @@ pub const Type = struct {
key.ref();
errdefer key.deref(comp);
- const self = try comp.gpa().createOne(Fn);
+ const self = try comp.gpa().create(Fn);
self.* = Fn{
.base = undefined,
.key = key,
@@ -492,13 +496,13 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const normal = &self.key.data.Normal;
const llvm_return_type = switch (normal.return_type.id) {
Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
else => try normal.return_type.getLlvmType(allocator, llvm_context),
};
- const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len);
+ const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
defer allocator.free(llvm_param_types);
for (llvm_param_types) |*llvm_param_type, i| {
llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
@@ -555,7 +559,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -611,11 +615,12 @@ pub const Type = struct {
}
}
- const self = try comp.gpa().create(Int{
+ const self = try comp.gpa().create(Int);
+ self.* = Int{
.base = undefined,
.key = key,
.garbage_node = undefined,
- });
+ };
errdefer comp.gpa().destroy(self);
const u_or_i = "ui"[@boolToInt(key.is_signed)];
@@ -653,7 +658,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
}
};
@@ -665,7 +670,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -777,17 +782,19 @@ pub const Type = struct {
}
}
- const self = try comp.gpa().create(Pointer{
+ const self = try comp.gpa().create(Pointer);
+ self.* = Pointer{
.base = undefined,
.key = normal_key,
.garbage_node = undefined,
- });
+ };
errdefer comp.gpa().destroy(self);
const size_str = switch (self.key.size) {
Size.One => "*",
Size.Many => "[*]",
Size.Slice => "[]",
+ Size.C => "[*c]",
};
const mut_str = switch (self.key.mut) {
Mut.Const => "const ",
@@ -829,7 +836,7 @@ pub const Type = struct {
return self;
}
- pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
}
@@ -875,11 +882,12 @@ pub const Type = struct {
}
}
- const self = try comp.gpa().create(Array{
+ const self = try comp.gpa().create(Array);
+ self.* = Array{
.base = undefined,
.key = key,
.garbage_node = undefined,
- });
+ };
errdefer comp.gpa().destroy(self);
const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
@@ -896,12 +904,24 @@ pub const Type = struct {
return self;
}
- pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
}
};
+ pub const Vector = struct {
+ base: Type,
+
+ pub fn destroy(self: *Vector, comp: *Compilation) void {
+ comp.gpa().destroy(self);
+ }
+
+ pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
+ @panic("TODO");
+ }
+ };
+
pub const ComptimeFloat = struct {
base: Type,
@@ -947,7 +967,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -959,7 +979,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -971,7 +991,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -983,7 +1003,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -995,7 +1015,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1015,7 +1035,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1035,7 +1055,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1047,7 +1067,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
+ builtin.TypeInfo.Pointer.Size.C => unreachable,
}
},
builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig
index e6dca4eff7..d8c0f7b5c8 100644
--- a/src-self-hosted/value.zig
+++ b/src-self-hosted/value.zig
@@ -57,7 +57,7 @@ pub const Value = struct {
std.debug.warn("{}", @tagName(base.id));
}
- pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) {
+ pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) {
Id.Type => unreachable,
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
@@ -135,14 +135,15 @@ pub const Value = struct {
symbol_name: Buffer,
pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {
- const self = try comp.gpa().create(FnProto{
+ const self = try comp.gpa().create(FnProto);
+ self.* = FnProto{
.base = Value{
.id = Value.Id.FnProto,
.typ = &fn_type.base,
.ref_count = std.atomic.Int(usize).init(1),
},
.symbol_name = symbol_name,
- });
+ };
fn_type.base.base.ref();
return self;
}
@@ -152,7 +153,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
const llvm_fn = llvm.AddFunction(
ofile.module,
@@ -190,14 +191,16 @@ pub const Value = struct {
/// Creates a Fn value with 1 ref
/// Takes ownership of symbol_name
pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {
- const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node{
+ const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node);
+ link_set_node.* = Compilation.FnLinkSet.Node{
.data = null,
.next = undefined,
.prev = undefined,
- });
+ };
errdefer comp.gpa().destroy(link_set_node);
- const self = try comp.gpa().create(Fn{
+ const self = try comp.gpa().create(Fn);
+ self.* = Fn{
.base = Value{
.id = Value.Id.Fn,
.typ = &fn_type.base,
@@ -209,7 +212,7 @@ pub const Value = struct {
.symbol_name = symbol_name,
.containing_object = Buffer.initNull(comp.gpa()),
.link_set_node = link_set_node,
- });
+ };
fn_type.base.base.ref();
fndef_scope.fn_val = self;
fndef_scope.base.ref();
@@ -235,7 +238,7 @@ pub const Value = struct {
/// We know that the function definition will end up in an .o file somewhere.
/// Here, all we have to do is generate a global prototype.
/// TODO cache the prototype per ObjectFile
- pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value {
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
const llvm_fn = llvm.AddFunction(
ofile.module,
@@ -280,8 +283,8 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
- const llvm_type = llvm.Int1TypeInContext(ofile.context);
+ pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
+ const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
if (self.x) {
return llvm.ConstAllOnes(llvm_type);
} else {
@@ -353,7 +356,8 @@ pub const Value = struct {
var ptr_type_consumed = false;
errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
- const self = try comp.gpa().create(Value.Ptr{
+ const self = try comp.gpa().create(Value.Ptr);
+ self.* = Value.Ptr{
.base = Value{
.id = Value.Id.Ptr,
.typ = &ptr_type.base,
@@ -366,7 +370,7 @@ pub const Value = struct {
},
},
.mut = Mut.CompTimeConst,
- });
+ };
ptr_type_consumed = true;
errdefer comp.gpa().destroy(self);
@@ -377,7 +381,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
// TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
switch (self.special) {
@@ -387,7 +391,7 @@ pub const Value = struct {
const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
const ptr_bit_count = ofile.comp.target_ptr_bits;
const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
- const indices = []llvm.ValueRef{
+ const indices = []*llvm.Value{
llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
};
@@ -430,14 +434,15 @@ pub const Value = struct {
}) catch unreachable);
errdefer array_type.base.base.deref(comp);
- const self = try comp.gpa().create(Value.Array{
+ const self = try comp.gpa().create(Value.Array);
+ self.* = Value.Array{
.base = Value{
.id = Value.Id.Array,
.typ = &array_type.base,
.ref_count = std.atomic.Int(usize).init(1),
},
.special = Special{ .OwnedBuffer = buffer },
- });
+ };
errdefer comp.gpa().destroy(self);
return self;
@@ -454,7 +459,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
switch (self.special) {
Special.Undefined => {
const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
@@ -509,14 +514,15 @@ pub const Value = struct {
big_int: std.math.big.Int,
pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {
- const self = try comp.gpa().create(Value.Int{
+ const self = try comp.gpa().create(Value.Int);
+ self.* = Value.Int{
.base = Value{
.id = Value.Id.Int,
.typ = typ,
.ref_count = std.atomic.Int(usize).init(1),
},
.big_int = undefined,
- });
+ };
typ.base.ref();
errdefer comp.gpa().destroy(self);
@@ -528,7 +534,7 @@ pub const Value = struct {
return self;
}
- pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
switch (self.base.typ.id) {
Type.Id.Int => {
const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
@@ -557,14 +563,15 @@ pub const Value = struct {
old.base.typ.base.ref();
errdefer old.base.typ.base.deref(comp);
- const new = try comp.gpa().create(Value.Int{
+ const new = try comp.gpa().create(Value.Int);
+ new.* = Value.Int{
.base = Value{
.id = Value.Id.Int,
.typ = old.base.typ,
.ref_count = std.atomic.Int(usize).init(1),
},
.big_int = undefined,
- });
+ };
errdefer comp.gpa().destroy(new);
new.big_int = try old.big_int.clone();
diff --git a/src/all_types.hpp b/src/all_types.hpp
index f7ada09a57..6fbd987b9e 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -56,9 +56,6 @@ struct IrExecutable {
size_t next_debug_id;
size_t *backward_branch_count;
size_t backward_branch_quota;
- bool invalid;
- bool is_inline;
- bool is_generic_instantiation;
ZigFn *fn_entry;
Buf *c_import_buf;
AstNode *source_node;
@@ -78,6 +75,10 @@ struct IrExecutable {
IrBasicBlock *coro_suspend_block;
IrBasicBlock *coro_final_cleanup_block;
ZigVar *coro_allocator_var;
+
+ bool invalid;
+ bool is_inline;
+ bool is_generic_instantiation;
};
enum OutType {
@@ -90,6 +91,9 @@ enum OutType {
enum ConstParentId {
ConstParentIdNone,
ConstParentIdStruct,
+ ConstParentIdErrUnionCode,
+ ConstParentIdErrUnionPayload,
+ ConstParentIdOptionalPayload,
ConstParentIdArray,
ConstParentIdUnion,
ConstParentIdScalar,
@@ -107,6 +111,15 @@ struct ConstParent {
ConstExprValue *struct_val;
size_t field_index;
} p_struct;
+ struct {
+ ConstExprValue *err_union_val;
+ } p_err_union_code;
+ struct {
+ ConstExprValue *err_union_val;
+ } p_err_union_payload;
+ struct {
+ ConstExprValue *optional_val;
+ } p_optional_payload;
struct {
ConstExprValue *union_val;
} p_union;
@@ -118,13 +131,11 @@ struct ConstParent {
struct ConstStructValue {
ConstExprValue *fields;
- ConstParent parent;
};
struct ConstUnionValue {
BigInt tag;
ConstExprValue *payload;
- ConstParent parent;
};
enum ConstArraySpecial {
@@ -138,7 +149,6 @@ struct ConstArrayValue {
union {
struct {
ConstExprValue *elements;
- ConstParent parent;
} s_none;
Buf *s_buf;
} data;
@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
ConstPtrSpecialBaseArray,
// The pointer points to a field in an underlying struct.
ConstPtrSpecialBaseStruct,
+ // The pointer points to the error set field of an error union
+ ConstPtrSpecialBaseErrorUnionCode,
+ // The pointer points to the payload field of an error union
+ ConstPtrSpecialBaseErrorUnionPayload,
+ // The pointer points to the payload field of an optional
+ ConstPtrSpecialBaseOptionalPayload,
// This means that we did a compile-time pointer reinterpret and we cannot
// understand the value of pointee at compile time. However, we will still
// emit a binary with a compile time known address.
// In this case index is the numeric address value.
- // We also use this for null pointer. We need the data layout for ConstCastOnly == true
- // types to be the same, so all optionals of pointer types use x_ptr
- // instead of x_optional
ConstPtrSpecialHardCodedAddr,
// This means that the pointer represents memory of assigning to _.
// That is, storing discards the data, and loading is invalid.
ConstPtrSpecialDiscard,
// This is actually a function.
ConstPtrSpecialFunction,
+ // This means the pointer is null. This is only allowed when the type is ?*T.
+ // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
+ // for that value to avoid doing comptime work.
+ // We need the data layout for ConstCastOnly == true
+ // types to be the same, so all optionals of pointer types use x_ptr
+ // instead of x_optional.
+ ConstPtrSpecialNull,
};
enum ConstPtrMut {
@@ -199,6 +219,15 @@ struct ConstPtrValue {
ConstExprValue *struct_val;
size_t field_index;
} base_struct;
+ struct {
+ ConstExprValue *err_union_val;
+ } base_err_union_code;
+ struct {
+ ConstExprValue *err_union_val;
+ } base_err_union_payload;
+ struct {
+ ConstExprValue *optional_val;
+ } base_optional_payload;
struct {
uint64_t addr;
} hard_coded_addr;
@@ -209,7 +238,7 @@ struct ConstPtrValue {
};
struct ConstErrValue {
- ErrorTableEntry *err;
+ ConstExprValue *error_set;
ConstExprValue *payload;
};
@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
struct ConstExprValue {
ZigType *type;
ConstValSpecial special;
+ ConstParent parent;
ConstGlobalRefs *global_refs;
union {
@@ -433,7 +463,7 @@ enum NodeType {
NodeTypeArrayType,
NodeTypeErrorType,
NodeTypeIfErrorExpr,
- NodeTypeTestExpr,
+ NodeTypeIfOptional,
NodeTypeErrorSetDecl,
NodeTypeCancel,
NodeTypeResume,
@@ -514,12 +544,7 @@ struct AstNodeDefer {
};
struct AstNodeVariableDeclaration {
- VisibMod visib_mod;
Buf *symbol;
- bool is_const;
- bool is_comptime;
- bool is_export;
- bool is_extern;
// one or both of type and expr will be non null
AstNode *type;
AstNode *expr;
@@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration {
AstNode *align_expr;
// populated if the "section(S)" is present
AstNode *section_expr;
+ Token *threadlocal_tok;
+
+ VisibMod visib_mod;
+ bool is_const;
+ bool is_comptime;
+ bool is_export;
+ bool is_extern;
};
struct AstNodeTestDecl {
@@ -605,7 +637,6 @@ enum CastOp {
CastOpFloatToInt,
CastOpBoolToInt,
CastOpResizeSlice,
- CastOpBytesToSlice,
CastOpNumLitToConcrete,
CastOpErrSet,
CastOpBitCast,
@@ -660,15 +691,17 @@ struct AstNodePointerType {
AstNode *align_expr;
BigInt *bit_offset_start;
BigInt *host_int_bytes;
+ AstNode *op_expr;
+ Token *allow_zero_token;
bool is_const;
bool is_volatile;
- AstNode *op_expr;
};
struct AstNodeArrayType {
AstNode *size;
AstNode *child_type;
AstNode *align_expr;
+ Token *allow_zero_token;
bool is_const;
bool is_volatile;
};
@@ -678,7 +711,7 @@ struct AstNodeUse {
AstNode *expr;
TldResolution resolution;
- IrInstruction *value;
+ ConstExprValue *value;
};
struct AstNodeIfBoolExpr {
@@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
enum PtrLen {
PtrLenUnknown,
PtrLenSingle,
+ PtrLenC,
};
struct ZigTypePointer {
@@ -1018,6 +1052,7 @@ struct ZigTypePointer {
uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
bool is_const;
bool is_volatile;
+ bool allow_zero;
};
struct ZigTypeInt {
@@ -1167,6 +1202,7 @@ struct ZigTypeFn {
FnGenParamInfo *gen_param_info;
LLVMTypeRef raw_type_ref;
+ ZigLLVMDIType *raw_di_type;
ZigType *bound_fn_parent;
};
@@ -1180,6 +1216,12 @@ struct ZigTypePromise {
ZigType *result_type;
};
+struct ZigTypeVector {
+ // The type must be a pointer, integer, or float
+ ZigType *elem_type;
+ uint32_t len;
+};
+
enum ZigTypeId {
ZigTypeIdInvalid,
ZigTypeIdMetaType,
@@ -1206,6 +1248,7 @@ enum ZigTypeId {
ZigTypeIdArgTuple,
ZigTypeIdOpaque,
ZigTypeIdPromise,
+ ZigTypeIdVector,
};
struct ZigType {
@@ -1232,6 +1275,7 @@ struct ZigType {
ZigTypeFn fn;
ZigTypeBoundFn bound_fn;
ZigTypePromise promise;
+ ZigTypeVector vector;
} data;
// use these fields to make sure we don't duplicate type table entries for the same type
@@ -1385,6 +1429,7 @@ enum BuiltinFnId {
BuiltinFnIdEnumToInt,
BuiltinFnIdIntToEnum,
BuiltinFnIdIntType,
+ BuiltinFnIdVectorType,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
BuiltinFnIdSetFloatMode,
@@ -1415,6 +1460,8 @@ enum BuiltinFnId {
BuiltinFnIdErrorReturnTrace,
BuiltinFnIdAtomicRmw,
BuiltinFnIdAtomicLoad,
+ BuiltinFnIdBswap,
+ BuiltinFnIdBitReverse,
};
struct BuiltinFnEntry {
@@ -1441,6 +1488,7 @@ enum PanicMsgId {
PanicMsgIdBadUnionField,
PanicMsgIdBadEnumValue,
PanicMsgIdFloatToInt,
+ PanicMsgIdPtrCastNull,
PanicMsgIdCount,
};
@@ -1455,11 +1503,12 @@ struct TypeId {
struct {
ZigType *child_type;
PtrLen ptr_len;
- bool is_const;
- bool is_volatile;
uint32_t alignment;
uint32_t bit_offset_in_host;
uint32_t host_int_bytes;
+ bool is_const;
+ bool is_volatile;
+ bool allow_zero;
} pointer;
struct {
ZigType *child_type;
@@ -1473,6 +1522,10 @@ struct TypeId {
ZigType *err_set_type;
ZigType *payload_type;
} error_union;
+ struct {
+ ZigType *elem_type;
+ uint32_t len;
+ } vector;
} data;
};
@@ -1487,8 +1540,12 @@ enum ZigLLVMFnId {
ZigLLVMFnIdFloor,
ZigLLVMFnIdCeil,
ZigLLVMFnIdSqrt,
+ ZigLLVMFnIdBswap,
+ ZigLLVMFnIdBitReverse,
};
+// There are a bunch of places in code that rely on these values being in
+// exactly this order.
enum AddSubMul {
AddSubMulAdd = 0,
AddSubMulSub = 1,
@@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey {
struct {
AddSubMul add_sub_mul;
uint32_t bit_count;
+ uint32_t vector_len; // 0 means not a vector
bool is_signed;
} overflow_arithmetic;
+ struct {
+ uint32_t bit_count;
+ } bswap;
+ struct {
+ uint32_t bit_count;
+ } bit_reverse;
} data;
};
@@ -1600,7 +1664,7 @@ struct CodeGen {
HashMap fn_type_table;
HashMap error_table;
HashMap generic_table;
- HashMap memoized_fn_eval_table;
+ HashMap memoized_fn_eval_table;
HashMap llvm_fn_table;
HashMap exported_symbol_names;
HashMap external_prototypes;
@@ -1694,6 +1758,7 @@ struct CodeGen {
ZigFn *cur_fn;
ZigFn *main_fn;
ZigFn *panic_fn;
+ TldFn *panic_tld_fn;
AstNode *root_export_decl;
CacheHash cache_hash;
@@ -1746,12 +1811,12 @@ struct CodeGen {
BuildMode build_mode;
OutType out_type;
ZigTarget zig_target;
+ TargetSubsystem subsystem;
bool is_static;
bool strip_debug_symbols;
bool is_test_build;
+ bool is_single_threaded;
bool is_native_target;
- bool windows_subsystem_windows;
- bool windows_subsystem_console;
bool linker_rdynamic;
bool no_rosegment_workaround;
bool each_lib_rpath;
@@ -1793,10 +1858,9 @@ enum VarLinkage {
struct ZigVar {
Buf name;
- ConstExprValue *value;
+ ConstExprValue *const_value;
+ ZigType *var_type;
LLVMValueRef value_ref;
- bool src_is_const;
- bool gen_is_const;
IrInstruction *is_comptime;
// which node is the declaration of the variable
AstNode *decl_node;
@@ -1806,17 +1870,22 @@ struct ZigVar {
Scope *parent_scope;
Scope *child_scope;
LLVMValueRef param_value_ref;
- bool shadowable;
size_t mem_slot_index;
IrExecutable *owner_exec;
size_t ref_count;
- VarLinkage linkage;
- uint32_t align_bytes;
// In an inline loop, multiple variables may be created,
// In this case, a reference to a variable should follow
// this pointer to the redefined variable.
ZigVar *next_var;
+
+ uint32_t align_bytes;
+ VarLinkage linkage;
+
+ bool shadowable;
+ bool src_is_const;
+ bool gen_is_const;
+ bool is_thread_local;
};
struct ErrorTableEntry {
@@ -1882,10 +1951,11 @@ struct ScopeBlock {
ZigList *incoming_values;
ZigList *incoming_blocks;
- bool safety_off;
AstNode *safety_set_node;
- bool fast_math_on;
AstNode *fast_math_set_node;
+
+ bool safety_off;
+ bool fast_math_on;
};
// This scope is created from every defer expression.
@@ -2021,8 +2091,19 @@ struct IrBasicBlock {
IrInstruction *must_be_comptime_source_instr;
};
+// These instructions are in transition to having "pass 1" instructions
+// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
+// and pass 2 are suffixed with Gen.
+// Once all instructions are separated in this way, they'll have different
+// base types for better type safety.
+// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
+// ir_analyze_* functions consume Src instructions and produce Gen instructions.
+// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
+// Src instructions do not have type information; Gen instructions do.
enum IrInstructionId {
IrInstructionIdInvalid,
+ IrInstructionIdDeclVarSrc,
+ IrInstructionIdDeclVarGen,
IrInstructionIdBr,
IrInstructionIdCondBr,
IrInstructionIdSwitchBr,
@@ -2031,7 +2112,6 @@ enum IrInstructionId {
IrInstructionIdPhi,
IrInstructionIdUnOp,
IrInstructionIdBinOp,
- IrInstructionIdDeclVar,
IrInstructionIdLoadPtr,
IrInstructionIdStorePtr,
IrInstructionIdFieldPtr,
@@ -2060,7 +2140,7 @@ enum IrInstructionId {
IrInstructionIdAsm,
IrInstructionIdSizeOf,
IrInstructionIdTestNonNull,
- IrInstructionIdUnwrapOptional,
+ IrInstructionIdOptionalUnwrapPtr,
IrInstructionIdOptionalWrap,
IrInstructionIdUnionTag,
IrInstructionIdClz,
@@ -2076,7 +2156,8 @@ enum IrInstructionId {
IrInstructionIdCompileLog,
IrInstructionIdErrName,
IrInstructionIdEmbedFile,
- IrInstructionIdCmpxchg,
+ IrInstructionIdCmpxchgSrc,
+ IrInstructionIdCmpxchgGen,
IrInstructionIdFence,
IrInstructionIdTruncate,
IrInstructionIdIntCast,
@@ -2085,6 +2166,7 @@ enum IrInstructionId {
IrInstructionIdFloatToInt,
IrInstructionIdBoolToInt,
IrInstructionIdIntType,
+ IrInstructionIdVectorType,
IrInstructionIdBoolNot,
IrInstructionIdMemset,
IrInstructionIdMemcpy,
@@ -2105,7 +2187,8 @@ enum IrInstructionId {
IrInstructionIdErrWrapPayload,
IrInstructionIdFnProto,
IrInstructionIdTestComptime,
- IrInstructionIdPtrCast,
+ IrInstructionIdPtrCastSrc,
+ IrInstructionIdPtrCastGen,
IrInstructionIdBitCast,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
@@ -2158,10 +2241,15 @@ enum IrInstructionId {
IrInstructionIdMergeErrRetTraces,
IrInstructionIdMarkErrRetTracePtr,
IrInstructionIdSqrt,
+ IrInstructionIdBswap,
+ IrInstructionIdBitReverse,
IrInstructionIdErrSetCast,
IrInstructionIdToBytes,
IrInstructionIdFromBytes,
IrInstructionIdCheckRuntimeScope,
+ IrInstructionIdVectorToArray,
+ IrInstructionIdArrayToVector,
+ IrInstructionIdAssertZero,
};
struct IrInstruction {
@@ -2183,6 +2271,22 @@ struct IrInstruction {
bool is_gen;
};
+struct IrInstructionDeclVarSrc {
+ IrInstruction base;
+
+ ZigVar *var;
+ IrInstruction *var_type;
+ IrInstruction *align_value;
+ IrInstruction *init_value;
+};
+
+struct IrInstructionDeclVarGen {
+ IrInstruction base;
+
+ ZigVar *var;
+ IrInstruction *init_value;
+};
+
struct IrInstructionCondBr {
IrInstruction base;
@@ -2291,20 +2395,11 @@ struct IrInstructionBinOp {
IrInstruction base;
IrInstruction *op1;
- IrBinOp op_id;
IrInstruction *op2;
+ IrBinOp op_id;
bool safety_check_on;
};
-struct IrInstructionDeclVar {
- IrInstruction base;
-
- ZigVar *var;
- IrInstruction *var_type;
- IrInstruction *align_value;
- IrInstruction *init_value;
-};
-
struct IrInstructionLoadPtr {
IrInstruction base;
@@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr {
IrInstruction *container_ptr;
Buf *field_name_buffer;
IrInstruction *field_name_expr;
- bool is_const;
};
struct IrInstructionStructFieldPtr {
@@ -2367,13 +2461,13 @@ struct IrInstructionCall {
ZigFn *fn_entry;
size_t arg_count;
IrInstruction **args;
- bool is_comptime;
LLVMValueRef tmp_ptr;
- FnInline fn_inline;
- bool is_async;
IrInstruction *async_allocator;
IrInstruction *new_stack;
+ FnInline fn_inline;
+ bool is_async;
+ bool is_comptime;
};
struct IrInstructionConst {
@@ -2504,6 +2598,7 @@ struct IrInstructionPtrType {
PtrLen ptr_len;
bool is_const;
bool is_volatile;
+ bool allow_zero;
};
struct IrInstructionPromiseType {
@@ -2516,9 +2611,10 @@ struct IrInstructionSliceType {
IrInstruction base;
IrInstruction *align_value;
+ IrInstruction *child_type;
bool is_const;
bool is_volatile;
- IrInstruction *child_type;
+ bool allow_zero;
};
struct IrInstructionAsm {
@@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull {
IrInstruction *value;
};
-struct IrInstructionUnwrapOptional {
+// Takes a pointer to an optional value, returns a pointer
+// to the payload.
+struct IrInstructionOptionalUnwrapPtr {
IrInstruction base;
- IrInstruction *value;
+ IrInstruction *base_ptr;
bool safety_check_on;
};
@@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile {
IrInstruction *name;
};
-struct IrInstructionCmpxchg {
+struct IrInstructionCmpxchgSrc {
IrInstruction base;
IrInstruction *type_value;
@@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg {
IrInstruction *success_order_value;
IrInstruction *failure_order_value;
- // if this instruction gets to runtime then we know these values:
- ZigType *type;
+ bool is_weak;
+};
+
+struct IrInstructionCmpxchgGen {
+ IrInstruction base;
+
+ IrInstruction *ptr;
+ IrInstruction *cmp_value;
+ IrInstruction *new_value;
+ LLVMValueRef tmp_ptr;
AtomicOrder success_order;
AtomicOrder failure_order;
-
bool is_weak;
-
- LLVMValueRef tmp_ptr;
};
struct IrInstructionFence {
@@ -2737,6 +2840,13 @@ struct IrInstructionIntType {
IrInstruction *bit_count;
};
+struct IrInstructionVectorType {
+ IrInstruction base;
+
+ IrInstruction *len;
+ IrInstruction *elem_type;
+};
+
struct IrInstructionBoolNot {
IrInstruction base;
@@ -2840,7 +2950,7 @@ struct IrInstructionTestErr {
struct IrInstructionUnwrapErrCode {
IrInstruction base;
- IrInstruction *value;
+ IrInstruction *err_union;
};
struct IrInstructionUnwrapErrPayload {
@@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime {
IrInstruction *value;
};
-struct IrInstructionPtrCast {
+struct IrInstructionPtrCastSrc {
IrInstruction base;
IrInstruction *dest_type;
IrInstruction *ptr;
+ bool safety_check_on;
+};
+
+struct IrInstructionPtrCastGen {
+ IrInstruction base;
+
+ IrInstruction *ptr;
+ bool safety_check_on;
};
struct IrInstructionBitCast {
@@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope {
IrInstruction *is_comptime;
};
+struct IrInstructionBswap {
+ IrInstruction base;
+
+ IrInstruction *type;
+ IrInstruction *op;
+};
+
+struct IrInstructionBitReverse {
+ IrInstruction base;
+
+ IrInstruction *type;
+ IrInstruction *op;
+};
+
+struct IrInstructionArrayToVector {
+ IrInstruction base;
+
+ IrInstruction *array;
+};
+
+struct IrInstructionVectorToArray {
+ IrInstruction base;
+
+ IrInstruction *vector;
+ LLVMValueRef tmp_ptr;
+};
+
+struct IrInstructionAssertZero {
+ IrInstruction base;
+
+ IrInstruction *target;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 2f4b173c5f..9941104bc4 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum
static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
-ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
- if (node->owner->c_import_node != nullptr) {
- // if this happens, then translate_c generated code that
- // failed semantic analysis, which isn't supposed to happen
- ErrorMsg *err = add_node_error(g, node->owner->c_import_node,
- buf_sprintf("compiler bug: @cImport generated invalid zig code"));
-
- add_error_note(g, err, node, msg);
-
- g->errors.append(err);
- return err;
- }
-
- ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
- node->owner->source_code, node->owner->line_offsets, msg);
-
- g->errors.append(err);
- return err;
-}
-
-ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
- if (node->owner->c_import_node != nullptr) {
+static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ImportTableEntry *owner, Token *token,
+ Buf *msg)
+{
+ if (owner->c_import_node != nullptr) {
// if this happens, then translate_c generated code that
// failed semantic analysis, which isn't supposed to happen
@@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
return note;
}
- ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
- node->owner->source_code, node->owner->line_offsets, msg);
+ ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
+ owner->source_code, owner->line_offsets, msg);
err_msg_add_note(parent_msg, err);
return err;
}
+ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg) {
+ if (owner->c_import_node != nullptr) {
+ // if this happens, then translate_c generated code that
+ // failed semantic analysis, which isn't supposed to happen
+ ErrorMsg *err = add_node_error(g, owner->c_import_node,
+ buf_sprintf("compiler bug: @cImport generated invalid zig code"));
+
+ add_error_note_token(g, err, owner, token, msg);
+
+ g->errors.append(err);
+ return err;
+ }
+ ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
+ owner->source_code, owner->line_offsets, msg);
+
+ g->errors.append(err);
+ return err;
+}
+
+ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
+ Token fake_token;
+ fake_token.start_line = node->line;
+ fake_token.start_column = node->column;
+ return add_token_error(g, node->owner, &fake_token, msg);
+}
+
+ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
+ Token fake_token;
+ fake_token.start_line = node->line;
+ fake_token.start_column = node->column;
+ return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg);
+}
+
ZigType *new_type_table_entry(ZigTypeId id) {
ZigType *entry = allocate(1);
entry->id = id;
@@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return nullptr;
}
zig_unreachable();
@@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return true;
}
zig_unreachable();
@@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
}
}
+ return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
+}
+
+uint64_t type_size_store(CodeGen *g, ZigType *type_entry) {
+ assert(type_is_complete(type_entry));
+
+ if (!type_has_bits(type_entry))
+ return 0;
+
+ if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
+ uint64_t size_in_bits = type_size_bits(g, type_entry);
+ return (size_in_bits + 7) / 8;
+ } else if (type_entry->id == ZigTypeIdArray) {
+ ZigType *child_type = type_entry->data.array.child_type;
+ if (child_type->id == ZigTypeIdStruct &&
+ child_type->data.structure.layout == ContainerLayoutPacked)
+ {
+ uint64_t size_in_bits = type_size_bits(g, type_entry);
+ return (size_in_bits + 7) / 8;
+ }
+ }
+
return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
}
@@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
return entry;
}
+static const char *ptr_len_to_star_str(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return "*";
+ case PtrLenUnknown:
+ return "[*]";
+ case PtrLenC:
+ return "[*c]";
+ }
+ zig_unreachable();
+}
+
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
- bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)
+ bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
+ uint32_t bit_offset_in_host, uint32_t host_int_bytes)
{
+ // TODO when implementing https://github.com/ziglang/zig/issues/1953
+ // move this to a parameter
+ bool allow_zero = (ptr_len == PtrLenC);
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
@@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
- if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
+ if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
@@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
type_id.data.pointer.host_int_bytes = host_int_bytes;
type_id.data.pointer.ptr_len = ptr_len;
+ type_id.data.pointer.allow_zero = allow_zero;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
@@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
- const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
+ const char *star_str = ptr_len_to_star_str(ptr_len);
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
+ const char *allow_zero_str;
+ if (ptr_len == PtrLenC) {
+ assert(allow_zero);
+ allow_zero_str = "";
+ } else {
+ allow_zero_str = allow_zero ? "allowzero " : "";
+ }
buf_resize(&entry->name, 0);
if (host_int_bytes == 0 && byte_alignment == 0) {
- buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%s%s%s%s%s",
+ star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
} else if (host_int_bytes == 0) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
+ const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
} else if (byte_alignment == 0) {
- buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
+ buf_ptr(&child_type->name));
} else {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
+ buf_ptr(&child_type->name));
}
assert(child_type->id != ZigTypeIdInvalid);
@@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
- if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
+ if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
+ bit_offset_in_host != 0 || allow_zero)
+ {
ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenSingle, 0, 0, host_int_bytes);
entry->type_ref = peer_type->type_ref;
@@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.explicit_alignment = byte_alignment;
entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
entry->data.pointer.host_int_bytes = host_int_bytes;
+ entry->data.pointer.allow_zero = allow_zero;
if (parent_pointer) {
*parent_pointer = entry;
@@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
if (child_type->zero_bits) {
entry->type_ref = LLVMInt1Type();
entry->di_type = g->builtin_types.entry_bool->di_type;
- } else if (type_is_codegen_pointer(child_type)) {
+ } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
assert(child_type->di_type);
// this is an optimization but also is necessary for calling C
// functions where all pointers are maybe pointers
// function types are technically pointers
entry->type_ref = child_type->type_ref;
entry->di_type = child_type->di_type;
+ if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
+ g->error_di_types.append(&entry->di_type);
+ }
} else {
assert(child_type->di_type);
// create a struct with a boolean whether this is the null value
@@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
ZigType *child_type = ptr_type->data.pointer.child_type;
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
- ptr_type->data.pointer.explicit_alignment != 0)
+ ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
{
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenUnknown, 0, 0, 0);
@@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(child_ptr_type->id == ZigTypeIdPointer);
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
- child_ptr_type->data.pointer.explicit_alignment != 0)
+ child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
{
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
@@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
}
if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
- if (abi_class == X64CABIClass_MEMORY) {
- return true;
- }
- zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
- buf_ptr(&fn_type_id->return_type->name));
+ return abi_class == X64CABIClass_MEMORY;
} else if (target_is_arm(&g->zig_target)) {
return type_size(g, fn_type_id->return_type) > 16;
}
@@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
- fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
+ fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
+ LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref),
+ LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), "");
}
g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
@@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
return entry;
}
-static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
+static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
+ Buf *type_name)
+{
size_t backward_branch_count = 0;
return ir_eval_const_value(g, scope, node, type_entry,
&backward_branch_count, default_backward_branch_quota,
- nullptr, nullptr, node, type_name, nullptr);
+ nullptr, nullptr, node, type_name, nullptr, nullptr);
}
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
- IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
- if (result->value.type->id == ZigTypeIdInvalid)
+ ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
+ if (type_is_invalid(result->type))
return g->builtin_types.entry_invalid;
- assert(result->value.special != ConstValSpecialRuntime);
- return result->value.data.x_type;
+ assert(result->special != ConstValSpecialRuntime);
+ return result->data.x_type;
}
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
@@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
}
static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
- IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
- if (type_is_invalid(align_result->value.type))
+ ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
+ if (type_is_invalid(align_result->type))
return false;
- uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
+ uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
if (align_bytes == 0) {
add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
return false;
@@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, 0, 0, 0);
ZigType *str_type = get_slice_type(g, ptr_type);
- IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
- if (type_is_invalid(instr->value.type))
+ ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
+ if (type_is_invalid(result_val->type))
return false;
- ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
- ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
+ ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
+ ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
@@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdFn:
+ case ZigTypeIdVector:
return true;
case ZigTypeIdStruct:
return type_entry->data.structure.layout == ContainerLayoutPacked;
@@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
zig_unreachable();
}
-static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
@@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
default:
return false;
}
+ case ZigTypeIdVector:
+ return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
case ZigTypeIdFloat:
return true;
case ZigTypeIdArray:
@@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
switch (type_requires_comptime(g, type_entry)) {
case ReqCompTimeNo:
break;
@@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
switch (type_requires_comptime(g, fn_type_id.return_type)) {
case ReqCompTimeInvalid:
return g->builtin_types.entry_invalid;
@@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
// In this first pass we resolve explicit tag values.
// In a second pass we will fill in the unspecified ones.
if (tag_value != nullptr) {
- IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
- if (result_inst->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
+ if (type_is_invalid(result->type)) {
enum_type->data.enumeration.is_invalid = true;
continue;
}
- assert(result_inst->value.special != ConstValSpecialRuntime);
- assert(result_inst->value.type->id == ZigTypeIdInt ||
- result_inst->value.type->id == ZigTypeIdComptimeInt);
- auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
+ assert(result->special != ConstValSpecialRuntime);
+ assert(result->type->id == ZigTypeIdInt ||
+ result->type->id == ZigTypeIdComptimeInt);
+ auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
if (entry == nullptr) {
- bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
+ bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
} else {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
+ bigint_append_buf(val_buf, &result->data.x_bigint, 10);
ErrorMsg *msg = add_node_error(g, tag_value,
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
@@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
buf_sprintf("enums, not structs, support field assignment"));
}
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeYes:
struct_type->data.structure.requires_comptime = true;
@@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
assert(decl_node->type == NodeTypeContainerDecl);
assert(struct_type->di_type);
+ size_t field_count = struct_type->data.structure.src_field_count;
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
struct_type->data.structure.abi_alignment = 1;
- }
-
- size_t field_count = struct_type->data.structure.src_field_count;
- for (size_t i = 0; i < field_count; i += 1) {
- TypeStructField *field = &struct_type->data.structure.fields[i];
-
- // If this assertion trips, look up the call stack. Probably something is
- // calling type_resolve with ResolveStatusAlignmentKnown when it should only
- // be resolving ResolveStatusZeroBitsKnown
- assert(field->type_entry != nullptr);
-
- if (type_is_invalid(field->type_entry)) {
- struct_type->data.structure.resolve_status = ResolveStatusInvalid;
- break;
+ for (size_t i = 0; i < field_count; i += 1) {
+ TypeStructField *field = &struct_type->data.structure.fields[i];
+ if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ break;
+ }
}
+ } else for (size_t i = 0; i < field_count; i += 1) {
+ TypeStructField *field = &struct_type->data.structure.fields[i];
+ uint32_t this_field_align;
- if (!type_has_bits(field->type_entry))
- continue;
+ // TODO If we have no type_entry for the field, we've already failed to
+ // compile the program correctly. This stage1 compiler needs a deeper
+ // reworking to make this correct, or we can ignore the problem
+ // and make sure it is fixed in stage2. This workaround is for when
+ // there is a false positive of a dependency loop, of alignment depending
+ // on itself. When this false positive happens we assume a pointer-aligned
+ // field, which is usually fine but could be incorrectly over-aligned or
+ // even under-aligned. See https://github.com/ziglang/zig/issues/1512
+ if (field->type_entry == nullptr) {
+ this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
+ } else {
+ if (type_is_invalid(field->type_entry)) {
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ break;
+ }
+
+ if (!type_has_bits(field->type_entry))
+ continue;
- // alignment of structs is the alignment of the most-aligned field
- if (struct_type->data.structure.layout != ContainerLayoutPacked) {
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
- uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
+ this_field_align = get_abi_alignment(g, field->type_entry);
assert(this_field_align != 0);
- if (this_field_align > struct_type->data.structure.abi_alignment) {
- struct_type->data.structure.abi_alignment = this_field_align;
- }
+ }
+ // alignment of structs is the alignment of the most-aligned field
+ if (this_field_align > struct_type->data.structure.abi_alignment) {
+ struct_type->data.structure.abi_alignment = this_field_align;
}
}
@@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
enum_type_node != nullptr;
bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
- bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr);
+ bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
ZigType *tag_type;
bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
bool *covered_enum_fields;
@@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
}
union_field->type_entry = field_type;
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
+ union_type->data.unionation.is_invalid = true;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeInvalid:
union_type->data.unionation.is_invalid = true;
@@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
// In a second pass we will fill in the unspecified ones.
if (tag_value != nullptr) {
ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
- IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
- if (result_inst->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
+ if (type_is_invalid(result->type)) {
union_type->data.unionation.is_invalid = true;
continue;
}
- assert(result_inst->value.special != ConstValSpecialRuntime);
- assert(result_inst->value.type->id == ZigTypeIdInt);
- auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
+ assert(result->special != ConstValSpecialRuntime);
+ assert(result->type->id == ZigTypeIdInt);
+ auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
if (entry == nullptr) {
- bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);
+ bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
} else {
Buf *val_buf = buf_alloc();
- bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
+ bigint_append_buf(val_buf, &result->data.x_bigint, 10);
ErrorMsg *msg = add_node_error(g, tag_value,
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
@@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
zig_unreachable();
}
-static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
- add_node_error(g, proto_node,
- buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
- buf_ptr(&fn_type->name)));
-}
+void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
+ ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
+ assert(panic_fn_type_val != nullptr);
+ assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
+ ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
-static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
- AstNode *proto_node = panic_fn->proto_node;
- assert(proto_node->type == NodeTypeFnProto);
- ZigType *fn_type = panic_fn->type_entry;
- FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
- if (fn_type_id->param_count != 2) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
- ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
- PtrLenUnknown, 0, 0, 0);
- ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
- if (fn_type_id->param_info[0].type != const_u8_slice) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ AstNode *fake_decl = allocate(1);
+ *fake_decl = *panic_fn->proto_node;
+ fake_decl->type = NodeTypeSymbol;
+ fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
- ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
- if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
-
- ZigType *actual_return_type = fn_type_id->return_type;
- if (actual_return_type != g->builtin_types.entry_unreachable) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ // call this for the side effects of casting to panic_fn_type
+ analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
}
ZigType *get_test_fn_type(CodeGen *g) {
@@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
if (ccc) {
if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
g->have_c_main = true;
- g->windows_subsystem_windows = false;
- g->windows_subsystem_console = true;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(symbol_name, "WinMain") &&
g->zig_target.os == OsWindows)
{
g->have_winmain = true;
- g->windows_subsystem_windows = true;
- g->windows_subsystem_console = false;
+ g->subsystem = TargetSubsystemWindows;
} else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
g->zig_target.os == OsWindows)
{
@@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
g->have_dllmain_crt_startup = true;
}
}
+
FnExport *fn_export = fn_table_entry->export_list.add_one();
memset(fn_export, 0, sizeof(FnExport));
buf_init_from_buf(&fn_export->name, symbol_name);
@@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
if (!fn_table_entry->type_entry->data.fn.is_generic) {
if (fn_def_node)
g->fn_defs.append(fn_table_entry);
+ }
- if (scope_is_root_decls(tld_fn->base.parent_scope) &&
- (import == g->root_import || import->package == g->panic_package))
+ if (scope_is_root_decls(tld_fn->base.parent_scope) &&
+ (import == g->root_import || import->package == g->panic_package))
+ {
+ if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
+ g->main_fn = fn_table_entry;
+ } else if ((import->package == g->panic_package || g->have_pub_panic) &&
+ buf_eql_str(&fn_table_entry->symbol_name, "panic"))
{
- if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
- g->main_fn = fn_table_entry;
- } else if ((import->package == g->panic_package || g->have_pub_panic) &&
- buf_eql_str(&fn_table_entry->symbol_name, "panic"))
- {
- g->panic_fn = fn_table_entry;
- typecheck_panic_fn(g, fn_table_entry);
- }
+ g->panic_fn = fn_table_entry;
+ g->panic_tld_fn = tld_fn;
}
}
} else if (source_node->type == NodeTypeTestDecl) {
@@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
resolve_top_level_decl(g, tld, false, tld->source_node);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
- tld_var->var->value = value;
+ tld_var->var->const_value = value;
+ tld_var->var->var_type = value->type;
tld_var->var->align_bytes = get_abi_alignment(g, value->type);
}
@@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeArrayType:
case NodeTypeErrorType:
case NodeTypeIfErrorExpr:
- case NodeTypeTestExpr:
+ case NodeTypeIfOptional:
case NodeTypeErrorSetDecl:
case NodeTypeCancel:
case NodeTypeResume:
@@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
case ZigTypeIdFn:
case ZigTypeIdBoundFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return type_entry;
}
zig_unreachable();
@@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
// Set name to nullptr to make the variable anonymous (not visible to programmer).
// TODO merge with definition of add_local_var in ir.cpp
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
- bool is_const, ConstExprValue *value, Tld *src_tld)
+ bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
{
Error err;
- assert(value);
+ assert(const_value != nullptr);
+ assert(var_type != nullptr);
ZigVar *variable_entry = allocate(1);
- variable_entry->value = value;
+ variable_entry->const_value = const_value;
+ variable_entry->var_type = var_type;
variable_entry->parent_scope = parent_scope;
variable_entry->shadowable = false;
variable_entry->mem_slot_index = SIZE_MAX;
@@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
assert(name);
buf_init_from_buf(&variable_entry->name, name);
- if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
- variable_entry->align_bytes = get_abi_alignment(g, value->type);
+ variable_entry->align_bytes = get_abi_alignment(g, var_type);
ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
if (existing_var && !existing_var->shadowable) {
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
ZigType *type;
if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
add_node_error(g, source_node,
buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
} else {
Scope *search_scope = nullptr;
if (src_tld == nullptr) {
@@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
- variable_entry->value->type = g->builtin_types.entry_invalid;
+ variable_entry->var_type = g->builtin_types.entry_invalid;
}
}
}
@@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
bool is_const = var_decl->is_const;
bool is_extern = var_decl->is_extern;
bool is_export = var_decl->is_export;
+ bool is_thread_local = var_decl->threadlocal_tok != nullptr;
ZigType *explicit_type = nullptr;
if (var_decl->type) {
@@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
linkage = VarLinkageInternal;
}
- IrInstruction *init_value = nullptr;
+ ConstExprValue *init_value = nullptr;
// TODO more validation for types that can't be used for export/extern variables
ZigType *implicit_type = nullptr;
@@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
} else if (var_decl->expr) {
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
assert(init_value);
- implicit_type = init_value->value.type;
+ implicit_type = init_value->type;
if (implicit_type->id == ZigTypeIdUnreachable) {
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
@@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
implicit_type = g->builtin_types.entry_invalid;
}
- assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
+ assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
} else if (linkage != VarLinkageExternal) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
@@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
ZigType *type = explicit_type ? explicit_type : implicit_type;
assert(type != nullptr); // should have been caught by the parser
- ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
+ ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
- is_const, init_val, &tld_var->base);
+ is_const, init_val, &tld_var->base, type);
tld_var->var->linkage = linkage;
+ tld_var->var->is_thread_local = is_thread_local;
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
- tld_var->var->value->type = g->builtin_types.entry_invalid;
+ tld_var->var->var_type = g->builtin_types.entry_invalid;
}
if (var_decl->align_expr != nullptr) {
if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
- tld_var->var->value->type = g->builtin_types.entry_invalid;
+ tld_var->var->var_type = g->builtin_types.entry_invalid;
}
}
@@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
}
}
+ if (is_thread_local && is_const) {
+ add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
+ }
+
g->global_vars.append(tld_var);
}
@@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) {
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return false;
}
zig_unreachable();
@@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
zig_unreachable();
}
}
@@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
if (type->id == ZigTypeIdFn) return type;
if (type->id == ZigTypeIdPromise) return type;
if (type->id == ZigTypeIdOptional) {
- if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;
+ if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
+ return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
+ }
if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
}
@@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
return ty;
}
+bool type_is_nonnull_ptr(ZigType *type) {
+ return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
+}
+
bool type_is_codegen_pointer(ZigType *type) {
return get_codegen_ptr_type(type) == type;
}
@@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
}
ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
- param_name, true, create_const_runtime(param_type), nullptr);
+ param_name, true, create_const_runtime(param_type), nullptr, param_type);
var->src_arg_index = i;
fn_table_entry->child_scope = var->child_scope;
var->shadowable = var->shadowable || is_var_args;
@@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
preview_use_decl(g, src_use_node);
}
- IrInstruction *use_target_value = src_use_node->data.use.value;
- if (use_target_value->value.type->id == ZigTypeIdInvalid) {
+ ConstExprValue *use_target_value = src_use_node->data.use.value;
+ if (type_is_invalid(use_target_value->type)) {
dst_use_node->owner->any_imports_failed = true;
return;
}
dst_use_node->data.use.resolution = TldResolutionOk;
- ConstExprValue *const_val = &use_target_value->value;
- assert(const_val->special != ConstValSpecialRuntime);
+ assert(use_target_value->special != ConstValSpecialRuntime);
- ImportTableEntry *target_import = const_val->data.x_import;
+ ImportTableEntry *target_import = use_target_value->data.x_import;
assert(target_import);
if (target_import->any_imports_failed) {
@@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
}
node->data.use.resolution = TldResolutionResolving;
- IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,
+ ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
- if (result->value.type->id == ZigTypeIdInvalid)
+ if (type_is_invalid(result->type))
node->owner->any_imports_failed = true;
node->data.use.value = result;
@@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
if (is_pub && ok_cc) {
if (buf_eql_str(proto_name, "main")) {
g->have_pub_main = true;
- g->windows_subsystem_windows = false;
- g->windows_subsystem_console = true;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(proto_name, "panic")) {
g->have_pub_panic = true;
}
@@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
return new_entry;
}
+bool is_valid_vector_elem_type(ZigType *elem_type) {
+ return elem_type->id == ZigTypeIdInt ||
+ elem_type->id == ZigTypeIdFloat ||
+ get_codegen_ptr_type(elem_type) != nullptr;
+}
+
+ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
+ assert(is_valid_vector_elem_type(elem_type));
+
+ TypeId type_id = {};
+ type_id.id = ZigTypeIdVector;
+ type_id.data.vector.len = len;
+ type_id.data.vector.elem_type = elem_type;
+
+ {
+ auto entry = g->type_table.maybe_get(type_id);
+ if (entry)
+ return entry->value;
+ }
+
+ ZigType *entry = new_type_table_entry(ZigTypeIdVector);
+ entry->zero_bits = (len == 0) || !type_has_bits(elem_type);
+ entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len);
+ entry->data.vector.len = len;
+ entry->data.vector.elem_type = elem_type;
+
+ buf_resize(&entry->name, 0);
+ buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name));
+
+ entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder,
+ len * type_size_bits(g, elem_type),
+ LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type, len);
+
+ g->type_table.put(type_id, entry);
+ return entry;
+}
+
ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
return &g->builtin_types.entry_c_int[c_int_type];
}
@@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) {
case ZigTypeIdFn:
case ZigTypeIdEnum:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
return false;
case ZigTypeIdArray:
case ZigTypeIdStruct:
@@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) {
return type_has_bits(type_entry->data.error_union.payload_type);
case ZigTypeIdOptional:
return type_has_bits(type_entry->data.maybe.child_type) &&
- !type_is_codegen_pointer(type_entry->data.maybe.child_type);
+ !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
+ type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
case ZigTypeIdUnion:
assert(type_entry->data.unionation.zero_bits_known);
if (type_entry->data.unionation.gen_field_count == 0)
@@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) {
void find_libc_include_path(CodeGen *g) {
if (g->libc_include_dir == nullptr) {
if (!g->is_native_target) {
- fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
- exit(1);
+ return;
}
if (g->zig_target.os == OsWindows) {
@@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
return true;
}
+static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
+ assert(const_val->data.x_err_set != nullptr);
+ return const_val->data.x_err_set->value ^ 2630160122;
+}
+
static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
uint32_t hash_val = 0;
switch (const_val->data.x_ptr.mut) {
@@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
return hash_val;
+ case ConstPtrSpecialBaseErrorUnionCode:
+ hash_val += (uint32_t)2994743799;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
+ return hash_val;
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ hash_val += (uint32_t)3456080131;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
+ return hash_val;
+ case ConstPtrSpecialBaseOptionalPayload:
+ hash_val += (uint32_t)3163140517;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
+ return hash_val;
case ConstPtrSpecialHardCodedAddr:
hash_val += (uint32_t)4048518294;
hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
@@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += (uint32_t)2590901619;
hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
return hash_val;
+ case ConstPtrSpecialNull:
+ hash_val += (uint32_t)1486246455;
+ return hash_val;
}
zig_unreachable();
}
@@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
return 2709806591;
case ZigTypeIdOptional:
if (get_codegen_ptr_type(const_val->type) != nullptr) {
- return hash_const_val(const_val) * 1992916303;
+ return hash_const_val_ptr(const_val) * 1992916303;
+ } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
+ return hash_const_val_error_set(const_val) * 3147031929;
} else {
if (const_val->data.x_optional) {
return hash_const_val(const_val->data.x_optional) * 1992916303;
@@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
// TODO better hashing algorithm
return 3415065496;
case ZigTypeIdErrorSet:
- assert(const_val->data.x_err_set != nullptr);
- return const_val->data.x_err_set->value ^ 2630160122;
+ return hash_const_val_error_set(const_val);
case ZigTypeIdNamespace:
return hash_ptr(const_val->data.x_import);
+ case ZigTypeIdVector:
+ // TODO better hashing algorithm
+ return 3647867726;
case ZigTypeIdBoundFn:
case ZigTypeIdInvalid:
case ZigTypeIdUnreachable:
@@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case ZigTypeIdBool:
case ZigTypeIdUnreachable:
case ZigTypeIdInt:
+ case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
@@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
return can_mutate_comptime_var_state(value->data.x_optional);
case ZigTypeIdErrorUnion:
- if (value->data.x_err_union.err != nullptr)
+ if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
return false;
assert(value->data.x_err_union.payload != nullptr);
return can_mutate_comptime_var_state(value->data.x_err_union.payload);
@@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdPointer:
+ case ZigTypeIdVector:
return true;
case ZigTypeIdArray:
@@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
while (scope) {
if (scope->id == ScopeIdVarDecl) {
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
- if (type_is_invalid(var_scope->var->value->type))
+ if (type_is_invalid(var_scope->var->var_type))
return false;
- if (can_mutate_comptime_var_state(var_scope->var->value))
+ if (can_mutate_comptime_var_state(var_scope->var->const_value))
return false;
} else if (scope->id == ScopeIdFnDef) {
return true;
@@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) {
while (scope) {
if (scope->id == ScopeIdVarDecl) {
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
- result += hash_const_val(var_scope->var->value);
+ result += hash_const_val(var_scope->var->const_value);
} else if (scope->id == ScopeIdFnDef) {
ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
result += hash_ptr(fn_scope->fn_entry);
@@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
if (a->id == ScopeIdVarDecl) {
ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
- if (a_var_scope->var->value->type != b_var_scope->var->value->type)
- return false;
- if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
+ if (a_var_scope->var->var_type != b_var_scope->var->var_type)
return false;
+ if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
+ b_var_scope->var->var_type == b_var_scope->var->const_value->type)
+ {
+ if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
+ return false;
+ } else {
+ zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
+ }
} else if (a->id == ScopeIdFnDef) {
ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
@@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
return false;
}
+// Whether the type has bits at runtime.
bool type_has_bits(ZigType *type_entry) {
assert(type_entry);
assert(!type_is_invalid(type_entry));
@@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) {
return !type_entry->zero_bits;
}
+// Whether you can infer the value based solely on the type.
+OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
+ assert(type_entry != nullptr);
+ Error err;
+ if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
+ return OnePossibleValueInvalid;
+ switch (type_entry->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdOpaque:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdMetaType:
+ case ZigTypeIdNamespace:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdOptional:
+ case ZigTypeIdFn:
+ case ZigTypeIdBool:
+ case ZigTypeIdFloat:
+ case ZigTypeIdPromise:
+ case ZigTypeIdErrorUnion:
+ return OnePossibleValueNo;
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdVoid:
+ case ZigTypeIdUnreachable:
+ return OnePossibleValueYes;
+ case ZigTypeIdArray:
+ if (type_entry->data.array.len == 0)
+ return OnePossibleValueYes;
+ return type_has_one_possible_value(g, type_entry->data.array.child_type);
+ case ZigTypeIdStruct:
+ for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
+ TypeStructField *field = &type_entry->data.structure.fields[i];
+ switch (type_has_one_possible_value(g, field->type_entry)) {
+ case OnePossibleValueInvalid:
+ return OnePossibleValueInvalid;
+ case OnePossibleValueNo:
+ return OnePossibleValueNo;
+ case OnePossibleValueYes:
+ continue;
+ }
+ }
+ return OnePossibleValueYes;
+ case ZigTypeIdErrorSet:
+ case ZigTypeIdEnum:
+ case ZigTypeIdInt:
+ case ZigTypeIdVector:
+ return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
+ case ZigTypeIdPointer:
+ return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
+ case ZigTypeIdUnion:
+ if (type_entry->data.unionation.src_field_count > 1)
+ return OnePossibleValueNo;
+ return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
+ }
+ zig_unreachable();
+}
+
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
Error err;
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
@@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdErrorSet:
case ZigTypeIdBool:
case ZigTypeIdInt:
+ case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdVoid:
case ZigTypeIdUnreachable:
@@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
return false;
return true;
+ case ConstPtrSpecialBaseErrorUnionCode:
+ if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
+ b->data.x_ptr.data.base_err_union_code.err_union_val &&
+ a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
+ b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
+ {
+ return false;
+ }
+ return true;
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
+ b->data.x_ptr.data.base_err_union_payload.err_union_val &&
+ a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
+ b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
+ {
+ return false;
+ }
+ return true;
+ case ConstPtrSpecialBaseOptionalPayload:
+ if (a->data.x_ptr.data.base_optional_payload.optional_val !=
+ b->data.x_ptr.data.base_optional_payload.optional_val &&
+ a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
+ b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
+ {
+ return false;
+ }
+ return true;
case ConstPtrSpecialHardCodedAddr:
if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
return false;
@@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
return true;
case ConstPtrSpecialFunction:
return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
+ case ConstPtrSpecialNull:
+ return true;
}
zig_unreachable();
}
+static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) {
+ assert(a->data.x_array.special != ConstArraySpecialUndef);
+ assert(b->data.x_array.special != ConstArraySpecialUndef);
+ if (a->data.x_array.special == ConstArraySpecialBuf &&
+ b->data.x_array.special == ConstArraySpecialBuf)
+ {
+ return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
+ }
+ expand_undef_array(g, a);
+ expand_undef_array(g, b);
+
+ ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
+ ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
+
+ for (size_t i = 0; i < len; i += 1) {
+ if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
+ return false;
+ }
+
+ return true;
+}
+
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
assert(a->type->id == b->type->id);
assert(a->special == ConstValSpecialStatic);
@@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
case ZigTypeIdPointer:
case ZigTypeIdFn:
return const_values_equal_ptr(a, b);
+ case ZigTypeIdVector:
+ assert(a->type->data.vector.len == b->type->data.vector.len);
+ return const_values_equal_array(g, a, b, a->type->data.vector.len);
case ZigTypeIdArray: {
assert(a->type->data.array.len == b->type->data.array.len);
- assert(a->data.x_array.special != ConstArraySpecialUndef);
- assert(b->data.x_array.special != ConstArraySpecialUndef);
- if (a->data.x_array.special == ConstArraySpecialBuf &&
- b->data.x_array.special == ConstArraySpecialBuf)
- {
- return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
- }
- expand_undef_array(g, a);
- expand_undef_array(g, b);
-
- size_t len = a->type->data.array.len;
- ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
- ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
-
- for (size_t i = 0; i < len; ++i) {
- if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
- return false;
- }
-
- return true;
+ return const_values_equal_array(g, a, b, a->type->data.array.len);
}
case ZigTypeIdStruct:
for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
@@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
}
}
-void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+ assert(type_entry->id == ZigTypeIdPointer);
+
+ if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
+ buf_append_buf(buf, &type_entry->name);
+ return;
+ }
+
switch (const_val->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
case ConstPtrSpecialRef:
case ConstPtrSpecialBaseStruct:
+ case ConstPtrSpecialBaseErrorUnionCode:
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ case ConstPtrSpecialBaseOptionalPayload:
buf_appendf(buf, "*");
- render_const_value(g, buf, const_ptr_pointee(g, const_val));
+ // TODO we need a source node for const_ptr_pointee because it can generate compile errors
+ render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
case ConstPtrSpecialBaseArray:
if (const_val->data.x_ptr.data.base_array.is_cstr) {
@@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
return;
} else {
buf_appendf(buf, "*");
- render_const_value(g, buf, const_ptr_pointee(g, const_val));
+ // TODO we need a source node for const_ptr_pointee because it can generate compile errors
+ render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
}
case ConstPtrSpecialHardCodedAddr:
@@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
return;
}
+ case ConstPtrSpecialNull:
+ buf_append_str(buf, "null");
+ return;
+ }
+ zig_unreachable();
+}
+
+static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
+ if (const_val->data.x_err_set == nullptr) {
+ buf_append_str(buf, "null");
+ } else {
+ buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
+ }
+}
+
+static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
+ ConstArrayValue *array = &const_val->data.x_array;
+ switch (array->special) {
+ case ConstArraySpecialUndef:
+ buf_append_str(buf, "undefined");
+ return;
+ case ConstArraySpecialBuf: {
+ Buf *array_buf = array->data.s_buf;
+ const char *base = &buf_ptr(array_buf)[start];
+ assert(start + len <= buf_len(array_buf));
+
+ buf_append_char(buf, '"');
+ for (size_t i = 0; i < len; i += 1) {
+ uint8_t c = base[i];
+ if (c == '"') {
+ buf_append_str(buf, "\\\"");
+ } else {
+ buf_append_char(buf, c);
+ }
+ }
+ buf_append_char(buf, '"');
+ return;
+ }
+ case ConstArraySpecialNone: {
+ ConstExprValue *base = &array->data.s_none.elements[start];
+ assert(start + len <= const_val->type->data.array.len);
+
+ buf_appendf(buf, "%s{", buf_ptr(type_name));
+ for (uint64_t i = 0; i < len; i += 1) {
+ if (i != 0) buf_appendf(buf, ",");
+ render_const_value(g, buf, &base[i]);
+ }
+ buf_appendf(buf, "}");
+ return;
+ }
}
zig_unreachable();
}
@@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdPointer:
return render_const_val_ptr(g, buf, const_val, type_entry);
- case ZigTypeIdArray:
- switch (const_val->data.x_array.special) {
- case ConstArraySpecialUndef:
- buf_append_str(buf, "undefined");
- return;
- case ConstArraySpecialBuf: {
- Buf *array_buf = const_val->data.x_array.data.s_buf;
- buf_append_char(buf, '"');
- for (size_t i = 0; i < buf_len(array_buf); i += 1) {
- uint8_t c = buf_ptr(array_buf)[i];
- if (c == '"') {
- buf_append_str(buf, "\\\"");
- } else {
- buf_append_char(buf, c);
- }
- }
- buf_append_char(buf, '"');
- return;
- }
- case ConstArraySpecialNone: {
- buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
- uint64_t len = type_entry->data.array.len;
- for (uint64_t i = 0; i < len; i += 1) {
- if (i != 0)
- buf_appendf(buf, ",");
- ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
- render_const_value(g, buf, child_value);
- }
- buf_appendf(buf, "}");
- return;
- }
- }
- zig_unreachable();
+ case ZigTypeIdArray: {
+ uint64_t len = type_entry->data.array.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
+ case ZigTypeIdVector: {
+ uint32_t len = type_entry->data.vector.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
case ZigTypeIdNull:
{
buf_appendf(buf, "null");
@@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
{
if (get_codegen_ptr_type(const_val->type) != nullptr)
return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
+ if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
+ return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
if (const_val->data.x_optional) {
render_const_value(g, buf, const_val->data.x_optional);
} else {
@@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdStruct:
{
- buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ if (is_slice(type_entry)) {
+ ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];
+ size_t len = bigint_as_unsigned(&len_val->data.x_bigint);
+
+ ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
+ if (ptr_val->special == ConstValSpecialUndef) {
+ assert(len == 0);
+ buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name));
+ return;
+ }
+ assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val;
+ size_t start = ptr_val->data.x_ptr.data.base_array.elem_index;
+
+ render_const_val_array(g, buf, &type_entry->name, array, start, len);
+ } else {
+ buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ }
return;
}
case ZigTypeIdEnum:
@@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
case ZigTypeIdErrorUnion:
{
buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
- if (const_val->data.x_err_union.err == nullptr) {
+ ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
+ if (err_set == nullptr) {
render_const_value(g, buf, const_val->data.x_err_union.payload);
} else {
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
- buf_ptr(&const_val->data.x_err_union.err->name));
+ buf_ptr(&err_set->name));
}
buf_appendf(buf, ")");
return;
@@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
return;
}
case ZigTypeIdErrorSet:
- {
- buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
- return;
- }
+ return render_const_val_err_set(g, buf, const_val, type_entry);
case ZigTypeIdArgTuple:
{
buf_appendf(buf, "(args value)");
@@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) {
((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
+ (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
@@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) {
case ZigTypeIdInt:
return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
(((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
+ case ZigTypeIdVector:
+ return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681);
}
zig_unreachable();
}
@@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
+ a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
a.data.pointer.alignment == b.data.pointer.alignment &&
a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
@@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) {
case ZigTypeIdInt:
return a.data.integer.is_signed == b.data.integer.is_signed &&
a.data.integer.bit_count == b.data.integer.bit_count;
+ case ZigTypeIdVector:
+ return a.data.vector.elem_type == b.data.vector.elem_type &&
+ a.data.vector.len == b.data.vector.len;
}
zig_unreachable();
}
@@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
case ZigLLVMFnIdSqrt:
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
+ case ZigLLVMFnIdBswap:
+ return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
+ case ZigLLVMFnIdBitReverse:
+ return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
case ZigLLVMFnIdOverflowArithmetic:
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
- ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820);
+ ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820) +
+ x.data.overflow_arithmetic.vector_len * 1435156945;
}
zig_unreachable();
}
@@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
return a.data.clz.bit_count == b.data.clz.bit_count;
case ZigLLVMFnIdPopCount:
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
+ case ZigLLVMFnIdBswap:
+ return a.data.bswap.bit_count == b.data.bswap.bit_count;
+ case ZigLLVMFnIdBitReverse:
+ return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
case ZigLLVMFnIdFloor:
case ZigLLVMFnIdCeil:
case ZigLLVMFnIdSqrt:
@@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
case ZigLLVMFnIdOverflowArithmetic:
return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
(a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&
- (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed);
+ (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed) &&
+ (a.data.overflow_arithmetic.vector_len == b.data.overflow_arithmetic.vector_len);
}
zig_unreachable();
}
// Canonicalize the array value as ConstArraySpecialNone
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
- assert(const_val->type->id == ZigTypeIdArray);
+ size_t elem_count;
+ ZigType *elem_type;
+ if (const_val->type->id == ZigTypeIdArray) {
+ elem_count = const_val->type->data.array.len;
+ elem_type = const_val->type->data.array.child_type;
+ } else if (const_val->type->id == ZigTypeIdVector) {
+ elem_count = const_val->type->data.vector.len;
+ elem_type = const_val->type->data.vector.elem_type;
+ } else {
+ zig_unreachable();
+ }
+ if (const_val->special == ConstValSpecialUndef) {
+ const_val->special = ConstValSpecialStatic;
+ const_val->data.x_array.special = ConstArraySpecialUndef;
+ }
switch (const_val->data.x_array.special) {
case ConstArraySpecialNone:
return;
case ConstArraySpecialUndef: {
const_val->data.x_array.special = ConstArraySpecialNone;
- size_t elem_count = const_val->type->data.array.len;
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
for (size_t i = 0; i < elem_count; i += 1) {
ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
- element_val->type = const_val->type->data.array.child_type;
+ element_val->type = elem_type;
init_const_undefined(g, element_val);
- ConstParent *parent = get_const_val_parent(g, element_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdArray;
- parent->data.p_array.array_val = const_val;
- parent->data.p_array.elem_index = i;
- }
+ element_val->parent.id = ConstParentIdArray;
+ element_val->parent.data.p_array.array_val = const_val;
+ element_val->parent.data.p_array.elem_index = i;
}
return;
}
@@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
g->string_literals_table.maybe_remove(buf);
const_val->data.x_array.special = ConstArraySpecialNone;
- size_t elem_count = const_val->type->data.array.len;
assert(elem_count == buf_len(buf));
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
for (size_t i = 0; i < elem_count; i += 1) {
@@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
+ this_char->parent.id = ConstParentIdArray;
+ this_char->parent.data.p_array.array_val = const_val;
+ this_char->parent.data.p_array.elem_index = i;
}
return;
}
@@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
zig_unreachable();
}
+// Deprecated. Reference the parent field directly.
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
- assert(value->type);
- ZigType *type_entry = value->type;
- if (type_entry->id == ZigTypeIdArray) {
- expand_undef_array(g, value);
- return &value->data.x_array.data.s_none.parent;
- } else if (type_entry->id == ZigTypeIdStruct) {
- return &value->data.x_struct.parent;
- } else if (type_entry->id == ZigTypeIdUnion) {
- return &value->data.x_union.parent;
- }
- return nullptr;
+ return &value->parent;
}
static const ZigTypeId all_type_ids[] = {
@@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = {
ZigTypeIdArgTuple,
ZigTypeIdOpaque,
ZigTypeIdPromise,
+ ZigTypeIdVector,
};
ZigTypeId type_id_at_index(size_t index) {
@@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) {
return 22;
case ZigTypeIdPromise:
return 23;
+ case ZigTypeIdVector:
+ return 24;
}
zig_unreachable();
}
@@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) {
return "Opaque";
case ZigTypeIdPromise:
return "Promise";
+ case ZigTypeIdVector:
+ return "Vector";
}
zig_unreachable();
}
@@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
if (is_libc && g->libc_link_lib != nullptr)
return g->libc_link_lib;
- if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS) {
+ if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) {
fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
"Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
exit(1);
@@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
resolve_top_level_decl(codegen, tld, false, nullptr);
assert(tld->id == TldIdVar);
TldVar *tld_var = (TldVar *)tld;
- ConstExprValue *var_value = tld_var->var->value;
+ ConstExprValue *var_value = tld_var->var->const_value;
assert(var_value != nullptr);
return var_value;
}
@@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
case ZigTypeIdBool:
return X64CABIClass_INTEGER;
case ZigTypeIdFloat:
+ case ZigTypeIdVector:
return X64CABIClass_SSE;
case ZigTypeIdStruct: {
// "If the size of an object is larger than four eightbytes, or it contains unaligned
@@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f
LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
return LLVMStoreSizeOfType(g->target_data_ref, field_type);
}
+
+Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
+ ConstExprValue *const_val, ZigType *wanted_type)
+{
+ ConstExprValue ptr_val = {};
+ ptr_val.special = ConstValSpecialStatic;
+ ptr_val.type = get_pointer_to_type(codegen, wanted_type, true);
+ ptr_val.data.x_ptr.mut = ConstPtrMutComptimeConst;
+ ptr_val.data.x_ptr.special = ConstPtrSpecialRef;
+ ptr_val.data.x_ptr.data.ref.pointee = const_val;
+ if (const_ptr_pointee(ira, codegen, &ptr_val, source_node) == nullptr)
+ return ErrorSemanticAnalyzeFail;
+
+ return ErrorNone;
+}
+
+const char *container_string(ContainerKind kind) {
+ switch (kind) {
+ case ContainerKindEnum: return "enum";
+ case ContainerKindStruct: return "struct";
+ case ContainerKindUnion: return "union";
+ }
+ zig_unreachable();
+}
+
+bool ptr_allows_addr_zero(ZigType *ptr_type) {
+ if (ptr_type->id == ZigTypeIdPointer) {
+ return ptr_type->data.pointer.allow_zero;
+ } else if (ptr_type->id == ZigTypeIdOptional) {
+ return true;
+ }
+ return false;
+}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index b506b533ca..956ef47309 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -12,14 +12,17 @@
void semantic_analyze(CodeGen *g);
ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
+ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg);
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
ZigType *new_type_table_entry(ZigTypeId id);
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
uint64_t type_size(CodeGen *g, ZigType *type_entry);
+uint64_t type_size_store(CodeGen *g, ZigType *type_entry);
uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
+ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type);
ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
@@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g);
void find_libc_lib_path(CodeGen *g);
bool type_has_bits(ZigType *type_entry);
-
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
+bool ptr_allows_addr_zero(ZigType *ptr_type);
+bool type_is_nonnull_ptr(ZigType *type);
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
@@ -73,6 +78,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
bool is_ref(ZigType *type_entry);
bool is_array_ref(ZigType *type_entry);
bool is_container_ref(ZigType *type_entry);
+bool is_valid_vector_elem_type(ZigType *elem_type);
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
void scan_import(CodeGen *g, ImportTableEntry *import);
void preview_use_decl(CodeGen *g, AstNode *node);
@@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope);
ImportTableEntry *get_scope_import(Scope *scope);
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
- bool is_const, ConstExprValue *init_value, Tld *src_tld);
+ bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
@@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
+const char *container_string(ContainerKind kind);
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
@@ -222,4 +229,15 @@ enum ReqCompTime {
};
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
+enum OnePossibleValue {
+ OnePossibleValueInvalid,
+ OnePossibleValueNo,
+ OnePossibleValueYes,
+};
+OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
+
+Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
+ ConstExprValue *const_val, ZigType *wanted_type);
+
+void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
#endif
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index f7eb646e16..7b57841205 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) {
return is_const ? "const" : "var";
}
-const char *container_string(ContainerKind kind) {
- switch (kind) {
- case ContainerKindEnum: return "enum";
- case ContainerKindStruct: return "struct";
- case ContainerKindUnion: return "union";
+static const char *thread_local_string(Token *tok) {
+ return (tok == nullptr) ? "" : "threadlocal ";
+}
+
+static const char *token_to_ptr_len_str(Token *tok) {
+ assert(tok != nullptr);
+ switch (tok->id) {
+ case TokenIdStar:
+ case TokenIdStarStar:
+ return "*";
+ case TokenIdBracketStarBracket:
+ return "[*]";
+ case TokenIdBracketStarCBracket:
+ return "[*c]";
+ default:
+ zig_unreachable();
}
- zig_unreachable();
}
static const char *node_type_str(NodeType node_type) {
@@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) {
return "ErrorType";
case NodeTypeIfErrorExpr:
return "IfErrorExpr";
- case NodeTypeTestExpr:
- return "TestExpr";
+ case NodeTypeIfOptional:
+ return "IfOptional";
case NodeTypeErrorSetDecl:
return "ErrorSetDecl";
case NodeTypeCancel:
@@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
if (node->data.if_err_expr.else_node)
return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
return node->data.if_err_expr.then_node->type == NodeTypeBlock;
- case NodeTypeTestExpr:
+ case NodeTypeIfOptional:
if (node->data.test_expr.else_node)
return statement_terminates_without_semicolon(node->data.test_expr.else_node);
return node->data.test_expr.then_node->type == NodeTypeBlock;
@@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
{
const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
+ const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok);
const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
- fprintf(ar->f, "%s%s%s ", pub_str, extern_str, const_or_var);
+ fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var);
print_symbol(ar, node->data.variable_declaration.symbol);
if (node->data.variable_declaration.type) {
@@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
case NodeTypePointerType:
{
if (!grouped) fprintf(ar->f, "(");
- const char *star = "[*]";
- if (node->data.pointer_type.star_token != nullptr &&
- (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
- {
- star = "*";
- }
- fprintf(ar->f, "%s", star);
+ const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
+ fprintf(ar->f, "%s", ptr_len_str);
if (node->data.pointer_type.align_expr != nullptr) {
fprintf(ar->f, "align(");
render_node_grouped(ar, node->data.pointer_type.align_expr);
@@ -974,7 +980,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
}
break;
}
- case NodeTypeTestExpr:
+ case NodeTypeIfOptional:
{
fprintf(ar->f, "if (");
render_node_grouped(ar, node->data.test_expr.target_node);
diff --git a/src/ast_render.hpp b/src/ast_render.hpp
index d37002d8c7..1652156eee 100644
--- a/src/ast_render.hpp
+++ b/src/ast_render.hpp
@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
-const char *container_string(ContainerKind kind);
-
#endif
-
diff --git a/src/bigint.cpp b/src/bigint.cpp
index 8a8d028e82..7299f2379c 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) {
bigint_add(x, ©, &one);
}
+
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
index 5e6c3b9a9d..4526a83c27 100644
--- a/src/cache_hash.cpp
+++ b/src/cache_hash.cpp
@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
assert(chf->path != nullptr);
OsFile this_file;
- if ((err = os_file_open_r(chf->path, &this_file)))
+ if ((err = os_file_open_r(chf->path, &this_file, &chf->mtime)))
return err;
- if ((err = os_file_mtime(this_file, &chf->mtime))) {
- os_file_close(this_file);
- return err;
- }
-
if ((err = hash_file(chf->bin_digest, this_file, contents))) {
os_file_close(this_file);
return err;
@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
// if the mtime matches we can trust the digest
OsFile this_file;
- if ((err = os_file_open_r(chf->path, &this_file))) {
+ OsTimeStamp actual_mtime;
+ if ((err = os_file_open_r(chf->path, &this_file, &actual_mtime))) {
fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
os_file_close(ch->manifest_file);
return ErrorCacheUnavailable;
}
- OsTimeStamp actual_mtime;
- if ((err = os_file_mtime(this_file, &actual_mtime))) {
- os_file_close(this_file);
- os_file_close(ch->manifest_file);
- return err;
- }
if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
os_file_close(this_file);
} else {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 1033ed8120..d2b2836b0c 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = {
};
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir)
+ Buf *zig_lib_dir, Buf *override_std_dir)
{
CodeGen *g = allocate(1);
@@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->zig_lib_dir = zig_lib_dir;
- g->zig_std_dir = buf_alloc();
- os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+ if (override_std_dir == nullptr) {
+ g->zig_std_dir = buf_alloc();
+ os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+ } else {
+ g->zig_std_dir = override_std_dir;
+ }
g->zig_c_headers_dir = buf_alloc();
os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
@@ -118,6 +122,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->string_literals_table.init(16);
g->type_info_cache.init(32);
g->is_test_build = false;
+ g->is_single_threaded = false;
buf_resize(&g->global_asm, 0);
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
@@ -178,7 +183,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
// On Darwin/MacOS/iOS, we always link libSystem which contains libc.
if (g->zig_target.os == OsMacOSX ||
- g->zig_target.os == OsIOS)
+ g->zig_target.os == OsIOS ||
+ g->zig_target.os == OsFreeBSD)
{
g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
g->link_libs_list.append(g->libc_link_lib);
@@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) {
g->darwin_frameworks.append(buf_create_from_str(framework));
}
-void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
- g->windows_subsystem_windows = mwindows;
- g->windows_subsystem_console = mconsole;
-}
-
void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) {
g->mmacosx_version_min = mmacosx_version_min;
}
@@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
static void generate_error_name_table(CodeGen *g);
+static bool value_is_all_undef(ConstExprValue *const_val);
+static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
@@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
}
}
+static bool cc_want_sret_attr(CallingConvention cc) {
+ switch (cc) {
+ case CallingConventionNaked:
+ zig_unreachable();
+ case CallingConventionC:
+ case CallingConventionCold:
+ case CallingConventionStdcall:
+ return true;
+ case CallingConventionAsync:
+ case CallingConventionUnspecified:
+ return false;
+ }
+ zig_unreachable();
+}
+
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
if (fn_table_entry->llvm_value)
return fn_table_entry->llvm_value;
@@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
unsigned init_gen_i = 0;
if (!type_has_bits(return_type)) {
// nothing to do
- } else if (type_is_codegen_pointer(return_type)) {
+ } else if (type_is_nonnull_ptr(return_type)) {
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
} else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
- addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
+ // Sret pointers must not be address 0
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
- if (cc == CallingConventionC) {
+ addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
+ if (cc_want_sret_attr(cc)) {
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
}
init_gen_i = 1;
@@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
if (err_ret_trace_arg_index != UINT32_MAX) {
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
}
@@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
import->di_file, line_number,
- fn_table_entry->type_entry->di_type, is_internal_linkage,
+ fn_table_entry->type_entry->data.fn.raw_di_type, is_internal_linkage,
is_definition, scope_line, flags, is_optimized, nullptr);
scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
@@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) {
ZigLLVMClearCurrentDebugLocation(g->builder);
}
-static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *type_entry,
+static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type,
const char *signed_name, const char *unsigned_name)
{
+ ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
char fn_name[64];
- assert(type_entry->id == ZigTypeIdInt);
- const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;
- sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, type_entry->data.integral.bit_count);
+ assert(int_type->id == ZigTypeIdInt);
+ const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name;
- LLVMTypeRef return_elem_types[] = {
- type_entry->type_ref,
- LLVMInt1Type(),
- };
LLVMTypeRef param_types[] = {
- type_entry->type_ref,
- type_entry->type_ref,
+ operand_type->type_ref,
+ operand_type->type_ref,
};
- LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
- LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
- LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
- assert(LLVMGetIntrinsicID(fn_val));
- return fn_val;
+
+ if (operand_type->id == ZigTypeIdVector) {
+ sprintf(fn_name, "llvm.%s.with.overflow.v%" PRIu32 "i%" PRIu32, signed_str,
+ operand_type->data.vector.len, int_type->data.integral.bit_count);
+
+ LLVMTypeRef return_elem_types[] = {
+ operand_type->type_ref,
+ LLVMVectorType(LLVMInt1Type(), operand_type->data.vector.len),
+ };
+ LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
+ LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
+ LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
+ assert(LLVMGetIntrinsicID(fn_val));
+ return fn_val;
+ } else {
+ sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, int_type->data.integral.bit_count);
+
+ LLVMTypeRef return_elem_types[] = {
+ operand_type->type_ref,
+ LLVMInt1Type(),
+ };
+ LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
+ LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
+ LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
+ assert(LLVMGetIntrinsicID(fn_val));
+ return fn_val;
+ }
}
-static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubMul add_sub_mul) {
- assert(type_entry->id == ZigTypeIdInt);
+static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSubMul add_sub_mul) {
+ ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
+ assert(int_type->id == ZigTypeIdInt);
ZigLLVMFnKey key = {};
key.id = ZigLLVMFnIdOverflowArithmetic;
- key.data.overflow_arithmetic.is_signed = type_entry->data.integral.is_signed;
+ key.data.overflow_arithmetic.is_signed = int_type->data.integral.is_signed;
key.data.overflow_arithmetic.add_sub_mul = add_sub_mul;
- key.data.overflow_arithmetic.bit_count = (uint32_t)type_entry->data.integral.bit_count;
+ key.data.overflow_arithmetic.bit_count = (uint32_t)int_type->data.integral.bit_count;
+ key.data.overflow_arithmetic.vector_len = (operand_type->id == ZigTypeIdVector) ?
+ operand_type->data.vector.len : 0;
auto existing_entry = g->llvm_fn_table.maybe_get(key);
if (existing_entry)
@@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM
LLVMValueRef fn_val;
switch (add_sub_mul) {
case AddSubMulAdd:
- fn_val = get_arithmetic_overflow_fn(g, type_entry, "sadd", "uadd");
+ fn_val = get_arithmetic_overflow_fn(g, operand_type, "sadd", "uadd");
break;
case AddSubMulSub:
- fn_val = get_arithmetic_overflow_fn(g, type_entry, "ssub", "usub");
+ fn_val = get_arithmetic_overflow_fn(g, operand_type, "ssub", "usub");
break;
case AddSubMulMul:
- fn_val = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");
+ fn_val = get_arithmetic_overflow_fn(g, operand_type, "smul", "umul");
break;
}
@@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
return buf_create_from_str("invalid enum value");
case PanicMsgIdFloatToInt:
return buf_create_from_str("integer part of floating point value out of bounds");
+ case PanicMsgIdPtrCastNull:
+ return buf_create_from_str("cast causes pointer to be null");
}
zig_unreachable();
}
@@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
if (g->build_mode == BuildModeDebug) {
ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
@@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
@@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
if (g->build_mode == BuildModeDebug) {
ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
@@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
+static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *int_type) {
+ LLVMValueRef zero = LLVMConstNull(int_type->type_ref);
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdCastTruncatedData);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ return nullptr;
+}
+
static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
ZigType *wanted_type, LLVMValueRef expr_val)
{
assert(actual_type->id == wanted_type->id);
+ assert(expr_val != nullptr);
uint64_t actual_bits;
uint64_t wanted_bits;
@@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
if (!want_runtime_safety)
return nullptr;
- LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
- LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
- LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
- LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
- LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
-
- LLVMPositionBuilderAtEnd(g->builder, fail_block);
- gen_safety_crash(g, PanicMsgIdCastTruncatedData);
-
- LLVMPositionBuilderAtEnd(g->builder, ok_block);
- return nullptr;
+ return gen_assert_zero(g, expr_val, actual_type);
}
LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
if (!want_runtime_safety) {
@@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
}
}
-static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *type_entry, AddSubMul op,
+typedef LLVMValueRef (*BuildBinOpFunc)(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, const char *);
+// These are lookup table using the AddSubMul enum as the lookup.
+// If AddSubMul ever changes, then these tables will be out of
+// date.
+static const BuildBinOpFunc float_op[3] = { LLVMBuildFAdd, LLVMBuildFSub, LLVMBuildFMul };
+static const BuildBinOpFunc wrap_op[3] = { LLVMBuildAdd, LLVMBuildSub, LLVMBuildMul };
+static const BuildBinOpFunc signed_op[3] = { LLVMBuildNSWAdd, LLVMBuildNSWSub, LLVMBuildNSWMul };
+static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, LLVMBuildNUWMul };
+
+static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op,
LLVMValueRef val1, LLVMValueRef val2)
{
- LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
- LLVMValueRef params[] = {
- val1,
- val2,
- };
- LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
- LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
- LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
+ LLVMValueRef overflow_bit;
+ LLVMValueRef result;
+
+ if (operand_type->id == ZigTypeIdVector) {
+ ZigType *int_type = operand_type->data.vector.elem_type;
+ assert(int_type->id == ZigTypeIdInt);
+ LLVMTypeRef one_more_bit_int = LLVMIntType(int_type->data.integral.bit_count + 1);
+ LLVMTypeRef one_more_bit_int_vector = LLVMVectorType(one_more_bit_int, operand_type->data.vector.len);
+ const auto buildExtFn = int_type->data.integral.is_signed ? LLVMBuildSExt : LLVMBuildZExt;
+ LLVMValueRef extended1 = buildExtFn(g->builder, val1, one_more_bit_int_vector, "");
+ LLVMValueRef extended2 = buildExtFn(g->builder, val2, one_more_bit_int_vector, "");
+ LLVMValueRef extended_result = wrap_op[op](g->builder, extended1, extended2, "");
+ result = LLVMBuildTrunc(g->builder, extended_result, operand_type->type_ref, "");
+
+ LLVMValueRef re_extended_result = buildExtFn(g->builder, result, one_more_bit_int_vector, "");
+ LLVMValueRef overflow_vector = LLVMBuildICmp(g->builder, LLVMIntNE, extended_result, re_extended_result, "");
+ LLVMTypeRef bitcast_int_type = LLVMIntType(operand_type->data.vector.len);
+ LLVMValueRef bitcasted_overflow = LLVMBuildBitCast(g->builder, overflow_vector, bitcast_int_type, "");
+ LLVMValueRef zero = LLVMConstNull(bitcast_int_type);
+ overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, bitcasted_overflow, zero, "");
+ } else {
+ LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op);
+ LLVMValueRef params[] = {
+ val1,
+ val2,
+ };
+ LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
+ result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
+ overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
+ }
+
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
@@ -1907,9 +1996,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
}
static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
- assert(alignment > 0);
LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
- LLVMSetAlignment(result, alignment);
+ LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
return result;
}
@@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
break;
}
- if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||
+ if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
ty->id == ZigTypeIdInt // TODO investigate if we need to change this
) {
switch (fn_walk->id) {
case FnWalkIdAttrs: {
ZigType *ptr_type = get_codegen_ptr_type(ty);
if (ptr_type != nullptr) {
- if (ty->id != ZigTypeIdOptional) {
+ if (type_is_nonnull_ptr(ty)) {
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
}
if (ptr_type->data.pointer.is_const) {
@@ -2018,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
assert(handle_is_ptr(ty));
switch (fn_walk->id) {
case FnWalkIdAttrs:
+ // arrays passed to C ABI functions may not be at address 0
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
fn_walk->data.attrs.gen_i += 1;
@@ -2057,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
case FnWalkIdAttrs:
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
+ // Byvalue parameters must not have address 0
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
fn_walk->data.attrs.gen_i += 1;
break;
@@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
}
- if (param_type->id == ZigTypeIdPointer) {
+ if (type_is_nonnull_ptr(param_type)) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
}
break;
@@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
assert(variable);
assert(variable->value_ref);
- if (!handle_is_ptr(variable->value->type)) {
+ if (!handle_is_ptr(variable->var_type)) {
clear_debug_source_node(g);
- gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
- variable->align_bytes, false);
+ gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
+ variable->value_ref, variable->align_bytes, false);
}
if (variable->decl_node) {
@@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
(op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
(op1->value.type->id == ZigTypeIdPointer &&
(op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
- op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
+ op1->value.type->data.pointer.ptr_len != PtrLenSingle)
);
- ZigType *type_entry = op1->value.type;
+ ZigType *operand_type = op1->value.type;
+ ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
bool want_runtime_safety = bin_op_instruction->safety_check_on &&
ir_want_runtime_safety(g, &bin_op_instruction->base);
@@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpCmpGreaterThan:
case IrBinOpCmpLessOrEq:
case IrBinOpCmpGreaterOrEq:
- if (type_entry->id == ZigTypeIdFloat) {
+ if (scalar_type->id == ZigTypeIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
- } else if (type_entry->id == ZigTypeIdInt) {
- LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
+ } else if (scalar_type->id == ZigTypeIdInt) {
+ LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, scalar_type->data.integral.is_signed);
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
- } else if (type_entry->id == ZigTypeIdEnum ||
- type_entry->id == ZigTypeIdErrorSet ||
- type_entry->id == ZigTypeIdBool ||
- get_codegen_ptr_type(type_entry) != nullptr)
+ } else if (scalar_type->id == ZigTypeIdEnum ||
+ scalar_type->id == ZigTypeIdErrorSet ||
+ scalar_type->id == ZigTypeIdBool ||
+ get_codegen_ptr_type(scalar_type) != nullptr)
{
LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
} else {
zig_unreachable();
}
+ case IrBinOpMult:
+ case IrBinOpMultWrap:
case IrBinOpAdd:
case IrBinOpAddWrap:
- if (type_entry->id == ZigTypeIdPointer) {
- assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
+ case IrBinOpSub:
+ case IrBinOpSubWrap: {
+ bool is_wrapping = (op_id == IrBinOpSubWrap || op_id == IrBinOpAddWrap || op_id == IrBinOpMultWrap);
+ AddSubMul add_sub_mul =
+ op_id == IrBinOpAdd || op_id == IrBinOpAddWrap ? AddSubMulAdd :
+ op_id == IrBinOpSub || op_id == IrBinOpSubWrap ? AddSubMulSub :
+ AddSubMulMul;
+
+ if (scalar_type->id == ZigTypeIdPointer) {
+ assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
+ LLVMValueRef subscript_value;
+ if (operand_type->id == ZigTypeIdVector)
+ zig_panic("TODO: Implement vector operations on pointers.");
+
+ switch (add_sub_mul) {
+ case AddSubMulAdd:
+ subscript_value = op2_value;
+ break;
+ case AddSubMulSub:
+ subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
+ break;
+ case AddSubMulMul:
+ zig_unreachable();
+ }
+
// TODO runtime safety
- return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, "");
- } else if (type_entry->id == ZigTypeIdFloat) {
+ return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
+ } else if (scalar_type->id == ZigTypeIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
- return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
- } else if (type_entry->id == ZigTypeIdInt) {
- bool is_wrapping = (op_id == IrBinOpAddWrap);
+ return float_op[add_sub_mul](g->builder, op1_value, op2_value, "");
+ } else if (scalar_type->id == ZigTypeIdInt) {
if (is_wrapping) {
- return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
+ return wrap_op[add_sub_mul](g->builder, op1_value, op2_value, "");
} else if (want_runtime_safety) {
- return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value);
- } else if (type_entry->data.integral.is_signed) {
- return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
+ return gen_overflow_op(g, operand_type, add_sub_mul, op1_value, op2_value);
+ } else if (scalar_type->data.integral.is_signed) {
+ return signed_op[add_sub_mul](g->builder, op1_value, op2_value, "");
} else {
- return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
+ return unsigned_op[add_sub_mul](g->builder, op1_value, op2_value, "");
}
} else {
zig_unreachable();
}
+ }
case IrBinOpBinOr:
return LLVMBuildOr(g->builder, op1_value, op2_value, "");
case IrBinOpBinXor:
@@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpBitShiftLeftLossy:
case IrBinOpBitShiftLeftExact:
{
- assert(type_entry->id == ZigTypeIdInt);
- LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
- type_entry, op2_value);
+ assert(scalar_type->id == ZigTypeIdInt);
+ LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
if (is_sloppy) {
return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
} else if (want_runtime_safety) {
- return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted);
- } else if (type_entry->data.integral.is_signed) {
+ return gen_overflow_shl_op(g, scalar_type, op1_value, op2_casted);
+ } else if (scalar_type->data.integral.is_signed) {
return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");
} else {
return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");
@@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpBitShiftRightLossy:
case IrBinOpBitShiftRightExact:
{
- assert(type_entry->id == ZigTypeIdInt);
- LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
- type_entry, op2_value);
+ assert(scalar_type->id == ZigTypeIdInt);
+ LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
if (is_sloppy) {
- if (type_entry->data.integral.is_signed) {
+ if (scalar_type->data.integral.is_signed) {
return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");
} else {
return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");
}
} else if (want_runtime_safety) {
- return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted);
- } else if (type_entry->data.integral.is_signed) {
+ return gen_overflow_shr_op(g, scalar_type, op1_value, op2_casted);
+ } else if (scalar_type->data.integral.is_signed) {
return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");
} else {
return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");
}
}
- case IrBinOpSub:
- case IrBinOpSubWrap:
- if (type_entry->id == ZigTypeIdPointer) {
- assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
- // TODO runtime safety
- LLVMValueRef subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
- return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
- } else if (type_entry->id == ZigTypeIdFloat) {
- ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
- return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
- } else if (type_entry->id == ZigTypeIdInt) {
- bool is_wrapping = (op_id == IrBinOpSubWrap);
- if (is_wrapping) {
- return LLVMBuildSub(g->builder, op1_value, op2_value, "");
- } else if (want_runtime_safety) {
- return gen_overflow_op(g, type_entry, AddSubMulSub, op1_value, op2_value);
- } else if (type_entry->data.integral.is_signed) {
- return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
- } else {
- return LLVMBuildNUWSub(g->builder, op1_value, op2_value, "");
- }
- } else {
- zig_unreachable();
- }
- case IrBinOpMult:
- case IrBinOpMultWrap:
- if (type_entry->id == ZigTypeIdFloat) {
- ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
- return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
- } else if (type_entry->id == ZigTypeIdInt) {
- bool is_wrapping = (op_id == IrBinOpMultWrap);
- if (is_wrapping) {
- return LLVMBuildMul(g->builder, op1_value, op2_value, "");
- } else if (want_runtime_safety) {
- return gen_overflow_op(g, type_entry, AddSubMulMul, op1_value, op2_value);
- } else if (type_entry->data.integral.is_signed) {
- return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
- } else {
- return LLVMBuildNUWMul(g->builder, op1_value, op2_value, "");
- }
- } else {
- zig_unreachable();
- }
case IrBinOpDivUnspecified:
return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, DivKindFloat);
+ op1_value, op2_value, scalar_type, DivKindFloat);
case IrBinOpDivExact:
return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, DivKindExact);
+ op1_value, op2_value, scalar_type, DivKindExact);
case IrBinOpDivTrunc:
return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, DivKindTrunc);
+ op1_value, op2_value, scalar_type, DivKindTrunc);
case IrBinOpDivFloor:
return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, DivKindFloor);
+ op1_value, op2_value, scalar_type, DivKindFloor);
case IrBinOpRemRem:
return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, RemKindRem);
+ op1_value, op2_value, scalar_type, RemKindRem);
case IrBinOpRemMod:
return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
- op1_value, op2_value, type_entry, RemKindMod);
+ op1_value, op2_value, scalar_type, RemKindMod);
}
zig_unreachable();
}
@@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
- return cast_instruction->tmp_ptr;
- }
- case CastOpBytesToSlice:
- {
- assert(cast_instruction->tmp_ptr);
- assert(wanted_type->id == ZigTypeIdStruct);
- assert(wanted_type->data.structure.is_slice);
- assert(actual_type->id == ZigTypeIdArray);
-
- ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
- ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
-
-
- size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- (unsigned)wanted_ptr_index, "");
- LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
- gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
-
- size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
- LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- (unsigned)wanted_len_index, "");
- LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
- actual_type->data.array.len / type_size(g, wanted_child_type), false);
- gen_store_untyped(g, len_val, len_ptr, 0, false);
-
return cast_instruction->tmp_ptr;
}
case CastOpIntToFloat:
@@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
}
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
- IrInstructionPtrCast *instruction)
+ IrInstructionPtrCastGen *instruction)
{
ZigType *wanted_type = instruction->base.value.type;
if (!type_has_bits(wanted_type)) {
return nullptr;
}
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
- return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
+ LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
+ bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
+ if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
+ return result_ptr;
+
+ LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdPtrCastNull);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ return result_ptr;
}
static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
@@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
}
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
- IrInstructionDeclVar *decl_var_instruction)
+ IrInstructionDeclVarGen *decl_var_instruction)
{
ZigVar *var = decl_var_instruction->var;
- if (!type_has_bits(var->value->type))
+ if (!type_has_bits(var->var_type))
return nullptr;
if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
@@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
IrInstruction *init_value = decl_var_instruction->init_value;
- bool have_init_expr = false;
-
- ConstExprValue *const_val = &init_value->value;
- if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
- have_init_expr = true;
+ bool have_init_expr = !value_is_all_undef(&init_value->value);
if (have_init_expr) {
- assert(var->value->type == init_value->value.type);
- ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
+ ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
PtrLenSingle, var->align_bytes, 0, 0);
LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
- } else {
- bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
- if (want_safe) {
- ZigType *usize = g->builtin_types.entry_usize;
- uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
- assert(size_bytes > 0);
-
- assert(var->align_bytes > 0);
-
- // memset uninitialized memory to 0xa
- LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
- LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
- LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
- LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
- ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
- }
+ } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
+ uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
+ gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
}
gen_var_debug_decl(g, var);
@@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
}
+static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
+ switch (const_val->data.x_array.special) {
+ case ConstArraySpecialUndef:
+ return true;
+ case ConstArraySpecialBuf:
+ return false;
+ case ConstArraySpecialNone:
+ for (size_t i = 0; i < len; i += 1) {
+ if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
+ return false;
+ }
+ return true;
+ }
+ zig_unreachable();
+}
+
+static bool value_is_all_undef(ConstExprValue *const_val) {
+ switch (const_val->special) {
+ case ConstValSpecialRuntime:
+ return false;
+ case ConstValSpecialUndef:
+ return true;
+ case ConstValSpecialStatic:
+ if (const_val->type->id == ZigTypeIdStruct) {
+ for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
+ if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
+ return false;
+ }
+ return true;
+ } else if (const_val->type->id == ZigTypeIdArray) {
+ return value_is_all_undef_array(const_val, const_val->type->data.array.len);
+ } else if (const_val->type->id == ZigTypeIdVector) {
+ return value_is_all_undef_array(const_val, const_val->type->data.vector.len);
+ } else {
+ return false;
+ }
+ }
+ zig_unreachable();
+}
+
+static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
+ assert(type_has_bits(value_type));
+ uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
+ assert(size_bytes > 0);
+ assert(ptr_align_bytes > 0);
+ // memset uninitialized memory to 0xaa
+ LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
+ LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
+ LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
+ ZigType *usize = g->builtin_types.entry_usize;
+ LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
+ ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
+}
+
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
- LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
- LLVMValueRef value = ir_llvm_value(g, instruction->value);
-
- assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
ZigType *ptr_type = instruction->ptr->value.type;
+ assert(ptr_type->id == ZigTypeIdPointer);
+ if (!type_has_bits(ptr_type))
+ return nullptr;
- gen_assign_raw(g, ptr, ptr_type, value);
-
+ bool have_init_expr = !value_is_all_undef(&instruction->value->value);
+ if (have_init_expr) {
+ LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
+ LLVMValueRef value = ir_llvm_value(g, instruction->value);
+ gen_assign_raw(g, ptr, ptr_type, value);
+ } else if (ir_want_runtime_safety(g, &instruction->base)) {
+ gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
+ ir_llvm_value(g, instruction->ptr));
+ }
return nullptr;
}
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
ZigVar *var = instruction->var;
- if (type_has_bits(var->value->type)) {
+ if (type_has_bits(var->var_type)) {
assert(var->value_ref);
return var->value_ref;
} else {
@@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
LLVMPositionBuilderAtEnd(g->builder, ok_block);
}
- LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");
+ LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
+ union_type->data.unionation.gen_union_index, "");
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
return bitcasted_union_field_ptr;
}
@@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
if (child_type->zero_bits) {
return maybe_handle;
} else {
- bool maybe_is_ptr = type_is_codegen_pointer(child_type);
- if (maybe_is_ptr) {
+ bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
+ if (is_scalar) {
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
} else {
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
@@ -3761,17 +3864,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
}
-static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
- IrInstructionUnwrapOptional *instruction)
+static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
+ IrInstructionOptionalUnwrapPtr *instruction)
{
- ZigType *ptr_type = instruction->value->value.type;
+ ZigType *ptr_type = instruction->base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *maybe_type = ptr_type->data.pointer.child_type;
assert(maybe_type->id == ZigTypeIdOptional);
ZigType *child_type = maybe_type->data.maybe.child_type;
- LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
- LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
+ LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
+ LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
@@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
if (child_type->zero_bits) {
return nullptr;
} else {
- bool maybe_is_ptr = type_is_codegen_pointer(child_type);
- if (maybe_is_ptr) {
+ bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
+ if (is_scalar) {
return maybe_ptr;
} else {
LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
@@ -3814,6 +3917,16 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
n_args = 1;
key.id = ZigLLVMFnIdPopCount;
key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
+ } else if (fn_id == BuiltinFnIdBswap) {
+ fn_name = "bswap";
+ n_args = 1;
+ key.id = ZigLLVMFnIdBswap;
+ key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
+ } else if (fn_id == BuiltinFnIdBitReverse) {
+ fn_name = "bitreverse";
+ n_args = 1;
+ key.id = ZigLLVMFnIdBitReverse;
+ key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count;
} else {
zig_unreachable();
}
@@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
zig_unreachable();
}
-static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
+static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
@@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
assert(maybe_type->id == ZigTypeIdOptional);
ZigType *child_type = maybe_type->data.maybe.child_type;
- if (type_is_codegen_pointer(child_type)) {
+ if (!handle_is_ptr(maybe_type)) {
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
}
assert(instruction->tmp_ptr != nullptr);
- assert(type_has_bits(instruction->type));
+ assert(type_has_bits(child_type));
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
- gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);
+ gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
@@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
assert(array_type->data.structure.is_slice);
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
+ assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
assert(ptr_index != SIZE_MAX);
@@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
}
-static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
- ZigType *ptr_type = instruction->value->value.type;
+static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
+ IrInstructionUnwrapErrCode *instruction)
+{
+ ZigType *ptr_type = instruction->err_union->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *err_union_type = ptr_type->data.pointer.child_type;
ZigType *payload_type = err_union_type->data.error_union.payload_type;
- LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
+ LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
if (type_has_bits(payload_type)) {
@@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
}
}
-static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
+static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
+ IrInstructionUnwrapErrPayload *instruction)
+{
+ bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
+ g->errors_by_index.length > 1;
+ if (!want_safety && !type_has_bits(instruction->base.value.type))
+ return nullptr;
ZigType *ptr_type = instruction->value->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *err_union_type = ptr_type->data.pointer.child_type;
@@ -4588,7 +4710,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
return err_union_handle;
}
- if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
+ if (want_safety) {
LLVMValueRef err_val;
if (type_has_bits(payload_type)) {
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
@@ -4627,7 +4749,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
}
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
- if (type_is_codegen_pointer(child_type)) {
+ if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
return payload_val;
}
@@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
}
+static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
+ LLVMValueRef op = ir_llvm_value(g, instruction->op);
+ ZigType *int_type = instruction->base.value.type;
+ assert(int_type->id == ZigTypeIdInt);
+ if (int_type->data.integral.bit_count % 16 == 0) {
+ LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);
+ return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
+ }
+ // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
+ ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
+ int_type->data.integral.bit_count + 8);
+ // aabbcc
+ LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, "");
+ // 00aabbcc
+ LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
+ LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
+ // ccbbaa00
+ LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,
+ LLVMConstInt(extended_type->type_ref, 8, false), "");
+ // 00ccbbaa
+ return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, "");
+}
+
+static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {
+ LLVMValueRef op = ir_llvm_value(g, instruction->op);
+ ZigType *int_type = instruction->base.value.type;
+ assert(int_type->id == ZigTypeIdInt);
+ LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBitReverse);
+ return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
+}
+
+static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable,
+ IrInstructionVectorToArray *instruction)
+{
+ ZigType *array_type = instruction->base.value.type;
+ assert(array_type->id == ZigTypeIdArray);
+ assert(handle_is_ptr(array_type));
+ assert(instruction->tmp_ptr);
+ LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
+ LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMPointerType(instruction->vector->value.type->type_ref, 0), "");
+ gen_store_untyped(g, vector, casted_ptr, 0, false);
+ return instruction->tmp_ptr;
+}
+
+static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
+ IrInstructionArrayToVector *instruction)
+{
+ ZigType *vector_type = instruction->base.value.type;
+ assert(vector_type->id == ZigTypeIdVector);
+ assert(!handle_is_ptr(vector_type));
+ LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
+ LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
+ LLVMPointerType(vector_type->type_ref, 0), "");
+ return gen_load_untyped(g, casted_ptr, 0, false, "");
+}
+
+static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
+ IrInstructionAssertZero *instruction)
+{
+ LLVMValueRef target = ir_llvm_value(g, instruction->target);
+ ZigType *int_type = instruction->target->value.type;
+ if (ir_want_runtime_safety(g, &instruction->base)) {
+ return gen_assert_zero(g, target, int_type);
+ }
+ return nullptr;
+}
+
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
@@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdCUndef:
case IrInstructionIdEmbedFile:
case IrInstructionIdIntType:
+ case IrInstructionIdVectorType:
case IrInstructionIdMemberCount:
case IrInstructionIdMemberType:
case IrInstructionIdMemberName:
@@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdToBytes:
case IrInstructionIdEnumToInt:
case IrInstructionIdCheckRuntimeScope:
+ case IrInstructionIdDeclVarSrc:
+ case IrInstructionIdPtrCastSrc:
+ case IrInstructionIdCmpxchgSrc:
zig_unreachable();
+ case IrInstructionIdDeclVarGen:
+ return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
case IrInstructionIdReturn:
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
- case IrInstructionIdDeclVar:
- return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
case IrInstructionIdBinOp:
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
case IrInstructionIdCast:
@@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
case IrInstructionIdTestNonNull:
return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
- case IrInstructionIdUnwrapOptional:
- return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
+ case IrInstructionIdOptionalUnwrapPtr:
+ return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
case IrInstructionIdClz:
return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
case IrInstructionIdCtz:
@@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
case IrInstructionIdErrName:
return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
- case IrInstructionIdCmpxchg:
- return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
+ case IrInstructionIdCmpxchgGen:
+ return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
case IrInstructionIdFence:
return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
case IrInstructionIdTruncate:
@@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdUnionInit:
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
- case IrInstructionIdPtrCast:
- return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
+ case IrInstructionIdPtrCastGen:
+ return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
case IrInstructionIdBitCast:
return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
case IrInstructionIdWidenOrShorten:
@@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
case IrInstructionIdSqrt:
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdBswap:
+ return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
+ case IrInstructionIdBitReverse:
+ return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
+ case IrInstructionIdArrayToVector:
+ return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
+ case IrInstructionIdVectorToArray:
+ return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
+ case IrInstructionIdAssertZero:
+ return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
}
zig_unreachable();
}
@@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
+static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
+static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
+static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
switch (parent->id) {
@@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
case ConstParentIdStruct:
return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
parent->data.p_struct.field_index);
+ case ConstParentIdErrUnionCode:
+ return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
+ case ConstParentIdErrUnionPayload:
+ return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
+ case ConstParentIdOptionalPayload:
+ return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
case ConstParentIdArray:
return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
parent->data.p_array.elem_index);
@@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
expand_undef_array(g, array_const_val);
- ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
+ ConstParent *parent = &array_const_val->parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
@@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
}
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
- ConstParent *parent = &struct_const_val->data.x_struct.parent;
+ ConstParent *parent = &struct_const_val->parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
ZigType *u32 = g->builtin_types.entry_u32;
@@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
}
+static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
+ ConstParent *parent = &err_union_const_val->parent;
+ LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
+
+ ZigType *u32 = g->builtin_types.entry_u32;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(u32->type_ref),
+ LLVMConstInt(u32->type_ref, err_union_err_index, false),
+ };
+ return LLVMConstInBoundsGEP(base_ptr, indices, 2);
+}
+
+static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
+ ConstParent *parent = &err_union_const_val->parent;
+ LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
+
+ ZigType *u32 = g->builtin_types.entry_u32;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(u32->type_ref),
+ LLVMConstInt(u32->type_ref, err_union_payload_index, false),
+ };
+ return LLVMConstInBoundsGEP(base_ptr, indices, 2);
+}
+
+static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
+ ConstParent *parent = &optional_const_val->parent;
+ LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
+
+ ZigType *u32 = g->builtin_types.entry_u32;
+ LLVMValueRef indices[] = {
+ LLVMConstNull(u32->type_ref),
+ LLVMConstInt(u32->type_ref, maybe_child_index, false),
+ };
+ return LLVMConstInBoundsGEP(base_ptr, indices, 2);
+}
+
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
- ConstParent *parent = &union_const_val->data.x_union.parent;
+ ConstParent *parent = &union_const_val->parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
ZigType *u32 = g->builtin_types.entry_u32;
@@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
}
case ZigTypeIdArray:
zig_panic("TODO bit pack an array");
+ case ZigTypeIdVector:
+ zig_panic("TODO bit pack a vector");
case ZigTypeIdUnion:
zig_panic("TODO bit pack a union");
case ZigTypeIdStruct:
@@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
zig_unreachable();
case ConstPtrSpecialRef:
{
- render_const_val_global(g, const_val, name);
+ assert(const_val->global_refs != nullptr);
ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
render_const_val(g, pointee, "");
render_const_val_global(g, pointee, "");
- ConstExprValue *other_val = pointee;
- const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
+ const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, const_val->type->type_ref);
return const_val->global_refs->llvm_value;
}
case ConstPtrSpecialBaseArray:
{
- render_const_val_global(g, const_val, name);
+ assert(const_val->global_refs != nullptr);
ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
- size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
assert(array_const_val->type->id == ZigTypeIdArray);
- if (array_const_val->type->zero_bits) {
+ if (!type_has_bits(array_const_val->type)) {
// make this a null pointer
ZigType *usize = g->builtin_types.entry_usize;
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
return const_val->global_refs->llvm_value;
}
- LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
- elem_index);
+ size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
const_val->global_refs->llvm_value = ptr_val;
- render_const_val_global(g, const_val, "");
return ptr_val;
}
case ConstPtrSpecialBaseStruct:
{
- render_const_val_global(g, const_val, name);
+ assert(const_val->global_refs != nullptr);
ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
assert(struct_const_val->type->id == ZigTypeIdStruct);
- if (struct_const_val->type->zero_bits) {
+ if (!type_has_bits(struct_const_val->type)) {
// make this a null pointer
ZigType *usize = g->builtin_types.entry_usize;
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
return const_val->global_refs->llvm_value;
}
size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
- size_t gen_field_index =
- struct_const_val->type->data.structure.fields[src_field_index].gen_index;
+ size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index;
LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
gen_field_index);
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
const_val->global_refs->llvm_value = ptr_val;
- render_const_val_global(g, const_val, "");
+ return ptr_val;
+ }
+ case ConstPtrSpecialBaseErrorUnionCode:
+ {
+ assert(const_val->global_refs != nullptr);
+ ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
+ assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
+ if (!type_has_bits(err_union_const_val->type)) {
+ // make this a null pointer
+ ZigType *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ return const_val->global_refs->llvm_value;
+ }
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->global_refs->llvm_value = ptr_val;
+ return ptr_val;
+ }
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ {
+ assert(const_val->global_refs != nullptr);
+ ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
+ assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
+ if (err_union_const_val->type->zero_bits) {
+ // make this a null pointer
+ ZigType *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ return const_val->global_refs->llvm_value;
+ }
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->global_refs->llvm_value = ptr_val;
+ return ptr_val;
+ }
+ case ConstPtrSpecialBaseOptionalPayload:
+ {
+ assert(const_val->global_refs != nullptr);
+ ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
+ assert(optional_const_val->type->id == ZigTypeIdOptional);
+ if (optional_const_val->type->zero_bits) {
+ // make this a null pointer
+ ZigType *usize = g->builtin_types.entry_usize;
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
+ const_val->type->type_ref);
+ return const_val->global_refs->llvm_value;
+ }
+ LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
+ LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
+ const_val->global_refs->llvm_value = ptr_val;
return ptr_val;
}
case ConstPtrSpecialHardCodedAddr:
{
- render_const_val_global(g, const_val, name);
+ assert(const_val->global_refs != nullptr);
uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
ZigType *usize = g->builtin_types.entry_usize;
- const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
- const_val->type->type_ref);
- render_const_val_global(g, const_val, "");
+ const_val->global_refs->llvm_value = LLVMConstIntToPtr(
+ LLVMConstInt(usize->type_ref, addr_value, false), const_val->type->type_ref);
return const_val->global_refs->llvm_value;
}
case ConstPtrSpecialFunction:
return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
+ case ConstPtrSpecialNull:
+ return LLVMConstNull(const_val->type->type_ref);
}
zig_unreachable();
}
+static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
+ uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
+ return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
+}
+
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
+ Error err;
+
ZigType *type_entry = const_val->type;
assert(!type_entry->zero_bits);
@@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
case ZigTypeIdInt:
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
case ZigTypeIdErrorSet:
- assert(const_val->data.x_err_set != nullptr);
- return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
- const_val->data.x_err_set->value, false);
+ return gen_const_val_err_set(g, const_val, name);
case ZigTypeIdFloat:
switch (type_entry->data.floating.bit_count) {
case 16:
@@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
} else if (type_is_codegen_pointer(child_type)) {
return gen_const_val_ptr(g, const_val, name);
+ } else if (child_type->id == ZigTypeIdErrorSet) {
+ return gen_const_val_err_set(g, const_val, name);
} else {
LLVMValueRef child_val;
LLVMValueRef maybe_val;
@@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
}
ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
assert(field_val->type != nullptr);
+ if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val,
+ type_struct_field->type_entry)))
+ {
+ zig_unreachable();
+ }
+
LLVMValueRef val = gen_const_val(g, field_val, "");
fields[type_struct_field->gen_index] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val);
@@ -5793,7 +6101,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
}
}
+ zig_unreachable();
}
+ case ZigTypeIdVector: {
+ uint32_t len = type_entry->data.vector.len;
+ switch (const_val->data.x_array.special) {
+ case ConstArraySpecialUndef:
+ return LLVMGetUndef(type_entry->type_ref);
+ case ConstArraySpecialNone: {
+ LLVMValueRef *values = allocate(len);
+ for (uint64_t i = 0; i < len; i += 1) {
+ ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
+ values[i] = gen_const_val(g, elem_value, "");
+ }
+ return LLVMConstVector(values, len);
+ }
+ case ConstArraySpecialBuf: {
+ Buf *buf = const_val->data.x_array.data.s_buf;
+ assert(buf_len(buf) == len);
+ LLVMValueRef *values = allocate(len);
+ for (uint64_t i = 0; i < len; i += 1) {
+ values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false);
+ }
+ return LLVMConstVector(values, len);
+ }
+ }
+ zig_unreachable();
+ }
case ZigTypeIdUnion:
{
LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
@@ -5891,7 +6225,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
ZigType *err_set_type = type_entry->data.error_union.err_set_type;
if (!type_has_bits(payload_type)) {
assert(type_has_bits(err_set_type));
- uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
+ ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
+ uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
return LLVMConstInt(g->err_tag_type->type_ref, value, false);
} else if (!type_has_bits(err_set_type)) {
assert(type_has_bits(payload_type));
@@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
LLVMValueRef err_tag_value;
LLVMValueRef err_payload_value;
bool make_unnamed_struct;
- if (const_val->data.x_err_union.err) {
- err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
+ ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
+ if (err_set != nullptr) {
+ err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
err_payload_value = LLVMConstNull(payload_type->type_ref);
make_unnamed_struct = false;
} else {
@@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) {
report_errors_and_maybe_exit(g);
}
+static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
+ if (var->is_thread_local && !g->is_single_threaded) {
+ LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
+ }
+}
+
static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
@@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) {
TldVar *tld_var = g->global_vars.at(i);
ZigVar *var = tld_var->var;
- if (var->value->type->id == ZigTypeIdComptimeFloat) {
+ if (var->var_type->id == ZigTypeIdComptimeFloat) {
// Generate debug info for it but that's it.
- ConstExprValue *const_val = var->value;
+ ConstExprValue *const_val = var->const_value;
assert(const_val->special != ConstValSpecialRuntime);
+ if (const_val->type != var->var_type) {
+ zig_panic("TODO debug info for var with ptr casted value");
+ }
ZigType *var_type = g->builtin_types.entry_f128;
ConstExprValue coerced_value;
coerced_value.special = ConstValSpecialStatic;
@@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) {
continue;
}
- if (var->value->type->id == ZigTypeIdComptimeInt) {
+ if (var->var_type->id == ZigTypeIdComptimeInt) {
// Generate debug info for it but that's it.
- ConstExprValue *const_val = var->value;
+ ConstExprValue *const_val = var->const_value;
assert(const_val->special != ConstValSpecialRuntime);
+ if (const_val->type != var->var_type) {
+ zig_panic("TODO debug info for var with ptr casted value");
+ }
size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
if (bits_needed < 8) {
bits_needed = 8;
@@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) {
continue;
}
- if (!type_has_bits(var->value->type))
+ if (!type_has_bits(var->var_type))
continue;
assert(var->decl_node);
@@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) {
if (var->linkage == VarLinkageExternal) {
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
if (existing_llvm_var) {
- global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));
+ global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
} else {
- global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));
+ global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
// TODO debug info for the extern variable
LLVMSetLinkage(global_value, LLVMExternalLinkage);
maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
+ set_global_tls(g, var, global_value);
}
} else {
bool exported = (var->linkage == VarLinkageExport);
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
- render_const_val(g, var->value, mangled_name);
- render_const_val_global(g, var->value, mangled_name);
- global_value = var->value->global_refs->llvm_global;
+ render_const_val(g, var->const_value, mangled_name);
+ render_const_val_global(g, var->const_value, mangled_name);
+ global_value = var->const_value->global_refs->llvm_global;
if (exported) {
LLVMSetLinkage(global_value, LLVMExternalLinkage);
@@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) {
LLVMSetAlignment(global_value, var->align_bytes);
// TODO debug info for function pointers
- if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
- gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
+ // Here we use const_value->type because that's the type of the llvm global,
+ // which we const ptr cast upon use to whatever it needs to be.
+ if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
+ gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
}
LLVMSetGlobalConstant(global_value, var->gen_is_const);
+ set_global_tls(g, var, global_value);
}
var->value_ref = global_value;
@@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) {
IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
LLVMValueRef *slot;
ZigType *slot_type = instruction->value.type;
+ uint32_t alignment_bytes = 0;
if (instruction->id == IrInstructionIdCast) {
IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
slot = &cast_instruction->tmp_ptr;
@@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdErrWrapCode) {
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
slot = &err_wrap_code_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdCmpxchg) {
- IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
+ } else if (instruction->id == IrInstructionIdCmpxchgGen) {
+ IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
slot = &cmpxchg_instruction->tmp_ptr;
+ } else if (instruction->id == IrInstructionIdVectorToArray) {
+ IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
+ alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
+ slot = &vector_to_array_instruction->tmp_ptr;
} else {
zig_unreachable();
}
- *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));
+ *slot = build_alloca(g, slot_type, "", alignment_bytes);
}
ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
@@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) {
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
ZigVar *var = fn_table_entry->variable_list.at(var_i);
- if (!type_has_bits(var->value->type)) {
+ if (!type_has_bits(var->var_type)) {
continue;
}
if (ir_get_var_is_comptime(var))
continue;
- switch (type_requires_comptime(g, var->value->type)) {
+ switch (type_requires_comptime(g, var->var_type)) {
case ReqCompTimeInvalid:
zig_unreachable();
case ReqCompTimeYes:
@@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) {
}
if (var->src_arg_index == SIZE_MAX) {
- var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
+ var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
- var->value->type->di_type, !g->strip_debug_symbols, 0);
+ var->var_type->di_type, !g->strip_debug_symbols, 0);
} else if (is_c_abi) {
fn_walk_var.data.vars.var = var;
@@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) {
ZigType *gen_type;
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
- if (handle_is_ptr(var->value->type)) {
+ if (handle_is_ptr(var->var_type)) {
if (gen_info->is_byval) {
- gen_type = var->value->type;
+ gen_type = var->var_type;
} else {
gen_type = gen_info->type;
}
var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
} else {
- gen_type = var->value->type;
- var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
+ gen_type = var->var_type;
+ var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
}
if (var->decl_node) {
var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
@@ -6719,6 +7076,7 @@ static void define_builtin_fns(CodeGen *g) {
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
+ create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
@@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
+ create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
+ create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2);
}
static const char *bool_to_str(bool b) {
@@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" instruction_addresses: []usize,\n"
"};\n\n");
+ buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
+
const char *cur_os = nullptr;
{
buf_appendf(contents, "pub const Os = enum {\n");
@@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" ArgTuple: void,\n"
" Opaque: void,\n"
" Promise: Promise,\n"
+ " Vector: Vector,\n"
"\n\n"
" pub const Int = struct {\n"
" is_signed: bool,\n"
@@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" One,\n"
" Many,\n"
" Slice,\n"
+ " C,\n"
" };\n"
" };\n"
"\n"
@@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" child: ?type,\n"
" };\n"
"\n"
+ " pub const Vector = struct {\n"
+ " len: u32,\n"
+ " child: type,\n"
+ " };\n"
+ "\n"
" pub const Definition = struct {\n"
" name: []const u8,\n"
" is_pub: bool,\n"
@@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
}
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
+ buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
@@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_buf(&cache_hash, compiler_id);
cache_int(&cache_hash, g->build_mode);
cache_bool(&cache_hash, g->is_test_build);
+ cache_bool(&cache_hash, g->is_single_threaded);
cache_int(&cache_hash, g->zig_target.arch.arch);
cache_int(&cache_hash, g->zig_target.arch.sub_arch);
cache_int(&cache_hash, g->zig_target.vendor);
@@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename);
g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
+ g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents);
scan_import(g, g->compile_var_import);
@@ -7231,8 +7603,7 @@ static void init(CodeGen *g) {
}
if (g->is_test_build) {
- g->windows_subsystem_windows = false;
- g->windows_subsystem_console = true;
+ g->subsystem = TargetSubsystemConsole;
}
assert(g->root_out_name);
@@ -7251,7 +7622,13 @@ static void init(CodeGen *g) {
LLVMTargetRef target_ref;
char *err_msg = nullptr;
if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {
- zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));
+ fprintf(stderr,
+ "Zig is expecting LLVM to understand this target: '%s'\n"
+ "However LLVM responded with: \"%s\"\n"
+ "Zig is unable to continue. This is a bug in Zig:\n"
+ "https://github.com/ziglang/zig/issues/438\n"
+ , buf_ptr(&g->triple_str), err_msg);
+ exit(1);
}
bool is_optimized = g->build_mode != BuildModeDebug;
@@ -7268,7 +7645,7 @@ static void init(CodeGen *g) {
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
- if (g->zig_target.os == OsWindows) {
+ if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) {
target_specific_cpu_args = "";
target_specific_features = "";
} else {
@@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
this_val->special = ConstValSpecialStatic;
this_val->type = struct_type;
- this_val->data.x_struct.parent.id = ConstParentIdArray;
- this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
- this_val->data.x_struct.parent.data.p_array.elem_index = i;
+ this_val->parent.id = ConstParentIdArray;
+ this_val->parent.data.p_array.array_val = test_fn_array;
+ this_val->parent.data.p_array.elem_index = i;
this_val->data.x_struct.fields = create_const_vals(2);
ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
@@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) {
report_errors_and_maybe_exit(g);
if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
+ g->zig_target.os != OsUefi &&
!g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
{
@@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {
}
}
+ typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
+
report_errors_and_maybe_exit(g);
}
@@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
case ZigTypeIdArray:
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
return;
+ case ZigTypeIdVector:
+ prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
+ return;
case ZigTypeIdOptional:
prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
return;
@@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
buf_appendf(out_buf, "%s", buf_ptr(child_buf));
return;
}
+ case ZigTypeIdVector:
+ zig_panic("TODO implement get_c_type for vector types");
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
@@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) {
case ZigTypeIdOptional:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
zig_unreachable();
case ZigTypeIdEnum:
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
@@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
if (!entry)
break;
- cache_buf(ch, entry->key);
- add_cache_pkg(g, ch, entry->value);
+ // TODO: I think we need a more sophisticated detection of
+ // packages we have already seen
+ if (entry->value != pkg) {
+ cache_buf(ch, entry->key);
+ add_cache_pkg(g, ch, entry->value);
+ }
}
}
@@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target.os);
cache_int(ch, g->zig_target.env_type);
cache_int(ch, g->zig_target.oformat);
+ cache_int(ch, g->subsystem);
cache_bool(ch, g->is_static);
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
+ cache_bool(ch, g->is_single_threaded);
cache_bool(ch, g->is_native_target);
- cache_bool(ch, g->windows_subsystem_windows);
- cache_bool(ch, g->windows_subsystem_console);
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->no_rosegment_workaround);
cache_bool(ch, g->each_lib_rpath);
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 1d39e4bf5e..4bd8f2dcca 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -15,7 +15,7 @@
#include
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir);
+ Buf *zig_lib_dir, Buf *override_std_dir);
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
@@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
-void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
diff --git a/src/ir.cpp b/src/ir.cpp
index 68a0b7f6f6..0fcbb60fe8 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -61,7 +61,7 @@ enum ConstCastResultId {
ConstCastResultIdType,
ConstCastResultIdUnresolvedInferredErrSet,
ConstCastResultIdAsyncAllocatorType,
- ConstCastResultIdNullWrapPtr
+ ConstCastResultIdBadAllowsZero,
};
struct ConstCastOnly;
@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
struct ConstCastErrUnionPayloadMismatch;
struct ConstCastErrSetMismatch;
struct ConstCastTypeMismatch;
+struct ConstCastBadAllowsZero;
struct ConstCastOnly {
ConstCastResultId id;
@@ -99,6 +100,7 @@ struct ConstCastOnly {
ConstCastOnly *null_wrap_ptr_child;
ConstCastArg fn_arg;
ConstCastArgNoAlias arg_no_alias;
+ ConstCastBadAllowsZero *bad_allows_zero;
} data;
};
@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
ZigList missing_errors;
};
+struct ConstCastBadAllowsZero {
+ ZigType *wanted_type;
+ ZigType *actual_type;
+};
+
+
enum UndefAllowed {
UndefOk,
UndefBad,
@@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
-static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
+static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
-static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
+static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val);
static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
- ZigType *dest_type, IrInstruction *dest_type_src);
+ ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
+static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
+static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
+static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
+static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
+ ZigType *ptr_type);
+static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *dest_type);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
case ConstPtrSpecialRef:
result = const_val->data.x_ptr.data.ref.pointee;
break;
- case ConstPtrSpecialBaseArray:
- expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val);
- result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[
- const_val->data.x_ptr.data.base_array.elem_index];
+ case ConstPtrSpecialBaseArray: {
+ ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
+ expand_undef_array(g, array_val);
+ result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
break;
+ }
case ConstPtrSpecialBaseStruct:
result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
const_val->data.x_ptr.data.base_struct.field_index];
break;
+ case ConstPtrSpecialBaseErrorUnionCode:
+ result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
+ break;
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
+ break;
+ case ConstPtrSpecialBaseOptionalPayload:
+ result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
+ break;
+ case ConstPtrSpecialNull:
+ result = const_val;
+ break;
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialDiscard:
@@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
return result;
}
+static bool is_opt_err_set(ZigType *ty) {
+ return ty->id == ZigTypeIdErrorSet ||
+ (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
+}
+
static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
if (a == b)
return true;
@@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
return true;
- return false;
-}
+ if (is_opt_err_set(a) && is_opt_err_set(b))
+ return true;
-ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
- ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
- if (const_val->type->id == ZigTypeIdPointer) {
- assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
- }
- return result;
+ return false;
}
static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
@@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
return new_bb;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) {
+ return IrInstructionIdDeclVarSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) {
+ return IrInstructionIdDeclVarGen;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
return IrInstructionIdCondBr;
}
@@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
return IrInstructionIdBinOp;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
- return IrInstructionIdDeclVar;
-}
-
static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
return IrInstructionIdExport;
}
@@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
return IrInstructionIdTestNonNull;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {
- return IrInstructionIdUnwrapOptional;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
+ return IrInstructionIdOptionalUnwrapPtr;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
@@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
return IrInstructionIdEmbedFile;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {
- return IrInstructionIdCmpxchg;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
+ return IrInstructionIdCmpxchgSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
+ return IrInstructionIdCmpxchgGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
@@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
return IrInstructionIdIntType;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
+ return IrInstructionIdVectorType;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
return IrInstructionIdBoolNot;
}
@@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
return IrInstructionIdTestComptime;
}
-static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
- return IrInstructionIdPtrCast;
+static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
+ return IrInstructionIdPtrCastSrc;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
+ return IrInstructionIdPtrCastGen;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
@@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
return IrInstructionIdSqrt;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
+ return IrInstructionIdBswap;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) {
+ return IrInstructionIdBitReverse;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
return IrInstructionIdCheckRuntimeScope;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) {
+ return IrInstructionIdVectorToArray;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) {
+ return IrInstructionIdArrayToVector;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) {
+ return IrInstructionIdAssertZero;
+}
+
template
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate(1);
@@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
ir_ref_instruction(condition, irb->current_basic_block);
ir_ref_bb(then_block);
ir_ref_bb(else_block);
- if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block);
+ if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
return &cond_br_instruction->base;
}
@@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
return &return_instruction->base;
}
-static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
- ZigType *type_entry)
-{
- assert(type_entry);
- IrInstructionConst *const_instruction = ir_create_instruction(irb, scope, source_node);
- const_instruction->base.value.type = type_entry;
- const_instruction->base.value.special = ConstValSpecialStatic;
- return &const_instruction->base;
-}
-
static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, source_node);
const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
@@ -1179,14 +1233,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
call_instruction->async_allocator = async_allocator;
call_instruction->new_stack = new_stack;
- if (fn_ref)
- ir_ref_instruction(fn_ref, irb->current_basic_block);
+ if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
for (size_t i = 0; i < arg_count; i += 1)
ir_ref_instruction(args[i], irb->current_basic_block);
- if (async_allocator)
- ir_ref_instruction(async_allocator, irb->current_basic_block);
- if (new_stack != nullptr)
- ir_ref_instruction(new_stack, irb->current_basic_block);
+ if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
+ if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
return &call_instruction->base;
}
@@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
container_init_list_instruction->item_count = item_count;
container_init_list_instruction->items = items;
- ir_ref_instruction(container_type, irb->current_basic_block);
+ if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
for (size_t i = 0; i < item_count; i += 1) {
ir_ref_instruction(items[i], irb->current_basic_block);
}
@@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
return &instruction->base;
}
-static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,
+static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
{
- IrInstructionDeclVar *decl_var_instruction = ir_build_instruction(irb, scope, source_node);
+ IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction(irb, scope, source_node);
decl_var_instruction->base.value.special = ConstValSpecialStatic;
decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
decl_var_instruction->var = var;
@@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
decl_var_instruction->align_value = align_value;
decl_var_instruction->init_value = init_value;
- if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);
- if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
+ if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
+ if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
ir_ref_instruction(init_value, irb->current_basic_block);
return &decl_var_instruction->base;
}
+static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigVar *var, IrInstruction *init_value)
+{
+ IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ decl_var_instruction->base.value.special = ConstValSpecialStatic;
+ decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
+ decl_var_instruction->var = var;
+ decl_var_instruction->init_value = init_value;
+
+ ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
+
+ return &decl_var_instruction->base;
+}
+
static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
{
@@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}
-static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
- bool safety_check_on)
+static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *base_ptr, bool safety_check_on)
{
- IrInstructionUnwrapOptional *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+ IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->base_ptr = base_ptr;
instruction->safety_check_on = safety_check_on;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(base_ptr, irb->current_basic_block);
return &instruction->base;
}
@@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,
- IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
+static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
IrInstruction *success_order_value, IrInstruction *failure_order_value,
- bool is_weak,
- ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
+ bool is_weak)
{
- IrInstructionCmpxchg *instruction = ir_build_instruction(irb, scope, source_node);
+ IrInstructionCmpxchgSrc *instruction = ir_build_instruction(irb, scope, source_node);
instruction->type_value = type_value;
instruction->ptr = ptr;
instruction->cmp_value = cmp_value;
@@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
instruction->success_order_value = success_order_value;
instruction->failure_order_value = failure_order_value;
instruction->is_weak = is_weak;
- instruction->type = type;
- instruction->success_order = success_order;
- instruction->failure_order = failure_order;
- if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block);
+ ir_ref_instruction(type_value, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
ir_ref_instruction(cmp_value, irb->current_basic_block);
ir_ref_instruction(new_value, irb->current_basic_block);
- if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block);
- if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block);
+ ir_ref_instruction(success_order_value, irb->current_basic_block);
+ ir_ref_instruction(failure_order_value, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
+ AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
+{
+ IrInstructionCmpxchgGen *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->ptr = ptr;
+ instruction->cmp_value = cmp_value;
+ instruction->new_value = new_value;
+ instruction->success_order = success_order;
+ instruction->failure_order = failure_order;
+ instruction->is_weak = is_weak;
+
+ ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+ ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
+ ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
+static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len,
+ IrInstruction *elem_type)
+{
+ IrInstructionVectorType *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->len = len;
+ instruction->elem_type = elem_type;
+
+ ir_ref_instruction(len, irb->current_basic_block);
+ ir_ref_instruction(elem_type, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
IrInstructionBoolNot *instruction = ir_build_instruction(irb, scope, source_node);
instruction->value = value;
@@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
}
static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *value)
+ IrInstruction *err_union)
{
IrInstructionUnwrapErrCode *instruction = ir_build_instruction(irb, scope, source_node);
- instruction->value = value;
+ instruction->err_union = err_union;
- ir_ref_instruction(value, irb->current_basic_block);
+ ir_ref_instruction(err_union, irb->current_basic_block);
return &instruction->base;
}
@@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
return &instruction->base;
}
-static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *dest_type, IrInstruction *ptr)
+static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
{
- IrInstructionPtrCast *instruction = ir_build_instruction(
+ IrInstructionPtrCastSrc *instruction = ir_build_instruction(
irb, scope, source_node);
instruction->dest_type = dest_type;
instruction->ptr = ptr;
+ instruction->safety_check_on = safety_check_on;
- if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
return &instruction->base;
}
+static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on)
+{
+ IrInstructionPtrCastGen *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ptr_type;
+ instruction->ptr = ptr;
+ instruction->safety_check_on = safety_check_on;
+
+ ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *dest_type, IrInstruction *value)
{
@@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
ir_ref_instruction(type_value, irb->current_basic_block);
- return &instruction->base;
+ return &instruction->base;
}
static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
@@ -2705,6 +2815,28 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
return &instruction->base;
}
+static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
+ IrInstructionBswap *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->type = type;
+ instruction->op = op;
+
+ if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+ ir_ref_instruction(op, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
+ IrInstructionBitReverse *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->type = type;
+ instruction->op = op;
+
+ if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
+ ir_ref_instruction(op, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node);
instruction->scope_is_comptime = scope_is_comptime;
@@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
return &instruction->base;
}
+static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *vector, ZigType *result_type)
+{
+ IrInstructionVectorToArray *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->vector = vector;
+
+ ir_ref_instruction(vector, ira->new_irb.current_basic_block);
+
+ ir_add_alloca(ira, &instruction->base, result_type);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *array, ZigType *result_type)
+{
+ IrInstructionArrayToVector *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = result_type;
+ instruction->array = array;
+
+ ir_ref_instruction(array, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *target)
+{
+ IrInstructionAssertZero *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ira->codegen->builtin_types.entry_void;
+ instruction->target = target;
+
+ ir_ref_instruction(target, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
if (defer_expr_value != irb->codegen->invalid_instruction) {
- if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) {
+ if (defer_expr_value->value.type != nullptr &&
+ defer_expr_value->value.type->id == ZigTypeIdUnreachable)
+ {
is_noreturn = true;
} else {
- ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
+ ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
+ defer_expr_value));
}
}
}
@@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
variable_entry->mem_slot_index = SIZE_MAX;
variable_entry->is_comptime = is_comptime;
variable_entry->src_arg_index = SIZE_MAX;
- variable_entry->value = create_const_vals(1);
+ variable_entry->const_value = create_const_vals(1);
if (is_comptime != nullptr) {
is_comptime->ref_count += 1;
@@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
ErrorMsg *msg = add_node_error(codegen, node,
buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
- variable_entry->value->type = codegen->builtin_types.entry_invalid;
+ variable_entry->var_type = codegen->builtin_types.entry_invalid;
} else {
ZigType *type;
if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
add_node_error(codegen, node,
buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
- variable_entry->value->type = codegen->builtin_types.entry_invalid;
+ variable_entry->var_type = codegen->builtin_types.entry_invalid;
} else {
Tld *tld = find_decl(codegen, parent_scope, name);
if (tld != nullptr) {
ErrorMsg *msg = add_node_error(codegen, node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
- variable_entry->value->type = codegen->builtin_types.entry_invalid;
+ variable_entry->var_type = codegen->builtin_types.entry_invalid;
}
}
}
@@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
scope_block->incoming_blocks = &incoming_blocks;
scope_block->incoming_values = &incoming_values;
scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
- scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));
+ scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
+ ir_should_inline(irb->exec, parent_scope));
}
bool is_continuation_unreachable = false;
@@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
// defer starts a new scope
child_scope = statement_node->data.defer.child_scope;
assert(child_scope);
- } else if (statement_value->id == IrInstructionIdDeclVar) {
+ } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
// variable declarations start a new scope
- IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
+ IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
child_scope = decl_var_instruction->var->child_scope;
} else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
// this statement's value must be void
@@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
}
-static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
+static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
assert(node->type == NodeTypeBinOpExpr);
AstNode *op1_node = node->data.bin_op_expr.op1;
@@ -3334,7 +3511,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, ok_block);
- IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
IrBasicBlock *after_ok_block = irb->current_basic_block;
ir_build_br(irb, parent_scope, node, end_block, is_comptime);
@@ -3452,7 +3629,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
case BinOpTypeMergeErrorSets:
return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
case BinOpTypeUnwrapOptional:
- return ir_gen_maybe_ok_or(irb, scope, node);
+ return ir_gen_orelse(irb, scope, node);
case BinOpTypeErrorUnion:
return ir_gen_error_union(irb, scope, node);
}
@@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
buf_ptr(variable_name)));
return irb->codegen->invalid_instruction;
}
+ assert(err == ErrorPrimitiveTypeNotFound);
} else {
IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
if (lval == LValPtr) {
@@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
Buf *name = fn_ref_expr->data.symbol_expr.symbol;
auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
- if (!entry) {
+ if (!entry) { // new built in not found
add_node_error(irb->codegen, node,
buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
return irb->codegen->invalid_instruction;
@@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg5_value == irb->codegen->invalid_instruction)
return arg5_value;
- IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,
- arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
- nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
+ IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
+ arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
return ir_lval_wrap(irb, scope, cmpxchg, lval);
}
case BuiltinFnIdFence:
@@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, int_type, lval);
}
+ case BuiltinFnIdVectorType:
+ {
+ 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 *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, vector_type, lval);
+ }
case BuiltinFnIdMemcpy:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -4315,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
return ir_lval_wrap(irb, scope, ptr_cast, lval);
}
case BuiltinFnIdBitCast:
@@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, result, lval);
}
+ case BuiltinFnIdBswap:
+ {
+ AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
+ IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
+ if (arg0_value == irb->codegen->invalid_instruction)
+ return arg0_value;
+
+ AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
+ IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
+ if (arg1_value == irb->codegen->invalid_instruction)
+ return arg1_value;
+
+ IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
+ case BuiltinFnIdBitReverse:
+ {
+ 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_bit_reverse(irb, scope, node, arg0_value, arg1_value);
+ return ir_lval_wrap(irb, scope, result, lval);
+ }
}
zig_unreachable();
}
@@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
}
}
- IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);
+ IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
+ is_async, async_allocator, nullptr);
return ir_lval_wrap(irb, scope, fn_call, lval);
}
@@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
if (condition == irb->codegen->invalid_instruction)
- return condition;
+ return irb->codegen->invalid_instruction;
IrInstruction *is_comptime;
if (ir_should_inline(irb->exec, scope)) {
@@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
if (then_expr_result == irb->codegen->invalid_instruction)
- return then_expr_result;
+ return irb->codegen->invalid_instruction;
IrBasicBlock *after_then_block = irb->current_basic_block;
if (!instr_is_unreachable(then_expr_result))
ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
@@ -4765,7 +4988,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
if (else_node) {
else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
if (else_expr_result == irb->codegen->invalid_instruction)
- return else_expr_result;
+ return irb->codegen->invalid_instruction;
} else {
else_expr_result = ir_build_const_void(irb, scope, node);
}
@@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
return ir_build_ref(irb, scope, value->source_node, value, false, false);
}
+static PtrLen star_token_to_ptr_len(TokenId token_id) {
+ switch (token_id) {
+ case TokenIdStar:
+ case TokenIdStarStar:
+ return PtrLenSingle;
+ case TokenIdBracketStarBracket:
+ return PtrLenUnknown;
+ case TokenIdBracketStarCBracket:
+ return PtrLenC;
+ default:
+ zig_unreachable();
+ }
+}
+
static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypePointerType);
- PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
- node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
+ PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
bool is_const = node->data.pointer_type.is_const;
bool is_volatile = node->data.pointer_type.is_volatile;
AstNode *expr_node = node->data.pointer_type.op_expr;
@@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
ptr_len, align_value, bit_offset_start, host_int_bytes);
}
-static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
+static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
LVal lval)
{
IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
@@ -4992,11 +5228,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
is_const, is_const, is_shadowable, is_comptime);
- // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
+ // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
// is inside var->child_scope
if (!is_extern && !variable_declaration->expr) {
- var->value->type = irb->codegen->builtin_types.entry_invalid;
+ var->var_type = irb->codegen->builtin_types.entry_invalid;
add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
return irb->codegen->invalid_instruction;
}
@@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
add_node_error(irb->codegen, variable_declaration->section_expr,
buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
}
+ if (variable_declaration->threadlocal_tok != nullptr) {
+ add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok,
+ buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol)));
+ }
// Temporarily set the name of the IrExecutable to the VariableDeclaration
// so that the struct or enum from the init expression inherits the name.
@@ -5023,7 +5263,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
if (init_value == irb->codegen->invalid_instruction)
return init_value;
- return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value);
+ return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
}
static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -5079,7 +5319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
err_val_ptr, false);
IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
- ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
}
ZigList incoming_values = {0};
@@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
true, false, false, is_comptime);
Scope *err_scope = err_var->child_scope;
IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
- ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
+ ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
if (else_result == irb->codegen->invalid_instruction)
@@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
}
ir_set_cursor_at_end_and_append_block(irb, body_block);
- IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);
+ IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
- ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
+ ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
ZigList incoming_values = {0};
ZigList incoming_blocks = {0};
@@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
Scope *child_scope = elem_var->child_scope;
IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
- ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
+ ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
AstNode *index_var_source_node;
@@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
- ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
+ ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
@@ -5561,8 +5801,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
}
-static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
- assert(node->type == NodeTypeTestExpr);
+static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+ assert(node->type == NodeTypeIfOptional);
Buf *var_symbol = node->data.test_expr.var_symbol;
AstNode *expr_node = node->data.test_expr.target_node;
@@ -5600,9 +5840,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
ZigVar *var = ir_create_var(irb, node, subexpr_scope,
var_symbol, is_const, is_const, is_shadowable, is_comptime);
- IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false);
+ IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
- ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
err_symbol, is_const, is_const, is_shadowable, is_comptime);
IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
- ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
err_var_scope = var->child_scope;
} else {
err_var_scope = subexpr_scope;
@@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
}
IrInstruction *var_type = nullptr; // infer the type
- ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
+ ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
} else {
child_scope = scope;
}
@@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
}
-static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
+static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
assert(node->type == NodeTypeUnwrapErrorExpr);
AstNode *op1_node = node->data.unwrap_err_expr.op1;
@@ -6181,7 +6421,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
return irb->codegen->invalid_instruction;
}
- return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone);
+ return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
}
@@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
is_const, is_const, is_shadowable, is_comptime);
err_scope = var->child_scope;
IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
- ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
+ ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
} else {
err_scope = parent_scope;
}
@@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
if (need_comma)
buf_append_char(name, ',');
- render_const_value(codegen, name, var_scope->var->value);
+ // TODO: const ptr reinterpret here to make the var type agree with the value?
+ render_const_value(codegen, name, var_scope->var->const_value);
return true;
}
@@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
// TODO relies on Zig not re-ordering fields
- IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);
+ IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
+ false);
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
atomic_state_field_name);
// set the is_canceled bit
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
@@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
// TODO relies on Zig not re-ordering fields
- IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);
+ IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
+ false);
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
atomic_state_field_name);
// clear the is_suspended bit
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
AtomicRmwOp_and, AtomicOrderSeqCst);
@@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
- ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
+ ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
@@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
- IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
@@ -6777,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
- IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
@@ -6989,7 +7232,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
if (maybe_ptr == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);
+ IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
if (lval == LValPtr)
return unwrapped_ptr;
@@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
case NodeTypeIfErrorExpr:
return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
- case NodeTypeTestExpr:
- return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
+ case NodeTypeIfOptional:
+ return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
case NodeTypeSwitchExpr:
return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
case NodeTypeCompTime:
@@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeSliceExpr:
return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
case NodeTypeUnwrapErrorExpr:
- return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);
+ return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
case NodeTypeContainerDecl:
return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
case NodeTypeFnProto:
@@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
ir_ref_bb(irb->current_basic_block);
ZigFn *fn_entry = exec_fn_entry(irb->exec);
+
bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
IrInstruction *coro_id;
IrInstruction *u8_ptr_type;
@@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
// TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
- ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
+ ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
- ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
+ ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
- IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
+ IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type,
+ coro_promise_ptr, false);
coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
- ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
+ ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
ImplicitAllocatorIdArg);
irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
- ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
+ ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
@@ -7147,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
ir_build_return(irb, coro_scope, node, undef);
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
- IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
+ IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr,
+ false);
irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
@@ -7225,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, 0, 0, 0));
IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
- IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
- IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
- irb->exec->coro_result_field_ptr);
+ IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
+ result_ptr, false);
+ IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
+ u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
fn_entry->type_entry->data.fn.fn_type_id.return_type);
IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
@@ -7242,7 +7489,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
// Before we destroy the coroutine frame, we need to load the target promise into
// a register or local variable which does not get spilled into the frame,
// otherwise llvm tries to access memory inside the destroyed frame.
- IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
+ IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
irb->exec->await_handle_var_ptr, false);
IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
ir_build_br(irb, scope, node, check_free_block, const_bool_false);
@@ -7277,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, 0, 0, 0));
- IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
+ IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
+ coro_mem_ptr_maybe, false);
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
@@ -7330,24 +7578,51 @@ static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *ms
return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg);
}
+static ErrorMsg *opt_ir_add_error_node(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, Buf *msg) {
+ if (ira != nullptr)
+ return exec_add_error_node(codegen, ira->new_irb.exec, source_node, msg);
+ else
+ return add_node_error(codegen, source_node, msg);
+}
+
static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
return ir_add_error_node(ira, source_instruction->source_node, msg);
}
-static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {
- ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);
+// This function takes a comptime ptr and makes the child const value conform to the type
+// described by the pointer.
+static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
+ ConstExprValue *ptr_val)
+{
+ Error err;
+ assert(ptr_val->type->id == ZigTypeIdPointer);
+ ConstExprValue tmp = {};
+ tmp.special = ConstValSpecialStatic;
+ tmp.type = ptr_val->type->data.pointer.child_type;
+ if ((err = ir_read_const_ptr(ira, codegen, source_node, &tmp, ptr_val)))
+ return err;
+ ConstExprValue *child_val = const_ptr_pointee_unchecked(codegen, ptr_val);
+ copy_const_val(child_val, &tmp, false);
+ return ErrorNone;
+}
+
+ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
+ AstNode *source_node)
+{
+ Error err;
+ ConstExprValue *val = const_ptr_pointee_unchecked(codegen, const_val);
assert(val != nullptr);
assert(const_val->type->id == ZigTypeIdPointer);
ZigType *expected_type = const_val->type->data.pointer.child_type;
if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
- ir_add_error_node(ira, source_node,
- buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955"));
- return nullptr;
+ if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
+ return nullptr;
+ return const_ptr_pointee_unchecked(codegen, const_val);
}
return val;
}
-static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
+static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
IrBasicBlock *bb = exec->basic_block_list.at(0);
for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
IrInstruction *instruction = bb->instruction_list.at(i);
@@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
if (value->value.special == ConstValSpecialRuntime) {
exec_add_error_node(codegen, exec, value->source_node,
buf_sprintf("unable to evaluate constant expression"));
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
}
- return value;
+ return &value->value;
} else if (ir_has_side_effects(instruction)) {
exec_add_error_node(codegen, exec, instruction->source_node,
buf_sprintf("unable to evaluate constant expression"));
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
}
}
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
}
static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
@@ -8086,6 +8361,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
+ assert(const_val_is_int || const_val_is_float);
if (other_type->id == ZigTypeIdFloat) {
if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
@@ -8376,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
return err_set_type;
}
-
static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
{
@@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (wanted_type == actual_type)
return result;
- // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
- // but not if we want a mutable pointer
- // and not if the actual pointer has zero bits
- if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
- wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
- actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
- {
- ConstCastOnly child = types_match_const_cast_only(ira,
- wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
- if (child.id == ConstCastResultIdInvalid)
- return child;
- if (child.id != ConstCastResultIdOk) {
- result.id = ConstCastResultIdNullWrapPtr;
- result.data.null_wrap_ptr_child = allocate_nonzero(1);
- *result.data.null_wrap_ptr_child = child;
- }
- return result;
- }
-
- // pointer const
- if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
- ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
- actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
+ // If pointers have the same representation in memory, they can be "const-casted".
+ // `const` attribute can be gained
+ // `volatile` attribute can be gained
+ // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
+ // but only if !wanted_is_mutable
+ // alignment can be decreased
+ // bit offset attributes must match exactly
+ // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
+ ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
+ ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
+ bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
+ bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
+ bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
+ bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
+ bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
+ (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
+ bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
+ (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
+ if (wanted_opt_or_ptr && actual_opt_or_ptr) {
+ ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
+ actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdPointerChild;
result.data.pointer_mismatch = allocate_nonzero(1);
result.data.pointer_mismatch->child = child;
- result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
- result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
+ result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
+ result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
return result;
}
- if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
+ bool ok_allows_zero = (wanted_allows_zero &&
+ (actual_allows_zero || !wanted_is_mutable)) ||
+ (!wanted_allows_zero && !actual_allows_zero);
+ if (!ok_allows_zero) {
+ result.id = ConstCastResultIdBadAllowsZero;
+ result.data.bad_allows_zero = allocate_nonzero(1);
+ result.data.bad_allows_zero->wanted_type = wanted_type;
+ result.data.bad_allows_zero->actual_type = actual_type;
+ return result;
+ }
+ if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
- if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
+ if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
- if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
- (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
- (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
- actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
- actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
- get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
+ bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
+ if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
+ type_has_bits(wanted_type) == type_has_bits(actual_type) &&
+ (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
+ (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
+ actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
+ actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
+ get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
{
return result;
}
@@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
*errors = reallocate(*errors, old_errors_count, *errors_count);
}
-static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) {
+static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
+ IrInstruction **instructions, size_t instruction_count)
+{
Error err;
assert(instruction_count >= 1);
IrInstruction *prev_inst = instructions[0];
@@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
size_t errors_count = 0;
ZigType *err_set_type = nullptr;
if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
+ if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
if (type_is_global_error_set(prev_inst->value.type)) {
err_set_type = ira->codegen->builtin_types.entry_global_error_set;
} else {
err_set_type = prev_inst->value.type;
- if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
- }
update_errors_helper(ira->codegen, &errors, &errors_count);
for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
@@ -8845,6 +9132,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (prev_type->id == ZigTypeIdArray) {
convert_to_const_slice = true;
}
+ if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
+ return ira->codegen->builtin_types.entry_invalid;
+ }
if (type_is_global_error_set(cur_type)) {
err_set_type = ira->codegen->builtin_types.entry_global_error_set;
continue;
@@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
continue;
}
- if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
- return ira->codegen->builtin_types.entry_invalid;
- }
update_errors_helper(ira->codegen, &errors, &errors_count);
@@ -8986,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
+ if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
+ (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
+ {
+ continue;
+ }
+
+ if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC &&
+ (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt))
+ {
+ prev_inst = cur_inst;
+ continue;
+ }
+
+ if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) {
+ if (prev_type->data.pointer.ptr_len == PtrLenC &&
+ types_match_const_cast_only(ira, prev_type->data.pointer.child_type,
+ cur_type->data.pointer.child_type, source_node,
+ !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ continue;
+ }
+ if (cur_type->data.pointer.ptr_len == PtrLenC &&
+ types_match_const_cast_only(ira, cur_type->data.pointer.child_type,
+ prev_type->data.pointer.child_type, source_node,
+ !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ prev_inst = cur_inst;
+ continue;
+ }
+ }
+
if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
continue;
}
@@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
const_val->type = new_type;
break;
case CastOpResizeSlice:
- case CastOpBytesToSlice:
// can't do it
zig_unreachable();
case CastOpIntToFloat:
@@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
}
return true;
}
+
+static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
+ IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
+ old_instruction->scope, old_instruction->source_node);
+ IrInstruction *new_instruction = &const_instruction->base;
+ new_instruction->value.type = ty;
+ new_instruction->value.special = ConstValSpecialStatic;
+ return new_instruction;
+}
+
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *wanted_type, CastOp cast_op, bool need_alloca)
{
if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
- cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice)
+ cast_op != CastOpResizeSlice)
{
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
&result->value, wanted_type))
{
@@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
if (instr_is_comptime(value)) {
- ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
+ ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
- result->value.type = wanted_type;
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
result->value.data.x_ptr.data.base_array.array_val = pointee;
@@ -9421,7 +9745,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
if (instr_is_comptime(value)) {
- ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
+ ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
@@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
assert(is_slice(wanted_type));
bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
value->value.data.x_ptr.mut;
@@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
return instruction;
}
-static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
- IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
- old_instruction->scope, old_instruction->source_node);
- IrInstruction *new_instruction = &const_instruction->base;
- new_instruction->value.type = ty;
- new_instruction->value.special = ConstValSpecialStatic;
- return new_instruction;
-}
-
static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
result->value.data.x_type = ty;
@@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
if (undef_allowed == UndefOk) {
return &value->value;
} else {
- ir_add_error(ira, value, buf_sprintf("use of undefined value"));
+ ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
return nullptr;
}
}
zig_unreachable();
}
-IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
+ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
- IrExecutable *parent_exec)
+ IrExecutable *parent_exec, AstNode *expected_type_source_node)
{
if (expected_type != nullptr && type_is_invalid(expected_type))
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
IrExecutable *ir_executable = allocate(1);
ir_executable->source_node = source_node;
@@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
ir_gen(codegen, node, scope, ir_executable);
if (ir_executable->invalid)
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
if (codegen->verbose_ir) {
fprintf(stderr, "\nSource: ");
ast_render(codegen, stderr, node, 4);
fprintf(stderr, "\n{ // (IR)\n");
- ir_print(codegen, stderr, ir_executable, 4);
+ ir_print(codegen, stderr, ir_executable, 2);
fprintf(stderr, "}\n");
}
IrExecutable *analyzed_executable = allocate(1);
@@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
analyzed_executable->backward_branch_count = backward_branch_count;
analyzed_executable->backward_branch_quota = backward_branch_quota;
analyzed_executable->begin_scope = scope;
- ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
+ ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
if (type_is_invalid(result_type))
- return codegen->invalid_instruction;
+ return &codegen->invalid_instruction->value;
if (codegen->verbose_ir) {
fprintf(stderr, "{ // (analyzed)\n");
- ir_print(codegen, stderr, analyzed_executable, 4);
+ ir_print(codegen, stderr, analyzed_executable, 2);
fprintf(stderr, "}\n");
}
@@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
return const_val->data.x_type;
}
+static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) {
+ if (type_is_invalid(type_value->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ if (type_value->value.type->id != ZigTypeIdMetaType) {
+ ErrorMsg *msg = ir_add_error(ira, type_value,
+ buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value.type->name)));
+ add_error_note(ira->codegen, msg, op_source->source_node,
+ buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
+ ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad);
+ if (!const_val)
+ return ira->codegen->builtin_types.entry_invalid;
+
+ assert(const_val->data.x_type != nullptr);
+ ZigType *result_type = const_val->data.x_type;
+ if (result_type->id != ZigTypeIdErrorSet) {
+ ErrorMsg *msg = ir_add_error(ira, type_value,
+ buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name)));
+ add_error_note(ira->codegen, msg, op_source->source_node,
+ buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+ return result_type;
+}
+
static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
if (fn_value == ira->codegen->invalid_instruction)
return nullptr;
@@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
return const_val->data.x_ptr.data.fn.fn_entry;
}
-static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {
+static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *wanted_type)
+{
assert(wanted_type->id == ZigTypeIdOptional);
if (instr_is_comptime(value)) {
@@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
source_instr->scope, source_instr->source_node);
const_instruction->base.value.special = ConstValSpecialStatic;
- if (get_codegen_ptr_type(wanted_type) != nullptr) {
+ if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
} else {
const_instruction->base.value.data.x_optional = val;
@@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
if (!val)
return ira->codegen->invalid_instruction;
+ ConstExprValue *err_set_val = create_const_vals(1);
+ err_set_val->type = wanted_type->data.error_union.err_set_type;
+ err_set_val->special = ConstValSpecialStatic;
+ err_set_val->data.x_err_set = nullptr;
+
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
source_instr->scope, source_instr->source_node);
const_instruction->base.value.type = wanted_type;
const_instruction->base.value.special = ConstValSpecialStatic;
- const_instruction->base.value.data.x_err_union.err = nullptr;
+ const_instruction->base.value.data.x_err_union.error_set = err_set_val;
const_instruction->base.value.data.x_err_union.payload = val;
return &const_instruction->base;
}
@@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
if (!val)
return ira->codegen->invalid_instruction;
+ ConstExprValue *err_set_val = create_const_vals(1);
+ err_set_val->special = ConstValSpecialStatic;
+ err_set_val->type = wanted_type->data.error_union.err_set_type;
+ err_set_val->data.x_err_set = val->data.x_err_set;
+
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
source_instr->scope, source_instr->source_node);
const_instruction->base.value.type = wanted_type;
const_instruction->base.value.special = ConstValSpecialStatic;
- const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;
+ const_instruction->base.value.data.x_err_union.error_set = err_set_val;
const_instruction->base.value.data.x_err_union.payload = nullptr;
return &const_instruction->base;
}
@@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, source_instr->scope, source_instr->source_node);
const_instruction->base.value.special = ConstValSpecialStatic;
if (get_codegen_ptr_type(wanted_type) != nullptr) {
- const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
- const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;
+ const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
+ } else if (is_opt_err_set(wanted_type)) {
+ const_instruction->base.value.data.x_err_set = nullptr;
} else {
const_instruction->base.value.data.x_optional = nullptr;
}
@@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
source_instruction->source_node, value, is_const, is_volatile);
new_instruction->value.type = ptr_type;
new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
- if (type_has_bits(ptr_type)) {
+ if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
assert(fn_entry);
fn_entry->alloca_list.append(new_instruction);
@@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
ZigType *array_type = array->value.type;
assert(array_type->id == ZigTypeIdArray);
- if (instr_is_comptime(array)) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ if (instr_is_comptime(array) || array_type->data.array.len == 0) {
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
result->value.type = wanted_type;
return result;
}
- IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, ira->codegen->builtin_types.entry_usize);
+ IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
init_const_usize(ira->codegen, &start->value, 0);
- IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, ira->codegen->builtin_types.entry_usize);
+ IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
@@ -9977,8 +10329,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
return result;
}
@@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
actual_type->data.enumeration.src_field_count == 1)
{
assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_bigint(&result->value, wanted_type,
&actual_type->data.enumeration.fields[0].value);
return result;
@@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
result->value.special = ConstValSpecialStatic;
result->value.type = wanted_type;
bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
@@ -10024,8 +10373,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
wanted_type->data.enumeration.src_field_count == 1)
{
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
result->value.special = ConstValSpecialStatic;
result->value.type = wanted_type;
TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
@@ -10042,8 +10390,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *target, ZigType *wanted_type)
{
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_undefined(ira->codegen, &result->value);
return result;
}
@@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
result->value.special = ConstValSpecialStatic;
result->value.type = wanted_type;
bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
@@ -10131,8 +10477,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
return ira->codegen->invalid_instruction;
}
}
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
result->value.type = wanted_type;
if (wanted_type->id == ZigTypeIdInt) {
bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
@@ -10142,6 +10487,18 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
return result;
}
+ // If the destination integer type has no bits, then we can emit a comptime
+ // zero. However, we still want to emit a runtime safety check to make sure
+ // the target is zero.
+ if (!type_has_bits(wanted_type)) {
+ assert(wanted_type->id == ZigTypeIdInt);
+ assert(type_has_bits(target->value.type));
+ ir_build_assert_zero(ira, source_instr, target);
+ IrInstruction *result = ir_const_unsigned(ira, source_instr, 0);
+ result->value.type = wanted_type;
+ return result;
+ }
+
IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
source_instr->source_node, target);
result->value.type = wanted_type;
@@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
return result;
}
@@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
if (wanted_type->id == ZigTypeIdComptimeFloat) {
float_init_float(&result->value, val);
} else if (wanted_type->id == ZigTypeIdComptimeInt) {
@@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
return ira->codegen->invalid_instruction;
@@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
ErrorTableEntry *err;
if (err_type->id == ZigTypeIdErrorUnion) {
- err = val->data.x_err_union.err;
+ err = val->data.x_err_union.error_set->data.x_err_set;
} else if (err_type->id == ZigTypeIdErrorSet) {
err = val->data.x_err_set;
} else {
@@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
return ira->codegen->invalid_instruction;
}
if (err_set_type->data.error_set.err_count == 0) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
- result->value.type = wanted_type;
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
bigint_init_unsigned(&result->value.data.x_bigint, 0);
return result;
} else if (err_set_type->data.error_set.err_count == 1) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
- source_instr->source_node, wanted_type);
- result->value.type = wanted_type;
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
bigint_init_unsigned(&result->value.data.x_bigint, err->value);
return result;
@@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
return ira->codegen->invalid_instruction;
assert(val->type->id == ZigTypeIdPointer);
- ConstExprValue *pointee = ir_const_ptr_pointee(ira, val, source_instr->source_node);
+ ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
@@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
array_val->type = array_type;
array_val->data.x_array.special = ConstArraySpecialNone;
array_val->data.x_array.data.s_none.elements = pointee;
- array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;
- array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;
+ array_val->parent.id = ConstParentIdScalar;
+ array_val->parent.data.p_scalar.scalar_val = pointee;
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
source_instr->scope, source_instr->source_node);
@@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
break;
}
+ case ConstCastResultIdBadAllowsZero: {
+ ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type;
+ ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type;
+ bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
+ bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
+ if (actual_allows_zero && !wanted_allows_zero) {
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("'%s' could have null values which are illegal in type '%s'",
+ buf_ptr(&actual_type->name),
+ buf_ptr(&wanted_type->name)));
+ } else {
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'",
+ buf_ptr(&wanted_type->name),
+ buf_ptr(&actual_type->name)));
+ }
+ break;
+ }
+ case ConstCastResultIdFnIsGeneric:
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("only one of the functions is generic"));
+ break;
case ConstCastResultIdFnAlign: // TODO
case ConstCastResultIdFnCC: // TODO
case ConstCastResultIdFnVarArgs: // TODO
- case ConstCastResultIdFnIsGeneric: // TODO
case ConstCastResultIdFnReturnType: // TODO
case ConstCastResultIdFnArgCount: // TODO
case ConstCastResultIdFnGenericArgCount: // TODO
case ConstCastResultIdFnArgNoAlias: // TODO
case ConstCastResultIdUnresolvedInferredErrSet: // TODO
case ConstCastResultIdAsyncAllocatorType: // TODO
- case ConstCastResultIdNullWrapPtr: // TODO
break;
}
}
+static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *array, ZigType *vector_type)
+{
+ if (instr_is_comptime(array)) {
+ // arrays and vectors have the same ConstExprValue representation
+ IrInstruction *result = ir_const(ira, source_instr, vector_type);
+ copy_const_val(&result->value, &array->value, false);
+ result->value.type = vector_type;
+ return result;
+ }
+ return ir_build_array_to_vector(ira, source_instr, array, vector_type);
+}
+
+static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *vector, ZigType *array_type)
+{
+ if (instr_is_comptime(vector)) {
+ // arrays and vectors have the same ConstExprValue representation
+ IrInstruction *result = ir_const(ira, source_instr, array_type);
+ copy_const_val(&result->value, &vector->value, false);
+ result->value.type = array_type;
+ return result;
+ }
+ return ir_build_vector_to_array(ira, source_instr, vector, array_type);
+}
+
+static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *integer, ZigType *dest_type)
+{
+ IrInstruction *unsigned_integer;
+ if (instr_is_comptime(integer)) {
+ unsigned_integer = integer;
+ } else {
+ assert(integer->value.type->id == ZigTypeIdInt);
+
+ if (integer->value.type->data.integral.bit_count >
+ ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
+ {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'",
+ buf_ptr(&integer->value.type->name),
+ buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (integer->value.type->data.integral.is_signed) {
+ ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
+ integer->value.type->data.integral.bit_count);
+ unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
+ if (type_is_invalid(unsigned_integer->value.type))
+ return ira->codegen->invalid_instruction;
+ } else {
+ unsigned_integer = integer;
+ }
+ }
+
+ return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
+}
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
ZigType *wanted_type, IrInstruction *value)
{
@@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
false).id == ConstCastResultIdOk)
{
- return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
} else if (actual_type->id == ZigTypeIdComptimeInt ||
actual_type->id == ZigTypeIdComptimeFloat)
{
if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
- return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
} else {
return ira->codegen->invalid_instruction;
}
@@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
wanted_child_type);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
- return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
+ return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
}
}
}
@@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
{
+ if (value->value.special == ConstValSpecialUndef) {
+ IrInstruction *result = ir_const(ira, source_instr, wanted_type);
+ result->value.special = ConstValSpecialUndef;
+ return result;
+ }
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
IrInstruction *result = ir_const(ira, source_instr, wanted_type);
@@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
// cast from [N]T to []const T
+ // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
assert(ptr_type->id == ZigTypeIdPointer);
@@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
// cast from [N]T to ?[]const T
+ // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
if (wanted_type->id == ZigTypeIdOptional &&
is_slice(wanted_type->data.maybe.child_type) &&
actual_type->id == ZigTypeIdArray)
@@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
- // cast from error set to error union type
+ // cast from E to E!T
if (wanted_type->id == ZigTypeIdErrorUnion &&
actual_type->id == ZigTypeIdErrorSet)
{
@@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
{
- return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
+ return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
}
}
@@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
+ // cast from @Vector(N, T) to [N]T
+ if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector &&
+ wanted_type->data.array.len == actual_type->data.vector.len &&
+ types_match_const_cast_only(ira, wanted_type->data.array.child_type,
+ actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
+ {
+ return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
+ }
+
+ // cast from [N]T to @Vector(N, T)
+ if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector &&
+ actual_type->data.array.len == wanted_type->data.vector.len &&
+ types_match_const_cast_only(ira, actual_type->data.array.child_type,
+ wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
+ {
+ return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
+ }
+
+ // casting between C pointers and normal pointers
+ if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
+ (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
+ types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
+ actual_type->data.pointer.child_type, source_node,
+ !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
+ }
+
+ // cast from integer to C pointer
+ if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
+ (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
+ {
+ return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
+ }
// cast from undefined to anything
if (actual_type->id == ZigTypeIdUndefined) {
@@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
ZigType *child_type = type_entry->data.pointer.child_type;
// dereferencing a *u0 is comptime known to be 0
if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, child_type);
+ IrInstruction *result = ir_const(ira, source_instruction, child_type);
init_const_unsigned_negative(&result->value, child_type, 0, false);
return result;
}
@@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
{
ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
if (pointee->special != ConstValSpecialRuntime) {
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, child_type);
+ IrInstruction *result = ir_const(ira, source_instruction, child_type);
- if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value,
+ if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
&ptr->value)))
{
return ira->codegen->invalid_instruction;
@@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
}
}
}
- // TODO if the instruction is a const ref instruction we can skip it
+ // if the instruction is a const ref instruction we can skip it
+ if (ptr->id == IrInstructionIdRef) {
+ IrInstructionRef *ref_inst = reinterpret_cast(ptr);
+ return ref_inst->value;
+ }
IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
source_instruction->source_node, ptr);
load_ptr_instruction->value.type = child_type;
@@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
return ir_unreach_error(ira);
IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
- if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) {
- ErrorMsg *msg = ira->codegen->errors.last();
- add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node,
- buf_sprintf("return type declared here"));
+ if (type_is_invalid(casted_value->value.type)) {
+ AstNode *source_node = ira->explicit_return_type_source_node;
+ if (source_node != nullptr) {
+ ErrorMsg *msg = ira->codegen->errors.last();
+ add_error_note(ira->codegen, msg, source_node,
+ buf_sprintf("return type declared here"));
+ }
return ir_unreach_error(ira);
}
@@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
- // TODO determine if we need to use copy_const_val here
- result->value = instruction->base.value;
+ copy_const_val(&result->value, &instruction->base.value, true);
return result;
}
@@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
}
static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
- if (op_id == IrBinOpCmpEq) {
- return cmp == CmpEQ;
- } else if (op_id == IrBinOpCmpNotEq) {
- return cmp != CmpEQ;
- } else if (op_id == IrBinOpCmpLessThan) {
- return cmp == CmpLT;
- } else if (op_id == IrBinOpCmpGreaterThan) {
- return cmp == CmpGT;
- } else if (op_id == IrBinOpCmpLessOrEq) {
- return cmp != CmpGT;
- } else if (op_id == IrBinOpCmpGreaterOrEq) {
- return cmp != CmpLT;
- } else {
- zig_unreachable();
+ switch (op_id) {
+ case IrBinOpCmpEq:
+ return cmp == CmpEQ;
+ case IrBinOpCmpNotEq:
+ return cmp != CmpEQ;
+ case IrBinOpCmpLessThan:
+ return cmp == CmpLT;
+ case IrBinOpCmpGreaterThan:
+ return cmp == CmpGT;
+ case IrBinOpCmpLessOrEq:
+ return cmp != CmpGT;
+ case IrBinOpCmpGreaterOrEq:
+ return cmp != CmpLT;
+ default:
+ zig_unreachable();
}
}
static bool optional_value_is_null(ConstExprValue *val) {
assert(val->special == ConstValSpecialStatic);
if (get_codegen_ptr_type(val->type) != nullptr) {
- return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
- val->data.x_ptr.data.hard_coded_addr.addr == 0;
+ if (val->data.x_ptr.special == ConstPtrSpecialNull) {
+ return true;
+ } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+ return val->data.x_ptr.data.hard_coded_addr.addr == 0;
+ } else {
+ return false;
+ }
+ } else if (is_opt_err_set(val->type)) {
+ return val->data.x_err_set == nullptr;
} else {
return val->data.x_optional == nullptr;
}
@@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
case ZigTypeIdComptimeInt:
case ZigTypeIdInt:
case ZigTypeIdFloat:
+ case ZigTypeIdVector:
operator_allowed = true;
break;
case ZigTypeIdBool:
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
- case ZigTypeIdPointer:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
case ZigTypeIdOpaque:
@@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
operator_allowed = is_equality_cmp;
break;
+ case ZigTypeIdPointer:
+ operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
+ break;
+
case ZigTypeIdUnreachable:
case ZigTypeIdArray:
case ZigTypeIdStruct:
@@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
if (casted_op2 == ira->codegen->invalid_instruction)
return ira->codegen->invalid_instruction;
- bool requires_comptime;
- switch (type_requires_comptime(ira->codegen, resolved_type)) {
- case ReqCompTimeYes:
- requires_comptime = true;
- break;
- case ReqCompTimeNo:
- requires_comptime = false;
- break;
- case ReqCompTimeInvalid:
+ bool one_possible_value;
+ switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
+ case OnePossibleValueInvalid:
return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ one_possible_value = true;
+ break;
+ case OnePossibleValueNo:
+ one_possible_value = false;
+ break;
}
- bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
if (op1_val == nullptr)
@@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
if (op2_val == nullptr)
return ira->codegen->invalid_instruction;
- bool answer;
if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
Cmp cmp_result = float_cmp(op1_val, op2_val);
- answer = resolve_cmp_op_id(op_id, cmp_result);
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
} else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
- answer = resolve_cmp_op_id(op_id, cmp_result);
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
+ } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
+ if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
+ (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op2_val->data.x_ptr.special == ConstPtrSpecialNull))
+ {
+ uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
+ 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
+ uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
+ 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
+ Cmp cmp_result;
+ if (op1_addr > op2_addr) {
+ cmp_result = CmpGT;
+ } else if (op1_addr < op2_addr) {
+ cmp_result = CmpLT;
+ } else {
+ cmp_result = CmpEQ;
+ }
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
+ }
} else {
bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
+ bool answer;
if (op_id == IrBinOpCmpEq) {
answer = are_equal;
} else if (op_id == IrBinOpCmpNotEq) {
@@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
} else {
zig_unreachable();
}
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
-
- return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
// some comparisons with unsigned numbers can be evaluated
@@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
return result;
}
-static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
- IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
+static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
+ ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
{
bool is_int;
bool is_float;
@@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
{
- return ErrorDivByZero;
+ return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
}
if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
- return ErrorNegativeDenominator;
+ return ir_add_error(ira, source_instr, buf_sprintf("negative denominator"));
}
switch (op_id) {
@@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
BigInt orig_bigint;
bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {
- return ErrorShiftedOutOneBits;
+ return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits"));
}
break;
}
@@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
BigInt remainder;
bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
if (bigint_cmp_zero(&remainder) != CmpEQ) {
- return ErrorExactDivRemainder;
+ return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
}
} else {
float_div_trunc(out_val, op1_val, op2_val);
ConstExprValue remainder;
float_rem(&remainder, op1_val, op2_val);
if (float_cmp_zero(&remainder) != CmpEQ) {
- return ErrorExactDivRemainder;
+ return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
}
}
break;
@@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
type_entry->data.integral.is_signed))
{
- return ErrorOverflow;
+ return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
}
}
out_val->type = type_entry;
out_val->special = ConstValSpecialStatic;
- return 0;
+ return nullptr;
+}
+
+// This works on operands that have already been checked to be comptime known.
+static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr,
+ ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val)
+{
+ IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry);
+ ConstExprValue *out_val = &result_instruction->value;
+ if (type_entry->id == ZigTypeIdVector) {
+ expand_undef_array(ira->codegen, op1_val);
+ expand_undef_array(ira->codegen, op2_val);
+ out_val->special = ConstValSpecialUndef;
+ expand_undef_array(ira->codegen, out_val);
+ size_t len = type_entry->data.vector.len;
+ ZigType *scalar_type = type_entry->data.vector.elem_type;
+ for (size_t i = 0; i < len; i += 1) {
+ ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i];
+ ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i];
+ ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
+ assert(scalar_op1_val->type == scalar_type);
+ assert(scalar_op2_val->type == scalar_type);
+ assert(scalar_out_val->type == scalar_type);
+ ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type,
+ scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
+ if (msg != nullptr) {
+ add_error_note(ira->codegen, msg, source_instr->source_node,
+ buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
+ return ira->codegen->invalid_instruction;
+ }
+ }
+ out_val->type = type_entry;
+ out_val->special = ConstValSpecialStatic;
+ } else {
+ if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) {
+ return ira->codegen->invalid_instruction;
+ }
+ }
+ return ir_implicit_cast(ira, result_instruction, type_entry);
}
static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
@@ -11816,24 +12360,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
if (op2_val == nullptr)
return ira->codegen->invalid_instruction;
- IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);
-
- int err;
- if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) {
- if (err == ErrorOverflow) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
- return ira->codegen->invalid_instruction;
- } else if (err == ErrorShiftedOutOneBits) {
- ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits"));
- return ira->codegen->invalid_instruction;
- } else {
- zig_unreachable();
- }
- return ira->codegen->invalid_instruction;
- }
-
- ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
- return result_instruction;
+ return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
} else if (op1->value.type->id == ZigTypeIdComptimeInt) {
ir_add_error(ira, &bin_op_instruction->base,
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
@@ -11852,7 +12379,71 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
return result;
}
+static bool ok_float_op(IrBinOp op) {
+ switch (op) {
+ case IrBinOpInvalid:
+ zig_unreachable();
+ case IrBinOpAdd:
+ case IrBinOpSub:
+ case IrBinOpMult:
+ case IrBinOpDivUnspecified:
+ case IrBinOpDivTrunc:
+ case IrBinOpDivFloor:
+ case IrBinOpDivExact:
+ case IrBinOpRemRem:
+ case IrBinOpRemMod:
+ return true;
+
+ case IrBinOpBoolOr:
+ case IrBinOpBoolAnd:
+ case IrBinOpCmpEq:
+ case IrBinOpCmpNotEq:
+ case IrBinOpCmpLessThan:
+ case IrBinOpCmpGreaterThan:
+ case IrBinOpCmpLessOrEq:
+ case IrBinOpCmpGreaterOrEq:
+ case IrBinOpBinOr:
+ case IrBinOpBinXor:
+ case IrBinOpBinAnd:
+ case IrBinOpBitShiftLeftLossy:
+ case IrBinOpBitShiftLeftExact:
+ case IrBinOpBitShiftRightLossy:
+ case IrBinOpBitShiftRightExact:
+ case IrBinOpAddWrap:
+ case IrBinOpSubWrap:
+ case IrBinOpMultWrap:
+ case IrBinOpRemUnspecified:
+ case IrBinOpArrayCat:
+ case IrBinOpArrayMult:
+ case IrBinOpMergeErrorSets:
+ return false;
+ }
+ zig_unreachable();
+}
+
+static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
+ if (lhs_type->id != ZigTypeIdPointer)
+ return false;
+ switch (op) {
+ case IrBinOpAdd:
+ case IrBinOpSub:
+ break;
+ default:
+ return false;
+ }
+ switch (lhs_type->data.pointer.ptr_len) {
+ case PtrLenSingle:
+ return false;
+ case PtrLenUnknown:
+ case PtrLenC:
+ break;
+ }
+ return true;
+}
+
static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ Error err;
+
IrInstruction *op1 = instruction->op1->child;
if (type_is_invalid(op1->value.type))
return ira->codegen->invalid_instruction;
@@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
IrBinOp op_id = instruction->op_id;
// look for pointer math
- if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
- (op_id == IrBinOpAdd || op_id == IrBinOpSub))
- {
+ if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
- if (casted_op2 == ira->codegen->invalid_instruction)
+ if (type_is_invalid(casted_op2->value.type))
return ira->codegen->invalid_instruction;
+ if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
+ IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
+ result->value.special = ConstValSpecialUndef;
+ return result;
+ }
+ if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
+ (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op1->value.data.x_ptr.special == ConstPtrSpecialNull))
+ {
+ uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
+ 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
+ uint64_t elem_offset;
+ if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
+ return ira->codegen->invalid_instruction;
+ ZigType *elem_type = op1->value.type->data.pointer.child_type;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
+ uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
+ uint64_t new_addr;
+ if (op_id == IrBinOpAdd) {
+ new_addr = start_addr + byte_offset;
+ } else if (op_id == IrBinOpSub) {
+ new_addr = start_addr - byte_offset;
+ } else {
+ zig_unreachable();
+ }
+ IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
+ result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
+ result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
+ return result;
+ }
+
IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, op_id, op1, casted_op2, true);
result->value.type = op1->value.type;
@@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
op_id = IrBinOpRemRem;
}
+ bool ok = false;
if (is_int) {
- // int
- } else if (is_float &&
- (op_id == IrBinOpAdd ||
- op_id == IrBinOpSub ||
- op_id == IrBinOpMult ||
- op_id == IrBinOpDivUnspecified ||
- op_id == IrBinOpDivTrunc ||
- op_id == IrBinOpDivFloor ||
- op_id == IrBinOpDivExact ||
- op_id == IrBinOpRemRem ||
- op_id == IrBinOpRemMod))
- {
- // float
- } else {
+ ok = true;
+ } else if (is_float && ok_float_op(op_id)) {
+ ok = true;
+ } else if (resolved_type->id == ZigTypeIdVector) {
+ ZigType *elem_type = resolved_type->data.vector.elem_type;
+ if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) {
+ ok = true;
+ } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) {
+ ok = true;
+ }
+ }
+ if (!ok) {
AstNode *source_node = instruction->base.source_node;
ir_add_error_node(ira, source_node,
buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
@@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
if (op2_val == nullptr)
return ira->codegen->invalid_instruction;
- IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);
-
- int err;
- if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) {
- if (err == ErrorDivByZero) {
- ir_add_error(ira, &instruction->base, buf_sprintf("division by zero"));
- return ira->codegen->invalid_instruction;
- } else if (err == ErrorOverflow) {
- ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow"));
- return ira->codegen->invalid_instruction;
- } else if (err == ErrorExactDivRemainder) {
- ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder"));
- return ira->codegen->invalid_instruction;
- } else if (err == ErrorNegativeDenominator) {
- ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator"));
- return ira->codegen->invalid_instruction;
- } else {
- zig_unreachable();
- }
- return ira->codegen->invalid_instruction;
- }
-
- ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false);
- return result_instruction;
+ return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
}
IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
@@ -12115,7 +12713,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];
- op1_array_end = bigint_as_unsigned(&len_val->data.x_bigint);
+ op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
} else {
ir_add_error(ira, op1,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
@@ -12125,13 +12723,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
ConstExprValue *op2_array_val;
size_t op2_array_index;
size_t op2_array_end;
+ bool op2_type_valid;
if (op2_type->id == ZigTypeIdArray) {
- if (op2_type->data.array.child_type != child_type) {
- ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
- buf_ptr(&child_type->name),
- buf_ptr(&op2->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
+ op2_type_valid = op2_type->data.array.child_type == child_type;
op2_array_val = op2_val;
op2_array_index = 0;
op2_array_end = op2_array_val->type->data.array.len;
@@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
op2_val->data.x_ptr.data.base_array.is_cstr)
{
- if (child_type != ira->codegen->builtin_types.entry_u8) {
- ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
- buf_ptr(&child_type->name),
- buf_ptr(&op2->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
+ op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
op2_array_end = op2_array_val->type->data.array.len - 1;
} else if (is_slice(op2_type)) {
ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
- if (ptr_type->data.pointer.child_type != child_type) {
- ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
- buf_ptr(&child_type->name),
- buf_ptr(&op2->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
+ op2_type_valid = ptr_type->data.pointer.child_type == child_type;
ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
- op2_array_end = op2_array_val->type->data.array.len;
ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];
- op2_array_end = bigint_as_unsigned(&len_val->data.x_bigint);
+ op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
} else {
ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
return ira->codegen->invalid_instruction;
}
+ if (!op2_type_valid) {
+ ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
+ buf_ptr(&child_type->name),
+ buf_ptr(&op2->value.type->name)));
+ return ira->codegen->invalid_instruction;
+ }
// The type of result is populated in the following if blocks
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
@@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
}
static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
- ZigType *op1_type = ir_resolve_type(ira, instruction->op1->child);
+ ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child);
if (type_is_invalid(op1_type))
return ira->codegen->invalid_instruction;
- if (op1_type->id != ZigTypeIdErrorSet) {
- ir_add_error(ira, instruction->op1,
- buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- ZigType *op2_type = ir_resolve_type(ira, instruction->op2->child);
+ ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child);
if (type_is_invalid(op2_type))
return ira->codegen->invalid_instruction;
- if (op2_type->id != ZigTypeIdErrorSet) {
- ir_add_error(ira, instruction->op2,
- buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
if (type_is_global_error_set(op1_type) ||
type_is_global_error_set(op2_type))
{
@@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {
+static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
+ IrInstructionDeclVarSrc *decl_var_instruction)
+{
Error err;
ZigVar *var = decl_var_instruction->var;
IrInstruction *init_value = decl_var_instruction->init_value->child;
if (type_is_invalid(init_value->value.type)) {
- var->value->type = ira->codegen->builtin_types.entry_invalid;
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_instruction;
}
@@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
ZigType *proposed_type = ir_resolve_type(ira, var_type);
explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
if (type_is_invalid(explicit_type)) {
- var->value->type = ira->codegen->builtin_types.entry_invalid;
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_instruction;
}
}
@@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
case ReqCompTimeInvalid:
result_type = ira->codegen->builtin_types.entry_invalid;
break;
- case ReqCompTimeYes: {
+ case ReqCompTimeYes:
var_class_requires_const = true;
if (!var->gen_is_const && !is_comptime_var) {
ir_add_error_node(ira, source_node,
@@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
result_type = ira->codegen->builtin_types.entry_invalid;
}
break;
- }
case ReqCompTimeNo:
if (casted_init_value->value.special == ConstValSpecialStatic &&
casted_init_value->value.type->id == ZigTypeIdFn &&
+ casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
{
var_class_requires_const = true;
@@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
break;
}
- if (var->value->type != nullptr && !is_comptime_var) {
+ if (var->var_type != nullptr && !is_comptime_var) {
// This is at least the second time we've seen this variable declaration during analysis.
// This means that this is actually a different variable due to, e.g. an inline while loop.
// We make a new variable so that it can hold a different type, and so the debug info can
@@ -12485,8 +13064,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
// This must be done after possibly creating a new variable above
var->ref_count = 0;
- var->value->type = result_type;
- assert(var->value->type);
+ var->var_type = result_type;
+ assert(var->var_type);
if (type_is_invalid(result_type)) {
return ir_const_void(ira, &decl_var_instruction->base);
@@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
if (decl_var_instruction->align_value == nullptr) {
if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
- var->value->type = ira->codegen->builtin_types.entry_invalid;
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
return ir_const_void(ira, &decl_var_instruction->base);
}
var->align_bytes = get_abi_alignment(ira->codegen, result_type);
} else {
if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
- var->value->type = ira->codegen->builtin_types.entry_invalid;
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
}
}
@@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
} else if (is_comptime_var) {
ir_add_error(ira, &decl_var_instruction->base,
buf_sprintf("cannot store runtime value in compile time variable"));
- var->value->type = ira->codegen->builtin_types.entry_invalid;
+ var->var_type = ira->codegen->builtin_types.entry_invalid;
return ira->codegen->invalid_instruction;
}
@@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
if (fn_entry)
fn_entry->variable_list.append(var);
- IrInstruction *result = ir_build_var_decl(&ira->new_irb,
- decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
- var, var_type, nullptr, casted_init_value);
- result->value.type = ira->codegen->builtin_types.entry_void;
- return result;
+ return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
}
static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
@@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdBool:
+ case ZigTypeIdVector:
break;
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
@@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
+ case ZigTypeIdVector:
zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
@@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
Buf *param_name = param_decl_node->data.param_decl.name;
ZigVar *var = add_variable(ira->codegen, param_decl_node,
- *exec_scope, param_name, true, arg_val, nullptr);
+ *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
*exec_scope = var->child_scope;
*next_proto_i += 1;
@@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
if (!param_name) return false;
if (!is_var_args) {
ZigVar *var = add_variable(ira->codegen, param_decl_node,
- *child_scope, param_name, true, arg_val, nullptr);
+ *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
*child_scope = var->child_scope;
var->shadowable = !comptime_arg;
@@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
return fn_entry->variable_list.at(next_var_i);
}
-static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
- ZigVar *var)
-{
+static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
while (var->next_var != nullptr) {
var = var->next_var;
}
@@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
assert(ira->codegen->errors.length != 0);
return ira->codegen->invalid_instruction;
}
- if (var->value->type == nullptr || type_is_invalid(var->value->type))
+ if (var->var_type == nullptr || type_is_invalid(var->var_type))
return ira->codegen->invalid_instruction;
bool comptime_var_mem = ir_get_var_is_comptime(var);
ConstExprValue *mem_slot = nullptr;
- if (var->value->special == ConstValSpecialStatic) {
- mem_slot = var->value;
+ if (var->const_value->special == ConstValSpecialStatic) {
+ mem_slot = var->const_value;
} else {
if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
// find the relevant exec_context
@@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
assert(!comptime_var_mem);
ptr_mut = ConstPtrMutRuntimeVar;
}
- return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type,
+ return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
ptr_mut, is_const, is_volatile, var->align_bytes);
}
}
@@ -13029,7 +13604,7 @@ no_mem_slot:
IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
instruction->scope, instruction->source_node, var);
- var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
+ var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
@@ -13038,6 +13613,96 @@ no_mem_slot:
return var_ptr_instruction;
}
+static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *ptr, IrInstruction *uncasted_value)
+{
+ if (ptr->value.type->id != ZigTypeIdPointer) {
+ ir_add_error(ira, ptr,
+ buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
+ return ir_const_void(ira, source_instr);
+ }
+
+ if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
+ ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ZigType *child_type = ptr->value.type->data.pointer.child_type;
+ IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
+ if (value == ira->codegen->invalid_instruction)
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
+ ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
+ return ira->codegen->invalid_instruction;
+ }
+ if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
+ if (instr_is_comptime(value)) {
+ ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
+ if (dest_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (dest_val->special != ConstValSpecialRuntime) {
+ // TODO this allows a value stored to have the original value modified and then
+ // have that affect what should be a copy. We need some kind of advanced copy-on-write
+ // system to make these two tests pass at the same time:
+ // * "string literal used as comptime slice is memoized"
+ // * "comptime modification of const struct field" - except modified to avoid
+ // ConstPtrMutComptimeVar, thus defeating the logic below.
+ bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
+ copy_const_val(dest_val, &value->value, same_global_refs);
+ if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueNo:
+ ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
+ break;
+ case OnePossibleValueYes:
+ break;
+ }
+ }
+ return ir_const_void(ira, source_instr);
+ }
+ }
+ ir_add_error(ira, source_instr,
+ buf_sprintf("cannot store runtime value in compile time variable"));
+ ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
+ dest_val->type = ira->codegen->builtin_types.entry_invalid;
+
+ return ira->codegen->invalid_instruction;
+ }
+ }
+
+ switch (type_requires_comptime(ira->codegen, child_type)) {
+ case ReqCompTimeInvalid:
+ return ira->codegen->invalid_instruction;
+ case ReqCompTimeYes:
+ switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueNo:
+ ir_add_error(ira, source_instr,
+ buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const_void(ira, source_instr);
+ }
+ zig_unreachable();
+ case ReqCompTimeNo:
+ break;
+ }
+
+ IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
+ ptr, value);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result;
+}
+
static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
@@ -13182,7 +13847,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
}
bool cacheable = fn_eval_cacheable(exec_scope, return_type);
- IrInstruction *result = nullptr;
+ ConstExprValue *result = nullptr;
if (cacheable) {
auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
if (entry)
@@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
AstNode *body_node = fn_entry->body_node;
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
- nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);
+ nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);
if (inferred_err_set_type != nullptr) {
inferred_err_set_type->data.error_set.infer_fn = nullptr;
- if (result->value.type->id == ZigTypeIdErrorUnion) {
- if (result->value.data.x_err_union.err != nullptr) {
+ if (result->type->id == ZigTypeIdErrorUnion) {
+ ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
+ if (err != nullptr) {
inferred_err_set_type->data.error_set.err_count = 1;
inferred_err_set_type->data.error_set.errors = allocate(1);
- inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err;
+ inferred_err_set_type->data.error_set.errors[0] = err;
}
- ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;
+ ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
- } else if (result->value.type->id == ZigTypeIdErrorSet) {
- inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;
- inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;
+ } else if (result->type->id == ZigTypeIdErrorSet) {
+ inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
+ inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
}
}
@@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
}
- if (type_is_invalid(result->value.type))
+ if (type_is_invalid(result->type))
return ira->codegen->invalid_instruction;
}
- IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);
- // TODO should we use copy_const_val?
- new_instruction->value = result->value;
+ IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
+ copy_const_val(&new_instruction->value, result, true);
new_instruction->value.type = return_type;
return ir_finish_anal(ira, new_instruction);
}
@@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
first_var_arg, inst_fn_type_id.param_count);
ZigVar *var = add_variable(ira->codegen, param_decl_node,
- impl_fn->child_scope, param_name, true, var_args_val, nullptr);
+ impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type);
impl_fn->child_scope = var->child_scope;
}
if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
- IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
+ ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
- nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
+ nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
+ IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
+ impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
+ const_instruction->base.value = *align_result;
uint32_t align_bytes = 0;
- ir_resolve_align(ira, align_result, &align_bytes);
+ ir_resolve_align(ira, &const_instruction->base, &align_bytes);
impl_fn->align_bytes = align_bytes;
inst_fn_type_id.alignment = align_bytes;
}
@@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
ira->codegen->fn_defs.append(impl_fn);
}
- ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
- if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
+ FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
+ if (fn_type_can_fail(impl_fn_type_id)) {
parent_fn_entry->calls_or_awaits_errorable_fn = true;
}
- size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
+ size_t impl_param_count = impl_fn_type_id->param_count;
if (call_instruction->is_async) {
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
fn_ref, casted_args, impl_param_count, async_allocator_inst);
@@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
call_instruction->base.scope, call_instruction->base.source_node,
impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
call_instruction->is_async, nullptr, casted_new_stack);
- new_call_instruction->value.type = return_type;
+ new_call_instruction->value.type = impl_fn_type_id->return_type;
- ir_add_alloca(ira, new_call_instruction, return_type);
+ ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
return ir_finish_anal(ira, new_call_instruction);
}
@@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
// out_val->type must be the type to read the pointer as
// if the type is different than the actual type then it does a comptime byte reinterpretation
-static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
+static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val)
{
Error err;
assert(out_val->type != nullptr);
- ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val);
+ ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
- if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown)))
+ if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
return ErrorSemanticAnalyzeFail;
- if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown)))
+ if ((err = type_resolve(codegen, out_val->type, ResolveStatusSizeKnown)))
return ErrorSemanticAnalyzeFail;
- size_t src_size = type_size(ira->codegen, pointee->type);
- size_t dst_size = type_size(ira->codegen, out_val->type);
+ // We don't need to read the padding bytes, so we look at type_size_store bytes
+ size_t src_size = type_size_store(codegen, pointee->type);
+ size_t dst_size = type_size_store(codegen, out_val->type);
- if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
- copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
+ if (dst_size <= src_size) {
+ if (types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
+ copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
+ return ErrorNone;
+ }
+ Buf buf = BUF_INIT;
+ buf_resize(&buf, src_size);
+ buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
+ if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
+ return err;
return ErrorNone;
}
- if (dst_size > src_size) {
- ir_add_error_node(ira, source_node,
- buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
- dst_size, buf_ptr(&pointee->type->name), src_size));
- return ErrorSemanticAnalyzeFail;
+ switch (ptr_val->data.x_ptr.special) {
+ case ConstPtrSpecialInvalid:
+ zig_unreachable();
+ case ConstPtrSpecialNull:
+ if (dst_size == 0)
+ return ErrorNone;
+ opt_ir_add_error_node(ira, codegen, source_node,
+ buf_sprintf("attempt to read %zu bytes from null pointer",
+ dst_size));
+ return ErrorSemanticAnalyzeFail;
+ case ConstPtrSpecialRef: {
+ opt_ir_add_error_node(ira, codegen, source_node,
+ buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
+ dst_size, buf_ptr(&pointee->type->name), src_size));
+ return ErrorSemanticAnalyzeFail;
+ }
+ case ConstPtrSpecialBaseArray: {
+ ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
+ assert(array_val->type->id == ZigTypeIdArray);
+ if (array_val->data.x_array.special != ConstArraySpecialNone)
+ zig_panic("TODO");
+ size_t elem_size = src_size;
+ size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
+ src_size = elem_size * (array_val->type->data.array.len - elem_index);
+ if (dst_size > src_size) {
+ opt_ir_add_error_node(ira, codegen, source_node,
+ buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
+ dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
+ return ErrorSemanticAnalyzeFail;
+ }
+ size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
+ Buf buf = BUF_INIT;
+ buf_resize(&buf, elem_count * elem_size);
+ for (size_t i = 0; i < elem_count; i += 1) {
+ ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
+ buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
+ }
+ if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
+ return err;
+ return ErrorNone;
+ }
+ case ConstPtrSpecialBaseStruct:
+ case ConstPtrSpecialBaseErrorUnionCode:
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ case ConstPtrSpecialBaseOptionalPayload:
+ case ConstPtrSpecialDiscard:
+ case ConstPtrSpecialHardCodedAddr:
+ case ConstPtrSpecialFunction:
+ zig_panic("TODO");
}
-
- Buf buf = BUF_INIT;
- buf_resize(&buf, src_size);
- buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
- buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
- return ErrorNone;
+ zig_unreachable();
}
static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
@@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
+ case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
@@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
return ir_unreach_error(ira);
- if (is_comptime || instr_is_comptime(condition)) {
+ ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
+ IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
+ if (type_is_invalid(casted_condition->value.type))
+ return ir_unreach_error(ira);
+
+ if (is_comptime || instr_is_comptime(casted_condition)) {
bool cond_is_true;
- if (!ir_resolve_bool(ira, condition, &cond_is_true))
+ if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
return ir_unreach_error(ira);
IrBasicBlock *old_dest_block = cond_is_true ?
@@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
return ir_finish_anal(ira, result);
}
- ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
- IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
- if (casted_condition == ira->codegen->invalid_instruction)
- return ir_unreach_error(ira);
-
assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
if (new_then_block == nullptr)
@@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
if (value->value.special != ConstValSpecialRuntime) {
IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
- // TODO use copy_const_val?
- result->value = value->value;
+ copy_const_val(&result->value, &value->value, true);
return result;
} else {
return value;
@@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
if (type_is_invalid(resolved_type))
return ira->codegen->invalid_instruction;
- if (resolved_type->id == ZigTypeIdComptimeFloat ||
- resolved_type->id == ZigTypeIdComptimeInt ||
- resolved_type->id == ZigTypeIdNull ||
- resolved_type->id == ZigTypeIdUndefined)
- {
- ir_add_error_node(ira, phi_instruction->base.source_node,
- buf_sprintf("unable to infer expression type"));
+ switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
+ case OnePossibleValueInvalid:
return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const(ira, &phi_instruction->base, resolved_type);
+ case OnePossibleValueNo:
+ break;
+ }
+
+ switch (type_requires_comptime(ira->codegen, resolved_type)) {
+ case ReqCompTimeInvalid:
+ return ira->codegen->invalid_instruction;
+ case ReqCompTimeYes:
+ ir_add_error_node(ira, phi_instruction->base.source_node,
+ buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
+ return ira->codegen->invalid_instruction;
+ case ReqCompTimeNo:
+ break;
}
bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
@@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
array_type = array_type->data.pointer.child_type;
ptr_type = ptr_type->data.pointer.child_type;
if (orig_array_ptr_val->special != ConstValSpecialRuntime) {
- orig_array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
+ orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (orig_array_ptr_val == nullptr)
return ira->codegen->invalid_instruction;
@@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
if (!ptr_val)
return ira->codegen->invalid_instruction;
- ConstExprValue *args_val = ir_const_ptr_pointee(ira, ptr_val, elem_ptr_instruction->base.source_node);
+ ConstExprValue *args_val = const_ptr_pointee(ira, ira->codegen, ptr_val, elem_ptr_instruction->base.source_node);
if (args_val == nullptr)
return ira->codegen->invalid_instruction;
size_t start = args_val->data.x_arg_tuple.start_index;
@@ -14238,7 +14964,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
(orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar ||
array_type->id == ZigTypeIdArray))
{
- ConstExprValue *array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,
+ ConstExprValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
elem_ptr_instruction->base.source_node);
if (array_ptr_val == nullptr)
return ira->codegen->invalid_instruction;
@@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO elem ptr on a const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO elem ptr on a const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO elem ptr on a const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO element ptr of a function casted to a ptr");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO elem ptr on a null pointer");
}
if (new_index >= mem_size) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
@@ -14339,10 +15073,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO elem ptr on a slice backed by const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO elem ptr on a slice backed by const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO elem ptr on a slice backed by const optional payload");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO elem ptr on a slice has a null pointer");
}
return result;
} else if (array_type->id == ZigTypeIdArray) {
@@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *struct_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);
+ ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (struct_val == nullptr)
return ira->codegen->invalid_instruction;
if (type_is_invalid(struct_val->type))
return ira->codegen->invalid_instruction;
- ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
- ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
is_const, is_volatile, PtrLenSingle, align_bytes,
(uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
(uint32_t)host_int_bytes_for_result_type);
@@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
return ira->codegen->invalid_instruction;
if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- ConstExprValue *union_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);
+ ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
if (union_val == nullptr)
return ira->codegen->invalid_instruction;
if (type_is_invalid(union_val->type))
@@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
- ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
+ ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
if (child_val == nullptr)
return ira->codegen->invalid_instruction;
@@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
return ira->codegen->invalid_instruction;
assert(container_ptr->value.type->id == ZigTypeIdPointer);
- ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);
+ ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
if (child_val == nullptr)
return ira->codegen->invalid_instruction;
ZigType *child_type = child_val->data.x_type;
@@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (!container_ptr_val)
return ira->codegen->invalid_instruction;
- ConstExprValue *namespace_val = ir_const_ptr_pointee(ira, container_ptr_val,
+ ConstExprValue *namespace_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val,
field_ptr_instruction->base.source_node);
if (namespace_val == nullptr)
return ira->codegen->invalid_instruction;
@@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
}
}
-static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
- IrInstruction *ptr = load_ptr_instruction->ptr->child;
- if (type_is_invalid(ptr->value.type))
- return ira->codegen->invalid_instruction;
- return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
-}
-
-static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
- IrInstruction *ptr = store_ptr_instruction->ptr->child;
+static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
+ IrInstruction *ptr = instruction->ptr->child;
if (type_is_invalid(ptr->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *value = store_ptr_instruction->value->child;
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- if (ptr->value.type->id != ZigTypeIdPointer) {
- ir_add_error(ira, ptr,
- buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
+ return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
+}
+
+static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
+ IrInstruction *ptr = instruction->ptr->child;
+ if (type_is_invalid(ptr->value.type))
return ira->codegen->invalid_instruction;
- }
-
- if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
- return ir_const_void(ira, &store_ptr_instruction->base);
- }
-
- if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
- ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
- return ira->codegen->invalid_instruction;
- }
-
- ZigType *child_type = ptr->value.type->data.pointer.child_type;
- IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);
- if (casted_value == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
-
- if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
- ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
- return ira->codegen->invalid_instruction;
- }
- if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
- if (instr_is_comptime(casted_value)) {
- ConstExprValue *dest_val = ir_const_ptr_pointee(ira, &ptr->value, store_ptr_instruction->base.source_node);
- if (dest_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (dest_val->special != ConstValSpecialRuntime) {
- *dest_val = casted_value->value;
- if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
- ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
- }
- return ir_const_void(ira, &store_ptr_instruction->base);
- }
- }
- ir_add_error(ira, &store_ptr_instruction->base,
- buf_sprintf("cannot store runtime value in compile time variable"));
- ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
- dest_val->type = ira->codegen->builtin_types.entry_invalid;
-
- return ira->codegen->invalid_instruction;
- }
- }
-
- IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
- store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
- ptr, casted_value);
- result->value.type = ira->codegen->builtin_types.entry_void;
- return result;
+ return ir_get_deref(ira, &instruction->base, ptr);
}
static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
@@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
ZigType *type_entry = expr_value->value.type;
if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- switch (type_entry->id) {
- case ZigTypeIdInvalid:
- zig_unreachable(); // handled above
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- case ZigTypeIdNamespace:
- case ZigTypeIdBoundFn:
- case ZigTypeIdMetaType:
- case ZigTypeIdVoid:
- case ZigTypeIdBool:
- case ZigTypeIdUnreachable:
- case ZigTypeIdInt:
- case ZigTypeIdFloat:
- case ZigTypeIdPointer:
- case ZigTypeIdArray:
- case ZigTypeIdStruct:
- case ZigTypeIdOptional:
- case ZigTypeIdErrorUnion:
- case ZigTypeIdErrorSet:
- case ZigTypeIdEnum:
- case ZigTypeIdUnion:
- case ZigTypeIdFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdOpaque:
- case ZigTypeIdPromise:
- return ir_const_type(ira, &typeof_instruction->base, type_entry);
- }
-
- zig_unreachable();
+ return ir_const_type(ira, &typeof_instruction->base, type_entry);
}
static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
IrInstructionToPtrType *to_ptr_type_instruction)
{
+ Error err;
+
IrInstruction *value = to_ptr_type_instruction->value->child;
ZigType *type_entry = value->value.type;
if (type_is_invalid(type_entry))
@@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
ptr_type = get_pointer_to_type(ira->codegen,
type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
} else if (is_slice(type_entry)) {
- ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle);
+ ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
+ ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
+ // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
+ if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
+ ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
+ return ira->codegen->invalid_instruction;
+ uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
+ uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
+ ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
+ }
} else if (type_entry->id == ZigTypeIdArgTuple) {
ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
if (!arg_tuple_val)
@@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
{
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
@@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdNamespace:
case ZigTypeIdBoundFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
{
if ((err = ensure_complete_type(ira->codegen, child_type)))
return ira->codegen->invalid_instruction;
@@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdPromise:
+ case ZigTypeIdVector:
{
uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
@@ -15568,11 +16243,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
- return ira->codegen->invalid_instruction;
-
+static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
ZigType *type_entry = value->value.type;
if (type_entry->id == ZigTypeIdOptional) {
@@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
if (!maybe_val)
return ira->codegen->invalid_instruction;
- return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));
+ return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
}
IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value);
+ source_inst->scope, source_inst->source_node, value);
result->value.type = ira->codegen->builtin_types.entry_bool;
return result;
} else if (type_entry->id == ZigTypeIdNull) {
- return ir_const_bool(ira, &instruction->base, false);
+ return ir_const_bool(ira, source_inst, false);
} else {
- return ir_const_bool(ira, &instruction->base, true);
+ return ir_const_bool(ira, source_inst, true);
}
}
-static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
- IrInstructionUnwrapOptional *unwrap_maybe_instruction)
-{
- IrInstruction *value = unwrap_maybe_instruction->value->child;
+static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
+ IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- ZigType *ptr_type = value->value.type;
+ return ir_analyze_test_non_null(ira, &instruction->base, value);
+}
+
+static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *base_ptr, bool safety_check_on)
+{
+ ZigType *ptr_type = base_ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *type_entry = ptr_type->data.pointer.child_type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id != ZigTypeIdOptional) {
- ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
+
+ if (type_entry->id != ZigTypeIdOptional) {
+ ir_add_error_node(ira, base_ptr->source_node,
buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
+
ZigType *child_type = type_entry->data.maybe.child_type;
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
- if (instr_is_comptime(value)) {
- ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+ if (instr_is_comptime(base_ptr)) {
+ ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- ConstExprValue *maybe_val = ir_const_ptr_pointee(ira, val, unwrap_maybe_instruction->base.source_node);
+ ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
if (maybe_val == nullptr)
return ira->codegen->invalid_instruction;
if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
if (optional_value_is_null(maybe_val)) {
- ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));
+ ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);
+ IrInstruction *result = ir_const(ira, source_instr, result_type);
ConstExprValue *out_val = &result->value;
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.mut = val->data.x_ptr.mut;
- if (type_is_codegen_pointer(child_type)) {
+ if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
out_val->data.x_ptr.data.ref.pointee = maybe_val;
} else {
out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
@@ -15643,13 +16320,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
}
}
- IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,
- unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,
- value, unwrap_maybe_instruction->safety_check_on);
+ IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, base_ptr, safety_check_on);
result->value.type = result_type;
return result;
}
+static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
+ IrInstructionOptionalUnwrapPtr *instruction)
+{
+ IrInstruction *base_ptr = instruction->base_ptr->child;
+ if (type_is_invalid(base_ptr->value.type))
+ return ira->codegen->invalid_instruction;
+
+ return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
+}
+
static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
IrInstruction *value = ctz_instruction->value->child;
if (type_is_invalid(value->value.type)) {
@@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
ConstExprValue *pointee_val = nullptr;
if (instr_is_comptime(target_value_ptr)) {
- pointee_val = ir_const_ptr_pointee(ira, &target_value_ptr->value, target_value_ptr->source_node);
+ pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
if (pointee_val == nullptr)
return ira->codegen->invalid_instruction;
-
+
if (pointee_val->special == ConstValSpecialRuntime)
pointee_val = nullptr;
}
@@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
- switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
- target_value_ptr);
+ IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
result->value.type = target_type;
return result;
}
@@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
- switch_target_instruction->base.source_node, target_value_ptr);
+ IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
union_value->value.type = target_type;
IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
@@ -16007,8 +16690,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return result;
}
- IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
- switch_target_instruction->base.source_node, target_value_ptr);
+ IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
enum_value->value.type = target_type;
return enum_value;
}
@@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
+ case ZigTypeIdVector:
ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
return ira->codegen->invalid_instruction;
@@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
if (!target_value_ptr)
return ira->codegen->invalid_instruction;
- ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, target_val_ptr, instruction->base.source_node);
+ ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.source_node);
if (pointee_val == nullptr)
return ira->codegen->invalid_instruction;
@@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
Error err;
assert(container_type->id == ZigTypeIdUnion);
- if ((err = ensure_complete_type(ira->codegen, container_type)))
+ if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
if (instr_field_count != 1) {
@@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
+ bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
+ || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
!type_has_bits(casted_field_value->value.type))
{
@@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
ConstExprValue *out_val = &result->value;
out_val->data.x_union.payload = field_val;
out_val->data.x_union.tag = type_field->enum_field->value;
-
- ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdUnion;
- parent->data.p_union.union_val = out_val;
- }
+ out_val->parent.id = ConstParentIdUnion;
+ out_val->parent.data.p_union.union_val = out_val;
return result;
}
@@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
return ira->codegen->invalid_instruction;
}
- if ((err = ensure_complete_type(ira->codegen, container_type)))
+ if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
size_t actual_field_count = container_type->data.structure.src_field_count;
@@ -16252,7 +16932,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
IrInstructionStructInitField *new_fields = allocate(actual_field_count);
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
+ bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
+ || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
ConstExprValue const_val = {};
const_val.special = ConstValSpecialStatic;
@@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
if (const_val.special == ConstValSpecialStatic) {
IrInstruction *result = ir_const(ira, instruction, nullptr);
ConstExprValue *out_val = &result->value;
- // TODO copy_const_val?
- *out_val = const_val;
- result->value.type = container_type;
+ copy_const_val(out_val, &const_val, true);
+ out_val->type = container_type;
for (size_t i = 0; i < instr_field_count; i += 1) {
ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
@@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstructionContainerInitList *instruction)
{
- IrInstruction *container_type_value = instruction->container_type->child;
- if (type_is_invalid(container_type_value->value.type))
+ ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
+ if (type_is_invalid(container_type))
return ira->codegen->invalid_instruction;
size_t elem_count = instruction->item_count;
- if (container_type_value->value.type->id == ZigTypeIdMetaType) {
- ZigType *container_type = ir_resolve_type(ira, container_type_value);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_instruction;
- if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
- return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
- 0, nullptr);
- } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
- // array is same as slice init but we make a compile error if the length is wrong
- ZigType *child_type;
- if (container_type->id == ZigTypeIdArray) {
- child_type = container_type->data.array.child_type;
- if (container_type->data.array.len != elem_count) {
- ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
+ if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
+ return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
+ 0, nullptr);
+ } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
+ // array is same as slice init but we make a compile error if the length is wrong
+ ZigType *child_type;
+ if (container_type->id == ZigTypeIdArray) {
+ child_type = container_type->data.array.child_type;
+ if (container_type->data.array.len != elem_count) {
+ ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
- ir_add_error(ira, &instruction->base,
- buf_sprintf("expected %s literal, found %s literal",
- buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
- return ira->codegen->invalid_instruction;
- }
- } else {
- ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
- assert(pointer_type->id == ZigTypeIdPointer);
- child_type = pointer_type->data.pointer.child_type;
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("expected %s literal, found %s literal",
+ buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
+ return ira->codegen->invalid_instruction;
}
+ } else {
+ ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
+ assert(pointer_type->id == ZigTypeIdPointer);
+ child_type = pointer_type->data.pointer.child_type;
+ }
- ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
+ ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
- ConstExprValue const_val = {};
- const_val.special = ConstValSpecialStatic;
- const_val.type = fixed_size_array_type;
- const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
+ ConstExprValue const_val = {};
+ const_val.special = ConstValSpecialStatic;
+ const_val.type = fixed_size_array_type;
+ const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
- bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
+ bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
- IrInstruction **new_items = allocate(elem_count);
+ IrInstruction **new_items = allocate(elem_count);
- IrInstruction *first_non_const_instruction = nullptr;
+ IrInstruction *first_non_const_instruction = nullptr;
- for (size_t i = 0; i < elem_count; i += 1) {
- IrInstruction *arg_value = instruction->items[i]->child;
- if (type_is_invalid(arg_value->value.type))
- return ira->codegen->invalid_instruction;
+ for (size_t i = 0; i < elem_count; i += 1) {
+ IrInstruction *arg_value = instruction->items[i]->child;
+ if (type_is_invalid(arg_value->value.type))
+ return ira->codegen->invalid_instruction;
- IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
- if (casted_arg == ira->codegen->invalid_instruction)
- return ira->codegen->invalid_instruction;
+ IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
+ if (casted_arg == ira->codegen->invalid_instruction)
+ return ira->codegen->invalid_instruction;
- new_items[i] = casted_arg;
-
- if (const_val.special == ConstValSpecialStatic) {
- if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
- ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
- if (!elem_val)
- return ira->codegen->invalid_instruction;
-
- copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
- } else {
- first_non_const_instruction = casted_arg;
- const_val.special = ConstValSpecialRuntime;
- }
- }
- }
+ new_items[i] = casted_arg;
if (const_val.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
- ConstExprValue *out_val = &result->value;
- // TODO copy_const_val?
- *out_val = const_val;
- result->value.type = fixed_size_array_type;
- for (size_t i = 0; i < elem_count; i += 1) {
- ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
- ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
- if (parent != nullptr) {
- parent->id = ConstParentIdArray;
- parent->data.p_array.array_val = out_val;
- parent->data.p_array.elem_index = i;
- }
+ if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
+ ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
+ if (!elem_val)
+ return ira->codegen->invalid_instruction;
+
+ copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
+ } else {
+ first_non_const_instruction = casted_arg;
+ const_val.special = ConstValSpecialRuntime;
}
- return result;
}
+ }
- if (is_comptime) {
- ir_add_error_node(ira, first_non_const_instruction->source_node,
- buf_sprintf("unable to evaluate constant expression"));
- return ira->codegen->invalid_instruction;
+ if (const_val.special == ConstValSpecialStatic) {
+ IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
+ ConstExprValue *out_val = &result->value;
+ copy_const_val(out_val, &const_val, true);
+ result->value.type = fixed_size_array_type;
+ for (size_t i = 0; i < elem_count; i += 1) {
+ ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
+ ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
+ if (parent != nullptr) {
+ parent->id = ConstParentIdArray;
+ parent->data.p_array.array_val = out_val;
+ parent->data.p_array.elem_index = i;
+ }
}
+ return result;
+ }
- IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node,
- container_type_value, elem_count, new_items);
- new_instruction->value.type = fixed_size_array_type;
- ir_add_alloca(ira, new_instruction, fixed_size_array_type);
- return new_instruction;
- } else if (container_type->id == ZigTypeIdVoid) {
- if (elem_count != 0) {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("void expression expects no arguments"));
- return ira->codegen->invalid_instruction;
- }
- return ir_const_void(ira, &instruction->base);
- } else {
- ir_add_error_node(ira, instruction->base.source_node,
- buf_sprintf("type '%s' does not support array initialization",
- buf_ptr(&container_type->name)));
+ if (is_comptime) {
+ ir_add_error_node(ira, first_non_const_instruction->source_node,
+ buf_sprintf("unable to evaluate constant expression"));
return ira->codegen->invalid_instruction;
}
+
+ IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
+ nullptr, elem_count, new_items);
+ new_instruction->value.type = fixed_size_array_type;
+ ir_add_alloca(ira, new_instruction, fixed_size_array_type);
+ return new_instruction;
+ } else if (container_type->id == ZigTypeIdVoid) {
+ if (elem_count != 0) {
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("void expression expects no arguments"));
+ return ira->codegen->invalid_instruction;
+ }
+ return ir_const_void(ira, &instruction->base);
} else {
- ir_add_error(ira, container_type_value,
- buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
+ ir_add_error_node(ira, instruction->base.source_node,
+ buf_sprintf("type '%s' does not support array initialization",
+ buf_ptr(&container_type->name)));
return ira->codegen->invalid_instruction;
}
}
-static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {
+static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
+ IrInstructionContainerInitFields *instruction)
+{
IrInstruction *container_type_value = instruction->container_type->child;
ZigType *container_type = ir_resolve_type(ira, container_type_value);
if (type_is_invalid(container_type))
@@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
if (type_is_invalid(value->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);
+ IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
if (type_is_invalid(casted_value->value.type))
return ira->codegen->invalid_instruction;
@@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
static TypeStructField *validate_byte_offset(IrAnalyze *ira,
IrInstruction *type_value,
IrInstruction *field_name_value,
- size_t *byte_offset)
+ size_t *byte_offset)
{
ZigType *container_type = ir_resolve_type(ira, type_value);
if (type_is_invalid(container_type))
@@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
Error err;
- static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review
- static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review
- if (type_info_var == nullptr) {
- type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
- assert(type_info_var->type->id == ZigTypeIdMetaType);
+ ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
+ assert(type_info_var->type->id == ZigTypeIdMetaType);
+ assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
- assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
- type_info_type = type_info_var->data.x_type;
- assert(type_info_type->id == ZigTypeIdUnion);
- }
+ ZigType *type_info_type = type_info_var->data.x_type;
+ assert(type_info_type->id == ZigTypeIdUnion);
if (type_name == nullptr && root == nullptr)
return type_info_type;
@@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
ZigVar *var = tld->var;
- if ((err = ensure_complete_type(ira->codegen, var->value->type)))
+ if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
return ira->codegen->builtin_types.entry_invalid;
- assert(var->value->type->id == ZigTypeIdMetaType);
- return var->value->data.x_type;
+
+ assert(var->const_value->type->id == ZigTypeIdMetaType);
+ return var->const_value->data.x_type;
}
static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
@@ -16857,13 +17526,12 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
definition_array->special = ConstValSpecialStatic;
definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
definition_array->data.x_array.special = ConstArraySpecialNone;
- definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
// Loop through the definitions and generate info.
decl_it = decls_scope->decl_table.entry_iterator();
- curr_entry = nullptr;
+ curr_entry = nullptr;
int definition_index = 0;
while ((curr_entry = decl_it.next()) != nullptr) {
// Skip comptime blocks and test functions.
@@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
inner_fields[2].special = ConstValSpecialStatic;
inner_fields[2].type = type_info_definition_data_type;
- inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;
- inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
- inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
+ inner_fields[2].parent.id = ConstParentIdStruct;
+ inner_fields[2].parent.data.p_struct.struct_val = definition_val;
+ inner_fields[2].parent.data.p_struct.field_index = 1;
switch (curr_entry->value->id) {
case TldIdVar:
{
ZigVar *var = ((TldVar *)curr_entry->value)->var;
- if ((err = ensure_complete_type(ira->codegen, var->value->type)))
+ if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
return ErrorSemanticAnalyzeFail;
- if (var->value->type->id == ZigTypeIdMetaType)
- {
+ if (var->const_value->type->id == ZigTypeIdMetaType) {
// We have a variable of type 'type', so it's actually a type definition.
// 0: Data.Type: type
bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
- inner_fields[2].data.x_union.payload = var->value;
- }
- else
- {
+ inner_fields[2].data.x_union.payload = var->const_value;
+ } else {
// We have a variable of another type, so we store the type of the variable.
// 1: Data.Var: type
bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
ConstExprValue *payload = create_const_vals(1);
payload->type = ira->codegen->builtin_types.entry_type;
- payload->data.x_type = var->value->type;
+ payload->data.x_type = var->const_value->type;
inner_fields[2].data.x_union.payload = payload;
}
@@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
ConstExprValue *fn_def_val = create_const_vals(1);
fn_def_val->special = ConstValSpecialStatic;
fn_def_val->type = type_info_fn_def_type;
- fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;
- fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];
+ fn_def_val->parent.id = ConstParentIdUnion;
+ fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
ConstExprValue *fn_def_fields = create_const_vals(9);
fn_def_val->data.x_struct.fields = fn_def_fields;
@@ -16990,12 +17655,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
ensure_field_index(fn_def_val->type, "return_type", 7);
fn_def_fields[7].special = ConstValSpecialStatic;
fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
- if (fn_entry->src_implicit_return_type != nullptr)
- fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type;
- else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr)
- fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type;
- else
- fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
+ fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
// arg_names: [][] const u8
ensure_field_index(fn_def_val->type, "arg_names", 8);
size_t fn_arg_count = fn_entry->variable_list.length;
@@ -17004,20 +17664,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
fn_arg_name_array->type = get_array_type(ira->codegen,
get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
- fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
- for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)
- {
+ for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
- fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;
- fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;
- fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
+ fn_arg_name_val->parent.id = ConstParentIdArray;
+ fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
+ fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
}
inner_fields[2].data.x_union.payload = fn_def_val;
@@ -17052,6 +17710,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
return ErrorNone;
}
+static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return 0;
+ case PtrLenUnknown:
+ return 1;
+ case PtrLenC:
+ return 3;
+ }
+ zig_unreachable();
+}
+
static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
Error err;
ZigType *attrs_type;
@@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
size_enum_index = 2;
} else if (ptr_type_entry->id == ZigTypeIdPointer) {
attrs_type = ptr_type_entry;
- size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1;
+ size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
} else {
zig_unreachable();
}
@@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
enum_field_val->data.x_struct.fields = inner_fields;
}
-static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstExprValue **out) {
+static Error ir_make_type_info_value(IrAnalyze *ira, AstNode *source_node, ZigType *type_entry, ConstExprValue **out) {
Error err;
assert(type_entry != nullptr);
assert(!type_is_invalid(type_entry));
- if ((err = ensure_complete_type(ira->codegen, type_entry)))
+ if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
return err;
- if (type_entry == ira->codegen->builtin_types.entry_global_error_set) {
- zig_panic("TODO implement @typeInfo for global error set");
- }
-
ConstExprValue *result = nullptr;
- switch (type_entry->id)
- {
+ switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdMetaType:
@@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
break;
}
+ case ZigTypeIdVector: {
+ result = create_const_vals(1);
+ result->special = ConstValSpecialStatic;
+ result->type = ir_type_info_get_type(ira, "Vector", nullptr);
+
+ ConstExprValue *fields = create_const_vals(2);
+ result->data.x_struct.fields = fields;
+
+ // len: usize
+ ensure_field_index(result->type, "len", 0);
+ fields[0].special = ConstValSpecialStatic;
+ fields[0].type = ira->codegen->builtin_types.entry_u32;
+ bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len);
+ // child: type
+ ensure_field_index(result->type, "child", 1);
+ fields[1].special = ConstValSpecialStatic;
+ fields[1].type = ira->codegen->builtin_types.entry_type;
+ fields[1].data.x_type = type_entry->data.vector.elem_type;
+
+ break;
+ }
case ZigTypeIdOptional:
{
result = create_const_vals(1);
@@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
enum_field_array->special = ConstValSpecialStatic;
enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
enum_field_array->data.x_array.special = ConstArraySpecialNone;
- enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
@@ -17320,9 +18005,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
- enum_field_val->data.x_struct.parent.id = ConstParentIdArray;
- enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;
- enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;
+ enum_field_val->parent.id = ConstParentIdArray;
+ enum_field_val->parent.data.p_array.array_val = enum_field_array;
+ enum_field_val->parent.data.p_array.elem_index = enum_field_index;
}
// defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 3);
@@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
ensure_field_index(result->type, "errors", 0);
ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr);
+ if (!resolve_inferred_error_set(ira->codegen, type_entry, source_node)) {
+ return ErrorSemanticAnalyzeFail;
+ }
+ if (type_is_global_error_set(type_entry)) {
+ ir_add_error_node(ira, source_node,
+ buf_sprintf("TODO: compiler bug: implement @typeInfo support for anyerror. https://github.com/ziglang/zig/issues/1936"));
+ return ErrorSemanticAnalyzeFail;
+ }
+
uint32_t error_count = type_entry->data.error_set.err_count;
ConstExprValue *error_array = create_const_vals(1);
error_array->special = ConstValSpecialStatic;
error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
error_array->data.x_array.special = ConstArraySpecialNone;
- error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
@@ -17373,9 +18066,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
error_val->data.x_struct.fields = inner_fields;
- error_val->data.x_struct.parent.id = ConstParentIdArray;
- error_val->data.x_struct.parent.data.p_array.array_val = error_array;
- error_val->data.x_struct.parent.data.p_array.elem_index = error_index;
+ error_val->parent.id = ConstParentIdArray;
+ error_val->parent.data.p_array.array_val = error_array;
+ error_val->parent.data.p_array.elem_index = error_index;
}
break;
@@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
union_field_array->special = ConstValSpecialStatic;
union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
union_field_array->data.x_array.special = ConstArraySpecialNone;
- union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
@@ -17477,9 +18169,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
union_field_val->data.x_struct.fields = inner_fields;
- union_field_val->data.x_struct.parent.id = ConstParentIdArray;
- union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;
- union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;
+ union_field_val->parent.id = ConstParentIdArray;
+ union_field_val->parent.data.p_array.array_val = union_field_array;
+ union_field_val->parent.data.p_array.elem_index = union_field_index;
}
// defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 3);
@@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
struct_field_array->special = ConstValSpecialStatic;
struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
struct_field_array->data.x_array.special = ConstArraySpecialNone;
- struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
@@ -17553,9 +18244,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
struct_field_val->data.x_struct.fields = inner_fields;
- struct_field_val->data.x_struct.parent.id = ConstParentIdArray;
- struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;
- struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;
+ struct_field_val->parent.id = ConstParentIdArray;
+ struct_field_val->parent.data.p_array.array_val = struct_field_array;
+ struct_field_val->parent.data.p_array.elem_index = struct_field_index;
}
// defs: []TypeInfo.Definition
ensure_field_index(result->type, "defs", 2);
@@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
fn_arg_array->special = ConstValSpecialStatic;
fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
fn_arg_array->data.x_array.special = ConstArraySpecialNone;
- fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
@@ -17662,9 +18352,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
}
fn_arg_val->data.x_struct.fields = inner_fields;
- fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
- fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;
- fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;
+ fn_arg_val->parent.id = ConstParentIdArray;
+ fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
+ fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
}
break;
@@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
{
ZigType *fn_type = type_entry->data.bound_fn.fn_type;
assert(fn_type->id == ZigTypeIdFn);
- if ((err = ir_make_type_info_value(ira, fn_type, &result)))
+ if ((err = ir_make_type_info_value(ira, source_node, fn_type, &result)))
return err;
break;
@@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
ConstExprValue *payload;
- if ((err = ir_make_type_info_value(ira, type_entry, &payload)))
+ if ((err = ir_make_type_info_value(ira, instruction->base.source_node, type_entry, &payload)))
return ira->codegen->invalid_instruction;
IrInstruction *result = ir_const(ira, &instruction->base, result_type);
@@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
if (payload != nullptr) {
assert(payload->type->id == ZigTypeIdStruct);
- payload->data.x_struct.parent.id = ConstParentIdUnion;
- payload->data.x_struct.parent.data.p_union.union_val = out_val;
+ payload->parent.id = ConstParentIdUnion;
+ payload->parent.data.p_union.union_val = out_val;
}
return result;
@@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
IrInstructionSetEvalBranchQuota *instruction)
{
- if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) {
- ir_add_error(ira, &instruction->base,
- buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack"));
- return ira->codegen->invalid_instruction;
- }
-
uint64_t new_quota;
if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
return ira->codegen->invalid_instruction;
@@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
// Execute the C import block like an inline function
ZigType *void_type = ira->codegen->builtin_types.entry_void;
- IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
+ ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
- &cimport_scope->buf, block_node, nullptr, nullptr);
- if (type_is_invalid(cimport_result->value.type))
+ &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
+ if (type_is_invalid(cimport_result->type))
return ira->codegen->invalid_instruction;
find_libc_include_path(ira->codegen);
@@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
return result;
}
-static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
+static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
if (type_is_invalid(operand_type))
return ira->codegen->invalid_instruction;
@@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
zig_panic("TODO compile-time execution of cmpxchg");
}
- IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
- nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,
- operand_type, success_order, failure_order);
+ IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
+ casted_ptr, casted_cmp_value, casted_new_value,
+ success_order, failure_order, instruction->is_weak);
result->value.type = get_optional_type(ira->codegen, operand_type);
ir_add_alloca(ira, result, result->value.type);
return result;
@@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
}
+ if (dest_type->id == ZigTypeIdComptimeInt) {
+ return ir_implicit_cast(ira, target, dest_type);
+ }
+
+ if (instr_is_comptime(target)) {
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ if (val == nullptr)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
+ bigint_truncate(&result->value.data.x_bigint, &val->data.x_bigint,
+ dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
+ return result;
+ }
+
+ if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) {
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
+ return result;
+ }
+
if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
@@ -18064,13 +18769,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
}
- if (target->value.special == ConstValSpecialStatic) {
- IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
- bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint,
- dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
- return result;
- }
-
IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, dest_type_value, target);
new_instruction->value.type = dest_type;
@@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
}
-static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
- Error err;
-
- if (ty->id == ZigTypeIdPointer) {
- if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
- return err;
- }
-
- *result_align = get_ptr_align(ira->codegen, ty);
- return ErrorNone;
-}
-
static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
Error err;
@@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
}
+static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
+ Error err;
+
+ ZigType *ptr_type = get_src_ptr_type(ty);
+ assert(ptr_type != nullptr);
+ if (ptr_type->id == ZigTypeIdPointer) {
+ if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
+ return err;
+ }
+
+ *result_align = get_ptr_align(ira->codegen, ty);
+ return ErrorNone;
+}
+
static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
if (type_is_invalid(dest_type))
@@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
}
+static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) {
+ uint64_t len;
+ if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
+ return ira->codegen->invalid_instruction;
+
+ ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
+ if (type_is_invalid(elem_type))
+ return ira->codegen->invalid_instruction;
+
+ if (!is_valid_vector_elem_type(elem_type)) {
+ ir_add_error(ira, instruction->elem_type,
+ buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
+ buf_ptr(&elem_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
+
+ return ir_const_type(ira, &instruction->base, vector_type);
+}
+
static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
IrInstruction *value = instruction->value->child;
if (type_is_invalid(value->value.type))
@@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO memset on const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO memset on const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO memset on const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO memset on const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO memset on ptr cast from function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO memset on null ptr");
}
size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
@@ -18623,10 +19352,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO memcpy on const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO memcpy on const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO memcpy on const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO memcpy on const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO memcpy on ptr cast from function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO memcpy on null ptr");
}
if (dest_start + count > dest_end) {
@@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
}
case ConstPtrSpecialBaseStruct:
zig_panic("TODO memcpy on const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO memcpy on const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO memcpy on const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO memcpy on const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
zig_unreachable();
case ConstPtrSpecialFunction:
zig_panic("TODO memcpy on ptr cast from function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO memcpy on null ptr");
}
if (src_start + count > src_end) {
@@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
if (type_is_invalid(ptr_ptr->value.type))
return ira->codegen->invalid_instruction;
- ZigType *ptr_type = ptr_ptr->value.type;
- assert(ptr_type->id == ZigTypeIdPointer);
- ZigType *array_type = ptr_type->data.pointer.child_type;
+ ZigType *ptr_ptr_type = ptr_ptr->value.type;
+ assert(ptr_ptr_type->id == ZigTypeIdPointer);
+ ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
IrInstruction *start = instruction->start->child;
if (type_is_invalid(start->value.type))
@@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
- ptr_type->data.pointer.is_const || is_comptime_const,
- ptr_type->data.pointer.is_volatile,
+ ptr_ptr_type->data.pointer.is_const || is_comptime_const,
+ ptr_ptr_type->data.pointer.is_volatile,
PtrLenUnknown,
- ptr_type->data.pointer.explicit_alignment, 0, 0);
+ ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
} else if (array_type->id == ZigTypeIdPointer) {
if (array_type->data.pointer.ptr_len == PtrLenSingle) {
@@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
if (array_type->id == ZigTypeIdPointer) {
ZigType *child_array_type = array_type->data.pointer.child_type;
assert(child_array_type->id == ZigTypeIdArray);
- parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
+ parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
return ira->codegen->invalid_instruction;
- array_val = ir_const_ptr_pointee(ira, parent_ptr, instruction->base.source_node);
+ array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node);
if (array_val == nullptr)
return ira->codegen->invalid_instruction;
rel_end = child_array_type->data.array.len;
abs_offset = 0;
} else {
- array_val = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
+ array_val = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
if (array_val == nullptr)
return ira->codegen->invalid_instruction;
rel_end = array_type->data.array.len;
@@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
}
} else if (array_type->id == ZigTypeIdPointer) {
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
- parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
+ parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
if (parent_ptr == nullptr)
return ira->codegen->invalid_instruction;
@@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
break;
case ConstPtrSpecialBaseStruct:
zig_panic("TODO slice const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO slice const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO slice const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO slice const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
array_val = nullptr;
abs_offset = 0;
@@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
break;
case ConstPtrSpecialFunction:
zig_panic("TODO slice of ptr cast from function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO slice of null ptr");
}
} else if (is_slice(array_type)) {
- ConstExprValue *slice_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);
+ ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
if (slice_ptr == nullptr)
return ira->codegen->invalid_instruction;
@@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
break;
case ConstPtrSpecialBaseStruct:
zig_panic("TODO slice const inner struct");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO slice const inner error union code");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO slice const inner error union payload");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO slice const inner optional payload");
case ConstPtrSpecialHardCodedAddr:
array_val = nullptr;
abs_offset = 0;
@@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
break;
case ConstPtrSpecialFunction:
zig_panic("TODO slice of slice cast from function");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO slice of null");
}
} else {
zig_unreachable();
@@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
zig_unreachable();
case ConstPtrSpecialBaseStruct:
zig_panic("TODO");
+ case ConstPtrSpecialBaseErrorUnionCode:
+ zig_panic("TODO");
+ case ConstPtrSpecialBaseErrorUnionPayload:
+ zig_panic("TODO");
+ case ConstPtrSpecialBaseOptionalPayload:
+ zig_panic("TODO");
case ConstPtrSpecialHardCodedAddr:
init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
parent_ptr->type->data.pointer.child_type,
@@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
break;
case ConstPtrSpecialFunction:
zig_panic("TODO");
+ case ConstPtrSpecialNull:
+ zig_panic("TODO");
}
ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
@@ -19165,6 +19934,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
case ZigTypeIdEnum:
case ZigTypeIdUnion:
case ZigTypeIdFn:
+ case ZigTypeIdVector:
{
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
@@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
{
BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
- ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, &casted_result_ptr->value, casted_result_ptr->source_node);
+ ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, &casted_result_ptr->value, casted_result_ptr->source_node);
if (pointee_val == nullptr)
return ira->codegen->invalid_instruction;
BigInt *dest_bigint = &pointee_val->data.x_bigint;
@@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
if (err_union_val->special != ConstValSpecialRuntime) {
- return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));
+ ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
+ return ir_const_bool(ira, &instruction->base, (err != nullptr));
}
}
@@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
}
}
-static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
- IrInstructionUnwrapErrCode *instruction)
-{
- IrInstruction *value = instruction->value->child;
- if (type_is_invalid(value->value.type))
+static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
+ IrInstruction *base_ptr = instruction->err_union->child;
+ if (type_is_invalid(base_ptr->value.type))
return ira->codegen->invalid_instruction;
- ZigType *ptr_type = value->value.type;
+ ZigType *ptr_type = base_ptr->value.type;
// This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *type_entry = ptr_type->data.pointer.child_type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdErrorUnion) {
- if (instr_is_comptime(value)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
- if (!ptr_val)
- return ira->codegen->invalid_instruction;
- ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
- if (err_union_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (err_union_val->special != ConstValSpecialRuntime) {
- ErrorTableEntry *err = err_union_val->data.x_err_union.err;
- assert(err);
- IrInstruction *result = ir_const(ira, &instruction->base,
- type_entry->data.error_union.err_set_type);
- result->value.data.x_err_set = err;
- return result;
- }
- }
-
- IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value);
- result->value.type = type_entry->data.error_union.err_set_type;
- return result;
- } else {
- ir_add_error(ira, value,
+ if (type_entry->id != ZigTypeIdErrorUnion) {
+ ir_add_error(ira, base_ptr,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
+
+ if (instr_is_comptime(base_ptr)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->invalid_instruction;
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ if (err_union_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (err_union_val->special != ConstValSpecialRuntime) {
+ ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
+ assert(err);
+
+ IrInstruction *result = ir_const(ira, &instruction->base,
+ type_entry->data.error_union.err_set_type);
+ result->value.data.x_err_set = err;
+ return result;
+ }
+ }
+
+ IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, base_ptr);
+ result->value.type = type_entry->data.error_union.err_set_type;
+ return result;
}
static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
@@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
assert(ptr_type->id == ZigTypeIdPointer);
ZigType *type_entry = ptr_type->data.pointer.child_type;
- if (type_is_invalid(type_entry)) {
+ if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
- } else if (type_entry->id == ZigTypeIdErrorUnion) {
- ZigType *payload_type = type_entry->data.error_union.payload_type;
- if (type_is_invalid(payload_type)) {
- return ira->codegen->invalid_instruction;
- }
- ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
- ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
- PtrLenSingle, 0, 0, 0);
- if (instr_is_comptime(value)) {
- ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
- if (!ptr_val)
- return ira->codegen->invalid_instruction;
- ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
- if (err_union_val == nullptr)
- return ira->codegen->invalid_instruction;
- if (err_union_val->special != ConstValSpecialRuntime) {
- ErrorTableEntry *err = err_union_val->data.x_err_union.err;
- if (err != nullptr) {
- ir_add_error(ira, &instruction->base,
- buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
- return ira->codegen->invalid_instruction;
- }
- IrInstruction *result = ir_const(ira, &instruction->base, result_type);
- result->value.data.x_ptr.special = ConstPtrSpecialRef;
- result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
- return result;
- }
- }
-
- IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
- result->value.type = result_type;
- return result;
- } else {
+ if (type_entry->id != ZigTypeIdErrorUnion) {
ir_add_error(ira, value,
buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
+ ZigType *payload_type = type_entry->data.error_union.payload_type;
+ if (type_is_invalid(payload_type))
+ return ira->codegen->invalid_instruction;
+
+ ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
+ ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
+ PtrLenSingle, 0, 0, 0);
+ if (instr_is_comptime(value)) {
+ ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
+ if (!ptr_val)
+ return ira->codegen->invalid_instruction;
+ ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
+ if (err_union_val == nullptr)
+ return ira->codegen->invalid_instruction;
+ if (err_union_val->special != ConstValSpecialRuntime) {
+ ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
+ if (err != nullptr) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *result = ir_const(ira, &instruction->base, result_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialRef;
+ result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
+ return result;
+ }
+ }
+
+ IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
+ result->value.type = result_type;
+ return result;
}
static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
@@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
return ira->codegen->invalid_instruction;
}
}
+ } else if (switch_type->id == ZigTypeIdBool) {
+ int seenTrue = 0;
+ int seenFalse = 0;
+ for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
+ IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
+
+ IrInstruction *value = range->start->child;
+
+ IrInstruction *casted_value = ir_implicit_cast(ira, value, switch_type);
+ if (type_is_invalid(casted_value->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ConstExprValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
+ if (!const_expr_val)
+ return ira->codegen->invalid_instruction;
+
+ assert(const_expr_val->type->id == ZigTypeIdBool);
+
+ if (const_expr_val->data.x_bool == true) {
+ seenTrue += 1;
+ } else {
+ seenFalse += 1;
+ }
+
+ if ((seenTrue > 1) || (seenFalse > 1)) {
+ ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
+ return ira->codegen->invalid_instruction;
+ }
+ }
+ if (((seenTrue < 1) || (seenFalse < 1)) && !instruction->have_else_prong) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));
+ return ira->codegen->invalid_instruction;
+ }
} else if (!instruction->have_else_prong) {
ir_add_error(ira, &instruction->base,
buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
@@ -19802,7 +20605,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
return ira->codegen->invalid_instruction;
}
- IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);
+ IrInstruction *result = ir_const(ira, target, result_type);
copy_const_val(&result->value, val, false);
result->value.type = result_type;
return result;
@@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
}
static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
- ZigType *dest_type, IrInstruction *dest_type_src)
+ ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on)
{
Error err;
@@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
// We have a check for zero bits later so we use get_src_ptr_type to
// validate src_type and dest_type.
- if (get_src_ptr_type(src_type) == nullptr) {
+ ZigType *src_ptr_type = get_src_ptr_type(src_type);
+ if (src_ptr_type == nullptr) {
ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
return ira->codegen->invalid_instruction;
}
- if (get_src_ptr_type(dest_type) == nullptr) {
+ ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
+ if (dest_ptr_type == nullptr) {
ir_add_error(ira, dest_type_src,
buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->invalid_instruction;
@@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
}
if (instr_is_comptime(ptr)) {
- ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
+ bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
+ UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
+ ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,
- dest_type);
+ if (val->special == ConstValSpecialStatic) {
+ bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
+ (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
+ val->data.x_ptr.data.hard_coded_addr.addr == 0);
+ if (is_addr_zero && !dest_allows_addr_zero) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+ }
+
+ IrInstruction *result = ir_const(ira, source_instr, dest_type);
copy_const_val(&result->value, val, false);
result->value.type = dest_type;
return result;
@@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
return ira->codegen->invalid_instruction;
}
- IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,
- source_instr->source_node, nullptr, ptr);
- casted_ptr->value.type = dest_type;
+ IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
ErrorMsg *msg = ir_add_error(ira, source_instr,
@@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
return result;
}
-static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
+static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
IrInstruction *dest_type_value = instruction->dest_type->child;
ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
if (type_is_invalid(dest_type))
@@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
if (type_is_invalid(src_type))
return ira->codegen->invalid_instruction;
- return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
+ return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value,
+ instruction->safety_check_on);
+}
+
+static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
+ size_t buf_i = 0;
+ // TODO optimize the buf case
+ expand_undef_array(codegen, val);
+ for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
+ ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
+ buf_write_value_bytes(codegen, &buf[buf_i], elem);
+ buf_i += type_size(codegen, elem->type);
+ }
}
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
+ if (val->special == ConstValSpecialUndef)
+ val->special = ConstValSpecialStatic;
assert(val->special == ConstValSpecialStatic);
switch (val->type->id) {
case ZigTypeIdInvalid:
@@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
zig_unreachable();
}
case ZigTypeIdArray:
- {
- size_t buf_i = 0;
- // TODO optimize the buf case
- expand_undef_array(codegen, val);
- for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
- ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
- buf_write_value_bytes(codegen, &buf[buf_i], elem);
- buf_i += type_size(codegen, elem->type);
- }
- }
- return;
+ return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
+ case ZigTypeIdVector:
+ return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
case ZigTypeIdStruct:
zig_panic("TODO buf_write_value_bytes struct type");
case ZigTypeIdOptional:
@@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
zig_unreachable();
}
-static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
+static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf,
+ ConstExprValue *val, ZigType *elem_type, size_t len)
+{
+ Error err;
+ uint64_t elem_size = type_size(codegen, elem_type);
+
+ switch (val->data.x_array.special) {
+ case ConstArraySpecialNone:
+ val->data.x_array.data.s_none.elements = create_const_vals(len);
+ for (size_t i = 0; i < len; i++) {
+ ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
+ elem->special = ConstValSpecialStatic;
+ elem->type = elem_type;
+ if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
+ return err;
+ }
+ return ErrorNone;
+ case ConstArraySpecialUndef:
+ zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
+ case ConstArraySpecialBuf:
+ zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
+ }
+ zig_unreachable();
+}
+
+static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
+ Error err;
assert(val->special == ConstValSpecialStatic);
switch (val->type->id) {
case ZigTypeIdInvalid:
@@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case ZigTypeIdPromise:
zig_unreachable();
case ZigTypeIdVoid:
- return;
+ return ErrorNone;
case ZigTypeIdBool:
val->data.x_bool = (buf[0] != 0);
- return;
+ return ErrorNone;
case ZigTypeIdInt:
bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
codegen->is_big_endian, val->type->data.integral.is_signed);
- return;
+ return ErrorNone;
case ZigTypeIdFloat:
float_read_ieee597(val, buf, codegen->is_big_endian);
- return;
+ return ErrorNone;
case ZigTypeIdPointer:
{
val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
@@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
codegen->is_big_endian, false);
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
- return;
+ return ErrorNone;
}
case ZigTypeIdArray:
- zig_panic("TODO buf_read_value_bytes array type");
+ return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
+ val->type->data.array.len);
+ case ZigTypeIdVector:
+ return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
+ val->type->data.vector.len);
+ case ZigTypeIdEnum:
+ switch (val->type->data.enumeration.layout) {
+ case ContainerLayoutAuto:
+ zig_panic("TODO buf_read_value_bytes enum auto");
+ case ContainerLayoutPacked:
+ zig_panic("TODO buf_read_value_bytes enum packed");
+ case ContainerLayoutExtern: {
+ ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
+ assert(tag_int_type->id == ZigTypeIdInt);
+ bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
+ codegen->is_big_endian, tag_int_type->data.integral.is_signed);
+ return ErrorNone;
+ }
+ }
+ zig_unreachable();
case ZigTypeIdStruct:
- zig_panic("TODO buf_read_value_bytes struct type");
+ switch (val->type->data.structure.layout) {
+ case ContainerLayoutAuto: {
+ ErrorMsg *msg = opt_ir_add_error_node(ira, codegen, source_node,
+ buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
+ buf_ptr(&val->type->name)));
+ add_error_note(codegen, msg, val->type->data.structure.decl_node,
+ buf_sprintf("declared here"));
+ return ErrorSemanticAnalyzeFail;
+ }
+ case ContainerLayoutExtern: {
+ size_t src_field_count = val->type->data.structure.src_field_count;
+ val->data.x_struct.fields = create_const_vals(src_field_count);
+ for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
+ ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
+ field_val->special = ConstValSpecialStatic;
+ TypeStructField *type_field = &val->type->data.structure.fields[field_i];
+ field_val->type = type_field->type_entry;
+ if (type_field->gen_index == SIZE_MAX)
+ continue;
+ size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref,
+ type_field->gen_index);
+ uint8_t *new_buf = buf + offset;
+ if ((err = buf_read_value_bytes(ira, codegen, source_node, new_buf, field_val)))
+ return err;
+ }
+ return ErrorNone;
+ }
+ case ContainerLayoutPacked:
+ zig_panic("TODO buf_read_value_bytes packed struct");
+ }
+ zig_unreachable();
case ZigTypeIdOptional:
zig_panic("TODO buf_read_value_bytes maybe type");
case ZigTypeIdErrorUnion:
zig_panic("TODO buf_read_value_bytes error union");
case ZigTypeIdErrorSet:
zig_panic("TODO buf_read_value_bytes pure error type");
- case ZigTypeIdEnum:
- zig_panic("TODO buf_read_value_bytes enum type");
case ZigTypeIdFn:
zig_panic("TODO buf_read_value_bytes fn type");
case ZigTypeIdUnion:
@@ -20043,8 +20937,86 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
+static bool type_can_bit_cast(ZigType *t) {
+ switch (t->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ case ZigTypeIdOpaque:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdNamespace:
+ case ZigTypeIdUnreachable:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdPointer:
+ return false;
+ default:
+ // TODO list these types out explicitly, there are probably some other invalid ones here
+ return true;
+ }
+}
+
+static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *dest_type)
+{
Error err;
+
+ ZigType *src_type = value->value.type;
+ assert(get_codegen_ptr_type(src_type) == nullptr);
+ assert(type_can_bit_cast(src_type));
+ assert(get_codegen_ptr_type(dest_type) == nullptr);
+ assert(type_can_bit_cast(dest_type));
+
+ if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
+
+ if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
+
+
+ uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
+ uint64_t src_size_bytes = type_size(ira->codegen, src_type);
+ if (dest_size_bytes != src_size_bytes) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
+ buf_ptr(&dest_type->name), dest_size_bytes,
+ buf_ptr(&src_type->name), src_size_bytes));
+ return ira->codegen->invalid_instruction;
+ }
+
+ uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
+ uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
+ if (dest_size_bits != src_size_bits) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
+ buf_ptr(&dest_type->name), dest_size_bits,
+ buf_ptr(&src_type->name), src_size_bits));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (instr_is_comptime(value)) {
+ ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, source_instr, dest_type);
+ uint8_t *buf = allocate_nonzero(src_size_bytes);
+ buf_write_value_bytes(ira->codegen, buf, val);
+ if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
+ return ira->codegen->invalid_instruction;
+ return result;
+ }
+
+ IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, nullptr, value);
+ result->value.type = dest_type;
+ return result;
+}
+
+static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
IrInstruction *dest_type_value = instruction->dest_type->child;
ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
if (type_is_invalid(dest_type))
@@ -20055,35 +21027,16 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
if (type_is_invalid(src_type))
return ira->codegen->invalid_instruction;
- if ((err = ensure_complete_type(ira->codegen, dest_type)))
- return ira->codegen->invalid_instruction;
-
- if ((err = ensure_complete_type(ira->codegen, src_type)))
- return ira->codegen->invalid_instruction;
-
if (get_codegen_ptr_type(src_type) != nullptr) {
ir_add_error(ira, value,
buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
return ira->codegen->invalid_instruction;
}
- switch (src_type->id) {
- case ZigTypeIdInvalid:
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdNamespace:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- default:
- break;
+ if (!type_can_bit_cast(src_type)) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->invalid_instruction;
}
if (get_codegen_ptr_type(dest_type) != nullptr) {
@@ -20092,50 +21045,40 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
}
- switch (dest_type->id) {
- case ZigTypeIdInvalid:
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdNamespace:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- default:
- break;
- }
-
- uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
- uint64_t src_size_bytes = type_size(ira->codegen, src_type);
- if (dest_size_bytes != src_size_bytes) {
- ir_add_error(ira, &instruction->base,
- buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
- buf_ptr(&dest_type->name), dest_size_bytes,
- buf_ptr(&src_type->name), src_size_bytes));
+ if (!type_can_bit_cast(dest_type)) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->invalid_instruction;
}
- if (instr_is_comptime(value)) {
- ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
+ return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
+}
+
+static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
+ ZigType *ptr_type)
+{
+ assert(get_src_ptr_type(ptr_type) != nullptr);
+ assert(type_has_bits(ptr_type));
+
+ IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
+ if (type_is_invalid(casted_int->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(casted_int)) {
+ ConstExprValue *val = ir_resolve_const(ira, casted_int, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
- uint8_t *buf = allocate_nonzero(src_size_bytes);
- buf_write_value_bytes(ira->codegen, buf, val);
- buf_read_value_bytes(ira->codegen, buf, &result->value);
+ IrInstruction *result = ir_const(ira, source_instr, ptr_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
+ result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
return result;
}
- IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, value);
- result->value.type = dest_type;
+ IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, nullptr, casted_int);
+ result->value.type = ptr_type;
return result;
}
@@ -20160,29 +21103,12 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
return ira->codegen->invalid_instruction;
}
+
IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
- if (type_is_invalid(casted_int->value.type))
- return ira->codegen->invalid_instruction;
-
- if (instr_is_comptime(casted_int)) {
- ConstExprValue *val = ir_resolve_const(ira, casted_int, UndefBad);
- if (!val)
- return ira->codegen->invalid_instruction;
-
- IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
- result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
- result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
- return result;
- }
-
- IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, casted_int);
- result->value.type = dest_type;
- return result;
+ return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
}
static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
@@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
case TldIdContainer:
case TldIdCompTime:
zig_unreachable();
- case TldIdVar:
- {
+ case TldIdVar: {
TldVar *tld_var = (TldVar *)tld;
ZigVar *var = tld_var->var;
@@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
return ir_get_deref(ira, &instruction->base, var_ptr);
}
}
- case TldIdFn:
- {
+ case TldIdFn: {
TldFn *tld_fn = (TldFn *)tld;
ZigFn *fn_entry = tld_fn->fn_entry;
assert(fn_entry->type_entry);
@@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
if (!val)
return ira->codegen->invalid_instruction;
if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
- IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, usize);
+ IrInstruction *result = ir_const(ira, &instruction->base, usize);
bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
result->value.type = usize;
return result;
@@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
} else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
return ira->codegen->invalid_instruction;
+ } else if (instruction->ptr_len == PtrLenC) {
+ if (!type_allowed_in_extern(ira->codegen, child_type)) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
+ return ira->codegen->invalid_instruction;
+ } else if (child_type->id == ZigTypeIdOpaque) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
+ return ira->codegen->invalid_instruction;
+ }
}
uint32_t align_bytes;
@@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
+ if (!type_has_bits(child_type)) {
+ align_bytes = 0;
+ }
} else {
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
@@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
return result;
}
+static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
+ ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+ if (type_is_invalid(int_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *op = instruction->op->child;
+ if (type_is_invalid(op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->id != ZigTypeIdInt) {
+ ir_add_error(ira, instruction->type,
+ buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (int_type->data.integral.bit_count % 8 != 0) {
+ ir_add_error(ira, instruction->type,
+ buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
+ buf_ptr(&int_type->name), int_type->data.integral.bit_count));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+ if (type_is_invalid(casted_op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->data.integral.bit_count == 0) {
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
+ return result;
+ }
+
+ if (int_type->data.integral.bit_count == 8) {
+ return casted_op;
+ }
+
+ if (instr_is_comptime(casted_op)) {
+ ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ size_t buf_size = int_type->data.integral.bit_count / 8;
+ uint8_t *buf = allocate_nonzero(buf_size);
+ bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
+ bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
+ int_type->data.integral.is_signed);
+ return result;
+ }
+
+ IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr, casted_op);
+ result->value.type = int_type;
+ return result;
+}
+
+static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) {
+ ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
+ if (type_is_invalid(int_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *op = instruction->op->child;
+ if (type_is_invalid(op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->id != ZigTypeIdInt) {
+ ir_add_error(ira, instruction->type,
+ buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
+ if (type_is_invalid(casted_op->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (int_type->data.integral.bit_count == 0) {
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ bigint_init_unsigned(&result->value.data.x_bigint, 0);
+ return result;
+ }
+
+ if (instr_is_comptime(casted_op)) {
+ ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, int_type);
+ size_t num_bits = int_type->data.integral.bit_count;
+ size_t buf_size = (num_bits + 7) / 8;
+ uint8_t *comptime_buf = allocate_nonzero(buf_size);
+ uint8_t *result_buf = allocate_nonzero(buf_size);
+ memset(comptime_buf,0,buf_size);
+ memset(result_buf,0,buf_size);
+
+ bigint_write_twos_complement(&val->data.x_bigint,comptime_buf,num_bits,ira->codegen->is_big_endian);
+
+ size_t bit_i = 0;
+ size_t bit_rev_i = num_bits - 1;
+ for (; bit_i < num_bits; bit_i++, bit_rev_i--) {
+ if (comptime_buf[bit_i / 8] & (1 << (bit_i % 8))) {
+ result_buf[bit_rev_i / 8] |= (1 << (bit_rev_i % 8));
+ }
+ }
+
+ bigint_read_twos_complement(&result->value.data.x_bigint,
+ result_buf,
+ int_type->data.integral.bit_count,
+ ira->codegen->is_big_endian,
+ int_type->data.integral.is_signed);
+
+ return result;
+ }
+
+ IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, nullptr, casted_op);
+ result->value.type = int_type;
+ return result;
+}
+
+
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
Error err;
IrInstruction *target = instruction->target->child;
@@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
case IrInstructionIdErrWrapCode:
case IrInstructionIdErrWrapPayload:
case IrInstructionIdCast:
+ case IrInstructionIdDeclVarGen:
+ case IrInstructionIdPtrCastGen:
+ case IrInstructionIdCmpxchgGen:
+ case IrInstructionIdArrayToVector:
+ case IrInstructionIdVectorToArray:
+ case IrInstructionIdAssertZero:
zig_unreachable();
case IrInstructionIdReturn:
@@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
case IrInstructionIdBinOp:
return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
- case IrInstructionIdDeclVar:
- return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
+ case IrInstructionIdDeclVarSrc:
+ return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
case IrInstructionIdLoadPtr:
return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
case IrInstructionIdStorePtr:
@@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
case IrInstructionIdTestNonNull:
return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
- case IrInstructionIdUnwrapOptional:
- return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);
+ case IrInstructionIdOptionalUnwrapPtr:
+ return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
case IrInstructionIdClz:
return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
case IrInstructionIdCtz:
@@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
case IrInstructionIdEmbedFile:
return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
- case IrInstructionIdCmpxchg:
- return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);
+ case IrInstructionIdCmpxchgSrc:
+ return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
case IrInstructionIdFence:
return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
case IrInstructionIdTruncate:
@@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
case IrInstructionIdIntType:
return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
+ case IrInstructionIdVectorType:
+ return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
case IrInstructionIdBoolNot:
return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
case IrInstructionIdMemset:
@@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
case IrInstructionIdPanic:
return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
- case IrInstructionIdPtrCast:
- return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);
+ case IrInstructionIdPtrCastSrc:
+ return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
case IrInstructionIdBitCast:
return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
case IrInstructionIdIntToPtr:
@@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
case IrInstructionIdSqrt:
return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
+ case IrInstructionIdBswap:
+ return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
+ case IrInstructionIdBitReverse:
+ return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction);
case IrInstructionIdIntToErr:
return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
case IrInstructionIdErrToInt:
@@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdBr:
case IrInstructionIdCondBr:
case IrInstructionIdSwitchBr:
- case IrInstructionIdDeclVar:
+ case IrInstructionIdDeclVarSrc:
+ case IrInstructionIdDeclVarGen:
case IrInstructionIdStorePtr:
case IrInstructionIdCall:
case IrInstructionIdReturn:
@@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCInclude:
case IrInstructionIdCDefine:
case IrInstructionIdCUndef:
- case IrInstructionIdCmpxchg:
case IrInstructionIdFence:
case IrInstructionIdMemset:
case IrInstructionIdMemcpy:
@@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdMergeErrRetTraces:
case IrInstructionIdMarkErrRetTracePtr:
case IrInstructionIdAtomicRmw:
+ case IrInstructionIdCmpxchgGen:
+ case IrInstructionIdCmpxchgSrc:
+ case IrInstructionIdAssertZero:
return true;
case IrInstructionIdPhi:
@@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSliceType:
case IrInstructionIdSizeOf:
case IrInstructionIdTestNonNull:
- case IrInstructionIdUnwrapOptional:
+ case IrInstructionIdOptionalUnwrapPtr:
case IrInstructionIdClz:
case IrInstructionIdCtz:
case IrInstructionIdPopCount:
@@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdEmbedFile:
case IrInstructionIdTruncate:
case IrInstructionIdIntType:
+ case IrInstructionIdVectorType:
case IrInstructionIdBoolNot:
case IrInstructionIdSlice:
case IrInstructionIdMemberCount:
@@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdErrWrapPayload:
case IrInstructionIdFnProto:
case IrInstructionIdTestComptime:
- case IrInstructionIdPtrCast:
+ case IrInstructionIdPtrCastSrc:
+ case IrInstructionIdPtrCastGen:
case IrInstructionIdBitCast:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
@@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCoroPromise:
case IrInstructionIdPromiseResultType:
case IrInstructionIdSqrt:
+ case IrInstructionIdBswap:
+ case IrInstructionIdBitReverse:
case IrInstructionIdAtomicLoad:
case IrInstructionIdIntCast:
case IrInstructionIdFloatCast:
@@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFromBytes:
case IrInstructionIdToBytes:
case IrInstructionIdEnumToInt:
+ case IrInstructionIdVectorToArray:
+ case IrInstructionIdArrayToVector:
return false;
case IrInstructionIdAsm:
diff --git a/src/ir.hpp b/src/ir.hpp
index b298750dec..0b85ad2c55 100644
--- a/src/ir.hpp
+++ b/src/ir.hpp
@@ -13,15 +13,18 @@
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
-IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
+ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
- IrExecutable *parent_exec);
+ IrExecutable *parent_exec, AstNode *expected_type_source_node);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node);
bool ir_has_side_effects(IrInstruction *instruction);
-ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val);
+
+struct IrAnalyze;
+ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
+ AstNode *source_node);
#endif
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 13c06e4e2d..75da24d1a9 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
}
}
-static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
+static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
const char *name = buf_ptr(&decl_var_instruction->var->name);
if (decl_var_instruction->var_type) {
@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
}
static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
- fprintf(irp->f, "*");
ir_print_other_instruction(irp, instruction->ptr);
+ fprintf(irp->f, ".*");
}
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
fprintf(irp->f, ")");
}
-static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
- fprintf(irp->f, "*");
+static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, " != null");
}
-static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
- fprintf(irp->f, "&??*");
- ir_print_other_instruction(irp, instruction->value);
+static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
+ fprintf(irp->f, "&");
+ ir_print_other_instruction(irp, instruction->base_ptr);
+ fprintf(irp->f, ".*.?");
if (!instruction->safety_check_on) {
fprintf(irp->f, " // no safety");
}
@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
fprintf(irp->f, ")");
}
-static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
+static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
fprintf(irp->f, "@cmpxchg(");
ir_print_other_instruction(irp, instruction->ptr);
fprintf(irp->f, ", ");
@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
+ fprintf(irp->f, "@cmpxchg(");
+ ir_print_other_instruction(irp, instruction->ptr);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->cmp_value);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->new_value);
+ fprintf(irp->f, ", TODO print atomic orders)");
+}
+
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
fprintf(irp->f, "@fence(");
ir_print_other_instruction(irp, instruction->order_value);
@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) {
+ fprintf(irp->f, "@Vector(");
+ ir_print_other_instruction(irp, instruction->len);
+ fprintf(irp->f, ", ");
+ ir_print_other_instruction(irp, instruction->elem_type);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
fprintf(irp->f, "! ");
ir_print_other_instruction(irp, instruction->value);
@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
}
static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
- fprintf(irp->f, "@unwrapErrorCode(");
- ir_print_other_instruction(irp, instruction->value);
+ fprintf(irp->f, "UnwrapErrorCode(");
+ ir_print_other_instruction(irp, instruction->err_union);
fprintf(irp->f, ")");
}
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
- fprintf(irp->f, "@unwrapErrorPayload(");
+ fprintf(irp->f, "ErrorUnionFieldPayload(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
if (!instruction->safety_check_on) {
@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
fprintf(irp->f, ")");
}
-static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
+static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
fprintf(irp->f, "@ptrCast(");
if (instruction->dest_type) {
ir_print_other_instruction(irp, instruction->dest_type);
@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
+ fprintf(irp->f, "@ptrCast(");
+ ir_print_other_instruction(irp, instruction->ptr);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
fprintf(irp->f, "@bitCast(");
if (instruction->dest_type) {
@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
}
static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
- fprintf(irp->f, "@widenOrShorten(");
+ fprintf(irp->f, "WidenOrShorten(");
ir_print_other_instruction(irp, instruction->target);
fprintf(irp->f, ")");
}
@@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
fprintf(irp->f, ")");
}
+static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) {
+ fprintf(irp->f, "ArrayToVector(");
+ ir_print_other_instruction(irp, instruction->array);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
+ fprintf(irp->f, "VectorToArray(");
+ ir_print_other_instruction(irp, instruction->vector);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {
+ fprintf(irp->f, "AssertZero(");
+ ir_print_other_instruction(irp, instruction->target);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
+ ZigVar *var = decl_var_instruction->var;
+ const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
+ const char *name = buf_ptr(&decl_var_instruction->var->name);
+ fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
+ var->align_bytes);
+
+ ir_print_other_instruction(irp, decl_var_instruction->init_value);
+ if (decl_var_instruction->var->is_comptime != nullptr) {
+ fprintf(irp->f, " // comptime = ");
+ ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
+ }
+}
+
+static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
+ fprintf(irp->f, "@bswap(");
+ if (instruction->type != nullptr) {
+ ir_print_other_instruction(irp, instruction->type);
+ } else {
+ fprintf(irp->f, "null");
+ }
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op);
+ fprintf(irp->f, ")");
+}
+
+static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) {
+ fprintf(irp->f, "@bitreverse(");
+ if (instruction->type != nullptr) {
+ ir_print_other_instruction(irp, instruction->type);
+ } else {
+ fprintf(irp->f, "null");
+ }
+ fprintf(irp->f, ",");
+ ir_print_other_instruction(irp, instruction->op);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdBinOp:
ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
break;
- case IrInstructionIdDeclVar:
- ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
+ case IrInstructionIdDeclVarSrc:
+ ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
break;
case IrInstructionIdCast:
ir_print_cast(irp, (IrInstructionCast *)instruction);
@@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
break;
case IrInstructionIdTestNonNull:
- ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
+ ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
break;
- case IrInstructionIdUnwrapOptional:
- ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
+ case IrInstructionIdOptionalUnwrapPtr:
+ ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
break;
case IrInstructionIdCtz:
ir_print_ctz(irp, (IrInstructionCtz *)instruction);
@@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdEmbedFile:
ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
break;
- case IrInstructionIdCmpxchg:
- ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
+ case IrInstructionIdCmpxchgSrc:
+ ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
+ break;
+ case IrInstructionIdCmpxchgGen:
+ ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
break;
case IrInstructionIdFence:
ir_print_fence(irp, (IrInstructionFence *)instruction);
@@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdIntType:
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
break;
+ case IrInstructionIdVectorType:
+ ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
+ break;
case IrInstructionIdBoolNot:
ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
break;
@@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdTestComptime:
ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
break;
- case IrInstructionIdPtrCast:
- ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
+ case IrInstructionIdPtrCastSrc:
+ ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
+ break;
+ case IrInstructionIdPtrCastGen:
+ ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
break;
case IrInstructionIdBitCast:
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
@@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSqrt:
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
break;
+ case IrInstructionIdBswap:
+ ir_print_bswap(irp, (IrInstructionBswap *)instruction);
+ break;
+ case IrInstructionIdBitReverse:
+ ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction);
+ break;
case IrInstructionIdAtomicLoad:
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
break;
@@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdCheckRuntimeScope:
ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
break;
+ case IrInstructionIdDeclVarGen:
+ ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
+ break;
+ case IrInstructionIdArrayToVector:
+ ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction);
+ break;
+ case IrInstructionIdVectorToArray:
+ ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
+ break;
+ case IrInstructionIdAssertZero:
+ ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/link.cpp b/src/link.cpp
index 188f976a86..58221a99ea 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
}
CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
- parent_gen->build_mode, parent_gen->zig_lib_dir);
+ parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
@@ -444,73 +444,20 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);
}
-static void construct_linker_job_coff(LinkJob *lj) {
+static void add_uefi_link_args(LinkJob *lj) {
+ lj->args.append("/BASE:0");
+ lj->args.append("/ENTRY:EfiMain");
+ lj->args.append("/OPT:REF");
+ lj->args.append("/SAFESEH:NO");
+ lj->args.append("/MERGE:.rdata=.data");
+ lj->args.append("/ALIGN:32");
+ lj->args.append("/NODEFAULTLIB");
+ lj->args.append("/SECTION:.xdata,D");
+}
+
+static void add_nt_link_args(LinkJob *lj, bool is_library) {
CodeGen *g = lj->codegen;
- lj->args.append("/ERRORLIMIT:0");
-
- if (g->libc_link_lib != nullptr) {
- find_libc_lib_path(g);
- }
-
- lj->args.append("-NOLOGO");
-
- if (!g->strip_debug_symbols) {
- lj->args.append("-DEBUG");
- }
-
- if (g->out_type == OutTypeExe) {
- // TODO compile time stack upper bound detection
- lj->args.append("/STACK:16777216");
- }
-
- coff_append_machine_arg(g, &lj->args);
-
- if (g->windows_subsystem_windows) {
- lj->args.append("/SUBSYSTEM:windows");
- } else if (g->windows_subsystem_console) {
- lj->args.append("/SUBSYSTEM:console");
- }
- // The commented out stuff is from when we linked with MinGW
- // Now that we're linking with LLD it remains to be determined
- // how to handle --target-environ gnu
- // These comments are a clue
-
- bool is_library = g->out_type == OutTypeLib;
- //bool dll = g->out_type == OutTypeLib;
- //bool shared = !g->is_static && dll;
- //if (g->is_static) {
- // lj->args.append("-Bstatic");
- //} else {
- // if (dll) {
- // lj->args.append("--dll");
- // } else if (shared) {
- // lj->args.append("--shared");
- // }
- // lj->args.append("-Bdynamic");
- // if (dll || shared) {
- // lj->args.append("-e");
- // if (g->zig_target.arch.arch == ZigLLVM_x86) {
- // lj->args.append("_DllMainCRTStartup@12");
- // } else {
- // lj->args.append("DllMainCRTStartup");
- // }
- // lj->args.append("--enable-auto-image-base");
- // }
- //}
-
- lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
-
- if (g->libc_link_lib != nullptr) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
-
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
- if (g->libc_static_lib_dir != nullptr) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
- }
- }
-
if (lj->link_in_crt) {
const char *lib_str = g->is_static ? "lib" : "";
const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
@@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) {
//https://msdn.microsoft.com/en-us/library/bb531344.aspx
lj->args.append("legacy_stdio_definitions.lib");
- //if (shared || dll) {
- // lj->args.append(get_libc_file(g, "dllcrt2.o"));
- //} else {
- // if (g->windows_linker_unicode) {
- // lj->args.append(get_libc_file(g, "crt2u.o"));
- // } else {
- // lj->args.append(get_libc_file(g, "crt2.o"));
- // }
- //}
- //lj->args.append(get_libc_static_file(g, "crtbegin.o"));
-
// msvcrt depends on kernel32
lj->args.append("kernel32.lib");
} else {
- lj->args.append("-NODEFAULTLIB");
+ lj->args.append("/NODEFAULTLIB");
if (!is_library) {
if (g->have_winmain) {
- lj->args.append("-ENTRY:WinMain");
+ lj->args.append("/ENTRY:WinMain");
} else {
- lj->args.append("-ENTRY:WinMainCRTStartup");
+ lj->args.append("/ENTRY:WinMainCRTStartup");
}
}
}
+}
+
+// These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning
+// up a bit for building the COFF linker args:
+// /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
+// /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
+// This commented out stuff is from when we linked with MinGW
+// Now that we're linking with LLD it remains to be determined
+// how to handle --target-environ gnu
+// These comments are a clue
+//bool dll = g->out_type == OutTypeLib;
+//bool shared = !g->is_static && dll;
+//if (g->is_static) {
+// lj->args.append("-Bstatic");
+//} else {
+// if (dll) {
+// lj->args.append("--dll");
+// } else if (shared) {
+// lj->args.append("--shared");
+// }
+// lj->args.append("-Bdynamic");
+// if (dll || shared) {
+// lj->args.append("-e");
+// if (g->zig_target.arch.arch == ZigLLVM_x86) {
+// lj->args.append("_DllMainCRTStartup@12");
+// } else {
+// lj->args.append("DllMainCRTStartup");
+// }
+// lj->args.append("--enable-auto-image-base");
+// }
+//}
+//if (shared || dll) {
+// lj->args.append(get_libc_file(g, "dllcrt2.o"));
+//} else {
+// if (g->windows_linker_unicode) {
+// lj->args.append(get_libc_file(g, "crt2u.o"));
+// } else {
+// lj->args.append(get_libc_file(g, "crt2.o"));
+// }
+//}
+//lj->args.append(get_libc_static_file(g, "crtbegin.o"));
+//if (g->libc_link_lib != nullptr) {
+//if (g->is_static) {
+// lj->args.append("--start-group");
+//}
+
+//lj->args.append("-lmingw32");
+
+//lj->args.append("-lgcc");
+//bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
+//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
+//if (!g->is_static && !is_android) {
+// if (!is_cyg_ming) {
+// lj->args.append("--as-needed");
+// }
+// //lj->args.append("-lgcc_s");
+// if (!is_cyg_ming) {
+// lj->args.append("--no-as-needed");
+// }
+//}
+//if (g->is_static && !is_android) {
+// //lj->args.append("-lgcc_eh");
+//}
+//if (is_android && !g->is_static) {
+// lj->args.append("-ldl");
+//}
+
+//lj->args.append("-lmoldname");
+//lj->args.append("-lmingwex");
+//lj->args.append("-lmsvcrt");
+
+
+//if (g->windows_subsystem_windows) {
+// lj->args.append("-lgdi32");
+// lj->args.append("-lcomdlg32");
+//}
+//lj->args.append("-ladvapi32");
+//lj->args.append("-lshell32");
+//lj->args.append("-luser32");
+//lj->args.append("-lkernel32");
+
+//if (g->is_static) {
+// lj->args.append("--end-group");
+//}
+
+//if (lj->link_in_crt) {
+// lj->args.append(get_libc_static_file(g, "crtend.o"));
+//}
+//}
+
+
+static void construct_linker_job_coff(LinkJob *lj) {
+ CodeGen *g = lj->codegen;
+
+ lj->args.append("/ERRORLIMIT:0");
+
+ if (g->libc_link_lib != nullptr) {
+ find_libc_lib_path(g);
+ }
+
+ lj->args.append("/NOLOGO");
+
+ if (!g->strip_debug_symbols) {
+ lj->args.append("/DEBUG");
+ }
+
+ if (g->out_type == OutTypeExe) {
+ // TODO compile time stack upper bound detection
+ lj->args.append("/STACK:16777216");
+ }
+
+ coff_append_machine_arg(g, &lj->args);
+
+ bool is_library = g->out_type == OutTypeLib;
+ switch (g->subsystem) {
+ case TargetSubsystemAuto:
+ break;
+ case TargetSubsystemConsole:
+ lj->args.append("/SUBSYSTEM:console");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemEfiApplication:
+ lj->args.append("/SUBSYSTEM:efi_application");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiBootServiceDriver:
+ lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiRom:
+ lj->args.append("/SUBSYSTEM:efi_rom");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiRuntimeDriver:
+ lj->args.append("/SUBSYSTEM:efi_runtime_driver");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemNative:
+ lj->args.append("/SUBSYSTEM:native");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemPosix:
+ lj->args.append("/SUBSYSTEM:posix");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemWindows:
+ lj->args.append("/SUBSYSTEM:windows");
+ add_nt_link_args(lj, is_library);
+ break;
+ }
+
+ lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
+
+ if (g->libc_link_lib != nullptr) {
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
+
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
+ if (g->libc_static_lib_dir != nullptr) {
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
+ }
+ }
if (is_library && !g->is_static) {
lj->args.append("-DLL");
@@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
}
}
- //if (g->libc_link_lib != nullptr) {
- //if (g->is_static) {
- // lj->args.append("--start-group");
- //}
-
- //lj->args.append("-lmingw32");
-
- //lj->args.append("-lgcc");
- //bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
- //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
- //if (!g->is_static && !is_android) {
- // if (!is_cyg_ming) {
- // lj->args.append("--as-needed");
- // }
- // //lj->args.append("-lgcc_s");
- // if (!is_cyg_ming) {
- // lj->args.append("--no-as-needed");
- // }
- //}
- //if (g->is_static && !is_android) {
- // //lj->args.append("-lgcc_eh");
- //}
- //if (is_android && !g->is_static) {
- // lj->args.append("-ldl");
- //}
-
- //lj->args.append("-lmoldname");
- //lj->args.append("-lmingwex");
- //lj->args.append("-lmsvcrt");
-
-
- //if (g->windows_subsystem_windows) {
- // lj->args.append("-lgdi32");
- // lj->args.append("-lcomdlg32");
- //}
- //lj->args.append("-ladvapi32");
- //lj->args.append("-lshell32");
- //lj->args.append("-luser32");
- //lj->args.append("-lkernel32");
-
- //if (g->is_static) {
- // lj->args.append("--end-group");
- //}
-
- //if (lj->link_in_crt) {
- // lj->args.append(get_libc_static_file(g, "crtend.o"));
- //}
- //}
}
diff --git a/src/main.cpp b/src/main.cpp
index 078dfb25f9..78446f9e98 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) {
return EXIT_FAILURE;
}
-static int print_full_usage(const char *arg0) {
- fprintf(stdout,
+static int print_full_usage(const char *arg0, FILE *file, int return_code) {
+ fprintf(file,
"Usage: %s [command] [options]\n"
"\n"
"Commands:\n"
@@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) {
" build-lib [source] create library from source or object files\n"
" build-obj [source] create object from source or assembly\n"
" builtin show the source code of that @import(\"builtin\")\n"
+ " fmt parse files and render in canonical zig format\n"
" help show this usage information\n"
" id print the base64-encoded compiler id\n"
" init-exe initialize a `zig build` application in the cwd\n"
@@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) {
" --release-fast build with optimizations on and safety off\n"
" --release-safe build with optimizations on and safety on\n"
" --release-small build with size optimizations on and safety off\n"
+ " --single-threaded source may assume it is only used single-threaded\n"
" --static output will be statically linked\n"
" --strip exclude debug symbols\n"
" --target-arch [name] specify target architecture\n"
@@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) {
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
+ " --override-std-dir [arg] use an alternate Zig standard library\n"
"\n"
"Link Options:\n"
" --dynamic-linker [path] set the path to ld.so\n"
@@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) {
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
" --no-rosegment compromise security to workaround valgrind bug\n"
- " -mconsole (windows) --subsystem console to the linker\n"
- " -mwindows (windows) --subsystem windows to the linker\n"
+ " --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n"
" -framework [name] (darwin) link against framework\n"
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
" -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
@@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) {
" --test-cmd [arg] specify test execution command one arg at a time\n"
" --test-cmd-bin appends test binary path to test cmd args\n"
, arg0);
- return EXIT_SUCCESS;
+ return return_code;
}
static const char *ZIG_ZEN = "\n"
@@ -371,8 +373,6 @@ int main(int argc, char **argv) {
const char *target_arch = nullptr;
const char *target_os = nullptr;
const char *target_environ = nullptr;
- bool mwindows = false;
- bool mconsole = false;
bool rdynamic = false;
const char *mmacosx_version_min = nullptr;
const char *mios_version_min = nullptr;
@@ -395,6 +395,9 @@ int main(int argc, char **argv) {
int runtime_args_start = -1;
bool no_rosegment_workaround = false;
bool system_linker_hack = false;
+ TargetSubsystem subsystem = TargetSubsystemAuto;
+ bool is_single_threaded = false;
+ Buf *override_std_dir = nullptr;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -430,7 +433,8 @@ int main(int argc, char **argv) {
Buf *build_runner_path = buf_alloc();
os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
- CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir());
+ CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ override_std_dir);
g->enable_time_report = timing_info;
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
codegen_set_out_name(g, buf_create_from_str("build"));
@@ -512,6 +516,31 @@ int main(int argc, char **argv) {
fprintf(stderr, "\n");
}
return (term.how == TerminationIdClean) ? term.code : -1;
+ } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
+ init_all_targets();
+ Buf *fmt_runner_path = buf_alloc();
+ os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
+ CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ nullptr);
+ g->is_single_threaded = true;
+ codegen_set_out_name(g, buf_create_from_str("fmt"));
+ g->enable_cache = true;
+
+ codegen_build_and_link(g);
+
+ ZigList args = {0};
+ for (int i = 2; i < argc; i += 1) {
+ args.append(argv[i]);
+ }
+ args.append(nullptr);
+ const char *exec_path = buf_ptr(&g->output_file_path);
+
+ os_execv(exec_path, args.items);
+
+ args.pop();
+ Termination term;
+ os_spawn_process(exec_path, args, &term);
+ return term.code;
}
for (int i = 1; i < argc; i += 1) {
@@ -524,6 +553,8 @@ int main(int argc, char **argv) {
build_mode = BuildModeSafeRelease;
} else if (strcmp(arg, "--release-small") == 0) {
build_mode = BuildModeSmallRelease;
+ } else if (strcmp(arg, "--help") == 0) {
+ return print_full_usage(arg0, stderr, EXIT_FAILURE);
} else if (strcmp(arg, "--strip") == 0) {
strip = true;
} else if (strcmp(arg, "--static") == 0) {
@@ -540,10 +571,6 @@ int main(int argc, char **argv) {
verbose_llvm_ir = true;
} else if (strcmp(arg, "--verbose-cimport") == 0) {
verbose_cimport = true;
- } else if (strcmp(arg, "-mwindows") == 0) {
- mwindows = true;
- } else if (strcmp(arg, "-mconsole") == 0) {
- mconsole = true;
} else if (strcmp(arg, "-rdynamic") == 0) {
rdynamic = true;
} else if (strcmp(arg, "--no-rosegment") == 0) {
@@ -556,6 +583,8 @@ int main(int argc, char **argv) {
disable_pic = true;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
+ } else if (strcmp(arg, "--single-threaded") == 0) {
+ is_single_threaded = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
@@ -647,6 +676,8 @@ int main(int argc, char **argv) {
clang_argv.append(argv[i]);
llvm_argv.append(argv[i]);
+ } else if (strcmp(arg, "--override-std-dir") == 0) {
+ override_std_dir = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
lib_dirs.append(argv[i]);
} else if (strcmp(arg, "--library") == 0) {
@@ -687,6 +718,37 @@ int main(int argc, char **argv) {
ver_patch = atoi(argv[i]);
} else if (strcmp(arg, "--test-cmd") == 0) {
test_exec_args.append(argv[i]);
+ } else if (strcmp(arg, "--subsystem") == 0) {
+ if (strcmp(argv[i], "console") == 0) {
+ subsystem = TargetSubsystemConsole;
+ } else if (strcmp(argv[i], "windows") == 0) {
+ subsystem = TargetSubsystemWindows;
+ } else if (strcmp(argv[i], "posix") == 0) {
+ subsystem = TargetSubsystemPosix;
+ } else if (strcmp(argv[i], "native") == 0) {
+ subsystem = TargetSubsystemNative;
+ } else if (strcmp(argv[i], "efi_application") == 0) {
+ subsystem = TargetSubsystemEfiApplication;
+ } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) {
+ subsystem = TargetSubsystemEfiBootServiceDriver;
+ } else if (strcmp(argv[i], "efi_rom") == 0) {
+ subsystem = TargetSubsystemEfiRom;
+ } else if (strcmp(argv[i], "efi_runtime_driver") == 0) {
+ subsystem = TargetSubsystemEfiRuntimeDriver;
+ } else {
+ fprintf(stderr, "invalid: --subsystem %s\n"
+ "Options are:\n"
+ " console\n"
+ " windows\n"
+ " posix\n"
+ " native\n"
+ " efi_application\n"
+ " efi_boot_service_driver\n"
+ " efi_rom\n"
+ " efi_runtime_driver\n"
+ , argv[i]);
+ return EXIT_FAILURE;
+ }
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return print_error_usage(arg0);
@@ -790,7 +852,8 @@ int main(int argc, char **argv) {
switch (cmd) {
case CmdBuiltin: {
- CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
+ CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir);
+ g->is_single_threaded = is_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
@@ -848,7 +911,10 @@ int main(int argc, char **argv) {
if (cmd == CmdRun && buf_out_name == nullptr) {
buf_out_name = buf_create_from_str("run");
}
- CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
+ CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
+ override_std_dir);
+ g->subsystem = subsystem;
+
if (disable_pic) {
if (out_type != OutTypeLib || !is_static) {
fprintf(stderr, "--disable-pic only applies to static libraries");
@@ -862,6 +928,7 @@ int main(int argc, char **argv) {
codegen_set_out_name(g, buf_out_name);
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
codegen_set_is_test(g, cmd == CmdTest);
+ g->is_single_threaded = is_single_threaded;
codegen_set_linker_script(g, linker_script);
if (each_lib_rpath)
codegen_set_each_lib_rpath(g, each_lib_rpath);
@@ -909,7 +976,6 @@ int main(int argc, char **argv) {
codegen_add_rpath(g, rpath_list.at(i));
}
- codegen_set_windows_subsystem(g, mwindows, mconsole);
codegen_set_rdynamic(g, rdynamic);
g->no_rosegment_workaround = no_rosegment_workaround;
if (mmacosx_version_min && mios_version_min) {
@@ -1042,7 +1108,7 @@ int main(int argc, char **argv) {
}
}
case CmdHelp:
- return print_full_usage(arg0);
+ return print_full_usage(arg0, stdout, EXIT_SUCCESS);
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
diff --git a/src/os.cpp b/src/os.cpp
index eba95b9f2f..8eb6b34654 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) {
if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
return ErrorUnexpected;
}
- buf_resize(out_path, cb);
+ buf_resize(out_path, cb - 1);
return ErrorNone;
#endif
return ErrorFileNotFound;
@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList &paths) {
#endif
}
-Error os_file_open_r(Buf *full_path, OsFile *out_file) {
+Error os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime) {
#if defined(ZIG_OS_WINDOWS)
// TODO use CreateFileW
HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
return ErrorUnexpected;
}
}
-
*out_file = result;
+
+ if (mtime != nullptr) {
+ FILETIME last_write_time;
+ if (!GetFileTime(result, nullptr, nullptr, &last_write_time)) {
+ CloseHandle(result);
+ return ErrorUnexpected;
+ }
+ mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
+ mtime->nsec = 0;
+ }
+
return ErrorNone;
#else
for (;;) {
@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
return ErrorFileSystem;
}
}
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) == -1) {
+ close(fd);
+ return ErrorFileSystem;
+ }
+ if (S_ISDIR(statbuf.st_mode)) {
+ close(fd);
+ return ErrorIsDir;
+ }
*out_file = fd;
+
+ if (mtime != nullptr) {
+#if defined(ZIG_OS_DARWIN)
+ mtime->sec = statbuf.st_mtimespec.tv_sec;
+ mtime->nsec = statbuf.st_mtimespec.tv_nsec;
+#else
+ mtime->sec = statbuf.st_mtim.tv_sec;
+ mtime->nsec = statbuf.st_mtim.tv_nsec;
+#endif
+ }
return ErrorNone;
}
#endif
@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
#endif
}
-Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
-#if defined(ZIG_OS_WINDOWS)
- FILETIME last_write_time;
- if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
- return ErrorUnexpected;
- mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
- mtime->nsec = 0;
- return ErrorNone;
-#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
- struct stat statbuf;
- if (fstat(file, &statbuf) == -1)
- return ErrorFileSystem;
-
- mtime->sec = statbuf.st_mtim.tv_sec;
- mtime->nsec = statbuf.st_mtim.tv_nsec;
- return ErrorNone;
-#elif defined(ZIG_OS_DARWIN)
- struct stat statbuf;
- if (fstat(file, &statbuf) == -1)
- return ErrorFileSystem;
-
- mtime->sec = statbuf.st_mtimespec.tv_sec;
- mtime->nsec = statbuf.st_mtimespec.tv_nsec;
- return ErrorNone;
-#else
-#error unimplemented
-#endif
-}
-
Error os_file_read(OsFile file, void *ptr, size_t *len) {
#if defined(ZIG_OS_WINDOWS)
DWORD amt_read;
diff --git a/src/os.hpp b/src/os.hpp
index d81a2362a5..68ac6e0171 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);
Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
-Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);
+Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime);
Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
-Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime);
Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
diff --git a/src/parser.cpp b/src/parser.cpp
index 077365995e..3a6ce04647 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
else_body = ast_expect(pc, body_parser);
}
- assert(res->type == NodeTypeTestExpr);
+ assert(res->type == NodeTypeIfOptional);
if (err_payload != nullptr) {
AstNodeTestExpr old = res->data.test_expr;
res->type = NodeTypeIfErrorExpr;
@@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
static AstNode *ast_parse_var_decl(ParseContext *pc) {
- Token *first = eat_token_if(pc, TokenIdKeywordConst);
- if (first == nullptr)
- first = eat_token_if(pc, TokenIdKeywordVar);
- if (first == nullptr)
- return nullptr;
-
+ Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
+ Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
+ if (mut_kw == nullptr)
+ mut_kw = eat_token_if(pc, TokenIdKeywordVar);
+ if (mut_kw == nullptr) {
+ if (thread_local_kw == nullptr) {
+ return nullptr;
+ } else {
+ ast_invalid_token_error(pc, peek_token(pc));
+ }
+ }
Token *identifier = expect_token(pc, TokenIdSymbol);
AstNode *type_expr = nullptr;
if (eat_token_if(pc, TokenIdColon) != nullptr)
@@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
expect_token(pc, TokenIdSemicolon);
- AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, first);
- res->data.variable_declaration.is_const = first->id == TokenIdKeywordConst;
+ AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
+ res->data.variable_declaration.threadlocal_tok = thread_local_kw;
+ res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
res->data.variable_declaration.symbol = token_buf(identifier);
res->data.variable_declaration.type = type_expr;
res->data.variable_declaration.align_expr = align_expr;
@@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
if (requires_semi && else_body == nullptr)
expect_token(pc, TokenIdSemicolon);
- assert(res->type == NodeTypeTestExpr);
+ assert(res->type == NodeTypeIfOptional);
if (err_payload != nullptr) {
AstNodeTestExpr old = res->data.test_expr;
res->type = NodeTypeIfErrorExpr;
@@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
Optional opt_payload = ast_parse_ptr_payload(pc);
PtrPayload payload;
- AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);
+ AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
res->data.test_expr.target_node = condition;
if (opt_payload.unwrap(&payload)) {
res->data.test_expr.var_symbol = token_buf(payload.payload);
@@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
// PtrTypeStart
// <- ASTERISK
// / ASTERISK2
-// / LBRACKET ASTERISK RBRACKET
+// / PTRUNKNOWN
+// / PTRC
static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
Token *asterisk = eat_token_if(pc, TokenIdStar);
if (asterisk != nullptr) {
@@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
return res;
}
+ Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
+ if (cptr != nullptr) {
+ AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
+ res->data.pointer_type.star_token = cptr;
+ return res;
+ }
+
return nullptr;
}
@@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.if_err_expr.then_node, visit, context);
visit_field(&node->data.if_err_expr.else_node, visit, context);
break;
- case NodeTypeTestExpr:
+ case NodeTypeIfOptional:
visit_field(&node->data.test_expr.target_node, visit, context);
visit_field(&node->data.test_expr.then_node, visit, context);
visit_field(&node->data.test_expr.else_node, visit, context);
diff --git a/src/target.cpp b/src/target.cpp
index 5a4b5252f1..b1434c6871 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -174,6 +174,7 @@ static const Os os_list[] = {
OsContiki,
OsAMDPAL,
OsZen,
+ OsUefi,
};
// Coordinate with zig_llvm.h
@@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {
case OsSolaris:
return ZigLLVM_Solaris;
case OsWindows:
+ case OsUefi:
return ZigLLVM_Win32;
case OsHaiku:
return ZigLLVM_Haiku;
@@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) {
return "freestanding";
case OsZen:
return "zen";
+ case OsUefi:
+ return "uefi";
case OsAnanas:
case OsCloudABI:
case OsDragonFly:
@@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case CIntTypeCount:
zig_unreachable();
}
+ case OsUefi:
case OsWindows:
switch (id) {
case CIntTypeShort:
@@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
zig_unreachable();
}
+bool target_allows_addr_zero(const ZigTarget *target) {
+ return target->os == OsFreestanding;
+}
+
const char *target_o_file_ext(ZigTarget *target) {
- if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows) {
+ if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
return ".obj";
} else {
return ".o";
@@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) {
const char *target_exe_file_ext(ZigTarget *target) {
if (target->os == OsWindows) {
return ".exe";
+ } else if (target->os == OsUefi) {
+ return ".efi";
} else {
return "";
}
}
const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {
- if (target->os == OsWindows) {
+ if (target->os == OsWindows || target->os == OsUefi) {
if (is_static) {
return ".lib";
} else {
diff --git a/src/target.hpp b/src/target.hpp
index 04652179d2..99d1cadf56 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -51,6 +51,19 @@ enum Os {
OsContiki,
OsAMDPAL,
OsZen,
+ OsUefi,
+};
+
+enum TargetSubsystem {
+ TargetSubsystemAuto, // Zig should infer the subsystem
+ TargetSubsystemConsole,
+ TargetSubsystemWindows,
+ TargetSubsystemPosix,
+ TargetSubsystemNative,
+ TargetSubsystemEfiApplication,
+ TargetSubsystemEfiBootServiceDriver,
+ TargetSubsystemEfiRom,
+ TargetSubsystemEfiRuntimeDriver,
};
struct ZigTarget {
@@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
ZigLLVM_OSType get_llvm_os_type(Os os_type);
bool target_is_arm(const ZigTarget *target);
+bool target_allows_addr_zero(const ZigTarget *target);
#endif
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 921ee4de09..9ff6ed3bbe 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"suspend", TokenIdKeywordSuspend},
{"switch", TokenIdKeywordSwitch},
{"test", TokenIdKeywordTest},
+ {"threadlocal", TokenIdKeywordThreadLocal},
{"true", TokenIdKeywordTrue},
{"try", TokenIdKeywordTry},
{"undefined", TokenIdKeywordUndefined},
@@ -220,6 +221,7 @@ enum TokenizeState {
TokenizeStateError,
TokenizeStateLBracket,
TokenizeStateLBracketStar,
+ TokenizeStateLBracketStarC,
};
@@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3)
static void tokenize_error(Tokenize *t, const char *format, ...) {
t->state = TokenizeStateError;
- if (t->cur_tok) {
- t->out->err_line = t->cur_tok->start_line;
- t->out->err_column = t->cur_tok->start_column;
- } else {
- t->out->err_line = t->line;
- t->out->err_column = t->column;
- }
+ t->out->err_line = t->line;
+ t->out->err_column = t->column;
va_list ap;
va_start(ap, format);
@@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
switch (c) {
case '*':
t.state = TokenizeStateLBracketStar;
- set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
break;
default:
// reinterpret as just an lbracket
@@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
}
break;
case TokenizeStateLBracketStar:
+ switch (c) {
+ case 'c':
+ t.state = TokenizeStateLBracketStarC;
+ set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
+ break;
+ case ']':
+ set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ invalid_char_error(&t, c);
+ }
+ break;
+ case TokenizeStateLBracketStarC:
switch (c) {
case ']':
end_token(&t);
@@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) {
break;
case TokenizeStateSawAmpersand:
switch (c) {
+ case '&':
+ tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");
+ break;
case '=':
set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
end_token(&t);
@@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateLineStringContinue:
case TokenizeStateLineStringContinueC:
case TokenizeStateLBracketStar:
+ case TokenizeStateLBracketStarC:
tokenize_error(&t, "unexpected EOF");
break;
case TokenizeStateLineComment:
@@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) {
case TokenIdBitShiftRightEq: return ">>=";
case TokenIdBitXorEq: return "^=";
case TokenIdBracketStarBracket: return "[*]";
+ case TokenIdBracketStarCBracket: return "[*c]";
case TokenIdCharLiteral: return "CharLiteral";
case TokenIdCmpEq: return "==";
case TokenIdCmpGreaterOrEq: return ">=";
@@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordStruct: return "struct";
case TokenIdKeywordSwitch: return "switch";
case TokenIdKeywordTest: return "test";
+ case TokenIdKeywordThreadLocal: return "threadlocal";
case TokenIdKeywordTrue: return "true";
case TokenIdKeywordTry: return "try";
case TokenIdKeywordUndefined: return "undefined";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index 1574e95571..62117b5779 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -29,6 +29,7 @@ enum TokenId {
TokenIdBitShiftRightEq,
TokenIdBitXorEq,
TokenIdBracketStarBracket,
+ TokenIdBracketStarCBracket,
TokenIdCharLiteral,
TokenIdCmpEq,
TokenIdCmpGreaterOrEq,
@@ -88,6 +89,7 @@ enum TokenId {
TokenIdKeywordSuspend,
TokenIdKeywordSwitch,
TokenIdKeywordTest,
+ TokenIdKeywordThreadLocal,
TokenIdKeywordTrue,
TokenIdKeywordTry,
TokenIdKeywordUndefined,
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 10f2124eb6..a51a671b06 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -4,7 +4,6 @@
* This file is part of zig, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
-
#include "all_types.hpp"
#include "analyze.hpp"
#include "c_tokenizer.hpp"
@@ -13,7 +12,7 @@
#include "os.hpp"
#include "translate_c.hpp"
#include "parser.hpp"
-
+#include "zig_clang.h"
#if __GNUC__ >= 8
#pragma GCC diagnostic push
@@ -30,8 +29,6 @@
#include
-using namespace clang;
-
struct Alias {
Buf *new_name;
Buf *canon_name;
@@ -87,13 +84,13 @@ struct Context {
HashMap decl_table;
HashMap macro_table;
HashMap global_table;
- SourceManager *source_manager;
+ ZigClangSourceManager *source_manager;
ZigList aliases;
AstNode *source_node;
bool warnings_on;
CodeGen *codegen;
- ASTContext *ctx;
+ ZigClangASTContext *ctx;
TransScopeRoot *global_scope;
HashMap ptr_params;
@@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
static TransScopeBlock *trans_scope_block_find(TransScope *scope);
-static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
-static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
-static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
+static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
+static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);
+static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);
-static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
ResultUsed result_used, TransLRValue lrval,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope);
-static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
-static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
+static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
+static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
+
+static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
+ ZigClangSourceLocation dest;
+ memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
+ return dest;
+}
+static ZigClangQualType bitcast(clang::QualType src) {
+ ZigClangQualType dest;
+ memcpy(&dest, &src, sizeof(ZigClangQualType));
+ return dest;
+}
+static clang::QualType bitcast(ZigClangQualType src) {
+ clang::QualType dest;
+ memcpy(&dest, &src, sizeof(ZigClangQualType));
+ return dest;
+}
ATTRIBUTE_PRINTF(3, 4)
-static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
+static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {
if (!c->warnings_on) {
return;
}
@@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
Buf *msg = buf_vprintf(format, ap);
va_end(ap);
- StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));
- const char *filename_bytes = (const char *)filename.bytes_begin();
+ ZigClangSourceLocation sl = bitcast(clang_sl);
+ const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
+ ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
Buf *path;
if (filename_bytes) {
path = buf_create_from_str(filename_bytes);
} else {
path = buf_sprintf("(no file)");
}
- unsigned line = c->source_manager->getSpellingLineNumber(sl);
- unsigned column = c->source_manager->getSpellingColumnNumber(sl);
+ unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
+ unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
}
@@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
node);
}
+static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return TokenIdStar;
+ case PtrLenUnknown:
+ return TokenIdBracketStarBracket;
+ case PtrLenC:
+ return TokenIdBracketStarCBracket;
+ }
+ zig_unreachable();
+}
+
static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
AstNode *node = trans_create_node(c, NodeTypePointerType);
node->data.pointer_type.star_token = allocate(1);
- node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;
- node->data.pointer_type.is_const = is_const;
+ node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
node->data.pointer_type.is_const = is_const;
node->data.pointer_type.is_volatile = is_volatile;
node->data.pointer_type.op_expr = child_node;
@@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
}
-static const char *decl_name(const Decl *decl) {
- const NamedDecl *named_decl = static_cast(decl);
+static const char *decl_name(const clang::Decl *decl) {
+ const clang::NamedDecl *named_decl = static_cast(decl);
return (const char *)named_decl->getName().bytes_begin();
}
static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
node->data.int_literal.bigint = allocate(1);
- bool is_negative = aps_int.isNegative();
+ bool is_negative = aps_int.isSigned() && aps_int.isNegative();
if (!is_negative) {
bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
return node;
@@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
}
-static const Type *qual_type_canon(QualType qt) {
+static const clang::Type *qual_type_canon(clang::QualType qt) {
return qt.getCanonicalType().getTypePtr();
}
-static QualType get_expr_qual_type(Context *c, const Expr *expr) {
+static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {
// String literals in C are `char *` but they should really be `const char *`.
- if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *cast_expr = static_cast(expr);
- if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
- const Expr *sub_expr = cast_expr->getSubExpr();
- if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
- QualType array_qt = sub_expr->getType();
- const ArrayType *array_type = static_cast(array_qt.getTypePtr());
- QualType pointee_qt = array_type->getElementType();
+ if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = static_cast(expr);
+ if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
+ const clang::Expr *sub_expr = cast_expr->getSubExpr();
+ if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
+ clang::QualType array_qt = sub_expr->getType();
+ const clang::ArrayType *array_type = static_cast(array_qt.getTypePtr());
+ clang::QualType pointee_qt = array_type->getElementType();
pointee_qt.addConst();
- return c->ctx->getPointerType(pointee_qt);
+ return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
}
}
}
return expr->getType();
}
-static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
- if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *cast_expr = static_cast(expr);
+static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
+ if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = static_cast(expr);
return get_expr_qual_type(c, cast_expr->getSubExpr());
}
return expr->getType();
}
-static AstNode *get_expr_type(Context *c, const Expr *expr) {
+static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
}
-static bool qual_types_equal(QualType t1, QualType t2) {
+static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
if (t1.isConstQualified() != t2.isConstQualified()) {
return false;
}
@@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) {
return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
-static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
- QualType t1 = get_expr_qual_type(c, expr1);
- QualType t2 = get_expr_qual_type(c, expr2);
+static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
+ clang::QualType t1 = get_expr_qual_type(c, expr1);
+ clang::QualType t2 = get_expr_qual_type(c, expr2);
return qual_types_equal(t1, t2);
}
-static bool qual_type_is_ptr(QualType qt) {
- const Type *ty = qual_type_canon(qt);
- return ty->getTypeClass() == Type::Pointer;
+static bool qual_type_is_ptr(clang::QualType qt) {
+ const clang::Type *ty = qual_type_canon(qt);
+ return ty->getTypeClass() == clang::Type::Pointer;
}
-static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
- const Type *ty = qual_type_canon(qt);
+static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
+ const clang::Type *ty = qual_type_canon(qt);
*is_ptr = false;
- if (ty->getTypeClass() == Type::Pointer) {
+ if (ty->getTypeClass() == clang::Type::Pointer) {
*is_ptr = true;
- const PointerType *pointer_ty = static_cast(ty);
- QualType child_qt = pointer_ty->getPointeeType();
+ const clang::PointerType *pointer_ty = static_cast(ty);
+ clang::QualType child_qt = pointer_ty->getPointeeType();
ty = child_qt.getTypePtr();
}
- if (ty->getTypeClass() == Type::FunctionProto) {
- return static_cast(ty);
+ if (ty->getTypeClass() == clang::Type::FunctionProto) {
+ return static_cast(ty);
}
return nullptr;
}
-static bool qual_type_is_fn_ptr(QualType qt) {
+static bool qual_type_is_fn_ptr(clang::QualType qt) {
bool is_ptr;
if (qual_type_get_fn_proto(qt, &is_ptr)) {
return is_ptr;
@@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
return false;
}
-static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
- const Type *ty = qt.getTypePtr();
+static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
+ const clang::Type *ty = qt.getTypePtr();
switch (ty->getTypeClass()) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
return 8;
- case BuiltinType::UInt128:
- case BuiltinType::Int128:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Int128:
return 128;
default:
return 0;
}
zig_unreachable();
}
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
const char *type_name = decl_name(typedef_decl);
if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
return 8;
@@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
}
-static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
- const SourceLocation &source_loc)
+static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
+ const clang::SourceLocation &source_loc)
{
uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
if (int_bit_width != 0) {
@@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
// FieldAccess
// FnCall (.builtin = true)
// Symbol "import"
-// StringLiteral "std"
+// clang::StringLiteral "std"
// Symbol "math"
// Symbol "Log2Int"
// zig_type_node
@@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
return log2int_fn_call;
}
-static bool qual_type_child_is_fn_proto(const QualType &qt) {
- if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
- const ParenType *paren_type = static_cast(qt.getTypePtr());
- if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
+static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
+ if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
+ const clang::ParenType *paren_type = static_cast(qt.getTypePtr());
+ if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
return true;
}
- } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
- const AttributedType *attr_type = static_cast(qt.getTypePtr());
+ } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
+ const clang::AttributedType *attr_type = static_cast(qt.getTypePtr());
return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
}
return false;
}
-static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,
- QualType src_type, AstNode *expr)
+static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
+ clang::QualType src_type, AstNode *expr)
{
if (qual_types_equal(dest_type, src_type)) {
return expr;
@@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
}
-static bool c_is_signed_integer(Context *c, QualType qt) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_signed_integer(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::SChar:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::Int128:
- case BuiltinType::WChar_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::WChar_S:
return true;
default:
return false;
}
}
-static bool c_is_unsigned_integer(Context *c, QualType qt) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128:
- case BuiltinType::WChar_U:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::WChar_U:
return true;
default:
return false;
}
}
-static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
return builtin_ty->getKind() == kind;
}
-static bool c_is_float(Context *c, QualType qt) {
- const Type *c_type = qt.getTypePtr();
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_float(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qt.getTypePtr();
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::Float128:
- case BuiltinType::LongDouble:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::Float128:
+ case clang::BuiltinType::LongDouble:
return true;
default:
return false;
}
}
-static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
+static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
// float and signed integer overflow is undefined behavior.
return false;
@@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
}
}
-static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {
+static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
- case Type::Builtin: {
- const BuiltinType *builtin_ty = static_cast(ty);
- return builtin_ty->getKind() == BuiltinType::Void;
+ case clang::Type::Builtin: {
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
+ return builtin_ty->getKind() == clang::BuiltinType::Void;
}
- case Type::Record: {
- const RecordType *record_ty = static_cast(ty);
+ case clang::Type::Record: {
+ const clang::RecordType *record_ty = static_cast(ty);
return record_ty->getDecl()->getDefinition() == nullptr;
}
- case Type::Elaborated: {
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ case clang::Type::Elaborated: {
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
}
- case Type::Typedef: {
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ case clang::Type::Typedef: {
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
}
default:
@@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
}
}
-static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
+static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Void:
+ case clang::BuiltinType::Void:
return trans_create_node_symbol_str(c, "c_void");
- case BuiltinType::Bool:
+ case clang::BuiltinType::Bool:
return trans_create_node_symbol_str(c, "bool");
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::Char8:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::Char8:
return trans_create_node_symbol_str(c, "u8");
- case BuiltinType::SChar:
+ case clang::BuiltinType::SChar:
return trans_create_node_symbol_str(c, "i8");
- case BuiltinType::UShort:
+ case clang::BuiltinType::UShort:
return trans_create_node_symbol_str(c, "c_ushort");
- case BuiltinType::UInt:
+ case clang::BuiltinType::UInt:
return trans_create_node_symbol_str(c, "c_uint");
- case BuiltinType::ULong:
+ case clang::BuiltinType::ULong:
return trans_create_node_symbol_str(c, "c_ulong");
- case BuiltinType::ULongLong:
+ case clang::BuiltinType::ULongLong:
return trans_create_node_symbol_str(c, "c_ulonglong");
- case BuiltinType::Short:
+ case clang::BuiltinType::Short:
return trans_create_node_symbol_str(c, "c_short");
- case BuiltinType::Int:
+ case clang::BuiltinType::Int:
return trans_create_node_symbol_str(c, "c_int");
- case BuiltinType::Long:
+ case clang::BuiltinType::Long:
return trans_create_node_symbol_str(c, "c_long");
- case BuiltinType::LongLong:
+ case clang::BuiltinType::LongLong:
return trans_create_node_symbol_str(c, "c_longlong");
- case BuiltinType::UInt128:
+ case clang::BuiltinType::UInt128:
return trans_create_node_symbol_str(c, "u128");
- case BuiltinType::Int128:
+ case clang::BuiltinType::Int128:
return trans_create_node_symbol_str(c, "i128");
- case BuiltinType::Float:
+ case clang::BuiltinType::Float:
return trans_create_node_symbol_str(c, "f32");
- case BuiltinType::Double:
+ case clang::BuiltinType::Double:
return trans_create_node_symbol_str(c, "f64");
- case BuiltinType::Float128:
+ case clang::BuiltinType::Float128:
return trans_create_node_symbol_str(c, "f128");
- case BuiltinType::Float16:
+ case clang::BuiltinType::Float16:
return trans_create_node_symbol_str(c, "f16");
- case BuiltinType::LongDouble:
+ case clang::BuiltinType::LongDouble:
return trans_create_node_symbol_str(c, "c_longdouble");
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::WChar_S:
- case BuiltinType::Half:
- case BuiltinType::NullPtr:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OMPArraySection:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::PseudoObject:
- case BuiltinType::UnknownAny:
- case BuiltinType::BuiltinFn:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::OMPArraySection:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
- case BuiltinType::OCLImage1dRO:
- case BuiltinType::OCLImage1dArrayRO:
- case BuiltinType::OCLImage1dBufferRO:
- case BuiltinType::OCLImage2dRO:
- case BuiltinType::OCLImage2dArrayRO:
- case BuiltinType::OCLImage2dDepthRO:
- case BuiltinType::OCLImage2dArrayDepthRO:
- case BuiltinType::OCLImage2dMSAARO:
- case BuiltinType::OCLImage2dArrayMSAARO:
- case BuiltinType::OCLImage2dMSAADepthRO:
- case BuiltinType::OCLImage2dArrayMSAADepthRO:
- case BuiltinType::OCLImage3dRO:
- case BuiltinType::OCLImage1dWO:
- case BuiltinType::OCLImage1dArrayWO:
- case BuiltinType::OCLImage1dBufferWO:
- case BuiltinType::OCLImage2dWO:
- case BuiltinType::OCLImage2dArrayWO:
- case BuiltinType::OCLImage2dDepthWO:
- case BuiltinType::OCLImage2dArrayDepthWO:
- case BuiltinType::OCLImage2dMSAAWO:
- case BuiltinType::OCLImage2dArrayMSAAWO:
- case BuiltinType::OCLImage2dMSAADepthWO:
- case BuiltinType::OCLImage2dArrayMSAADepthWO:
- case BuiltinType::OCLImage3dWO:
- case BuiltinType::OCLImage1dRW:
- case BuiltinType::OCLImage1dArrayRW:
- case BuiltinType::OCLImage1dBufferRW:
- case BuiltinType::OCLImage2dRW:
- case BuiltinType::OCLImage2dArrayRW:
- case BuiltinType::OCLImage2dDepthRW:
- case BuiltinType::OCLImage2dArrayDepthRW:
- case BuiltinType::OCLImage2dMSAARW:
- case BuiltinType::OCLImage2dArrayMSAARW:
- case BuiltinType::OCLImage2dMSAADepthRW:
- case BuiltinType::OCLImage2dArrayMSAADepthRW:
- case BuiltinType::OCLImage3dRW:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
+ case clang::BuiltinType::OCLImage1dRO:
+ case clang::BuiltinType::OCLImage1dArrayRO:
+ case clang::BuiltinType::OCLImage1dBufferRO:
+ case clang::BuiltinType::OCLImage2dRO:
+ case clang::BuiltinType::OCLImage2dArrayRO:
+ case clang::BuiltinType::OCLImage2dDepthRO:
+ case clang::BuiltinType::OCLImage2dArrayDepthRO:
+ case clang::BuiltinType::OCLImage2dMSAARO:
+ case clang::BuiltinType::OCLImage2dArrayMSAARO:
+ case clang::BuiltinType::OCLImage2dMSAADepthRO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case clang::BuiltinType::OCLImage3dRO:
+ case clang::BuiltinType::OCLImage1dWO:
+ case clang::BuiltinType::OCLImage1dArrayWO:
+ case clang::BuiltinType::OCLImage1dBufferWO:
+ case clang::BuiltinType::OCLImage2dWO:
+ case clang::BuiltinType::OCLImage2dArrayWO:
+ case clang::BuiltinType::OCLImage2dDepthWO:
+ case clang::BuiltinType::OCLImage2dArrayDepthWO:
+ case clang::BuiltinType::OCLImage2dMSAAWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAAWO:
+ case clang::BuiltinType::OCLImage2dMSAADepthWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case clang::BuiltinType::OCLImage3dWO:
+ case clang::BuiltinType::OCLImage1dRW:
+ case clang::BuiltinType::OCLImage1dArrayRW:
+ case clang::BuiltinType::OCLImage1dBufferRW:
+ case clang::BuiltinType::OCLImage2dRW:
+ case clang::BuiltinType::OCLImage2dArrayRW:
+ case clang::BuiltinType::OCLImage2dDepthRW:
+ case clang::BuiltinType::OCLImage2dArrayDepthRW:
+ case clang::BuiltinType::OCLImage2dMSAARW:
+ case clang::BuiltinType::OCLImage2dArrayMSAARW:
+ case clang::BuiltinType::OCLImage2dMSAADepthRW:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case clang::BuiltinType::OCLImage3dRW:
+ case clang::BuiltinType::OCLSampler:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLClkEvent:
+ case clang::BuiltinType::OCLQueue:
+ case clang::BuiltinType::OCLReserveID:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
emit_warning(c, source_loc, "unsupported builtin type");
return nullptr;
}
break;
}
- case Type::Pointer:
+ case clang::Type::Pointer:
{
- const PointerType *pointer_ty = static_cast(ty);
- QualType child_qt = pointer_ty->getPointeeType();
+ const clang::PointerType *pointer_ty = static_cast(ty);
+ clang::QualType child_qt = pointer_ty->getPointeeType();
AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
if (child_node == nullptr) {
emit_warning(c, source_loc, "pointer to unsupported type");
@@ -925,90 +950,93 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
}
- PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
-
- AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_node, ptr_len);
- return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
+ if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
+ AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
+ child_qt.isVolatileQualified(), child_node, PtrLenSingle);
+ return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
+ } else {
+ return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
+ child_qt.isVolatileQualified(), child_node, PtrLenC);
+ }
}
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
return resolve_typedef_decl(c, typedef_decl);
}
- case Type::Elaborated:
+ case clang::Type::Elaborated:
{
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
switch (elaborated_ty->getKeyword()) {
- case ETK_Struct:
- case ETK_Enum:
- case ETK_Union:
+ case clang::ETK_Struct:
+ case clang::ETK_Enum:
+ case clang::ETK_Union:
return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
- case ETK_Interface:
- case ETK_Class:
- case ETK_Typename:
- case ETK_None:
+ case clang::ETK_Interface:
+ case clang::ETK_Class:
+ case clang::ETK_Typename:
+ case clang::ETK_None:
emit_warning(c, source_loc, "unsupported elaborated type");
return nullptr;
}
}
- case Type::FunctionProto:
+ case clang::Type::FunctionProto:
{
- const FunctionProtoType *fn_proto_ty = static_cast(ty);
+ const clang::FunctionProtoType *fn_proto_ty = static_cast(ty);
AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
switch (fn_proto_ty->getCallConv()) {
- case CC_C: // __attribute__((cdecl))
+ case clang::CC_C: // __attribute__((cdecl))
proto_node->data.fn_proto.cc = CallingConventionC;
proto_node->data.fn_proto.is_extern = true;
break;
- case CC_X86StdCall: // __attribute__((stdcall))
+ case clang::CC_X86StdCall: // __attribute__((stdcall))
proto_node->data.fn_proto.cc = CallingConventionStdcall;
break;
- case CC_X86FastCall: // __attribute__((fastcall))
+ case clang::CC_X86FastCall: // __attribute__((fastcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
return nullptr;
- case CC_X86ThisCall: // __attribute__((thiscall))
+ case clang::CC_X86ThisCall: // __attribute__((thiscall))
emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
return nullptr;
- case CC_X86VectorCall: // __attribute__((vectorcall))
+ case clang::CC_X86VectorCall: // __attribute__((vectorcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
return nullptr;
- case CC_X86Pascal: // __attribute__((pascal))
+ case clang::CC_X86Pascal: // __attribute__((pascal))
emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
return nullptr;
- case CC_Win64: // __attribute__((ms_abi))
+ case clang::CC_Win64: // __attribute__((ms_abi))
emit_warning(c, source_loc, "unsupported calling convention: win64");
return nullptr;
- case CC_X86_64SysV: // __attribute__((sysv_abi))
+ case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
return nullptr;
- case CC_X86RegCall:
+ case clang::CC_X86RegCall:
emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
return nullptr;
- case CC_AAPCS: // __attribute__((pcs("aapcs")))
+ case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs");
return nullptr;
- case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
+ case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
return nullptr;
- case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
+ case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
return nullptr;
- case CC_SpirFunction: // default for OpenCL functions on SPIR target
+ case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
return nullptr;
- case CC_OpenCLKernel:
+ case clang::CC_OpenCLKernel:
emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
return nullptr;
- case CC_Swift:
+ case clang::CC_Swift:
emit_warning(c, source_loc, "unsupported calling convention: Swift");
return nullptr;
- case CC_PreserveMost:
+ case clang::CC_PreserveMost:
emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
return nullptr;
- case CC_PreserveAll:
+ case clang::CC_PreserveAll:
emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
return nullptr;
}
@@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return nullptr;
}
// convert c_void to actual void (only for return type)
- // we do want to look at the AstNode instead of QualType, because
+ // we do want to look at the AstNode instead of clang::QualType, because
// if they do something like:
// typedef Foo void;
// void foo(void) -> Foo;
@@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
}
for (size_t i = 0; i < param_count; i += 1) {
- QualType qt = fn_proto_ty->getParamType(i);
+ clang::QualType qt = fn_proto_ty->getParamType(i);
AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
if (param_type_node == nullptr) {
@@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return proto_node;
}
- case Type::Record:
+ case clang::Type::Record:
{
- const RecordType *record_ty = static_cast(ty);
+ const clang::RecordType *record_ty = static_cast(ty);
return resolve_record_decl(c, record_ty->getDecl());
}
- case Type::Enum:
+ case clang::Type::Enum:
{
- const EnumType *enum_ty = static_cast(ty);
+ const clang::EnumType *enum_ty = static_cast(ty);
return resolve_enum_decl(c, enum_ty->getDecl());
}
- case Type::ConstantArray:
+ case clang::Type::ConstantArray:
{
- const ConstantArrayType *const_arr_ty = static_cast(ty);
+ const clang::ConstantArrayType *const_arr_ty = static_cast(ty);
AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
if (child_type_node == nullptr) {
emit_warning(c, source_loc, "unresolved array element type");
@@ -1088,84 +1116,84 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
AstNode *size_node = trans_create_node_unsigned(c, size);
return trans_create_node_array_type(c, size_node, child_type_node);
}
- case Type::Paren:
+ case clang::Type::Paren:
{
- const ParenType *paren_ty = static_cast(ty);
+ const clang::ParenType *paren_ty = static_cast(ty);
return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
}
- case Type::Decayed:
+ case clang::Type::Decayed:
{
- const DecayedType *decayed_ty = static_cast(ty);
+ const clang::DecayedType *decayed_ty = static_cast(ty);
return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
}
- case Type::Attributed:
+ case clang::Type::Attributed:
{
- const AttributedType *attributed_ty = static_cast(ty);
+ const clang::AttributedType *attributed_ty = static_cast(ty);
return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
}
- case Type::IncompleteArray:
+ case clang::Type::IncompleteArray:
{
- const IncompleteArrayType *incomplete_array_ty = static_cast(ty);
- QualType child_qt = incomplete_array_ty->getElementType();
+ const clang::IncompleteArrayType *incomplete_array_ty = static_cast(ty);
+ clang::QualType child_qt = incomplete_array_ty->getElementType();
AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
if (child_type_node == nullptr) {
emit_warning(c, source_loc, "unresolved array element type");
return nullptr;
}
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown);
+ child_qt.isVolatileQualified(), child_type_node, PtrLenC);
return pointer_node;
}
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionNoProto:
- case Type::UnresolvedUsing:
- case Type::Adjusted:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::Auto:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Complex:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- case Type::Pipe:
- case Type::ObjCTypeParam:
- case Type::DeducedTemplateSpecialization:
- case Type::DependentAddressSpace:
- case Type::DependentVector:
+ case clang::Type::BlockPointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer:
+ case clang::Type::VariableArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ case clang::Type::FunctionNoProto:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Adjusted:
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::UnaryTransform:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Auto:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ case clang::Type::Complex:
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::Atomic:
+ case clang::Type::Pipe:
+ case clang::Type::ObjCTypeParam:
+ case clang::Type::DeducedTemplateSpecialization:
+ case clang::Type::DependentAddressSpace:
+ case clang::Type::DependentVector:
emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {
+static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {
return trans_type(c, qt.getTypePtr(), source_loc);
}
-static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt,
+static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
AstNode *block_node, TransScope **out_node_scope)
{
assert(block_node->type == NodeTypeBlock);
- for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
+ for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
AstNode *child_node;
scope = trans_stmt(c, scope, *it, &child_node);
if (scope == nullptr)
@@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
return ErrorNone;
}
-static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,
+static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
TransScope **out_node_scope)
{
TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
@@ -1188,8 +1216,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun
return child_scope_block->node;
}
-static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {
- const Expr *value_expr = stmt->getRetValue();
+static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
+ const clang::Expr *value_expr = stmt->getRetValue();
if (value_expr == nullptr) {
return trans_create_node(c, NodeTypeReturnExpr);
} else {
@@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
}
}
-static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
+static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
llvm::APSInt result;
- if (!stmt->EvaluateAsInt(result, *c->ctx)) {
+ if (!stmt->EvaluateAsInt(result, *reinterpret_cast(c->ctx))) {
emit_warning(c, stmt->getLocStart(), "invalid integer literal");
return nullptr;
}
@@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
}
static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
- const ConditionalOperator *stmt)
+ const clang::ConditionalOperator *stmt)
{
AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
- Expr *cond_expr = stmt->getCond();
- Expr *true_expr = stmt->getTrueExpr();
- Expr *false_expr = stmt->getFalseExpr();
+ clang::Expr *cond_expr = stmt->getCond();
+ clang::Expr *true_expr = stmt->getTrueExpr();
+ clang::Expr *false_expr = stmt->getFalseExpr();
node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
if (node->data.if_bool_expr.condition == nullptr)
@@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
return maybe_suppress_result(c, result_used, node);
}
-static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
+static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1249,7 +1277,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
return node;
}
-static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
+static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1265,7 +1293,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh
return node;
}
-static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {
+static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {
if (result_used == ResultUsedNo) {
// common case
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
@@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
}
}
-static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,
- Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)
+static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
+ clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
{
- const SourceLocation &rhs_location = rhs_expr->getLocStart();
+ const clang::SourceLocation &rhs_location = rhs_expr->getLocStart();
AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
// lhs >> u5(rh)
@@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
}
-static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) {
+static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
switch (stmt->getOpcode()) {
- case BO_PtrMemD:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");
+ case clang::BO_PtrMemD:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemD");
return nullptr;
- case BO_PtrMemI:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
+ case clang::BO_PtrMemI:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemI");
return nullptr;
- case BO_Cmp:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Cmp");
+ case clang::BO_Cmp:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp");
return nullptr;
- case BO_Mul:
+ case clang::BO_Mul:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
stmt->getRHS());
- case BO_Div:
+ case clang::BO_Div:
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
// unsigned/float division uses the operator
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
@@ -1363,7 +1391,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
fn_call->data.fn_call_expr.params.append(rhs);
return fn_call;
}
- case BO_Rem:
+ case clang::BO_Rem:
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
// unsigned/float division uses the operator
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
@@ -1378,43 +1406,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
fn_call->data.fn_call_expr.params.append(rhs);
return fn_call;
}
- case BO_Add:
+ case clang::BO_Add:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
stmt->getRHS());
- case BO_Sub:
+ case clang::BO_Sub:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
stmt->getRHS());
- case BO_Shl:
+ case clang::BO_Shl:
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
- case BO_Shr:
+ case clang::BO_Shr:
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
- case BO_LT:
+ case clang::BO_LT:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
- case BO_GT:
+ case clang::BO_GT:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
- case BO_LE:
+ case clang::BO_LE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
- case BO_GE:
+ case clang::BO_GE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
- case BO_EQ:
+ case clang::BO_EQ:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
- case BO_NE:
+ case clang::BO_NE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
- case BO_And:
+ case clang::BO_And:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
- case BO_Xor:
+ case clang::BO_Xor:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
- case BO_Or:
+ case clang::BO_Or:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
- case BO_LAnd:
+ case clang::BO_LAnd:
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
- case BO_LOr:
+ case clang::BO_LOr:
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
- case BO_Assign:
+ case clang::BO_Assign:
return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
- case BO_Comma:
+ case clang::BO_Comma:
{
TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
@@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
return scope_block->node;
}
- case BO_MulAssign:
- case BO_DivAssign:
- case BO_RemAssign:
- case BO_AddAssign:
- case BO_SubAssign:
- case BO_ShlAssign:
- case BO_ShrAssign:
- case BO_AndAssign:
- case BO_XorAssign:
- case BO_OrAssign:
+ case clang::BO_MulAssign:
+ case clang::BO_DivAssign:
+ case clang::BO_RemAssign:
+ case clang::BO_AddAssign:
+ case clang::BO_SubAssign:
+ case clang::BO_ShlAssign:
+ case clang::BO_ShrAssign:
+ case clang::BO_AndAssign:
+ case clang::BO_XorAssign:
+ case clang::BO_OrAssign:
zig_unreachable();
}
@@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
}
static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
+ const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
{
- const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
+ const clang::SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
@@ -1530,7 +1558,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
}
static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
+ const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
{
if (result_used == ResultUsedNo) {
// simple common case, where the C and Zig are identical:
@@ -1590,76 +1618,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt)
+ const clang::CompoundAssignOperator *stmt)
{
switch (stmt->getOpcode()) {
- case BO_MulAssign:
+ case clang::BO_MulAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
- case BO_DivAssign:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
+ case clang::BO_DivAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_DivAssign");
return nullptr;
- case BO_RemAssign:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
+ case clang::BO_RemAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_RemAssign");
return nullptr;
- case BO_Cmp:
- emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_Cmp");
+ case clang::BO_Cmp:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_Cmp");
return nullptr;
- case BO_AddAssign:
+ case clang::BO_AddAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
- case BO_SubAssign:
+ case clang::BO_SubAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
- case BO_ShlAssign:
+ case clang::BO_ShlAssign:
return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
- case BO_ShrAssign:
+ case clang::BO_ShrAssign:
return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
- case BO_AndAssign:
+ case clang::BO_AndAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
- case BO_XorAssign:
+ case clang::BO_XorAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
- case BO_OrAssign:
+ case clang::BO_OrAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
- case BO_PtrMemD:
- case BO_PtrMemI:
- case BO_Assign:
- case BO_Mul:
- case BO_Div:
- case BO_Rem:
- case BO_Add:
- case BO_Sub:
- case BO_Shl:
- case BO_Shr:
- case BO_LT:
- case BO_GT:
- case BO_LE:
- case BO_GE:
- case BO_EQ:
- case BO_NE:
- case BO_And:
- case BO_Xor:
- case BO_Or:
- case BO_LAnd:
- case BO_LOr:
- case BO_Comma:
+ case clang::BO_PtrMemD:
+ case clang::BO_PtrMemI:
+ case clang::BO_Assign:
+ case clang::BO_Mul:
+ case clang::BO_Div:
+ case clang::BO_Rem:
+ case clang::BO_Add:
+ case clang::BO_Sub:
+ case clang::BO_Shl:
+ case clang::BO_Shr:
+ case clang::BO_LT:
+ case clang::BO_GT:
+ case clang::BO_LE:
+ case clang::BO_GE:
+ case clang::BO_EQ:
+ case clang::BO_NE:
+ case clang::BO_And:
+ case clang::BO_Xor:
+ case clang::BO_Or:
+ case clang::BO_LAnd:
+ case clang::BO_LOr:
+ case clang::BO_Comma:
zig_unreachable();
}
zig_unreachable();
}
-static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) {
+static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
switch (stmt->getCastKind()) {
- case CK_LValueToRValue:
+ case clang::CK_LValueToRValue:
return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
- case CK_IntegralCast:
+ case clang::CK_IntegralCast:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
@@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
stmt->getSubExpr()->getType(), target_node);
}
- case CK_FunctionToPointerDecay:
- case CK_ArrayToPointerDecay:
+ case clang::CK_FunctionToPointerDecay:
+ case clang::CK_ArrayToPointerDecay:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
return nullptr;
return target_node;
}
- case CK_BitCast:
+ case clang::CK_BitCast:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
@@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
node->data.fn_call_expr.params.append(target_node);
return node;
}
- case CK_NullToPointer:
- return trans_create_node(c, NodeTypeNullLiteral);
- case CK_Dependent:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
+ case clang::CK_NullToPointer:
+ return trans_create_node_unsigned(c, 0);
+ case clang::CK_Dependent:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dependent");
return nullptr;
- case CK_LValueBitCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");
+ case clang::CK_LValueBitCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_LValueBitCast");
return nullptr;
- case CK_NoOp:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp");
+ case clang::CK_NoOp:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NoOp");
return nullptr;
- case CK_BaseToDerived:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived");
+ case clang::CK_BaseToDerived:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerived");
return nullptr;
- case CK_DerivedToBase:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase");
+ case clang::CK_DerivedToBase:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBase");
return nullptr;
- case CK_UncheckedDerivedToBase:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
+ case clang::CK_UncheckedDerivedToBase:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UncheckedDerivedToBase");
return nullptr;
- case CK_Dynamic:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic");
+ case clang::CK_Dynamic:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dynamic");
return nullptr;
- case CK_ToUnion:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");
+ case clang::CK_ToUnion:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToUnion");
return nullptr;
- case CK_NullToMemberPointer:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer");
+ case clang::CK_NullToMemberPointer:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NullToMemberPointer");
return nullptr;
- case CK_BaseToDerivedMemberPointer:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
+ case clang::CK_BaseToDerivedMemberPointer:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerivedMemberPointer");
return nullptr;
- case CK_DerivedToBaseMemberPointer:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
+ case clang::CK_DerivedToBaseMemberPointer:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBaseMemberPointer");
return nullptr;
- case CK_MemberPointerToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean");
+ case clang::CK_MemberPointerToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_MemberPointerToBoolean");
return nullptr;
- case CK_ReinterpretMemberPointer:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
+ case clang::CK_ReinterpretMemberPointer:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ReinterpretMemberPointer");
return nullptr;
- case CK_UserDefinedConversion:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion");
+ case clang::CK_UserDefinedConversion:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UserDefinedConversion");
return nullptr;
- case CK_ConstructorConversion:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion");
+ case clang::CK_ConstructorConversion:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ConstructorConversion");
return nullptr;
- case CK_IntegralToPointer:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer");
+ case clang::CK_IntegralToPointer:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToPointer");
return nullptr;
- case CK_PointerToIntegral:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral");
+ case clang::CK_PointerToIntegral:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToIntegral");
return nullptr;
- case CK_PointerToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean");
+ case clang::CK_PointerToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToBoolean");
return nullptr;
- case CK_ToVoid:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid");
+ case clang::CK_ToVoid:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToVoid");
return nullptr;
- case CK_VectorSplat:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat");
+ case clang::CK_VectorSplat:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_VectorSplat");
return nullptr;
- case CK_IntegralToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean");
+ case clang::CK_IntegralToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToBoolean");
return nullptr;
- case CK_IntegralToFloating:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating");
+ case clang::CK_IntegralToFloating:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToFloating");
return nullptr;
- case CK_FloatingToIntegral:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral");
+ case clang::CK_FloatingToIntegral:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToIntegral");
return nullptr;
- case CK_FloatingToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean");
+ case clang::CK_FloatingToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToBoolean");
return nullptr;
- case CK_BooleanToSignedIntegral:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral");
+ case clang::CK_BooleanToSignedIntegral:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BooleanToSignedIntegral");
return nullptr;
- case CK_FloatingCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast");
+ case clang::CK_FloatingCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingCast");
return nullptr;
- case CK_CPointerToObjCPointerCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");
+ case clang::CK_CPointerToObjCPointerCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CPointerToObjCPointerCast");
return nullptr;
- case CK_BlockPointerToObjCPointerCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");
+ case clang::CK_BlockPointerToObjCPointerCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BlockPointerToObjCPointerCast");
return nullptr;
- case CK_AnyPointerToBlockPointerCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");
+ case clang::CK_AnyPointerToBlockPointerCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AnyPointerToBlockPointerCast");
return nullptr;
- case CK_ObjCObjectLValueCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast");
+ case clang::CK_ObjCObjectLValueCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ObjCObjectLValueCast");
return nullptr;
- case CK_FloatingRealToComplex:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex");
+ case clang::CK_FloatingRealToComplex:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingRealToComplex");
return nullptr;
- case CK_FloatingComplexToReal:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal");
+ case clang::CK_FloatingComplexToReal:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToReal");
return nullptr;
- case CK_FloatingComplexToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean");
+ case clang::CK_FloatingComplexToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToBoolean");
return nullptr;
- case CK_FloatingComplexCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast");
+ case clang::CK_FloatingComplexCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexCast");
return nullptr;
- case CK_FloatingComplexToIntegralComplex:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");
+ case clang::CK_FloatingComplexToIntegralComplex:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToIntegralComplex");
return nullptr;
- case CK_IntegralRealToComplex:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex");
+ case clang::CK_IntegralRealToComplex:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralRealToComplex");
return nullptr;
- case CK_IntegralComplexToReal:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal");
+ case clang::CK_IntegralComplexToReal:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToReal");
return nullptr;
- case CK_IntegralComplexToBoolean:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean");
+ case clang::CK_IntegralComplexToBoolean:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToBoolean");
return nullptr;
- case CK_IntegralComplexCast:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast");
+ case clang::CK_IntegralComplexCast:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexCast");
return nullptr;
- case CK_IntegralComplexToFloatingComplex:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");
+ case clang::CK_IntegralComplexToFloatingComplex:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToFloatingComplex");
return nullptr;
- case CK_ARCProduceObject:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject");
+ case clang::CK_ARCProduceObject:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCProduceObject");
return nullptr;
- case CK_ARCConsumeObject:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject");
+ case clang::CK_ARCConsumeObject:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCConsumeObject");
return nullptr;
- case CK_ARCReclaimReturnedObject:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");
+ case clang::CK_ARCReclaimReturnedObject:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCReclaimReturnedObject");
return nullptr;
- case CK_ARCExtendBlockObject:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject");
+ case clang::CK_ARCExtendBlockObject:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCExtendBlockObject");
return nullptr;
- case CK_AtomicToNonAtomic:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic");
+ case clang::CK_AtomicToNonAtomic:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AtomicToNonAtomic");
return nullptr;
- case CK_NonAtomicToAtomic:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic");
+ case clang::CK_NonAtomicToAtomic:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NonAtomicToAtomic");
return nullptr;
- case CK_CopyAndAutoreleaseBlockObject:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");
+ case clang::CK_CopyAndAutoreleaseBlockObject:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CopyAndAutoreleaseBlockObject");
return nullptr;
- case CK_BuiltinFnToFnPtr:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");
+ case clang::CK_BuiltinFnToFnPtr:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BuiltinFnToFnPtr");
return nullptr;
- case CK_ZeroToOCLEvent:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent");
+ case clang::CK_ZeroToOCLEvent:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLEvent");
return nullptr;
- case CK_ZeroToOCLQueue:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue");
+ case clang::CK_ZeroToOCLQueue:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLQueue");
return nullptr;
- case CK_AddressSpaceConversion:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion");
+ case clang::CK_AddressSpaceConversion:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AddressSpaceConversion");
return nullptr;
- case CK_IntToOCLSampler:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler");
+ case clang::CK_IntToOCLSampler:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntToOCLSampler");
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {
- const ValueDecl *value_decl = stmt->getDecl();
+static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
+ const clang::ValueDecl *value_decl = stmt->getDecl();
Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
if (lrval == TransLValue) {
@@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
}
static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
- const UnaryOperator *stmt, BinOpType assign_op)
+ const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (result_used == ResultUsedNo) {
// common case
@@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
}
static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
- const UnaryOperator *stmt, BinOpType assign_op)
+ const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (result_used == ResultUsedNo) {
// common case
@@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
return child_scope->node;
}
-static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) {
+static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
switch (stmt->getOpcode()) {
- case UO_PostInc:
+ case clang::UO_PostInc:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
- case UO_PostDec:
+ case clang::UO_PostDec:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
- case UO_PreInc:
+ case clang::UO_PreInc:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
- case UO_PreDec:
+ case clang::UO_PreDec:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
- case UO_AddrOf:
+ case clang::UO_AddrOf:
{
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
if (value_node == nullptr)
return value_node;
return trans_create_node_addr_of(c, value_node);
}
- case UO_Deref:
+ case clang::UO_Deref:
{
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
if (value_node == nullptr)
@@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
return trans_create_node_ptr_deref(c, unwrapped);
}
- case UO_Plus:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
+ case clang::UO_Plus:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Plus");
return nullptr;
- case UO_Minus:
+ case clang::UO_Minus:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
@@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
return nullptr;
}
}
- case UO_Not:
+ case clang::UO_Not:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
}
- case UO_LNot:
+ case clang::UO_LNot:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
}
- case UO_Real:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");
+ case clang::UO_Real:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Real");
return nullptr;
- case UO_Imag:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag");
+ case clang::UO_Imag:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag");
return nullptr;
- case UO_Extension:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension");
+ case clang::UO_Extension:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension");
return nullptr;
- case UO_Coawait:
- emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait");
+ case clang::UO_Coawait:
+ emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait");
return nullptr;
}
zig_unreachable();
}
-static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt,
+static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt,
AstNode **out_node, TransScope **out_scope)
{
// declarations are added via the scope
@@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
assert(scope_block != nullptr);
for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
- Decl *decl = *iter;
+ clang::Decl *decl = *iter;
switch (decl->getKind()) {
- case Decl::Var: {
- VarDecl *var_decl = (VarDecl *)decl;
- QualType qual_type = var_decl->getTypeSourceInfo()->getType();
+ case clang::Decl::Var: {
+ clang::VarDecl *var_decl = (clang::VarDecl *)decl;
+ clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
AstNode *init_node = nullptr;
if (var_decl->hasInit()) {
init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);
@@ -2114,220 +2142,220 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
scope_block->node->data.block.statements.append(node);
continue;
}
- case Decl::AccessSpec:
+ case clang::Decl::AccessSpec:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");
return ErrorUnexpected;
- case Decl::Block:
+ case clang::Decl::Block:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");
return ErrorUnexpected;
- case Decl::Captured:
+ case clang::Decl::Captured:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");
return ErrorUnexpected;
- case Decl::ClassScopeFunctionSpecialization:
+ case clang::Decl::ClassScopeFunctionSpecialization:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");
return ErrorUnexpected;
- case Decl::Empty:
+ case clang::Decl::Empty:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");
return ErrorUnexpected;
- case Decl::Export:
+ case clang::Decl::Export:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");
return ErrorUnexpected;
- case Decl::ExternCContext:
+ case clang::Decl::ExternCContext:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");
return ErrorUnexpected;
- case Decl::FileScopeAsm:
+ case clang::Decl::FileScopeAsm:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");
return ErrorUnexpected;
- case Decl::Friend:
+ case clang::Decl::Friend:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");
return ErrorUnexpected;
- case Decl::FriendTemplate:
+ case clang::Decl::FriendTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");
return ErrorUnexpected;
- case Decl::Import:
+ case clang::Decl::Import:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");
return ErrorUnexpected;
- case Decl::LinkageSpec:
+ case clang::Decl::LinkageSpec:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");
return ErrorUnexpected;
- case Decl::Label:
+ case clang::Decl::Label:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");
return ErrorUnexpected;
- case Decl::Namespace:
+ case clang::Decl::Namespace:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");
return ErrorUnexpected;
- case Decl::NamespaceAlias:
+ case clang::Decl::NamespaceAlias:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");
return ErrorUnexpected;
- case Decl::ObjCCompatibleAlias:
+ case clang::Decl::ObjCCompatibleAlias:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");
return ErrorUnexpected;
- case Decl::ObjCCategory:
+ case clang::Decl::ObjCCategory:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");
return ErrorUnexpected;
- case Decl::ObjCCategoryImpl:
+ case clang::Decl::ObjCCategoryImpl:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");
return ErrorUnexpected;
- case Decl::ObjCImplementation:
+ case clang::Decl::ObjCImplementation:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");
return ErrorUnexpected;
- case Decl::ObjCInterface:
+ case clang::Decl::ObjCInterface:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");
return ErrorUnexpected;
- case Decl::ObjCProtocol:
+ case clang::Decl::ObjCProtocol:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");
return ErrorUnexpected;
- case Decl::ObjCMethod:
+ case clang::Decl::ObjCMethod:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");
return ErrorUnexpected;
- case Decl::ObjCProperty:
+ case clang::Decl::ObjCProperty:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");
return ErrorUnexpected;
- case Decl::BuiltinTemplate:
+ case clang::Decl::BuiltinTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");
return ErrorUnexpected;
- case Decl::ClassTemplate:
+ case clang::Decl::ClassTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");
return ErrorUnexpected;
- case Decl::FunctionTemplate:
+ case clang::Decl::FunctionTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");
return ErrorUnexpected;
- case Decl::TypeAliasTemplate:
+ case clang::Decl::TypeAliasTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");
return ErrorUnexpected;
- case Decl::VarTemplate:
+ case clang::Decl::VarTemplate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");
return ErrorUnexpected;
- case Decl::TemplateTemplateParm:
+ case clang::Decl::TemplateTemplateParm:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");
return ErrorUnexpected;
- case Decl::Enum:
+ case clang::Decl::Enum:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");
return ErrorUnexpected;
- case Decl::Record:
+ case clang::Decl::Record:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");
return ErrorUnexpected;
- case Decl::CXXRecord:
+ case clang::Decl::CXXRecord:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");
return ErrorUnexpected;
- case Decl::ClassTemplateSpecialization:
+ case clang::Decl::ClassTemplateSpecialization:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");
return ErrorUnexpected;
- case Decl::ClassTemplatePartialSpecialization:
+ case clang::Decl::ClassTemplatePartialSpecialization:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");
return ErrorUnexpected;
- case Decl::TemplateTypeParm:
+ case clang::Decl::TemplateTypeParm:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");
return ErrorUnexpected;
- case Decl::ObjCTypeParam:
+ case clang::Decl::ObjCTypeParam:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");
return ErrorUnexpected;
- case Decl::TypeAlias:
+ case clang::Decl::TypeAlias:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");
return ErrorUnexpected;
- case Decl::Typedef:
+ case clang::Decl::Typedef:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");
return ErrorUnexpected;
- case Decl::UnresolvedUsingTypename:
+ case clang::Decl::UnresolvedUsingTypename:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");
return ErrorUnexpected;
- case Decl::Using:
+ case clang::Decl::Using:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");
return ErrorUnexpected;
- case Decl::UsingDirective:
+ case clang::Decl::UsingDirective:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");
return ErrorUnexpected;
- case Decl::UsingPack:
+ case clang::Decl::UsingPack:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");
return ErrorUnexpected;
- case Decl::UsingShadow:
+ case clang::Decl::UsingShadow:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");
return ErrorUnexpected;
- case Decl::ConstructorUsingShadow:
+ case clang::Decl::ConstructorUsingShadow:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");
return ErrorUnexpected;
- case Decl::Binding:
+ case clang::Decl::Binding:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");
return ErrorUnexpected;
- case Decl::Field:
+ case clang::Decl::Field:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");
return ErrorUnexpected;
- case Decl::ObjCAtDefsField:
+ case clang::Decl::ObjCAtDefsField:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");
return ErrorUnexpected;
- case Decl::ObjCIvar:
+ case clang::Decl::ObjCIvar:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");
return ErrorUnexpected;
- case Decl::Function:
+ case clang::Decl::Function:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");
return ErrorUnexpected;
- case Decl::CXXDeductionGuide:
+ case clang::Decl::CXXDeductionGuide:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");
return ErrorUnexpected;
- case Decl::CXXMethod:
+ case clang::Decl::CXXMethod:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");
return ErrorUnexpected;
- case Decl::CXXConstructor:
+ case clang::Decl::CXXConstructor:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");
return ErrorUnexpected;
- case Decl::CXXConversion:
+ case clang::Decl::CXXConversion:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");
return ErrorUnexpected;
- case Decl::CXXDestructor:
+ case clang::Decl::CXXDestructor:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");
return ErrorUnexpected;
- case Decl::MSProperty:
+ case clang::Decl::MSProperty:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");
return ErrorUnexpected;
- case Decl::NonTypeTemplateParm:
+ case clang::Decl::NonTypeTemplateParm:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");
return ErrorUnexpected;
- case Decl::Decomposition:
+ case clang::Decl::Decomposition:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");
return ErrorUnexpected;
- case Decl::ImplicitParam:
+ case clang::Decl::ImplicitParam:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");
return ErrorUnexpected;
- case Decl::OMPCapturedExpr:
+ case clang::Decl::OMPCapturedExpr:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");
return ErrorUnexpected;
- case Decl::ParmVar:
+ case clang::Decl::ParmVar:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");
return ErrorUnexpected;
- case Decl::VarTemplateSpecialization:
+ case clang::Decl::VarTemplateSpecialization:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");
return ErrorUnexpected;
- case Decl::VarTemplatePartialSpecialization:
+ case clang::Decl::VarTemplatePartialSpecialization:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");
return ErrorUnexpected;
- case Decl::EnumConstant:
+ case clang::Decl::EnumConstant:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");
return ErrorUnexpected;
- case Decl::IndirectField:
+ case clang::Decl::IndirectField:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");
return ErrorUnexpected;
- case Decl::OMPDeclareReduction:
+ case clang::Decl::OMPDeclareReduction:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");
return ErrorUnexpected;
- case Decl::UnresolvedUsingValue:
+ case clang::Decl::UnresolvedUsingValue:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");
return ErrorUnexpected;
- case Decl::OMPThreadPrivate:
+ case clang::Decl::OMPThreadPrivate:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");
return ErrorUnexpected;
- case Decl::ObjCPropertyImpl:
+ case clang::Decl::ObjCPropertyImpl:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");
return ErrorUnexpected;
- case Decl::PragmaComment:
+ case clang::Decl::PragmaComment:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");
return ErrorUnexpected;
- case Decl::PragmaDetectMismatch:
+ case clang::Decl::PragmaDetectMismatch:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");
return ErrorUnexpected;
- case Decl::StaticAssert:
+ case clang::Decl::StaticAssert:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");
return ErrorUnexpected;
- case Decl::TranslationUnit:
+ case clang::Decl::TranslationUnit:
emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");
return ErrorUnexpected;
}
@@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
}
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {
AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
if (res == nullptr)
return nullptr;
@@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
}
- const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
+ const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
auto classs = ty->getTypeClass();
switch (classs) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Bool:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::UInt128:
- case BuiltinType::Int128:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::Float128:
- case BuiltinType::LongDouble:
- case BuiltinType::WChar_U:
- case BuiltinType::Char8:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::WChar_S:
- case BuiltinType::Float16:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::Float128:
+ case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char8:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Float16:
return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
- case BuiltinType::NullPtr:
- return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+ case clang::BuiltinType::NullPtr:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
+ trans_create_node_unsigned(c, 0));
- case BuiltinType::Void:
- case BuiltinType::Half:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OMPArraySection:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::PseudoObject:
- case BuiltinType::UnknownAny:
- case BuiltinType::BuiltinFn:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::OCLImage1dRO:
- case BuiltinType::OCLImage1dArrayRO:
- case BuiltinType::OCLImage1dBufferRO:
- case BuiltinType::OCLImage2dRO:
- case BuiltinType::OCLImage2dArrayRO:
- case BuiltinType::OCLImage2dDepthRO:
- case BuiltinType::OCLImage2dArrayDepthRO:
- case BuiltinType::OCLImage2dMSAARO:
- case BuiltinType::OCLImage2dArrayMSAARO:
- case BuiltinType::OCLImage2dMSAADepthRO:
- case BuiltinType::OCLImage2dArrayMSAADepthRO:
- case BuiltinType::OCLImage3dRO:
- case BuiltinType::OCLImage1dWO:
- case BuiltinType::OCLImage1dArrayWO:
- case BuiltinType::OCLImage1dBufferWO:
- case BuiltinType::OCLImage2dWO:
- case BuiltinType::OCLImage2dArrayWO:
- case BuiltinType::OCLImage2dDepthWO:
- case BuiltinType::OCLImage2dArrayDepthWO:
- case BuiltinType::OCLImage2dMSAAWO:
- case BuiltinType::OCLImage2dArrayMSAAWO:
- case BuiltinType::OCLImage2dMSAADepthWO:
- case BuiltinType::OCLImage2dArrayMSAADepthWO:
- case BuiltinType::OCLImage3dWO:
- case BuiltinType::OCLImage1dRW:
- case BuiltinType::OCLImage1dArrayRW:
- case BuiltinType::OCLImage1dBufferRW:
- case BuiltinType::OCLImage2dRW:
- case BuiltinType::OCLImage2dArrayRW:
- case BuiltinType::OCLImage2dDepthRW:
- case BuiltinType::OCLImage2dArrayDepthRW:
- case BuiltinType::OCLImage2dMSAARW:
- case BuiltinType::OCLImage2dArrayMSAARW:
- case BuiltinType::OCLImage2dMSAADepthRW:
- case BuiltinType::OCLImage2dArrayMSAADepthRW:
- case BuiltinType::OCLImage3dRW:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::OMPArraySection:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::OCLImage1dRO:
+ case clang::BuiltinType::OCLImage1dArrayRO:
+ case clang::BuiltinType::OCLImage1dBufferRO:
+ case clang::BuiltinType::OCLImage2dRO:
+ case clang::BuiltinType::OCLImage2dArrayRO:
+ case clang::BuiltinType::OCLImage2dDepthRO:
+ case clang::BuiltinType::OCLImage2dArrayDepthRO:
+ case clang::BuiltinType::OCLImage2dMSAARO:
+ case clang::BuiltinType::OCLImage2dArrayMSAARO:
+ case clang::BuiltinType::OCLImage2dMSAADepthRO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case clang::BuiltinType::OCLImage3dRO:
+ case clang::BuiltinType::OCLImage1dWO:
+ case clang::BuiltinType::OCLImage1dArrayWO:
+ case clang::BuiltinType::OCLImage1dBufferWO:
+ case clang::BuiltinType::OCLImage2dWO:
+ case clang::BuiltinType::OCLImage2dArrayWO:
+ case clang::BuiltinType::OCLImage2dDepthWO:
+ case clang::BuiltinType::OCLImage2dArrayDepthWO:
+ case clang::BuiltinType::OCLImage2dMSAAWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAAWO:
+ case clang::BuiltinType::OCLImage2dMSAADepthWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case clang::BuiltinType::OCLImage3dWO:
+ case clang::BuiltinType::OCLImage1dRW:
+ case clang::BuiltinType::OCLImage1dArrayRW:
+ case clang::BuiltinType::OCLImage1dBufferRW:
+ case clang::BuiltinType::OCLImage2dRW:
+ case clang::BuiltinType::OCLImage2dArrayRW:
+ case clang::BuiltinType::OCLImage2dDepthRW:
+ case clang::BuiltinType::OCLImage2dArrayDepthRW:
+ case clang::BuiltinType::OCLImage2dMSAARW:
+ case clang::BuiltinType::OCLImage2dArrayMSAARW:
+ case clang::BuiltinType::OCLImage2dMSAADepthRW:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case clang::BuiltinType::OCLImage3dRW:
+ case clang::BuiltinType::OCLSampler:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLClkEvent:
+ case clang::BuiltinType::OCLQueue:
+ case clang::BuiltinType::OCLReserveID:
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
return res;
}
break;
}
- case Type::Pointer:
- return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+ case clang::Type::Pointer:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
+ trans_create_node_unsigned(c, 0));
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
return res;
}
- case Type::Enum:
+ case clang::Type::Enum:
{
- const EnumType *enum_ty = static_cast(ty);
+ const clang::EnumType *enum_ty = static_cast(ty);
AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
return to_enum_zero_cmp(c, res, enum_type);
}
- case Type::Elaborated:
+ case clang::Type::Elaborated:
{
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
switch (elaborated_ty->getKeyword()) {
- case ETK_Enum: {
+ case clang::ETK_Enum: {
AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());
return to_enum_zero_cmp(c, res, enum_type);
}
- case ETK_Struct:
- case ETK_Union:
- case ETK_Interface:
- case ETK_Class:
- case ETK_Typename:
- case ETK_None:
+ case clang::ETK_Struct:
+ case clang::ETK_Union:
+ case clang::ETK_Interface:
+ case clang::ETK_Class:
+ case clang::ETK_Typename:
+ case clang::ETK_None:
return res;
}
}
- case Type::FunctionProto:
- case Type::Record:
- case Type::ConstantArray:
- case Type::Paren:
- case Type::Decayed:
- case Type::Attributed:
- case Type::IncompleteArray:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionNoProto:
- case Type::UnresolvedUsing:
- case Type::Adjusted:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::Auto:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Complex:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- case Type::Pipe:
- case Type::ObjCTypeParam:
- case Type::DeducedTemplateSpecialization:
- case Type::DependentAddressSpace:
- case Type::DependentVector:
+ case clang::Type::FunctionProto:
+ case clang::Type::Record:
+ case clang::Type::ConstantArray:
+ case clang::Type::Paren:
+ case clang::Type::Decayed:
+ case clang::Type::Attributed:
+ case clang::Type::IncompleteArray:
+ case clang::Type::BlockPointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer:
+ case clang::Type::VariableArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ case clang::Type::FunctionNoProto:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Adjusted:
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::UnaryTransform:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Auto:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ case clang::Type::Complex:
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::Atomic:
+ case clang::Type::Pipe:
+ case clang::Type::ObjCTypeParam:
+ case clang::Type::DeducedTemplateSpecialization:
+ case clang::Type::DependentAddressSpace:
+ case clang::Type::DependentVector:
return res;
}
zig_unreachable();
}
-static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
+static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
@@ -2611,7 +2641,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt
return while_scope->node;
}
-static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
+static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) {
// if (c) t
// if (c) t else e
AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
@@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
return if_node;
}
-static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
+static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);
@@ -2641,16 +2671,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
return nullptr;
bool is_ptr = false;
- const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
+ const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
AstNode *callee_node = nullptr;
if (is_ptr && fn_ty) {
- if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *implicit_cast = static_cast(stmt->getCallee());
- if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
- if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {
- const DeclRefExpr *decl_ref = static_cast(implicit_cast->getSubExpr());
- const Decl *decl = decl_ref->getFoundDecl();
- if (decl->getKind() == Decl::Function) {
+ if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *implicit_cast = static_cast(stmt->getCallee());
+ if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
+ if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
+ const clang::DeclRefExpr *decl_ref = static_cast(implicit_cast->getSubExpr());
+ const clang::Decl *decl = decl_ref->getFoundDecl();
+ if (decl->getKind() == clang::Decl::Function) {
callee_node = callee_raw_node;
}
}
@@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
node->data.fn_call_expr.fn_ref_expr = callee_node;
unsigned num_args = stmt->getNumArgs();
- const Expr * const* args = stmt->getArgs();
+ const clang::Expr * const* args = stmt->getArgs();
for (unsigned i = 0; i < num_args; i += 1) {
AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
if (arg_node == nullptr)
@@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
return node;
}
-static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) {
+static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) {
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
if (container_node == nullptr)
return nullptr;
@@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
return node;
}
-static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) {
+static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
if (container_node == nullptr)
return nullptr;
@@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
}
static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
- const CStyleCastExpr *stmt, TransLRValue lrvalue)
+ const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
{
AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
if (sub_expr_node == nullptr)
@@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
}
static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
- const UnaryExprOrTypeTraitExpr *stmt)
+ const clang::UnaryExprOrTypeTraitExpr *stmt)
{
AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
if (type_node == nullptr)
@@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
return node;
}
-static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {
+static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
AstNode *body_node;
TransScope *child_scope;
- if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
+ if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
// there's already a block in C, so we'll append our condition to it.
// c: do {
// c: a;
@@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
return while_scope->node;
}
-static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {
+static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) {
AstNode *loop_block_node;
TransScopeWhile *while_scope;
TransScope *cond_scope;
- const Stmt *init_stmt = stmt->getInit();
+ const clang::Stmt *init_stmt = stmt->getInit();
if (init_stmt == nullptr) {
while_scope = trans_scope_while_create(c, parent_scope);
loop_block_node = while_scope->node;
@@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
child_scope->node->data.block.statements.append(while_scope->node);
}
- const Stmt *cond_stmt = stmt->getCond();
+ const clang::Stmt *cond_stmt = stmt->getCond();
if (cond_stmt == nullptr) {
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
} else {
- if (Expr::classof(cond_stmt)) {
- const Expr *cond_expr = static_cast(cond_stmt);
+ if (clang::Expr::classof(cond_stmt)) {
+ const clang::Expr *cond_expr = static_cast(cond_stmt);
while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
if (while_scope->node->data.while_expr.condition == nullptr)
@@ -2838,7 +2868,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
}
}
- const Stmt *inc_stmt = stmt->getInc();
+ const clang::Stmt *inc_stmt = stmt->getInc();
if (inc_stmt != nullptr) {
AstNode *inc_node;
TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);
@@ -2861,12 +2891,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
return loop_block_node;
}
-static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) {
+static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) {
TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
TransScopeSwitch *switch_scope;
- const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
+ const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
if (var_decl_stmt == nullptr) {
switch_scope = trans_scope_switch_create(c, &block_scope->base);
} else {
@@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
switch_scope->end_label_name = end_label_name;
block_scope->node->data.block.name = end_label_name;
- const Expr *cond_expr = stmt->getCond();
+ const clang::Expr *cond_expr = stmt->getCond();
assert(cond_expr != nullptr);
AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
@@ -2894,9 +2924,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
switch_scope->switch_node->data.switch_expr.expr = expr_node;
AstNode *body_node;
- const Stmt *body_stmt = stmt->getBody();
- if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {
- if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,
+ const clang::Stmt *body_stmt = stmt->getBody();
+ if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
+ if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
block_scope->node, nullptr))
{
return nullptr;
@@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
return nullptr;
}
-static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node,
+static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node,
TransScope **out_scope) {
*out_node = nullptr;
@@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
return ErrorNone;
}
-static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node,
+static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node,
TransScope **out_scope)
{
*out_node = nullptr;
@@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
return ErrorNone;
}
-static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) {
+static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) {
switch (stmt->getKind()) {
- case StringLiteral::Ascii:
- case StringLiteral::UTF8:
+ case clang::StringLiteral::Ascii:
+ case clang::StringLiteral::UTF8:
return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
- case StringLiteral::UTF16:
+ case clang::StringLiteral::UTF16:
emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
return nullptr;
- case StringLiteral::UTF32:
+ case clang::StringLiteral::UTF32:
emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
return nullptr;
- case StringLiteral::Wide:
+ case clang::StringLiteral::Wide:
emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) {
+static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) {
TransScope *cur_scope = scope;
while (cur_scope != nullptr) {
if (cur_scope->id == TransScopeIdWhile) {
@@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
zig_unreachable();
}
-static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) {
+static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) {
return trans_create_node(c, NodeTypeContinue);
}
@@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
return ErrorNone;
}
-static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
ResultUsed result_used, TransLRValue lrvalue,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope)
{
- Stmt::StmtClass sc = stmt->getStmtClass();
+ clang::Stmt::StmtClass sc = stmt->getStmtClass();
switch (sc) {
- case Stmt::ReturnStmtClass:
+ case clang::Stmt::ReturnStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_return_stmt(c, scope, (const ReturnStmt *)stmt));
- case Stmt::CompoundStmtClass:
+ trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
+ case clang::Stmt::CompoundStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));
- case Stmt::IntegerLiteralClass:
+ trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
+ case clang::Stmt::IntegerLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_integer_literal(c, (const IntegerLiteral *)stmt));
- case Stmt::ConditionalOperatorClass:
+ trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
+ case clang::Stmt::ConditionalOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));
- case Stmt::BinaryOperatorClass:
+ trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
+ case clang::Stmt::BinaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));
- case Stmt::CompoundAssignOperatorClass:
+ trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
+ case clang::Stmt::CompoundAssignOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));
- case Stmt::ImplicitCastExprClass:
+ trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
+ case clang::Stmt::ImplicitCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));
- case Stmt::DeclRefExprClass:
+ trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
+ case clang::Stmt::DeclRefExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));
- case Stmt::UnaryOperatorClass:
+ trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
+ case clang::Stmt::UnaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));
- case Stmt::DeclStmtClass:
- return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);
- case Stmt::DoStmtClass:
- case Stmt::WhileStmtClass: {
- AstNode *while_node = sc == Stmt::DoStmtClass
- ? trans_do_loop(c, scope, (const DoStmt *)stmt)
- : trans_while_loop(c, scope, (const WhileStmt *)stmt);
+ trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
+ case clang::Stmt::DeclStmtClass:
+ return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::DoStmtClass:
+ case clang::Stmt::WhileStmtClass: {
+ AstNode *while_node = sc == clang::Stmt::DoStmtClass
+ ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
+ : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
if (while_node == nullptr)
return ErrorUnexpected;
@@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
return wrap_stmt(out_node, out_child_scope, scope, while_node);
}
- case Stmt::IfStmtClass:
+ case clang::Stmt::IfStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_if_statement(c, scope, (const IfStmt *)stmt));
- case Stmt::CallExprClass:
+ trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
+ case clang::Stmt::CallExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));
- case Stmt::NullStmtClass:
+ trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
+ case clang::Stmt::NullStmtClass:
*out_node = nullptr;
*out_child_scope = scope;
return ErrorNone;
- case Stmt::MemberExprClass:
+ case clang::Stmt::MemberExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_member_expr(c, scope, (const MemberExpr *)stmt));
- case Stmt::ArraySubscriptExprClass:
+ trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
+ case clang::Stmt::ArraySubscriptExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));
- case Stmt::CStyleCastExprClass:
+ trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
+ case clang::Stmt::CStyleCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));
- case Stmt::UnaryExprOrTypeTraitExprClass:
+ trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
+ case clang::Stmt::UnaryExprOrTypeTraitExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));
- case Stmt::ForStmtClass: {
- AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);
+ trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
+ case clang::Stmt::ForStmtClass: {
+ AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
return wrap_stmt(out_node, out_child_scope, scope, node);
}
- case Stmt::StringLiteralClass:
+ case clang::Stmt::StringLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_string_literal(c, scope, (const StringLiteral *)stmt));
- case Stmt::BreakStmtClass:
+ trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
+ case clang::Stmt::BreakStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_break_stmt(c, scope, (const BreakStmt *)stmt));
- case Stmt::ContinueStmtClass:
+ trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
+ case clang::Stmt::ContinueStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));
- case Stmt::ParenExprClass:
+ trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
+ case clang::Stmt::ParenExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));
- case Stmt::SwitchStmtClass:
+ trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
+ case clang::Stmt::SwitchStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
- case Stmt::CaseStmtClass:
- return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);
- case Stmt::DefaultStmtClass:
- return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);
- case Stmt::NoStmtClass:
+ trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
+ case clang::Stmt::CaseStmtClass:
+ return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::DefaultStmtClass:
+ return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::NoStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
return ErrorUnexpected;
- case Stmt::GCCAsmStmtClass:
+ case clang::Stmt::GCCAsmStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");
return ErrorUnexpected;
- case Stmt::MSAsmStmtClass:
+ case clang::Stmt::MSAsmStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");
return ErrorUnexpected;
- case Stmt::AttributedStmtClass:
+ case clang::Stmt::AttributedStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");
return ErrorUnexpected;
- case Stmt::CXXCatchStmtClass:
+ case clang::Stmt::CXXCatchStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");
return ErrorUnexpected;
- case Stmt::CXXForRangeStmtClass:
+ case clang::Stmt::CXXForRangeStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");
return ErrorUnexpected;
- case Stmt::CXXTryStmtClass:
+ case clang::Stmt::CXXTryStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");
return ErrorUnexpected;
- case Stmt::CapturedStmtClass:
+ case clang::Stmt::CapturedStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");
return ErrorUnexpected;
- case Stmt::CoreturnStmtClass:
+ case clang::Stmt::CoreturnStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");
return ErrorUnexpected;
- case Stmt::CoroutineBodyStmtClass:
+ case clang::Stmt::CoroutineBodyStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
return ErrorUnexpected;
- case Stmt::BinaryConditionalOperatorClass:
+ case clang::Stmt::BinaryConditionalOperatorClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
return ErrorUnexpected;
- case Stmt::AddrLabelExprClass:
+ case clang::Stmt::AddrLabelExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");
return ErrorUnexpected;
- case Stmt::ArrayInitIndexExprClass:
+ case clang::Stmt::ArrayInitIndexExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");
return ErrorUnexpected;
- case Stmt::ArrayInitLoopExprClass:
+ case clang::Stmt::ArrayInitLoopExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
return ErrorUnexpected;
- case Stmt::ArrayTypeTraitExprClass:
+ case clang::Stmt::ArrayTypeTraitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
return ErrorUnexpected;
- case Stmt::AsTypeExprClass:
+ case clang::Stmt::AsTypeExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");
return ErrorUnexpected;
- case Stmt::AtomicExprClass:
+ case clang::Stmt::AtomicExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
return ErrorUnexpected;
- case Stmt::BlockExprClass:
+ case clang::Stmt::BlockExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
return ErrorUnexpected;
- case Stmt::CXXBindTemporaryExprClass:
+ case clang::Stmt::CXXBindTemporaryExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");
return ErrorUnexpected;
- case Stmt::CXXBoolLiteralExprClass:
+ case clang::Stmt::CXXBoolLiteralExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");
return ErrorUnexpected;
- case Stmt::CXXConstructExprClass:
+ case clang::Stmt::CXXConstructExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");
return ErrorUnexpected;
- case Stmt::CXXTemporaryObjectExprClass:
+ case clang::Stmt::CXXTemporaryObjectExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");
return ErrorUnexpected;
- case Stmt::CXXDefaultArgExprClass:
+ case clang::Stmt::CXXDefaultArgExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");
return ErrorUnexpected;
- case Stmt::CXXDefaultInitExprClass:
+ case clang::Stmt::CXXDefaultInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");
return ErrorUnexpected;
- case Stmt::CXXDeleteExprClass:
+ case clang::Stmt::CXXDeleteExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");
return ErrorUnexpected;
- case Stmt::CXXDependentScopeMemberExprClass:
+ case clang::Stmt::CXXDependentScopeMemberExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");
return ErrorUnexpected;
- case Stmt::CXXFoldExprClass:
+ case clang::Stmt::CXXFoldExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");
return ErrorUnexpected;
- case Stmt::CXXInheritedCtorInitExprClass:
+ case clang::Stmt::CXXInheritedCtorInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");
return ErrorUnexpected;
- case Stmt::CXXNewExprClass:
+ case clang::Stmt::CXXNewExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");
return ErrorUnexpected;
- case Stmt::CXXNoexceptExprClass:
+ case clang::Stmt::CXXNoexceptExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");
return ErrorUnexpected;
- case Stmt::CXXNullPtrLiteralExprClass:
+ case clang::Stmt::CXXNullPtrLiteralExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");
return ErrorUnexpected;
- case Stmt::CXXPseudoDestructorExprClass:
+ case clang::Stmt::CXXPseudoDestructorExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");
return ErrorUnexpected;
- case Stmt::CXXScalarValueInitExprClass:
+ case clang::Stmt::CXXScalarValueInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");
return ErrorUnexpected;
- case Stmt::CXXStdInitializerListExprClass:
+ case clang::Stmt::CXXStdInitializerListExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");
return ErrorUnexpected;
- case Stmt::CXXThisExprClass:
+ case clang::Stmt::CXXThisExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");
return ErrorUnexpected;
- case Stmt::CXXThrowExprClass:
+ case clang::Stmt::CXXThrowExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");
return ErrorUnexpected;
- case Stmt::CXXTypeidExprClass:
+ case clang::Stmt::CXXTypeidExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");
return ErrorUnexpected;
- case Stmt::CXXUnresolvedConstructExprClass:
+ case clang::Stmt::CXXUnresolvedConstructExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");
return ErrorUnexpected;
- case Stmt::CXXUuidofExprClass:
+ case clang::Stmt::CXXUuidofExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
return ErrorUnexpected;
- case Stmt::CUDAKernelCallExprClass:
+ case clang::Stmt::CUDAKernelCallExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
return ErrorUnexpected;
- case Stmt::CXXMemberCallExprClass:
+ case clang::Stmt::CXXMemberCallExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
return ErrorUnexpected;
- case Stmt::CXXOperatorCallExprClass:
+ case clang::Stmt::CXXOperatorCallExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");
return ErrorUnexpected;
- case Stmt::UserDefinedLiteralClass:
+ case clang::Stmt::UserDefinedLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
return ErrorUnexpected;
- case Stmt::CXXFunctionalCastExprClass:
+ case clang::Stmt::CXXFunctionalCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
return ErrorUnexpected;
- case Stmt::CXXConstCastExprClass:
+ case clang::Stmt::CXXConstCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");
return ErrorUnexpected;
- case Stmt::CXXDynamicCastExprClass:
+ case clang::Stmt::CXXDynamicCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");
return ErrorUnexpected;
- case Stmt::CXXReinterpretCastExprClass:
+ case clang::Stmt::CXXReinterpretCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");
return ErrorUnexpected;
- case Stmt::CXXStaticCastExprClass:
+ case clang::Stmt::CXXStaticCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");
return ErrorUnexpected;
- case Stmt::ObjCBridgedCastExprClass:
+ case clang::Stmt::ObjCBridgedCastExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");
return ErrorUnexpected;
- case Stmt::CharacterLiteralClass:
+ case clang::Stmt::CharacterLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");
return ErrorUnexpected;
- case Stmt::ChooseExprClass:
+ case clang::Stmt::ChooseExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");
return ErrorUnexpected;
- case Stmt::CompoundLiteralExprClass:
+ case clang::Stmt::CompoundLiteralExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");
return ErrorUnexpected;
- case Stmt::ConvertVectorExprClass:
+ case clang::Stmt::ConvertVectorExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");
return ErrorUnexpected;
- case Stmt::CoawaitExprClass:
+ case clang::Stmt::CoawaitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");
return ErrorUnexpected;
- case Stmt::CoyieldExprClass:
+ case clang::Stmt::CoyieldExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");
return ErrorUnexpected;
- case Stmt::DependentCoawaitExprClass:
+ case clang::Stmt::DependentCoawaitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");
return ErrorUnexpected;
- case Stmt::DependentScopeDeclRefExprClass:
+ case clang::Stmt::DependentScopeDeclRefExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");
return ErrorUnexpected;
- case Stmt::DesignatedInitExprClass:
+ case clang::Stmt::DesignatedInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");
return ErrorUnexpected;
- case Stmt::DesignatedInitUpdateExprClass:
+ case clang::Stmt::DesignatedInitUpdateExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");
return ErrorUnexpected;
- case Stmt::ExprWithCleanupsClass:
+ case clang::Stmt::ExprWithCleanupsClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");
return ErrorUnexpected;
- case Stmt::ExpressionTraitExprClass:
+ case clang::Stmt::ExpressionTraitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");
return ErrorUnexpected;
- case Stmt::ExtVectorElementExprClass:
+ case clang::Stmt::ExtVectorElementExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");
return ErrorUnexpected;
- case Stmt::FloatingLiteralClass:
+ case clang::Stmt::FloatingLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");
return ErrorUnexpected;
- case Stmt::FunctionParmPackExprClass:
+ case clang::Stmt::FunctionParmPackExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");
return ErrorUnexpected;
- case Stmt::GNUNullExprClass:
+ case clang::Stmt::GNUNullExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");
return ErrorUnexpected;
- case Stmt::GenericSelectionExprClass:
+ case clang::Stmt::GenericSelectionExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");
return ErrorUnexpected;
- case Stmt::ImaginaryLiteralClass:
+ case clang::Stmt::ImaginaryLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");
return ErrorUnexpected;
- case Stmt::ImplicitValueInitExprClass:
+ case clang::Stmt::ImplicitValueInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");
return ErrorUnexpected;
- case Stmt::InitListExprClass:
+ case clang::Stmt::InitListExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");
return ErrorUnexpected;
- case Stmt::LambdaExprClass:
+ case clang::Stmt::LambdaExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");
return ErrorUnexpected;
- case Stmt::MSPropertyRefExprClass:
+ case clang::Stmt::MSPropertyRefExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");
return ErrorUnexpected;
- case Stmt::MSPropertySubscriptExprClass:
+ case clang::Stmt::MSPropertySubscriptExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");
return ErrorUnexpected;
- case Stmt::MaterializeTemporaryExprClass:
+ case clang::Stmt::MaterializeTemporaryExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
return ErrorUnexpected;
- case Stmt::NoInitExprClass:
+ case clang::Stmt::NoInitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
return ErrorUnexpected;
- case Stmt::OMPArraySectionExprClass:
+ case clang::Stmt::OMPArraySectionExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");
return ErrorUnexpected;
- case Stmt::ObjCArrayLiteralClass:
+ case clang::Stmt::ObjCArrayLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");
return ErrorUnexpected;
- case Stmt::ObjCAvailabilityCheckExprClass:
+ case clang::Stmt::ObjCAvailabilityCheckExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");
return ErrorUnexpected;
- case Stmt::ObjCBoolLiteralExprClass:
+ case clang::Stmt::ObjCBoolLiteralExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");
return ErrorUnexpected;
- case Stmt::ObjCBoxedExprClass:
+ case clang::Stmt::ObjCBoxedExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");
return ErrorUnexpected;
- case Stmt::ObjCDictionaryLiteralClass:
+ case clang::Stmt::ObjCDictionaryLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");
return ErrorUnexpected;
- case Stmt::ObjCEncodeExprClass:
+ case clang::Stmt::ObjCEncodeExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");
return ErrorUnexpected;
- case Stmt::ObjCIndirectCopyRestoreExprClass:
+ case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
return ErrorUnexpected;
- case Stmt::ObjCIsaExprClass:
+ case clang::Stmt::ObjCIsaExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");
return ErrorUnexpected;
- case Stmt::ObjCIvarRefExprClass:
+ case clang::Stmt::ObjCIvarRefExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");
return ErrorUnexpected;
- case Stmt::ObjCMessageExprClass:
+ case clang::Stmt::ObjCMessageExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");
return ErrorUnexpected;
- case Stmt::ObjCPropertyRefExprClass:
+ case clang::Stmt::ObjCPropertyRefExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");
return ErrorUnexpected;
- case Stmt::ObjCProtocolExprClass:
+ case clang::Stmt::ObjCProtocolExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");
return ErrorUnexpected;
- case Stmt::ObjCSelectorExprClass:
+ case clang::Stmt::ObjCSelectorExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");
return ErrorUnexpected;
- case Stmt::ObjCStringLiteralClass:
+ case clang::Stmt::ObjCStringLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");
return ErrorUnexpected;
- case Stmt::ObjCSubscriptRefExprClass:
+ case clang::Stmt::ObjCSubscriptRefExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");
return ErrorUnexpected;
- case Stmt::OffsetOfExprClass:
+ case clang::Stmt::OffsetOfExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");
return ErrorUnexpected;
- case Stmt::OpaqueValueExprClass:
+ case clang::Stmt::OpaqueValueExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");
return ErrorUnexpected;
- case Stmt::UnresolvedLookupExprClass:
+ case clang::Stmt::UnresolvedLookupExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");
return ErrorUnexpected;
- case Stmt::UnresolvedMemberExprClass:
+ case clang::Stmt::UnresolvedMemberExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");
return ErrorUnexpected;
- case Stmt::PackExpansionExprClass:
+ case clang::Stmt::PackExpansionExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
return ErrorUnexpected;
- case Stmt::ParenListExprClass:
+ case clang::Stmt::ParenListExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
return ErrorUnexpected;
- case Stmt::PredefinedExprClass:
+ case clang::Stmt::PredefinedExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
return ErrorUnexpected;
- case Stmt::PseudoObjectExprClass:
+ case clang::Stmt::PseudoObjectExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
return ErrorUnexpected;
- case Stmt::ShuffleVectorExprClass:
+ case clang::Stmt::ShuffleVectorExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");
return ErrorUnexpected;
- case Stmt::SizeOfPackExprClass:
+ case clang::Stmt::SizeOfPackExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
return ErrorUnexpected;
- case Stmt::StmtExprClass:
+ case clang::Stmt::StmtExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
return ErrorUnexpected;
- case Stmt::SubstNonTypeTemplateParmExprClass:
+ case clang::Stmt::SubstNonTypeTemplateParmExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
return ErrorUnexpected;
- case Stmt::SubstNonTypeTemplateParmPackExprClass:
+ case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
return ErrorUnexpected;
- case Stmt::TypeTraitExprClass:
+ case clang::Stmt::TypeTraitExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");
return ErrorUnexpected;
- case Stmt::TypoExprClass:
+ case clang::Stmt::TypoExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
return ErrorUnexpected;
- case Stmt::VAArgExprClass:
+ case clang::Stmt::VAArgExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
return ErrorUnexpected;
- case Stmt::GotoStmtClass:
+ case clang::Stmt::GotoStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
return ErrorUnexpected;
- case Stmt::IndirectGotoStmtClass:
+ case clang::Stmt::IndirectGotoStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
return ErrorUnexpected;
- case Stmt::LabelStmtClass:
+ case clang::Stmt::LabelStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");
return ErrorUnexpected;
- case Stmt::MSDependentExistsStmtClass:
+ case clang::Stmt::MSDependentExistsStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
return ErrorUnexpected;
- case Stmt::OMPAtomicDirectiveClass:
+ case clang::Stmt::OMPAtomicDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPBarrierDirectiveClass:
+ case clang::Stmt::OMPBarrierDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPCancelDirectiveClass:
+ case clang::Stmt::OMPCancelDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPCancellationPointDirectiveClass:
+ case clang::Stmt::OMPCancellationPointDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPCriticalDirectiveClass:
+ case clang::Stmt::OMPCriticalDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPFlushDirectiveClass:
+ case clang::Stmt::OMPFlushDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPDistributeDirectiveClass:
+ case clang::Stmt::OMPDistributeDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPDistributeParallelForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPDistributeSimdDirectiveClass:
+ case clang::Stmt::OMPDistributeSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPForDirectiveClass:
+ case clang::Stmt::OMPForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPForSimdDirectiveClass:
+ case clang::Stmt::OMPForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPParallelForDirectiveClass:
+ case clang::Stmt::OMPParallelForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPParallelForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPSimdDirectiveClass:
+ case clang::Stmt::OMPSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetSimdDirectiveClass:
+ case clang::Stmt::OMPTargetSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskLoopDirectiveClass:
+ case clang::Stmt::OMPTaskLoopDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskLoopSimdDirectiveClass:
+ case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPMasterDirectiveClass:
+ case clang::Stmt::OMPMasterDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPOrderedDirectiveClass:
+ case clang::Stmt::OMPOrderedDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPParallelDirectiveClass:
+ case clang::Stmt::OMPParallelDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPParallelSectionsDirectiveClass:
+ case clang::Stmt::OMPParallelSectionsDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPSectionDirectiveClass:
+ case clang::Stmt::OMPSectionDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPSectionsDirectiveClass:
+ case clang::Stmt::OMPSectionsDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPSingleDirectiveClass:
+ case clang::Stmt::OMPSingleDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetDataDirectiveClass:
+ case clang::Stmt::OMPTargetDataDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetDirectiveClass:
+ case clang::Stmt::OMPTargetDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetEnterDataDirectiveClass:
+ case clang::Stmt::OMPTargetEnterDataDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetExitDataDirectiveClass:
+ case clang::Stmt::OMPTargetExitDataDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetParallelDirectiveClass:
+ case clang::Stmt::OMPTargetParallelDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetParallelForDirectiveClass:
+ case clang::Stmt::OMPTargetParallelForDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDirectiveClass:
+ case clang::Stmt::OMPTargetTeamsDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTargetUpdateDirectiveClass:
+ case clang::Stmt::OMPTargetUpdateDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskDirectiveClass:
+ case clang::Stmt::OMPTaskDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskgroupDirectiveClass:
+ case clang::Stmt::OMPTaskgroupDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskwaitDirectiveClass:
+ case clang::Stmt::OMPTaskwaitDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTaskyieldDirectiveClass:
+ case clang::Stmt::OMPTaskyieldDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");
return ErrorUnexpected;
- case Stmt::OMPTeamsDirectiveClass:
+ case clang::Stmt::OMPTeamsDirectiveClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");
return ErrorUnexpected;
- case Stmt::ObjCAtCatchStmtClass:
+ case clang::Stmt::ObjCAtCatchStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCAtFinallyStmtClass:
+ case clang::Stmt::ObjCAtFinallyStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCAtSynchronizedStmtClass:
+ case clang::Stmt::ObjCAtSynchronizedStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCAtThrowStmtClass:
+ case clang::Stmt::ObjCAtThrowStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCAtTryStmtClass:
+ case clang::Stmt::ObjCAtTryStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCAutoreleasePoolStmtClass:
+ case clang::Stmt::ObjCAutoreleasePoolStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");
return ErrorUnexpected;
- case Stmt::ObjCForCollectionStmtClass:
+ case clang::Stmt::ObjCForCollectionStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");
return ErrorUnexpected;
- case Stmt::SEHExceptStmtClass:
+ case clang::Stmt::SEHExceptStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");
return ErrorUnexpected;
- case Stmt::SEHFinallyStmtClass:
+ case clang::Stmt::SEHFinallyStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");
return ErrorUnexpected;
- case Stmt::SEHLeaveStmtClass:
+ case clang::Stmt::SEHLeaveStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");
return ErrorUnexpected;
- case Stmt::SEHTryStmtClass:
+ case clang::Stmt::SEHTryStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");
return ErrorUnexpected;
- case Stmt::FixedPointLiteralClass:
+ case clang::Stmt::FixedPointLiteralClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass");
return ErrorUnexpected;
}
@@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
}
// Returns null if there was an error
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr,
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,
TransLRValue lrval)
{
AstNode *result_node;
@@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
// Statements have no result and no concept of L or R value.
// Returns child scope, or null if there was an error
-static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) {
+static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {
TransScope *child_scope;
if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
return nullptr;
@@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
return child_scope;
}
-static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
+static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
if (get_global(c, fn_name)) {
@@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
proto_node->data.fn_proto.name = fn_name;
proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
- StorageClass sc = fn_decl->getStorageClass();
- if (sc == SC_None) {
+ clang::StorageClass sc = fn_decl->getStorageClass();
+ if (sc == clang::SC_None) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;
- } else if (sc == SC_Extern || sc == SC_Static) {
+ } else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
- } else if (sc == SC_PrivateExtern) {
+ } else if (sc == clang::SC_PrivateExtern) {
emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
return;
} else {
@@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
AstNode *param_node = proto_node->data.fn_proto.params.at(i);
- const ParmVarDecl *param = fn_decl->getParamDecl(i);
+ const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);
const char *name = decl_name(param);
Buf *proto_param_name;
@@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
// actual function definition with body
c->ptr_params.clear();
- Stmt *body = fn_decl->getBody();
+ clang::Stmt *body = fn_decl->getBody();
AstNode *actual_body_node;
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
if (result_scope == nullptr) {
@@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
}
-static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {
+static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {
AstNode *node = trans_create_node_symbol_str(c, primitive_name);
c->decl_table.put(typedef_decl, node);
return node;
}
-static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
+static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
}
- QualType child_qt = typedef_decl->getUnderlyingType();
+ clang::QualType child_qt = typedef_decl->getUnderlyingType();
Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
if (buf_eql_str(type_name, "uint8_t")) {
@@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
return symbol_node;
}
-struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
+struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,
Buf *full_type_name, Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
@@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
return symbol_node;
}
-static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
+static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
- const EnumDecl *enum_def = enum_decl->getDefinition();
+ const clang::EnumDecl *enum_def = enum_decl->getDefinition();
if (!enum_def) {
return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
}
@@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
it_end = enum_def->enumerator_end();
it != it_end; ++it, field_count += 1)
{
- const EnumConstantDecl *enum_const = *it;
+ const clang::EnumConstantDecl *enum_const = *it;
if (enum_const->getInitExpr()) {
pure_enum = false;
}
@@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
// TODO only emit this tag type if the enum tag type is not the default.
// I don't know what the default is, need to figure out how clang is deciding.
// it appears to at least be different across gcc/msvc
- if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
- !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
+ if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
+ !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
{
enum_node->data.container_decl.init_arg_expr = tag_int_type;
}
@@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
it_end = enum_def->enumerator_end();
it != it_end; ++it, i += 1)
{
- const EnumConstantDecl *enum_const = *it;
+ const clang::EnumConstantDecl *enum_const = *it;
Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
Buf *field_name;
@@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
}
}
-static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,
+static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,
Buf *full_type_name, Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
@@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
return symbol_node;
}
-static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
+static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
Buf *full_type_name = (bare_name == nullptr) ?
nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
- RecordDecl *record_def = record_decl->getDefinition();
+ clang::RecordDecl *record_def = record_decl->getDefinition();
if (record_def == nullptr) {
return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
}
@@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
it_end = record_def->field_end();
it != it_end; ++it, field_count += 1)
{
- const FieldDecl *field_decl = *it;
+ const clang::FieldDecl *field_decl = *it;
if (field_decl->isBitField()) {
emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
@@ -4035,7 +4065,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
it_end = record_def->field_end();
it != it_end; ++it, i += 1)
{
- const FieldDecl *field_decl = *it;
+ const clang::FieldDecl *field_decl = *it;
AstNode *field_node = trans_create_node(c, NodeTypeStructField);
field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
@@ -4062,13 +4092,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
}
}
-static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) {
+static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {
switch (ap_value->getKind()) {
- case APValue::Int:
+ case clang::APValue::Int:
return trans_create_node_apint(c, ap_value->getInt());
- case APValue::Uninitialized:
+ case clang::APValue::Uninitialized:
return trans_create_node(c, NodeTypeUndefinedLiteral);
- case APValue::Array: {
+ case clang::APValue::Array: {
emit_warning(c, source_loc, "TODO add a test case for this code");
unsigned init_count = ap_value->getArrayInitializedElts();
@@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
unsigned leftover_count = all_count - init_count;
AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
+ if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer.
+ bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count);
+ }
init_node->data.container_init_expr.type = arr_type_node;
init_node->data.container_init_expr.kind = ContainerInitKindArray;
- QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
+ clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();
for (size_t i = 0; i < init_count; i += 1) {
- APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
+ clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
if (elem_node == nullptr)
return nullptr;
@@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
return init_node;
}
- APValue &filler_ap_val = ap_value->getArrayFiller();
+ clang::APValue &filler_ap_val = ap_value->getArrayFiller();
AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
if (filler_node == nullptr)
return nullptr;
+ AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType);
+ *filler_arr_type = *arr_type_node;
+ filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1);
+
AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
- init_node->data.container_init_expr.type = arr_type_node;
- init_node->data.container_init_expr.kind = ContainerInitKindArray;
- init_node->data.container_init_expr.entries.append(filler_node);
+ filler_arr_1->data.container_init_expr.type = filler_arr_type;
+ filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
+ filler_arr_1->data.container_init_expr.entries.append(filler_node);
AstNode *rhs_node;
if (leftover_count == 1) {
@@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
}
+ if (init_count == 0) {
+ return rhs_node;
+ }
+
return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
}
- case APValue::LValue: {
- const APValue::LValueBase lval_base = ap_value->getLValueBase();
- if (const Expr *expr = lval_base.dyn_cast()) {
+ case clang::APValue::LValue: {
+ const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
+ if (const clang::Expr *expr = lval_base.dyn_cast()) {
return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
}
- //const ValueDecl *value_decl = lval_base.get();
- emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
+ //const clang::ValueDecl *value_decl = lval_base.get();
+ emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
return nullptr;
}
- case APValue::Float:
+ case clang::APValue::Float:
emit_warning(c, source_loc, "unsupported initializer value kind: Float");
return nullptr;
- case APValue::ComplexInt:
+ case clang::APValue::ComplexInt:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
return nullptr;
- case APValue::ComplexFloat:
+ case clang::APValue::ComplexFloat:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
return nullptr;
- case APValue::Vector:
+ case clang::APValue::Vector:
emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
return nullptr;
- case APValue::Struct:
+ case clang::APValue::Struct:
emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
return nullptr;
- case APValue::Union:
+ case clang::APValue::Union:
emit_warning(c, source_loc, "unsupported initializer value kind: Union");
return nullptr;
- case APValue::MemberPointer:
+ case clang::APValue::MemberPointer:
emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
return nullptr;
- case APValue::AddrLabelDiff:
+ case clang::APValue::AddrLabelDiff:
emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
return nullptr;
}
zig_unreachable();
}
-static void visit_var_decl(Context *c, const VarDecl *var_decl) {
+static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
Buf *name = buf_create_from_str(decl_name(var_decl));
switch (var_decl->getTLSKind()) {
- case VarDecl::TLS_None:
+ case clang::VarDecl::TLS_None:
break;
- case VarDecl::TLS_Static:
+ case clang::VarDecl::TLS_Static:
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - static thread local storage", buf_ptr(name));
return;
- case VarDecl::TLS_Dynamic:
+ case clang::VarDecl::TLS_Dynamic:
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
return;
}
- QualType qt = var_decl->getType();
+ clang::QualType qt = var_decl->getType();
AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
if (var_type == nullptr) {
emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
@@ -4179,7 +4220,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
if (is_static && !is_extern) {
AstNode *init_node;
if (var_decl->hasInit()) {
- APValue *ap_value = var_decl->evaluateValue();
+ clang::APValue *ap_value = var_decl->evaluateValue();
if (ap_value == nullptr) {
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
@@ -4209,24 +4250,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
return;
}
-static bool decl_visitor(void *context, const Decl *decl) {
+static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
+ const clang::Decl *decl = reinterpret_cast(zdecl);
Context *c = (Context*)context;
switch (decl->getKind()) {
- case Decl::Function:
- visit_fn_decl(c, static_cast(decl));
+ case clang::Decl::Function:
+ visit_fn_decl(c, static_cast(decl));
break;
- case Decl::Typedef:
- resolve_typedef_decl(c, static_cast(decl));
+ case clang::Decl::Typedef:
+ resolve_typedef_decl(c, static_cast(decl));
break;
- case Decl::Enum:
- resolve_enum_decl(c, static_cast(decl));
+ case clang::Decl::Enum:
+ resolve_enum_decl(c, static_cast(decl));
break;
- case Decl::Record:
- resolve_record_decl(c, static_cast(decl));
+ case clang::Decl::Record:
+ resolve_record_decl(c, static_cast(decl));
break;
- case Decl::Var:
- visit_var_decl(c, static_cast(decl));
+ case clang::Decl::Var:
+ visit_var_decl(c, static_cast(decl));
break;
default:
emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
@@ -4568,7 +4610,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
} else if (first_tok->id == CTokIdAsterisk) {
*tok_i += 1;
- node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown);
+ node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
} else {
return node;
}
@@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
c->macro_table.put(name, result_node);
}
-static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
+static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
+ clang::ASTUnit *unit = reinterpret_cast(zunit);
CTokenize ctok = {{0}};
// TODO if we see #undef, delete it from the table
- for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
+ for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
switch (entity->getKind()) {
- case PreprocessedEntity::InvalidKind:
- case PreprocessedEntity::InclusionDirectiveKind:
- case PreprocessedEntity::MacroExpansionKind:
+ case clang::PreprocessedEntity::InvalidKind:
+ case clang::PreprocessedEntity::InclusionDirectiveKind:
+ case clang::PreprocessedEntity::MacroExpansionKind:
continue;
- case PreprocessedEntity::MacroDefinitionKind:
+ case clang::PreprocessedEntity::MacroDefinitionKind:
{
- MacroDefinitionRecord *macro = static_cast(entity);
+ clang::MacroDefinitionRecord *macro = static_cast(entity);
const char *raw_name = macro->getName()->getNameStart();
- SourceRange range = macro->getSourceRange();
- SourceLocation begin_loc = range.getBegin();
- SourceLocation end_loc = range.getEnd();
+ clang::SourceRange range = macro->getSourceRange();
+ clang::SourceLocation begin_loc = range.getBegin();
+ clang::SourceLocation end_loc = range.getEnd();
if (begin_loc == end_loc) {
// this means it is a macro without a value
@@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
continue;
}
- const char *begin_c = c->source_manager->getCharacterData(begin_loc);
+ const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc));
process_macro(c, &ctok, name, begin_c);
}
}
@@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
clang_argv.append("-isystem");
clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
- clang_argv.append("-isystem");
- clang_argv.append(buf_ptr(codegen->libc_include_dir));
+ if (codegen->libc_include_dir != nullptr) {
+ clang_argv.append("-isystem");
+ clang_argv.append(buf_ptr(codegen->libc_include_dir));
+ }
// windows c runtime requires -D_DEBUG if using debug libraries
if (codegen->build_mode == BuildModeDebug) {
@@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
clang_argv.append(target_file);
+ if (codegen->verbose_cimport) {
+ fprintf(stderr, "clang");
+ for (size_t i = 0; i < clang_argv.length; i += 1) {
+ fprintf(stderr, " %s", clang_argv.at(i));
+ }
+ fprintf(stderr, "\n");
+ }
+
// to make the [start...end] argument work
clang_argv.append(nullptr);
- IntrusiveRefCntPtr diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
+ clang::IntrusiveRefCntPtr diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
- std::shared_ptr pch_container_ops = std::make_shared();
+ std::shared_ptr pch_container_ops = std::make_shared();
bool only_local_decls = true;
bool capture_diagnostics = true;
@@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
bool single_file_parse = false;
bool for_serialization = false;
const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
- std::unique_ptr err_unit;
- std::unique_ptr ast_unit(ASTUnit::LoadFromCommandLine(
+ std::unique_ptr err_unit;
+ ZigClangASTUnit *ast_unit = reinterpret_cast(clang::ASTUnit::LoadFromCommandLine(
&clang_argv.at(0), &clang_argv.last(),
pch_container_ops, diags, resources_path,
- only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
- false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,
- single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
+ only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
+ false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
+ single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
nullptr));
// Early failures in LoadFromCommandLine may return with ErrUnit unset.
@@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
if (diags->getClient()->getNumErrors() > 0) {
if (ast_unit) {
- err_unit = std::move(ast_unit);
+ err_unit = std::unique_ptr(reinterpret_cast(ast_unit));
}
- for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
+ for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
it_end = err_unit->stored_diag_end();
it != it_end; ++it)
{
switch (it->getLevel()) {
- case DiagnosticsEngine::Ignored:
- case DiagnosticsEngine::Note:
- case DiagnosticsEngine::Remark:
- case DiagnosticsEngine::Warning:
+ case clang::DiagnosticsEngine::Ignored:
+ case clang::DiagnosticsEngine::Note:
+ case clang::DiagnosticsEngine::Remark:
+ case clang::DiagnosticsEngine::Warning:
continue;
- case DiagnosticsEngine::Error:
- case DiagnosticsEngine::Fatal:
+ case clang::DiagnosticsEngine::Error:
+ case clang::DiagnosticsEngine::Fatal:
break;
}
StringRef msg_str_ref = it->getMessage();
Buf *msg = string_ref_to_buf(msg_str_ref);
- FullSourceLoc fsl = it->getLocation();
+ clang::FullSourceLoc fsl = it->getLocation();
if (fsl.hasManager()) {
- FileID file_id = fsl.getFileID();
- StringRef filename = fsl.getManager().getFilename(fsl);
+ clang::FileID file_id = fsl.getFileID();
+ clang::StringRef filename = fsl.getManager().getFilename(fsl);
unsigned line = fsl.getSpellingLineNumber() - 1;
unsigned column = fsl.getSpellingColumnNumber() - 1;
unsigned offset = fsl.getManager().getFileOffset(fsl);
@@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
return ErrorCCompileErrors;
}
- c->ctx = &ast_unit->getASTContext();
- c->source_manager = &ast_unit->getSourceManager();
+ c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
+ c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
c->root = trans_create_node(c, NodeTypeContainerDecl);
c->root->data.container_decl.is_root = true;
- ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
+ ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor);
- process_preprocessor_entities(c, *ast_unit);
+ process_preprocessor_entities(c, ast_unit);
render_macros(c);
render_aliases(c);
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
new file mode 100644
index 0000000000..4220d778a0
--- /dev/null
+++ b/src/zig_clang.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+
+/*
+ * The point of this file is to contain all the Clang C++ API interaction so that:
+ * 1. The compile time of other files is kept under control.
+ * 2. Provide a C interface to the Clang functions we need for self-hosting purposes.
+ * 3. Prevent C++ from infecting the rest of the project.
+ */
+#include "zig_clang.h"
+
+#if __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
+#include
+#include
+#include
+
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+
+// Detect additions to the enum
+void zig2clang_BO(ZigClangBO op) {
+ switch (op) {
+ case ZigClangBO_PtrMemD:
+ case ZigClangBO_PtrMemI:
+ case ZigClangBO_Cmp:
+ case ZigClangBO_Mul:
+ case ZigClangBO_Div:
+ case ZigClangBO_Rem:
+ case ZigClangBO_Add:
+ case ZigClangBO_Sub:
+ case ZigClangBO_Shl:
+ case ZigClangBO_Shr:
+ case ZigClangBO_LT:
+ case ZigClangBO_GT:
+ case ZigClangBO_LE:
+ case ZigClangBO_GE:
+ case ZigClangBO_EQ:
+ case ZigClangBO_NE:
+ case ZigClangBO_And:
+ case ZigClangBO_Xor:
+ case ZigClangBO_Or:
+ case ZigClangBO_LAnd:
+ case ZigClangBO_LOr:
+ case ZigClangBO_Assign:
+ case ZigClangBO_Comma:
+ case ZigClangBO_MulAssign:
+ case ZigClangBO_DivAssign:
+ case ZigClangBO_RemAssign:
+ case ZigClangBO_AddAssign:
+ case ZigClangBO_SubAssign:
+ case ZigClangBO_ShlAssign:
+ case ZigClangBO_ShrAssign:
+ case ZigClangBO_AndAssign:
+ case ZigClangBO_XorAssign:
+ case ZigClangBO_OrAssign:
+ break;
+ }
+}
+
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
+
+// This function detects additions to the enum
+void zig2clang_UO(ZigClangUO op) {
+ switch (op) {
+ case ZigClangUO_AddrOf:
+ case ZigClangUO_Coawait:
+ case ZigClangUO_Deref:
+ case ZigClangUO_Extension:
+ case ZigClangUO_Imag:
+ case ZigClangUO_LNot:
+ case ZigClangUO_Minus:
+ case ZigClangUO_Not:
+ case ZigClangUO_Plus:
+ case ZigClangUO_PostDec:
+ case ZigClangUO_PostInc:
+ case ZigClangUO_PreDec:
+ case ZigClangUO_PreInc:
+ case ZigClangUO_Real:
+ break;
+ }
+}
+
+static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
+
+static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
+static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
+ ZigClangSourceLocation dest;
+ memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
+ return dest;
+}
+static clang::SourceLocation bitcast(ZigClangSourceLocation src) {
+ clang::SourceLocation dest;
+ memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
+ return dest;
+}
+
+static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), "");
+static ZigClangQualType bitcast(clang::QualType src) {
+ ZigClangQualType dest;
+ memcpy(&dest, &src, sizeof(ZigClangQualType));
+ return dest;
+}
+static clang::QualType bitcast(ZigClangQualType src) {
+ clang::QualType dest;
+ memcpy(&dest, &src, sizeof(ZigClangQualType));
+ return dest;
+}
+
+ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return bitcast(reinterpret_cast(self)->getSpellingLoc(bitcast(Loc)));
+}
+
+const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *self,
+ ZigClangSourceLocation SpellingLoc)
+{
+ StringRef s = reinterpret_cast(self)->getFilename(bitcast(SpellingLoc));
+ return (const char *)s.bytes_begin();
+}
+
+unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return reinterpret_cast(self)->getSpellingLineNumber(bitcast(Loc));
+}
+
+unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return reinterpret_cast(self)->getSpellingColumnNumber(bitcast(Loc));
+}
+
+const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self,
+ ZigClangSourceLocation SL)
+{
+ return reinterpret_cast(self)->getCharacterData(bitcast(SL));
+}
+
+ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) {
+ return bitcast(reinterpret_cast(self)->getPointerType(bitcast(T)));
+}
+
+ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
+ clang::ASTContext *result = &reinterpret_cast(self)->getASTContext();
+ return reinterpret_cast(result);
+}
+
+ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
+ clang::SourceManager *result = &reinterpret_cast(self)->getSourceManager();
+ return reinterpret_cast(result);
+}
+
+bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
+ bool (*Fn)(void *context, const ZigClangDecl *decl))
+{
+ return reinterpret_cast(self)->visitLocalTopLevelDecls(context,
+ reinterpret_cast(Fn));
+}
diff --git a/src/zig_clang.h b/src/zig_clang.h
new file mode 100644
index 0000000000..c7d749cbd9
--- /dev/null
+++ b/src/zig_clang.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_ZIG_CLANG_H
+#define ZIG_ZIG_CLANG_H
+
+#ifdef __cplusplus
+#define ZIG_EXTERN_C extern "C"
+#else
+#define ZIG_EXTERN_C
+#endif
+
+// ATTENTION: If you modify this file, be sure to update the corresponding
+// extern function declarations in the self-hosted compiler.
+
+struct ZigClangSourceLocation {
+ unsigned ID;
+};
+
+struct ZigClangQualType {
+ void *ptr;
+};
+
+struct ZigClangAPValue;
+struct ZigClangASTContext;
+struct ZigClangASTUnit;
+struct ZigClangArraySubscriptExpr;
+struct ZigClangArrayType;
+struct ZigClangAttributedType;
+struct ZigClangBinaryOperator;
+struct ZigClangBreakStmt;
+struct ZigClangBuiltinType;
+struct ZigClangCStyleCastExpr;
+struct ZigClangCallExpr;
+struct ZigClangCaseStmt;
+struct ZigClangCompoundAssignOperator;
+struct ZigClangCompoundStmt;
+struct ZigClangConditionalOperator;
+struct ZigClangConstantArrayType;
+struct ZigClangContinueStmt;
+struct ZigClangDecayedType;
+struct ZigClangDecl;
+struct ZigClangDeclRefExpr;
+struct ZigClangDeclStmt;
+struct ZigClangDefaultStmt;
+struct ZigClangDiagnosticOptions;
+struct ZigClangDiagnosticsEngine;
+struct ZigClangDoStmt;
+struct ZigClangElaboratedType;
+struct ZigClangEnumConstantDecl;
+struct ZigClangEnumDecl;
+struct ZigClangEnumType;
+struct ZigClangExpr;
+struct ZigClangFieldDecl;
+struct ZigClangFileID;
+struct ZigClangForStmt;
+struct ZigClangFullSourceLoc;
+struct ZigClangFunctionDecl;
+struct ZigClangFunctionProtoType;
+struct ZigClangIfStmt;
+struct ZigClangImplicitCastExpr;
+struct ZigClangIncompleteArrayType;
+struct ZigClangIntegerLiteral;
+struct ZigClangMacroDefinitionRecord;
+struct ZigClangMemberExpr;
+struct ZigClangNamedDecl;
+struct ZigClangNone;
+struct ZigClangPCHContainerOperations;
+struct ZigClangParenExpr;
+struct ZigClangParenType;
+struct ZigClangParmVarDecl;
+struct ZigClangPointerType;
+struct ZigClangPreprocessedEntity;
+struct ZigClangRecordDecl;
+struct ZigClangRecordType;
+struct ZigClangReturnStmt;
+struct ZigClangSkipFunctionBodiesScope;
+struct ZigClangSourceManager;
+struct ZigClangSourceRange;
+struct ZigClangStmt;
+struct ZigClangStorageClass;
+struct ZigClangStringLiteral;
+struct ZigClangStringRef;
+struct ZigClangSwitchStmt;
+struct ZigClangType;
+struct ZigClangTypedefNameDecl;
+struct ZigClangTypedefType;
+struct ZigClangUnaryExprOrTypeTraitExpr;
+struct ZigClangUnaryOperator;
+struct ZigClangValueDecl;
+struct ZigClangVarDecl;
+struct ZigClangWhileStmt;
+
+enum ZigClangBO {
+ ZigClangBO_PtrMemD,
+ ZigClangBO_PtrMemI,
+ ZigClangBO_Mul,
+ ZigClangBO_Div,
+ ZigClangBO_Rem,
+ ZigClangBO_Add,
+ ZigClangBO_Sub,
+ ZigClangBO_Shl,
+ ZigClangBO_Shr,
+ ZigClangBO_Cmp,
+ ZigClangBO_LT,
+ ZigClangBO_GT,
+ ZigClangBO_LE,
+ ZigClangBO_GE,
+ ZigClangBO_EQ,
+ ZigClangBO_NE,
+ ZigClangBO_And,
+ ZigClangBO_Xor,
+ ZigClangBO_Or,
+ ZigClangBO_LAnd,
+ ZigClangBO_LOr,
+ ZigClangBO_Assign,
+ ZigClangBO_MulAssign,
+ ZigClangBO_DivAssign,
+ ZigClangBO_RemAssign,
+ ZigClangBO_AddAssign,
+ ZigClangBO_SubAssign,
+ ZigClangBO_ShlAssign,
+ ZigClangBO_ShrAssign,
+ ZigClangBO_AndAssign,
+ ZigClangBO_XorAssign,
+ ZigClangBO_OrAssign,
+ ZigClangBO_Comma,
+};
+
+enum ZigClangUO {
+ ZigClangUO_PostInc,
+ ZigClangUO_PostDec,
+ ZigClangUO_PreInc,
+ ZigClangUO_PreDec,
+ ZigClangUO_AddrOf,
+ ZigClangUO_Deref,
+ ZigClangUO_Plus,
+ ZigClangUO_Minus,
+ ZigClangUO_Not,
+ ZigClangUO_LNot,
+ ZigClangUO_Real,
+ ZigClangUO_Imag,
+ ZigClangUO_Extension,
+ ZigClangUO_Coawait,
+};
+
+//struct ZigClangCC_AAPCS;
+//struct ZigClangCC_AAPCS_VFP;
+//struct ZigClangCC_C;
+//struct ZigClangCC_IntelOclBicc;
+//struct ZigClangCC_OpenCLKernel;
+//struct ZigClangCC_PreserveAll;
+//struct ZigClangCC_PreserveMost;
+//struct ZigClangCC_SpirFunction;
+//struct ZigClangCC_Swift;
+//struct ZigClangCC_Win64;
+//struct ZigClangCC_X86FastCall;
+//struct ZigClangCC_X86Pascal;
+//struct ZigClangCC_X86RegCall;
+//struct ZigClangCC_X86StdCall;
+//struct ZigClangCC_X86ThisCall;
+//struct ZigClangCC_X86VectorCall;
+//struct ZigClangCC_X86_64SysV;
+
+//struct ZigClangCK_ARCConsumeObject;
+//struct ZigClangCK_ARCExtendBlockObject;
+//struct ZigClangCK_ARCProduceObject;
+//struct ZigClangCK_ARCReclaimReturnedObject;
+//struct ZigClangCK_AddressSpaceConversion;
+//struct ZigClangCK_AnyPointerToBlockPointerCast;
+//struct ZigClangCK_ArrayToPointerDecay;
+//struct ZigClangCK_AtomicToNonAtomic;
+//struct ZigClangCK_BaseToDerived;
+//struct ZigClangCK_BaseToDerivedMemberPointer;
+//struct ZigClangCK_BitCast;
+//struct ZigClangCK_BlockPointerToObjCPointerCast;
+//struct ZigClangCK_BooleanToSignedIntegral;
+//struct ZigClangCK_BuiltinFnToFnPtr;
+//struct ZigClangCK_CPointerToObjCPointerCast;
+//struct ZigClangCK_ConstructorConversion;
+//struct ZigClangCK_CopyAndAutoreleaseBlockObject;
+//struct ZigClangCK_Dependent;
+//struct ZigClangCK_DerivedToBase;
+//struct ZigClangCK_DerivedToBaseMemberPointer;
+//struct ZigClangCK_Dynamic;
+//struct ZigClangCK_FloatingCast;
+//struct ZigClangCK_FloatingComplexCast;
+//struct ZigClangCK_FloatingComplexToBoolean;
+//struct ZigClangCK_FloatingComplexToIntegralComplex;
+//struct ZigClangCK_FloatingComplexToReal;
+//struct ZigClangCK_FloatingRealToComplex;
+//struct ZigClangCK_FloatingToBoolean;
+//struct ZigClangCK_FloatingToIntegral;
+//struct ZigClangCK_FunctionToPointerDecay;
+//struct ZigClangCK_IntToOCLSampler;
+//struct ZigClangCK_IntegralCast;
+//struct ZigClangCK_IntegralComplexCast;
+//struct ZigClangCK_IntegralComplexToBoolean;
+//struct ZigClangCK_IntegralComplexToFloatingComplex;
+//struct ZigClangCK_IntegralComplexToReal;
+//struct ZigClangCK_IntegralRealToComplex;
+//struct ZigClangCK_IntegralToBoolean;
+//struct ZigClangCK_IntegralToFloating;
+//struct ZigClangCK_IntegralToPointer;
+//struct ZigClangCK_LValueBitCast;
+//struct ZigClangCK_LValueToRValue;
+//struct ZigClangCK_MemberPointerToBoolean;
+//struct ZigClangCK_NoOp;
+//struct ZigClangCK_NonAtomicToAtomic;
+//struct ZigClangCK_NullToMemberPointer;
+//struct ZigClangCK_NullToPointer;
+//struct ZigClangCK_ObjCObjectLValueCast;
+//struct ZigClangCK_PointerToBoolean;
+//struct ZigClangCK_PointerToIntegral;
+//struct ZigClangCK_ReinterpretMemberPointer;
+//struct ZigClangCK_ToUnion;
+//struct ZigClangCK_ToVoid;
+//struct ZigClangCK_UncheckedDerivedToBase;
+//struct ZigClangCK_UserDefinedConversion;
+//struct ZigClangCK_VectorSplat;
+//struct ZigClangCK_ZeroToOCLEvent;
+//struct ZigClangCK_ZeroToOCLQueue;
+
+//struct ZigClangETK_Class;
+//struct ZigClangETK_Enum;
+//struct ZigClangETK_Interface;
+//struct ZigClangETK_None;
+//struct ZigClangETK_Struct;
+//struct ZigClangETK_Typename;
+//struct ZigClangETK_Union;
+
+//struct ZigClangSC_None;
+//struct ZigClangSC_PrivateExtern;
+//struct ZigClangSC_Static;
+
+//struct ZigClangTU_Complete;
+
+ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,
+ ZigClangSourceLocation SpellingLoc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,
+ ZigClangSourceLocation SL);
+
+ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);
+
+ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);
+ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);
+ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context,
+ bool (*Fn)(void *context, const ZigClangDecl *decl));
+#endif
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index bda8fa0adc..e5a4890914 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch
return reinterpret_cast(di_type);
}
+struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
+ uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count)
+{
+ SmallVector subrange;
+ subrange.push_back(reinterpret_cast(dibuilder)->getOrCreateSubrange(0, elem_count));
+ DIType *di_type = reinterpret_cast(dibuilder)->createVectorType(
+ SizeInBits,
+ AlignInBits,
+ reinterpret_cast(Ty),
+ reinterpret_cast(dibuilder)->getOrCreateArray(subrange));
+ return reinterpret_cast(di_type);
+}
+
ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)
{
@@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
reinterpret_cast(file),
lineno,
di_sub_type,
- is_local_to_unit, is_definition, scope_line, DINode::FlagZero, is_optimized,
+ is_local_to_unit, is_definition, scope_line, DINode::FlagStaticMember, is_optimized,
nullptr,
reinterpret_cast(decl_subprogram));
return reinterpret_cast(result);
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index 551a4a7448..b5b0e97b53 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB
unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
+ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
+ uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count);
+
ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
diff --git a/std/array_list.zig b/std/array_list.zig
index 3ee425fe14..e2535d6393 100644
--- a/std/array_list.zig
+++ b/std/array_list.zig
@@ -1,7 +1,7 @@
const std = @import("index.zig");
const debug = std.debug;
const assert = debug.assert;
-const assertError = debug.assertError;
+const testing = std.testing;
const mem = std.mem;
const Allocator = mem.Allocator;
@@ -212,8 +212,8 @@ test "std.ArrayList.init" {
var list = ArrayList(i32).init(allocator);
defer list.deinit();
- assert(list.count() == 0);
- assert(list.capacity() == 0);
+ testing.expect(list.count() == 0);
+ testing.expect(list.capacity() == 0);
}
test "std.ArrayList.basic" {
@@ -224,7 +224,7 @@ test "std.ArrayList.basic" {
defer list.deinit();
// setting on empty list is out of bounds
- assertError(list.setOrError(0, 1), error.OutOfBounds);
+ testing.expectError(error.OutOfBounds, list.setOrError(0, 1));
{
var i: usize = 0;
@@ -236,44 +236,44 @@ test "std.ArrayList.basic" {
{
var i: usize = 0;
while (i < 10) : (i += 1) {
- assert(list.items[i] == @intCast(i32, i + 1));
+ testing.expect(list.items[i] == @intCast(i32, i + 1));
}
}
for (list.toSlice()) |v, i| {
- assert(v == @intCast(i32, i + 1));
+ testing.expect(v == @intCast(i32, i + 1));
}
for (list.toSliceConst()) |v, i| {
- assert(v == @intCast(i32, i + 1));
+ testing.expect(v == @intCast(i32, i + 1));
}
- assert(list.pop() == 10);
- assert(list.len == 9);
+ testing.expect(list.pop() == 10);
+ testing.expect(list.len == 9);
list.appendSlice([]const i32{
1,
2,
3,
}) catch unreachable;
- assert(list.len == 12);
- assert(list.pop() == 3);
- assert(list.pop() == 2);
- assert(list.pop() == 1);
- assert(list.len == 9);
+ testing.expect(list.len == 12);
+ testing.expect(list.pop() == 3);
+ testing.expect(list.pop() == 2);
+ testing.expect(list.pop() == 1);
+ testing.expect(list.len == 9);
list.appendSlice([]const i32{}) catch unreachable;
- assert(list.len == 9);
+ testing.expect(list.len == 9);
// can only set on indices < self.len
list.set(7, 33);
list.set(8, 42);
- assertError(list.setOrError(9, 99), error.OutOfBounds);
- assertError(list.setOrError(10, 123), error.OutOfBounds);
+ testing.expectError(error.OutOfBounds, list.setOrError(9, 99));
+ testing.expectError(error.OutOfBounds, list.setOrError(10, 123));
- assert(list.pop() == 42);
- assert(list.pop() == 33);
+ testing.expect(list.pop() == 42);
+ testing.expect(list.pop() == 33);
}
test "std.ArrayList.swapRemove" {
@@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" {
try list.append(7);
//remove from middle
- assert(list.swapRemove(3) == 4);
- assert(list.at(3) == 7);
- assert(list.len == 6);
+ testing.expect(list.swapRemove(3) == 4);
+ testing.expect(list.at(3) == 7);
+ testing.expect(list.len == 6);
//remove from end
- assert(list.swapRemove(5) == 6);
- assert(list.len == 5);
+ testing.expect(list.swapRemove(5) == 6);
+ testing.expect(list.len == 5);
//remove from front
- assert(list.swapRemove(0) == 1);
- assert(list.at(0) == 5);
- assert(list.len == 4);
+ testing.expect(list.swapRemove(0) == 1);
+ testing.expect(list.at(0) == 5);
+ testing.expect(list.len == 4);
}
test "std.ArrayList.swapRemoveOrError" {
@@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" {
defer list.deinit();
// Test just after initialization
- assertError(list.swapRemoveOrError(0), error.OutOfBounds);
+ testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
// Test after adding one item and remote it
try list.append(1);
- assert((try list.swapRemoveOrError(0)) == 1);
- assertError(list.swapRemoveOrError(0), error.OutOfBounds);
+ testing.expect((try list.swapRemoveOrError(0)) == 1);
+ testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
// Test after adding two items and remote both
try list.append(1);
try list.append(2);
- assert((try list.swapRemoveOrError(1)) == 2);
- assert((try list.swapRemoveOrError(0)) == 1);
- assertError(list.swapRemoveOrError(0), error.OutOfBounds);
+ testing.expect((try list.swapRemoveOrError(1)) == 2);
+ testing.expect((try list.swapRemoveOrError(0)) == 1);
+ testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
// Test out of bounds with one item
try list.append(1);
- assertError(list.swapRemoveOrError(1), error.OutOfBounds);
+ testing.expectError(error.OutOfBounds, list.swapRemoveOrError(1));
// Test out of bounds with two items
try list.append(2);
- assertError(list.swapRemoveOrError(2), error.OutOfBounds);
+ testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
}
test "std.ArrayList.iterator" {
@@ -342,22 +342,22 @@ test "std.ArrayList.iterator" {
var count: i32 = 0;
var it = list.iterator();
while (it.next()) |next| {
- assert(next == count + 1);
+ testing.expect(next == count + 1);
count += 1;
}
- assert(count == 3);
- assert(it.next() == null);
+ testing.expect(count == 3);
+ testing.expect(it.next() == null);
it.reset();
count = 0;
while (it.next()) |next| {
- assert(next == count + 1);
+ testing.expect(next == count + 1);
count += 1;
if (count == 2) break;
}
it.reset();
- assert(it.next().? == 1);
+ testing.expect(it.next().? == 1);
}
test "std.ArrayList.insert" {
@@ -368,10 +368,10 @@ test "std.ArrayList.insert" {
try list.append(2);
try list.append(3);
try list.insert(0, 5);
- assert(list.items[0] == 5);
- assert(list.items[1] == 1);
- assert(list.items[2] == 2);
- assert(list.items[3] == 3);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items[1] == 1);
+ testing.expect(list.items[2] == 2);
+ testing.expect(list.items[3] == 3);
}
test "std.ArrayList.insertSlice" {
@@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" {
9,
8,
});
- assert(list.items[0] == 1);
- assert(list.items[1] == 9);
- assert(list.items[2] == 8);
- assert(list.items[3] == 2);
- assert(list.items[4] == 3);
- assert(list.items[5] == 4);
+ testing.expect(list.items[0] == 1);
+ testing.expect(list.items[1] == 9);
+ testing.expect(list.items[2] == 8);
+ testing.expect(list.items[3] == 2);
+ testing.expect(list.items[4] == 3);
+ testing.expect(list.items[5] == 4);
const items = []const i32{1};
try list.insertSlice(0, items[0..0]);
- assert(list.len == 6);
- assert(list.items[0] == 1);
+ testing.expect(list.len == 6);
+ testing.expect(list.items[0] == 1);
+}
+
+const Item = struct {
+ integer: i32,
+ sub_items: ArrayList(Item),
+};
+
+test "std.ArrayList: ArrayList(T) of struct T" {
+ var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
+ try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
+ testing.expect(root.sub_items.items[0].integer == 42);
}
diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig
index 1aab4c32de..bdc86c0981 100644
--- a/std/atomic/queue.zig
+++ b/std/atomic/queue.zig
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
const AtomicOrder = builtin.AtomicOrder;
const AtomicRmwOp = builtin.AtomicRmwOp;
const assert = std.debug.assert;
+const expect = std.testing.expect;
/// Many producer, many consumer, non-allocating, thread-safe.
/// Uses a mutex to protect access.
@@ -170,20 +171,36 @@ test "std.atomic.Queue" {
.get_count = 0,
};
- var putters: [put_thread_count]*std.os.Thread = undefined;
- for (putters) |*t| {
- t.* = try std.os.spawnThread(&context, startPuts);
- }
- var getters: [put_thread_count]*std.os.Thread = undefined;
- for (getters) |*t| {
- t.* = try std.os.spawnThread(&context, startGets);
- }
+ if (builtin.single_threaded) {
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ expect(startPuts(&context) == 0);
+ }
+ }
+ context.puts_done = 1;
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ expect(startGets(&context) == 0);
+ }
+ }
+ } else {
+ var putters: [put_thread_count]*std.os.Thread = undefined;
+ for (putters) |*t| {
+ t.* = try std.os.spawnThread(&context, startPuts);
+ }
+ var getters: [put_thread_count]*std.os.Thread = undefined;
+ for (getters) |*t| {
+ t.* = try std.os.spawnThread(&context, startGets);
+ }
- for (putters) |t|
- t.wait();
- _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
- for (getters) |t|
- t.wait();
+ for (putters) |t|
+ t.wait();
+ _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
+ for (getters) |t|
+ t.wait();
+ }
if (context.put_sum != context.get_sum) {
std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
@@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 {
while (put_count != 0) : (put_count -= 1) {
std.os.time.sleep(1); // let the os scheduler be our fuzz
const x = @bitCast(i32, r.random.scalar(u32));
- const node = ctx.allocator.create(Queue(i32).Node{
+ const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
+ node.* = Queue(i32).Node{
.prev = undefined,
.next = undefined,
.data = x,
- }) catch unreachable;
+ };
ctx.queue.put(node);
_ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
}
@@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" {
};
queue.put(&node_1);
- assert(queue.get().?.data == 0);
+ expect(queue.get().?.data == 0);
var node_2 = Queue(i32).Node{
.data = 2,
@@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" {
};
queue.put(&node_3);
- assert(queue.get().?.data == 1);
+ expect(queue.get().?.data == 1);
- assert(queue.get().?.data == 2);
+ expect(queue.get().?.data == 2);
var node_4 = Queue(i32).Node{
.data = 4,
@@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" {
};
queue.put(&node_4);
- assert(queue.get().?.data == 3);
+ expect(queue.get().?.data == 3);
node_3.next = null;
- assert(queue.get().?.data == 4);
+ expect(queue.get().?.data == 4);
- assert(queue.get() == null);
+ expect(queue.get() == null);
}
test "std.atomic.Queue dump" {
@@ -294,7 +312,7 @@ test "std.atomic.Queue dump" {
// Test empty stream
sos.reset();
try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
- assert(mem.eql(u8, buffer[0..sos.pos],
+ expect(mem.eql(u8, buffer[0..sos.pos],
\\head: (null)
\\tail: (null)
\\
@@ -318,7 +336,7 @@ test "std.atomic.Queue dump" {
\\ (null)
\\
, @ptrToInt(queue.head), @ptrToInt(queue.tail));
- assert(mem.eql(u8, buffer[0..sos.pos], expected));
+ expect(mem.eql(u8, buffer[0..sos.pos], expected));
// Test a stream with two elements
var node_1 = Queue(i32).Node{
@@ -339,5 +357,5 @@ test "std.atomic.Queue dump" {
\\ (null)
\\
, @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail));
- assert(mem.eql(u8, buffer[0..sos.pos], expected));
+ expect(mem.eql(u8, buffer[0..sos.pos], expected));
}
diff --git a/std/atomic/stack.zig b/std/atomic/stack.zig
index b69a93733c..4d0d5075e0 100644
--- a/std/atomic/stack.zig
+++ b/std/atomic/stack.zig
@@ -1,13 +1,17 @@
const assert = std.debug.assert;
const builtin = @import("builtin");
const AtomicOrder = builtin.AtomicOrder;
+const expect = std.testing.expect;
/// Many reader, many writer, non-allocating, thread-safe
/// Uses a spinlock to protect push() and pop()
+/// When building in single threaded mode, this is a simple linked list.
pub fn Stack(comptime T: type) type {
return struct {
root: ?*Node,
- lock: u8,
+ lock: @typeOf(lock_init),
+
+ const lock_init = if (builtin.single_threaded) {} else u8(0);
pub const Self = @This();
@@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type {
pub fn init() Self {
return Self{
.root = null,
- .lock = 0,
+ .lock = lock_init,
};
}
@@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type {
}
pub fn push(self: *Self, node: *Node) void {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ if (builtin.single_threaded) {
+ node.next = self.root;
+ self.root = node;
+ } else {
+ while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
- node.next = self.root;
- self.root = node;
+ node.next = self.root;
+ self.root = node;
+ }
}
pub fn pop(self: *Self) ?*Node {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+ if (builtin.single_threaded) {
+ const root = self.root orelse return null;
+ self.root = root.next;
+ return root;
+ } else {
+ while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
- const root = self.root orelse return null;
- self.root = root.next;
- return root;
+ const root = self.root orelse return null;
+ self.root = root.next;
+ return root;
+ }
}
pub fn isEmpty(self: *Self) bool {
@@ -90,20 +105,36 @@ test "std.atomic.stack" {
.get_count = 0,
};
- var putters: [put_thread_count]*std.os.Thread = undefined;
- for (putters) |*t| {
- t.* = try std.os.spawnThread(&context, startPuts);
- }
- var getters: [put_thread_count]*std.os.Thread = undefined;
- for (getters) |*t| {
- t.* = try std.os.spawnThread(&context, startGets);
- }
+ if (builtin.single_threaded) {
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ expect(startPuts(&context) == 0);
+ }
+ }
+ context.puts_done = 1;
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ expect(startGets(&context) == 0);
+ }
+ }
+ } else {
+ var putters: [put_thread_count]*std.os.Thread = undefined;
+ for (putters) |*t| {
+ t.* = try std.os.spawnThread(&context, startPuts);
+ }
+ var getters: [put_thread_count]*std.os.Thread = undefined;
+ for (getters) |*t| {
+ t.* = try std.os.spawnThread(&context, startGets);
+ }
- for (putters) |t|
- t.wait();
- _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
- for (getters) |t|
- t.wait();
+ for (putters) |t|
+ t.wait();
+ _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
+ for (getters) |t|
+ t.wait();
+ }
if (context.put_sum != context.get_sum) {
std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
@@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 {
while (put_count != 0) : (put_count -= 1) {
std.os.time.sleep(1); // let the os scheduler be our fuzz
const x = @bitCast(i32, r.random.scalar(u32));
- const node = ctx.allocator.create(Stack(i32).Node{
+ const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
+ node.* = Stack(i32).Node{
.next = undefined,
.data = x,
- }) catch unreachable;
+ };
ctx.stack.push(node);
_ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
}
diff --git a/std/base64.zig b/std/base64.zig
index bc0bdb1bd3..cfe8ea95f8 100644
--- a/std/base64.zig
+++ b/std/base64.zig
@@ -1,5 +1,6 @@
const std = @import("index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
var buffer: [0x100]u8 = undefined;
var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)];
standard_encoder.encode(encoded, expected_decoded);
- assert(mem.eql(u8, encoded, expected_encoded));
+ testing.expectEqualSlices(u8, expected_encoded, encoded);
}
// Base64Decoder
@@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
var buffer: [0x100]u8 = undefined;
var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)];
try standard_decoder.decode(decoded, expected_encoded);
- assert(mem.eql(u8, decoded, expected_decoded));
+ testing.expectEqualSlices(u8, expected_decoded, decoded);
}
// Base64DecoderWithIgnore
@@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
var buffer: [0x100]u8 = undefined;
var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);
- assert(written <= decoded.len);
- assert(mem.eql(u8, decoded[0..written], expected_decoded));
+ testing.expect(written <= decoded.len);
+ testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
}
// Base64DecoderUnsafe
@@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
var buffer: [0x100]u8 = undefined;
var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)];
standard_decoder_unsafe.decode(decoded, expected_encoded);
- assert(mem.eql(u8, decoded, expected_decoded));
+ testing.expectEqualSlices(u8, expected_decoded, decoded);
}
}
@@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
var buffer: [0x100]u8 = undefined;
var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
var written = try standard_decoder_ignore_space.decode(decoded, encoded);
- assert(mem.eql(u8, decoded[0..written], expected_decoded));
+ testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
}
fn testError(encoded: []const u8, expected_err: anyerror) !void {
diff --git a/std/buf_map.zig b/std/buf_map.zig
index a82d1b731a..f8d3d5e04d 100644
--- a/std/buf_map.zig
+++ b/std/buf_map.zig
@@ -2,7 +2,7 @@ const std = @import("index.zig");
const HashMap = std.HashMap;
const mem = std.mem;
const Allocator = mem.Allocator;
-const assert = std.debug.assert;
+const testing = std.testing;
/// BufMap copies keys and values before they go into the map, and
/// frees them when they get removed.
@@ -16,7 +16,7 @@ pub const BufMap = struct {
return self;
}
- pub fn deinit(self: *const BufMap) void {
+ pub fn deinit(self: *BufMap) void {
var it = self.hash_map.iterator();
while (true) {
const entry = it.next() orelse break;
@@ -27,16 +27,34 @@ pub const BufMap = struct {
self.hash_map.deinit();
}
- pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
- self.delete(key);
- const key_copy = try self.copy(key);
- errdefer self.free(key_copy);
- const value_copy = try self.copy(value);
- errdefer self.free(value_copy);
- _ = try self.hash_map.put(key_copy, value_copy);
+ /// Same as `set` but the key and value become owned by the BufMap rather
+ /// than being copied.
+ /// If `setMove` fails, the ownership of key and value does not transfer.
+ pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
+ const get_or_put = try self.hash_map.getOrPut(key);
+ if (get_or_put.found_existing) {
+ self.free(get_or_put.kv.key);
+ get_or_put.kv.key = key;
+ }
+ get_or_put.kv.value = value;
}
- pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {
+ /// `key` and `value` are copied into the BufMap.
+ pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
+ const value_copy = try self.copy(value);
+ errdefer self.free(value_copy);
+ // Avoid copying key if it already exists
+ const get_or_put = try self.hash_map.getOrPut(key);
+ if (!get_or_put.found_existing) {
+ get_or_put.kv.key = self.copy(key) catch |err| {
+ _ = self.hash_map.remove(key);
+ return err;
+ };
+ }
+ get_or_put.kv.value = value_copy;
+ }
+
+ pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
const entry = self.hash_map.get(key) orelse return null;
return entry.value;
}
@@ -47,7 +65,7 @@ pub const BufMap = struct {
self.free(entry.value);
}
- pub fn count(self: *const BufMap) usize {
+ pub fn count(self: BufMap) usize {
return self.hash_map.count();
}
@@ -55,11 +73,11 @@ pub const BufMap = struct {
return self.hash_map.iterator();
}
- fn free(self: *const BufMap, value: []const u8) void {
+ fn free(self: BufMap, value: []const u8) void {
self.hash_map.allocator.free(value);
}
- fn copy(self: *const BufMap, value: []const u8) ![]const u8 {
+ fn copy(self: BufMap, value: []const u8) ![]u8 {
return mem.dupe(self.hash_map.allocator, u8, value);
}
};
@@ -72,17 +90,17 @@ test "BufMap" {
defer bufmap.deinit();
try bufmap.set("x", "1");
- assert(mem.eql(u8, bufmap.get("x").?, "1"));
- assert(1 == bufmap.count());
+ testing.expect(mem.eql(u8, bufmap.get("x").?, "1"));
+ testing.expect(1 == bufmap.count());
try bufmap.set("x", "2");
- assert(mem.eql(u8, bufmap.get("x").?, "2"));
- assert(1 == bufmap.count());
+ testing.expect(mem.eql(u8, bufmap.get("x").?, "2"));
+ testing.expect(1 == bufmap.count());
try bufmap.set("x", "3");
- assert(mem.eql(u8, bufmap.get("x").?, "3"));
- assert(1 == bufmap.count());
+ testing.expect(mem.eql(u8, bufmap.get("x").?, "3"));
+ testing.expect(1 == bufmap.count());
bufmap.delete("x");
- assert(0 == bufmap.count());
+ testing.expect(0 == bufmap.count());
}
diff --git a/std/buf_set.zig b/std/buf_set.zig
index ab2d8e7c34..7ccd94c179 100644
--- a/std/buf_set.zig
+++ b/std/buf_set.zig
@@ -2,7 +2,7 @@ const std = @import("index.zig");
const HashMap = @import("hash_map.zig").HashMap;
const mem = @import("mem.zig");
const Allocator = mem.Allocator;
-const assert = std.debug.assert;
+const testing = std.testing;
pub const BufSet = struct {
hash_map: BufSetHashMap,
@@ -68,9 +68,9 @@ test "BufSet" {
defer bufset.deinit();
try bufset.put("x");
- assert(bufset.count() == 1);
+ testing.expect(bufset.count() == 1);
bufset.delete("x");
- assert(bufset.count() == 0);
+ testing.expect(bufset.count() == 0);
try bufset.put("x");
try bufset.put("y");
diff --git a/std/buffer.zig b/std/buffer.zig
index 2b71c26749..371655f1e5 100644
--- a/std/buffer.zig
+++ b/std/buffer.zig
@@ -3,6 +3,7 @@ const debug = std.debug;
const mem = std.mem;
const Allocator = mem.Allocator;
const assert = debug.assert;
+const testing = std.testing;
const ArrayList = std.ArrayList;
/// A buffer that allocates memory and maintains a null byte at the end.
@@ -141,19 +142,19 @@ test "simple Buffer" {
const cstr = @import("cstr.zig");
var buf = try Buffer.init(debug.global_allocator, "");
- assert(buf.len() == 0);
+ testing.expect(buf.len() == 0);
try buf.append("hello");
try buf.append(" ");
try buf.append("world");
- assert(buf.eql("hello world"));
- assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
+ testing.expect(buf.eql("hello world"));
+ testing.expect(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
var buf2 = try Buffer.initFromBuffer(buf);
- assert(buf.eql(buf2.toSliceConst()));
+ testing.expect(buf.eql(buf2.toSliceConst()));
- assert(buf.startsWith("hell"));
- assert(buf.endsWith("orld"));
+ testing.expect(buf.startsWith("hell"));
+ testing.expect(buf.endsWith("orld"));
try buf2.resize(4);
- assert(buf.startsWith(buf2.toSlice()));
+ testing.expect(buf.startsWith(buf2.toSlice()));
}
diff --git a/std/build.zig b/std/build.zig
index 90f5bec656..0dbbded802 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -89,7 +89,7 @@ pub const Builder = struct {
};
pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
- const env_map = allocator.createOne(BufMap) catch unreachable;
+ const env_map = allocator.create(BufMap) catch unreachable;
env_map.* = os.getEnvMap(allocator) catch unreachable;
var self = Builder{
.zig_exe = zig_exe,
@@ -145,8 +145,8 @@ pub const Builder = struct {
pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {
self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default
- self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable;
- self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable;
+ self.lib_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "lib" }) catch unreachable;
+ self.exe_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "bin" }) catch unreachable;
}
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
@@ -170,7 +170,8 @@ pub const Builder = struct {
}
pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {
- const test_step = self.allocator.create(TestStep.init(self, root_src)) catch unreachable;
+ const test_step = self.allocator.create(TestStep) catch unreachable;
+ test_step.* = TestStep.init(self, root_src);
return test_step;
}
@@ -202,18 +203,21 @@ pub const Builder = struct {
}
pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
- const write_file_step = self.allocator.create(WriteFileStep.init(self, file_path, data)) catch unreachable;
+ const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
+ write_file_step.* = WriteFileStep.init(self, file_path, data);
return write_file_step;
}
pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {
const data = self.fmt(format, args);
- const log_step = self.allocator.create(LogStep.init(self, data)) catch unreachable;
+ const log_step = self.allocator.create(LogStep) catch unreachable;
+ log_step.* = LogStep.init(self, data);
return log_step;
}
pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {
- const remove_dir_step = self.allocator.create(RemoveDirStep.init(self, dir_path)) catch unreachable;
+ const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
+ remove_dir_step.* = RemoveDirStep.init(self, dir_path);
return remove_dir_step;
}
@@ -320,7 +324,7 @@ pub const Builder = struct {
fn processNixOSEnvVars(self: *Builder) void {
if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
- var it = mem.split(nix_cflags_compile, " ");
+ var it = mem.tokenize(nix_cflags_compile, " ");
while (true) {
const word = it.next() orelse break;
if (mem.eql(u8, word, "-isystem")) {
@@ -338,7 +342,7 @@ pub const Builder = struct {
assert(err == error.EnvironmentVariableNotFound);
}
if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
- var it = mem.split(nix_ldflags, " ");
+ var it = mem.tokenize(nix_ldflags, " ");
while (true) {
const word = it.next() orelse break;
if (mem.eql(u8, word, "-rpath")) {
@@ -414,10 +418,11 @@ pub const Builder = struct {
}
pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {
- const step_info = self.allocator.create(TopLevelStep{
+ const step_info = self.allocator.create(TopLevelStep) catch unreachable;
+ step_info.* = TopLevelStep{
.step = Step.initNoOp(name, self.allocator),
.description = description,
- }) catch unreachable;
+ };
self.top_level_steps.append(step_info) catch unreachable;
return &step_info.step;
}
@@ -613,10 +618,14 @@ pub const Builder = struct {
///::dest_rel_path is relative to prefix path or it can be an absolute path
pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
- const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable;
+ const full_dest_path = os.path.resolve(
+ self.allocator,
+ [][]const u8{ self.prefix, dest_rel_path },
+ ) catch unreachable;
self.pushInstalledFile(full_dest_path);
- const install_step = self.allocator.create(InstallFileStep.init(self, src_path, full_dest_path)) catch unreachable;
+ const install_step = self.allocator.create(InstallFileStep) catch unreachable;
+ install_step.* = InstallFileStep.init(self, src_path, full_dest_path);
return install_step;
}
@@ -647,7 +656,7 @@ pub const Builder = struct {
}
fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {
- return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable;
+ return os.path.resolve(self.allocator, [][]const u8{ self.build_root, rel_path }) catch unreachable;
}
pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 {
@@ -670,7 +679,7 @@ pub const Builder = struct {
if (os.path.isAbsolute(name)) {
return name;
}
- const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension));
+ const full_path = try os.path.join(self.allocator, [][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) });
if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@@ -683,9 +692,9 @@ pub const Builder = struct {
if (os.path.isAbsolute(name)) {
return name;
}
- var it = mem.split(PATH, []u8{os.path.delimiter});
+ var it = mem.tokenize(PATH, []u8{os.path.delimiter});
while (it.next()) |path| {
- const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));
+ const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@@ -699,7 +708,7 @@ pub const Builder = struct {
return name;
}
for (paths) |path| {
- const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));
+ const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
if (os.path.real(self.allocator, full_path)) |real_path| {
return real_path;
} else |_| {
@@ -865,43 +874,51 @@ pub const LibExeObjStep = struct {
};
pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
- const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, false, ver)) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
return self;
}
pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep {
- const self = builder.allocator.create(initC(builder, name, Kind.Lib, version, false)) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initC(builder, name, Kind.Lib, version, false);
return self;
}
pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
- const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0))) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
return self;
}
pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {
- const self = builder.allocator.create(initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true)) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
return self;
}
pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
- const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0))) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
return self;
}
pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
- const self = builder.allocator.create(initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false)) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
self.object_src = src;
return self;
}
pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
- const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));
return self;
}
pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep {
- const self = builder.allocator.create(initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false)) catch unreachable;
+ const self = builder.allocator.create(LibExeObjStep) catch unreachable;
+ self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
return self;
}
@@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct {
}
pub fn getOutputPath(self: *LibExeObjStep) []const u8 {
- return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;
+ return if (self.output_path) |output_path| output_path else os.path.join(
+ self.builder.allocator,
+ [][]const u8{ self.builder.cache_root, self.out_filename },
+ ) catch unreachable;
}
pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
@@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct {
}
pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
- return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;
+ return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(
+ self.builder.allocator,
+ [][]const u8{ self.builder.cache_root, self.out_h_filename },
+ ) catch unreachable;
}
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
@@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct {
}
if (self.build_options_contents.len() > 0) {
- const build_options_file = try os.path.join(builder.allocator, builder.cache_root, builder.fmt("{}_build_options.zig", self.name));
+ const build_options_file = try os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", self.name) },
+ );
try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());
try zig_args.append("--pkg-begin");
try zig_args.append("build_options");
@@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct {
cc_args.append("-c") catch unreachable;
cc_args.append(abs_source_file) catch unreachable;
- const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
+ const cache_o_src = os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.cache_root, source_file },
+ ) catch unreachable;
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir);
}
@@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct {
cc_args.append("-current_version") catch unreachable;
cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable;
- const install_name = builder.pathFromRoot(os.path.join(builder.allocator, builder.cache_root, self.major_only_filename) catch unreachable);
+ const install_name = builder.pathFromRoot(os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.cache_root, self.major_only_filename },
+ ) catch unreachable);
cc_args.append("-install_name") catch unreachable;
cc_args.append(install_name) catch unreachable;
} else {
@@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct {
cc_args.append("-c") catch unreachable;
cc_args.append(abs_source_file) catch unreachable;
- const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;
+ const cache_o_src = os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.cache_root, source_file },
+ ) catch unreachable;
if (os.path.dirname(cache_o_src)) |cache_o_dir| {
try builder.makePath(cache_o_dir);
}
@@ -1672,6 +1707,7 @@ pub const TestStep = struct {
no_rosegment: bool,
output_path: ?[]const u8,
system_linker_hack: bool,
+ override_std_dir: ?[]const u8,
pub fn init(builder: *Builder, root_src: []const u8) TestStep {
const step_name = builder.fmt("test {}", root_src);
@@ -1693,6 +1729,7 @@ pub const TestStep = struct {
.no_rosegment = false,
.output_path = null,
.system_linker_hack = false,
+ .override_std_dir = null,
};
}
@@ -1723,6 +1760,10 @@ pub const TestStep = struct {
self.build_mode = mode;
}
+ pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void {
+ self.override_std_dir = dir_path;
+ }
+
pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {
self.output_path = file_path;
@@ -1737,7 +1778,10 @@ pub const TestStep = struct {
return output_path;
} else {
const basename = self.builder.fmt("test{}", self.target.exeFileExt());
- return os.path.join(self.builder.allocator, self.builder.cache_root, basename) catch unreachable;
+ return os.path.join(
+ self.builder.allocator,
+ [][]const u8{ self.builder.cache_root, basename },
+ ) catch unreachable;
}
}
@@ -1900,6 +1944,10 @@ pub const TestStep = struct {
if (self.system_linker_hack) {
try zig_args.append("--system-linker-hack");
}
+ if (self.override_std_dir) |dir| {
+ try zig_args.append("--override-std-dir");
+ try zig_args.append(builder.pathFromRoot(dir));
+ }
try builder.spawnChild(zig_args.toSliceConst());
}
@@ -1914,13 +1962,14 @@ pub const CommandStep = struct {
/// ::argv is copied.
pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {
- const self = builder.allocator.create(CommandStep{
+ const self = builder.allocator.create(CommandStep) catch unreachable;
+ self.* = CommandStep{
.builder = builder,
.step = Step.init(argv[0], builder.allocator, make),
.argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
.cwd = cwd,
.env_map = env_map,
- }) catch unreachable;
+ };
mem.copy([]const u8, self.argv, argv);
self.step.name = self.argv[0];
@@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct {
LibExeObjStep.Kind.Exe => builder.exe_dir,
LibExeObjStep.Kind.Lib => builder.lib_dir,
};
- const self = builder.allocator.create(Self{
+ const self = builder.allocator.create(Self) catch unreachable;
+ self.* = Self{
.builder = builder,
.step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
.artifact = artifact,
- .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,
- }) catch unreachable;
+ .dest_file = os.path.join(
+ builder.allocator,
+ [][]const u8{ dest_dir, artifact.out_filename },
+ ) catch unreachable,
+ };
self.step.dependOn(&artifact.step);
builder.pushInstalledFile(self.dest_file);
if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
- builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable);
- builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable);
+ builder.pushInstalledFile(os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.lib_dir, artifact.major_only_filename },
+ ) catch unreachable);
+ builder.pushInstalledFile(os.path.join(
+ builder.allocator,
+ [][]const u8{ builder.lib_dir, artifact.name_only_filename },
+ ) catch unreachable);
}
return self;
}
@@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
const out_dir = os.path.dirname(output_path) orelse ".";
const out_basename = os.path.basename(output_path);
// sym link for libfoo.so.1 to libfoo.so.1.2.3
- const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable;
+ const major_only_path = os.path.join(
+ allocator,
+ [][]const u8{ out_dir, filename_major_only },
+ ) catch unreachable;
os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
return err;
};
// sym link for libfoo.so to libfoo.so.1
- const name_only_path = os.path.join(allocator, out_dir, filename_name_only) catch unreachable;
+ const name_only_path = os.path.join(
+ allocator,
+ [][]const u8{ out_dir, filename_name_only },
+ ) catch unreachable;
os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
return err;
diff --git a/std/c/darwin.zig b/std/c/darwin.zig
index 86c5e4828e..4f0ea4a02b 100644
--- a/std/c/darwin.zig
+++ b/std/c/darwin.zig
@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {
};
pub const timeval = extern struct {
- tv_sec: isize,
- tv_usec: isize,
+ tv_sec: c_long,
+ tv_usec: i32,
};
pub const timezone = extern struct {
@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {
ext: [2]u64,
};
+pub const mach_port_t = c_uint;
+pub const clock_serv_t = mach_port_t;
+pub const clock_res_t = c_int;
+pub const mach_port_name_t = natural_t;
+pub const natural_t = c_uint;
+pub const mach_timespec_t = extern struct {
+ tv_sec: c_uint,
+ tv_nsec: clock_res_t,
+};
+pub const kern_return_t = c_int;
+pub const host_t = mach_port_t;
+pub const CALENDAR_CLOCK = 1;
+
+pub extern fn mach_host_self() mach_port_t;
+pub extern fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
+pub extern fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clock_serv: ?[*]clock_serv_t) kern_return_t;
+pub extern fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
+
// sys/types.h on macos uses #pragma pack() so these checks are
// to make sure the struct is laid out the same. These values were
// produced from C code using the offsetof macro.
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index 421e964827..2f2f4c0a1b 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -1,5 +1,3 @@
-const timespec = @import("../os/freebsd/index.zig").timespec;
-
extern "c" fn __error() *c_int;
pub const _errno = __error;
@@ -15,6 +13,17 @@ pub extern "c" fn kevent(
pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
+pub extern "c" fn getdirentries(fd: c_int, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;
+pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn pipe2(arg0: *[2]c_int, arg1: u32) c_int;
+pub extern "c" fn preadv(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
+pub extern "c" fn pwritev(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
+pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int;
+pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
+pub extern "c" fn setuid(uid: c_uint) c_int;
+pub extern "c" fn kill(pid: c_int, sig: c_int) c_int;
+pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int;
+pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int;
/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
pub const Kevent = extern struct {
@@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct {
__size: [56]u8,
__align: c_long,
};
+
+pub const msghdr = extern struct {
+ msg_name: *u8,
+ msg_namelen: socklen_t,
+ msg_iov: *iovec,
+ msg_iovlen: i32,
+ __pad1: i32,
+ msg_control: *u8,
+ msg_controllen: socklen_t,
+ __pad2: socklen_t,
+ msg_flags: i32,
+};
+
+pub const Stat = extern struct {
+ dev: u64,
+ ino: u64,
+ nlink: usize,
+
+ mode: u16,
+ __pad0: u16,
+ uid: u32,
+ gid: u32,
+ __pad1: u32,
+ rdev: u64,
+
+ atim: timespec,
+ mtim: timespec,
+ ctim: timespec,
+ birthtim: timespec,
+
+ size: i64,
+ blocks: i64,
+ blksize: isize,
+ flags: u32,
+ gen: u64,
+ __spare: [10]u64,
+};
+
+pub const timespec = extern struct {
+ tv_sec: isize,
+ tv_nsec: isize,
+};
+
+pub const dirent = extern struct {
+ d_fileno: usize,
+ d_off: i64,
+ d_reclen: u16,
+ d_type: u8,
+ d_pad0: u8,
+ d_namlen: u16,
+ d_pad1: u16,
+ d_name: [256]u8,
+};
+
+pub const in_port_t = u16;
+pub const sa_family_t = u16;
+
+pub const sockaddr = extern union {
+ in: sockaddr_in,
+ in6: sockaddr_in6,
+};
+
+pub const sockaddr_in = extern struct {
+ len: u8,
+ family: sa_family_t,
+ port: in_port_t,
+ addr: [16]u8,
+ zero: [8]u8,
+};
+
+pub const sockaddr_in6 = extern struct {
+ len: u8,
+ family: sa_family_t,
+ port: in_port_t,
+ flowinfo: u32,
+ addr: [16]u8,
+ scope_id: u32,
+};
diff --git a/std/c/index.zig b/std/c/index.zig
index 4aab39d931..058d879c09 100644
--- a/std/c/index.zig
+++ b/std/c/index.zig
@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
-pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int;
+pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
diff --git a/std/coff.zig b/std/coff.zig
index 6a1aa34b46..53bd2a4b7a 100644
--- a/std/coff.zig
+++ b/std/coff.zig
@@ -51,7 +51,7 @@ pub const Coff = struct {
// Seek to PE File Header (coff header)
try self.in_file.seekTo(pe_pointer_offset);
- const pe_magic_offset = try in.readIntLe(u32);
+ const pe_magic_offset = try in.readIntLittle(u32);
try self.in_file.seekTo(pe_magic_offset);
var pe_header_magic: [4]u8 = undefined;
@@ -60,13 +60,13 @@ pub const Coff = struct {
return error.InvalidPEHeader;
self.coff_header = CoffHeader{
- .machine = try in.readIntLe(u16),
- .number_of_sections = try in.readIntLe(u16),
- .timedate_stamp = try in.readIntLe(u32),
- .pointer_to_symbol_table = try in.readIntLe(u32),
- .number_of_symbols = try in.readIntLe(u32),
- .size_of_optional_header = try in.readIntLe(u16),
- .characteristics = try in.readIntLe(u16),
+ .machine = try in.readIntLittle(u16),
+ .number_of_sections = try in.readIntLittle(u16),
+ .timedate_stamp = try in.readIntLittle(u32),
+ .pointer_to_symbol_table = try in.readIntLittle(u32),
+ .number_of_symbols = try in.readIntLittle(u32),
+ .size_of_optional_header = try in.readIntLittle(u16),
+ .characteristics = try in.readIntLittle(u16),
};
switch (self.coff_header.machine) {
@@ -79,7 +79,7 @@ pub const Coff = struct {
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
const in = &file_stream.stream;
- self.pe_header.magic = try in.readIntLe(u16);
+ self.pe_header.magic = try in.readIntLittle(u16);
// For now we're only interested in finding the reference to the .pdb,
// so we'll skip most of this header, which size is different in 32
// 64 bits by the way.
@@ -93,14 +93,14 @@ pub const Coff = struct {
try self.in_file.seekForward(skip_size);
- const number_of_rva_and_sizes = try in.readIntLe(u32);
+ const number_of_rva_and_sizes = try in.readIntLittle(u32);
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
return error.InvalidPEHeader;
for (self.pe_header.data_directory) |*data_dir| {
data_dir.* = OptionalHeader.DataDirectory{
- .virtual_address = try in.readIntLe(u32),
- .size = try in.readIntLe(u32),
+ .virtual_address = try in.readIntLittle(u32),
+ .size = try in.readIntLittle(u32),
};
}
}
@@ -124,7 +124,7 @@ pub const Coff = struct {
if (!mem.eql(u8, cv_signature, "RSDS"))
return error.InvalidPEMagic;
try in.readNoEof(self.guid[0..]);
- self.age = try in.readIntLe(u32);
+ self.age = try in.readIntLittle(u32);
// Finally read the null-terminated string.
var byte = try in.readByte();
@@ -157,15 +157,15 @@ pub const Coff = struct {
try self.sections.append(Section{
.header = SectionHeader{
.name = name,
- .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
- .virtual_address = try in.readIntLe(u32),
- .size_of_raw_data = try in.readIntLe(u32),
- .pointer_to_raw_data = try in.readIntLe(u32),
- .pointer_to_relocations = try in.readIntLe(u32),
- .pointer_to_line_numbers = try in.readIntLe(u32),
- .number_of_relocations = try in.readIntLe(u16),
- .number_of_line_numbers = try in.readIntLe(u16),
- .characteristics = try in.readIntLe(u32),
+ .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
+ .virtual_address = try in.readIntLittle(u32),
+ .size_of_raw_data = try in.readIntLittle(u32),
+ .pointer_to_raw_data = try in.readIntLittle(u32),
+ .pointer_to_relocations = try in.readIntLittle(u32),
+ .pointer_to_line_numbers = try in.readIntLittle(u32),
+ .number_of_relocations = try in.readIntLittle(u16),
+ .number_of_line_numbers = try in.readIntLittle(u16),
+ .characteristics = try in.readIntLittle(u32),
},
});
}
diff --git a/std/crypto/blake2.zig b/std/crypto/blake2.zig
index dc68d806d2..e3de65916a 100644
--- a/std/crypto/blake2.zig
+++ b/std/crypto/blake2.zig
@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
const rr = d.h[0 .. out_len / 32];
for (rr) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
}
}
@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
var v: [16]u32 = undefined;
for (m) |*r, i| {
- r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);
+ // TODO https://github.com/ziglang/zig/issues/863
+ r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
}
var k: usize = 0;
@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
const rr = d.h[0 .. out_len / 64];
for (rr) |s, j| {
- mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
}
}
@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
var v: [16]u64 = undefined;
for (m) |*r, i| {
- r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);
+ r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
}
var k: usize = 0;
diff --git a/std/crypto/chacha20.zig b/std/crypto/chacha20.zig
index 059bc82088..d964f4c03d 100644
--- a/std/crypto/chacha20.zig
+++ b/std/crypto/chacha20.zig
@@ -4,6 +4,7 @@ const std = @import("../index.zig");
const mem = std.mem;
const endian = std.endian;
const assert = std.debug.assert;
+const testing = std.testing;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
@@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
}
for (x) |_, i| {
- mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
}
}
@@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
const c = "expand 32-byte k";
const constant_le = []u32{
- mem.readIntLE(u32, c[0..4]),
- mem.readIntLE(u32, c[4..8]),
- mem.readIntLE(u32, c[8..12]),
- mem.readIntLE(u32, c[12..16]),
+ mem.readIntSliceLittle(u32, c[0..4]),
+ mem.readIntSliceLittle(u32, c[4..8]),
+ mem.readIntSliceLittle(u32, c[8..12]),
+ mem.readIntSliceLittle(u32, c[12..16]),
};
mem.copy(u32, ctx[0..], constant_le[0..4]);
@@ -117,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
- k[0] = mem.readIntLE(u32, key[0..4]);
- k[1] = mem.readIntLE(u32, key[4..8]);
- k[2] = mem.readIntLE(u32, key[8..12]);
- k[3] = mem.readIntLE(u32, key[12..16]);
- k[4] = mem.readIntLE(u32, key[16..20]);
- k[5] = mem.readIntLE(u32, key[20..24]);
- k[6] = mem.readIntLE(u32, key[24..28]);
- k[7] = mem.readIntLE(u32, key[28..32]);
+ k[0] = mem.readIntSliceLittle(u32, key[0..4]);
+ k[1] = mem.readIntSliceLittle(u32, key[4..8]);
+ k[2] = mem.readIntSliceLittle(u32, key[8..12]);
+ k[3] = mem.readIntSliceLittle(u32, key[12..16]);
+ k[4] = mem.readIntSliceLittle(u32, key[16..20]);
+ k[5] = mem.readIntSliceLittle(u32, key[20..24]);
+ k[6] = mem.readIntSliceLittle(u32, key[24..28]);
+ k[7] = mem.readIntSliceLittle(u32, key[28..32]);
c[0] = counter;
- c[1] = mem.readIntLE(u32, nonce[0..4]);
- c[2] = mem.readIntLE(u32, nonce[4..8]);
- c[3] = mem.readIntLE(u32, nonce[8..12]);
+ c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
+ c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
+ c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
chaCha20_internal(out, in, k, c);
}
@@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
- k[0] = mem.readIntLE(u32, key[0..4]);
- k[1] = mem.readIntLE(u32, key[4..8]);
- k[2] = mem.readIntLE(u32, key[8..12]);
- k[3] = mem.readIntLE(u32, key[12..16]);
- k[4] = mem.readIntLE(u32, key[16..20]);
- k[5] = mem.readIntLE(u32, key[20..24]);
- k[6] = mem.readIntLE(u32, key[24..28]);
- k[7] = mem.readIntLE(u32, key[28..32]);
+ k[0] = mem.readIntSliceLittle(u32, key[0..4]);
+ k[1] = mem.readIntSliceLittle(u32, key[4..8]);
+ k[2] = mem.readIntSliceLittle(u32, key[8..12]);
+ k[3] = mem.readIntSliceLittle(u32, key[12..16]);
+ k[4] = mem.readIntSliceLittle(u32, key[16..20]);
+ k[5] = mem.readIntSliceLittle(u32, key[20..24]);
+ k[6] = mem.readIntSliceLittle(u32, key[24..28]);
+ k[7] = mem.readIntSliceLittle(u32, key[28..32]);
c[0] = @truncate(u32, counter);
c[1] = @truncate(u32, counter >> 32);
- c[2] = mem.readIntLE(u32, nonce[0..4]);
- c[3] = mem.readIntLE(u32, nonce[4..8]);
+ c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
+ c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
const block_size = (1 << 6);
const big_block = (block_size << 32);
@@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" {
};
chaCha20IETF(result[0..], input[0..], 1, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
// Chacha20 is self-reversing.
var plaintext: [114]u8 = undefined;
chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
- assert(mem.compare(u8, input, plaintext) == mem.Compare.Equal);
+ testing.expect(mem.compare(u8, input, plaintext) == mem.Compare.Equal);
}
// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
@@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" {
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 2" {
@@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" {
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 3" {
@@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" {
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 4" {
@@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" {
const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
}
test "crypto.chacha20 test vector 5" {
@@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" {
};
chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
- assert(mem.eql(u8, expected_result, result));
+ testing.expectEqualSlices(u8, expected_result, result);
}
diff --git a/std/crypto/md5.zig b/std/crypto/md5.zig
index 8663fa751f..994a7fa25c 100644
--- a/std/crypto/md5.zig
+++ b/std/crypto/md5.zig
@@ -112,7 +112,8 @@ pub const Md5 = struct {
d.round(d.buf[0..]);
for (d.s) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
}
}
diff --git a/std/crypto/poly1305.zig b/std/crypto/poly1305.zig
index a5d9fcdf57..64adb17c45 100644
--- a/std/crypto/poly1305.zig
+++ b/std/crypto/poly1305.zig
@@ -6,8 +6,8 @@ const std = @import("../index.zig");
const builtin = @import("builtin");
const Endian = builtin.Endian;
-const readInt = std.mem.readInt;
-const writeInt = std.mem.writeInt;
+const readIntSliceLittle = std.mem.readIntSliceLittle;
+const writeIntSliceLittle = std.mem.writeIntSliceLittle;
pub const Poly1305 = struct {
const Self = @This();
@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
{
var i: usize = 0;
while (i < 1) : (i += 1) {
- ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;
+ ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
}
}
{
var i: usize = 1;
while (i < 4) : (i += 1) {
- ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;
+ ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
}
}
{
var i: usize = 0;
while (i < 4) : (i += 1) {
- ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);
+ ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
}
}
@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
const nb_blocks = nmsg.len >> 4;
var i: usize = 0;
while (i < nb_blocks) : (i += 1) {
- ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
- ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
- ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
- ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
+ ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
+ ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
+ ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
+ ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
polyBlock(ctx);
nmsg = nmsg[16..];
}
@@ -210,10 +210,11 @@ pub const Poly1305 = struct {
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
- writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
- writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
- writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
- writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
+ writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
+ writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
+ writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
ctx.secureZero();
}
@@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" {
var mac: [16]u8 = undefined;
Poly1305.create(mac[0..], msg, key);
- std.debug.assert(std.mem.eql(u8, mac, expected_mac));
+ std.testing.expectEqualSlices(u8, expected_mac, mac);
}
diff --git a/std/crypto/sha1.zig b/std/crypto/sha1.zig
index 1cb0b17434..d5aab8f33f 100644
--- a/std/crypto/sha1.zig
+++ b/std/crypto/sha1.zig
@@ -109,7 +109,8 @@ pub const Sha1 = struct {
d.round(d.buf[0..]);
for (d.s) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
}
}
diff --git a/std/crypto/sha2.zig b/std/crypto/sha2.zig
index 7e9749364b..0476a3a25e 100644
--- a/std/crypto/sha2.zig
+++ b/std/crypto/sha2.zig
@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
const rr = d.s[0 .. params.out_len / 32];
for (rr) |s, j| {
- mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
}
}
@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
const rr = d.s[0 .. params.out_len / 64];
for (rr) |s, j| {
- mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
}
}
diff --git a/std/crypto/sha3.zig b/std/crypto/sha3.zig
index 881370e686..e686e1337c 100644
--- a/std/crypto/sha3.zig
+++ b/std/crypto/sha3.zig
@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
var c = []const u64{0} ** 5;
for (s) |*r, i| {
- r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);
+ r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
}
comptime var x: usize = 0;
@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
}
for (s) |r, i| {
- mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
}
}
diff --git a/std/crypto/test.zig b/std/crypto/test.zig
index 3fa24272e5..258cdf7320 100644
--- a/std/crypto/test.zig
+++ b/std/crypto/test.zig
@@ -1,6 +1,7 @@
-const debug = @import("../debug/index.zig");
-const mem = @import("../mem.zig");
-const fmt = @import("../fmt/index.zig");
+const std = @import("../index.zig");
+const testing = std.testing;
+const mem = std.mem;
+const fmt = std.fmt;
// Hash using the specified hasher `H` asserting `expected == H(input)`.
pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void {
@@ -17,5 +18,5 @@ pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
}
- debug.assert(mem.eql(u8, expected_bytes, input));
+ testing.expectEqualSlices(u8, expected_bytes, input);
}
diff --git a/std/crypto/x25519.zig b/std/crypto/x25519.zig
index 281813b457..9349569f97 100644
--- a/std/crypto/x25519.zig
+++ b/std/crypto/x25519.zig
@@ -7,8 +7,8 @@ const builtin = @import("builtin");
const fmt = std.fmt;
const Endian = builtin.Endian;
-const readInt = std.mem.readInt;
-const writeInt = std.mem.writeInt;
+const readIntSliceLittle = std.mem.readIntSliceLittle;
+const writeIntSliceLittle = std.mem.writeIntSliceLittle;
// Based on Supercop's ref10 implementation.
pub const X25519 = struct {
@@ -255,16 +255,16 @@ const Fe = struct {
var t: [10]i64 = undefined;
- t[0] = readInt(s[0..4], u32, Endian.Little);
- t[1] = readInt(s[4..7], u32, Endian.Little) << 6;
- t[2] = readInt(s[7..10], u32, Endian.Little) << 5;
- t[3] = readInt(s[10..13], u32, Endian.Little) << 3;
- t[4] = readInt(s[13..16], u32, Endian.Little) << 2;
- t[5] = readInt(s[16..20], u32, Endian.Little);
- t[6] = readInt(s[20..23], u32, Endian.Little) << 7;
- t[7] = readInt(s[23..26], u32, Endian.Little) << 5;
- t[8] = readInt(s[26..29], u32, Endian.Little) << 4;
- t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;
+ t[0] = readIntSliceLittle(u32, s[0..4]);
+ t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
+ t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
+ t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
+ t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
+ t[5] = readIntSliceLittle(u32, s[16..20]);
+ t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
+ t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
+ t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
+ t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
carry1(h, t[0..]);
}
@@ -544,14 +544,15 @@ const Fe = struct {
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
}
- writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);
- writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);
- writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);
- writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);
- writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);
- writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);
- writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);
- writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);
+ // TODO https://github.com/ziglang/zig/issues/863
+ writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
+ writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
+ writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
+ writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
+ writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
+ writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
+ writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
+ writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
std.mem.secureZero(i64, t[0..]);
}
@@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" {
var pk_calculated: [32]u8 = undefined;
try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
- std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk));
- std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected));
+ std.testing.expect(X25519.createPublicKey(pk_calculated[0..], sk));
+ std.testing.expect(std.mem.eql(u8, pk_calculated, pk_expected));
}
test "x25519 rfc7748 vector1" {
@@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" {
var output: [32]u8 = undefined;
- std.debug.assert(X25519.create(output[0..], secret_key, public_key));
- std.debug.assert(std.mem.eql(u8, output, expected_output));
+ std.testing.expect(X25519.create(output[0..], secret_key, public_key));
+ std.testing.expect(std.mem.eql(u8, output, expected_output));
}
test "x25519 rfc7748 vector2" {
@@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" {
var output: [32]u8 = undefined;
- std.debug.assert(X25519.create(output[0..], secret_key, public_key));
- std.debug.assert(std.mem.eql(u8, output, expected_output));
+ std.testing.expect(X25519.create(output[0..], secret_key, public_key));
+ std.testing.expect(std.mem.eql(u8, output, expected_output));
}
test "x25519 rfc7748 one iteration" {
@@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" {
var i: usize = 0;
while (i < 1) : (i += 1) {
var output: [32]u8 = undefined;
- std.debug.assert(X25519.create(output[0..], k, u));
+ std.testing.expect(X25519.create(output[0..], k, u));
std.mem.copy(u8, u[0..], k[0..]);
std.mem.copy(u8, k[0..], output[0..]);
}
- std.debug.assert(std.mem.eql(u8, k[0..], expected_output));
+ std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
}
test "x25519 rfc7748 1,000 iterations" {
@@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" {
var i: usize = 0;
while (i < 1000) : (i += 1) {
var output: [32]u8 = undefined;
- std.debug.assert(X25519.create(output[0..], k, u));
+ std.testing.expect(X25519.create(output[0..], k, u));
std.mem.copy(u8, u[0..], k[0..]);
std.mem.copy(u8, k[0..], output[0..]);
}
- std.debug.assert(std.mem.eql(u8, k[0..], expected_output));
+ std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
}
test "x25519 rfc7748 1,000,000 iterations" {
@@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" {
var i: usize = 0;
while (i < 1000000) : (i += 1) {
var output: [32]u8 = undefined;
- std.debug.assert(X25519.create(output[0..], k, u));
+ std.testing.expect(X25519.create(output[0..], k, u));
std.mem.copy(u8, u[0..], k[0..]);
std.mem.copy(u8, k[0..], output[0..]);
}
- std.debug.assert(std.mem.eql(u8, k[0..], expected_output));
+ std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
}
diff --git a/std/cstr.zig b/std/cstr.zig
index a8aaf21279..abd2eac48f 100644
--- a/std/cstr.zig
+++ b/std/cstr.zig
@@ -2,7 +2,7 @@ const std = @import("index.zig");
const builtin = @import("builtin");
const debug = std.debug;
const mem = std.mem;
-const assert = debug.assert;
+const testing = std.testing;
pub const line_sep = switch (builtin.os) {
builtin.Os.windows => "\r\n",
@@ -42,8 +42,8 @@ test "cstr fns" {
}
fn testCStrFnsImpl() void {
- assert(cmp(c"aoeu", c"aoez") == -1);
- assert(len(c"123456789") == 9);
+ testing.expect(cmp(c"aoeu", c"aoez") == -1);
+ testing.expect(len(c"123456789") == 9);
}
/// Returns a mutable slice with 1 more byte of length which is a null byte.
diff --git a/std/debug/index.zig b/std/debug/index.zig
index 4a96e9d259..7e5be9acef 100644
--- a/std/debug/index.zig
+++ b/std/debug/index.zig
@@ -37,7 +37,6 @@ const Module = struct {
var stderr_file: os.File = undefined;
var stderr_file_out_stream: os.File.OutStream = undefined;
-/// TODO multithreaded awareness
var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
var stderr_mutex = std.Mutex.init();
pub fn warn(comptime fmt: []const u8, args: ...) void {
@@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {
/// This function invokes undefined behavior when `ok` is `false`.
/// In Debug and ReleaseSafe modes, calls to this function are always
/// generated, and the `unreachable` statement triggers a panic.
-/// In ReleaseFast and ReleaseSmall modes, calls to this function can be
-/// optimized away.
+/// In ReleaseFast and ReleaseSmall modes, calls to this function are
+/// optimized away, and in fact the optimizer is able to use the assertion
+/// in its heuristics.
+/// Inside a test block, it is best to use the `std.testing` module rather
+/// than this function, because this function may not detect a test failure
+/// in ReleaseFast and ReleaseSafe mode. Outside of a test block, this assert
+/// function is the correct function to use.
pub fn assert(ok: bool) void {
- if (!ok) {
- // In ReleaseFast test mode, we still want assert(false) to crash, so
- // we insert an explicit call to @panic instead of unreachable.
- // TODO we should use `assertOrPanic` in tests and remove this logic.
- if (builtin.is_test) {
- @panic("assertion failure");
- } else {
- unreachable; // assertion failure
- }
- }
-}
-
-/// TODO: add `==` operator for `error_union == error_set`, and then
-/// remove this function
-pub fn assertError(value: var, expected_error: anyerror) void {
- if (value) {
- @panic("expected error");
- } else |actual_error| {
- assert(actual_error == expected_error);
- }
-}
-
-/// Call this function when you want to panic if the condition is not true.
-/// If `ok` is `false`, this function will panic in every release mode.
-pub fn assertOrPanic(ok: bool) void {
- if (!ok) {
- @panic("assertion failure");
- }
+ if (!ok) unreachable; // assertion failure
}
pub fn panic(comptime format: []const u8, args: ...) noreturn {
@@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows(
start_addr: ?usize,
) !void {
var addr_buf: [1024]usize = undefined;
- const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast
- const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null);
+ const n = windows.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**c_void, &addr_buf), null);
const addrs = addr_buf[0..n];
var start_i: usize = if (start_addr) |saddr| blk: {
for (addrs) |addr, i| {
@@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows(
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
switch (builtin.os) {
builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color),
- builtin.Os.linux => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color),
+ builtin.Os.linux, builtin.Os.freebsd => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color),
builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),
else => return error.UnsupportedOperatingSystem,
}
@@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
switch (subsect_hdr.Kind) {
pdb.DebugSubsectionKind.Lines => {
- var line_index: usize = sect_offset;
+ var line_index = sect_offset;
const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);
if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
line_index += @sizeOf(pdb.LineFragmentHeader);
-
- const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
- line_index += @sizeOf(pdb.LineBlockFragmentHeader);
-
- const has_column = line_hdr.Flags.LF_HaveColumns;
-
const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
- if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
- var line_i: usize = 0;
+
+ // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
+ // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
+ // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
+ const subsection_end_index = sect_offset + subsect_hdr.Length;
+ while (line_index < subsection_end_index) {
+ const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
+ line_index += @sizeOf(pdb.LineBlockFragmentHeader);
const start_line_index = line_index;
- while (line_i < block_hdr.NumLines) : (line_i += 1) {
- const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
- line_index += @sizeOf(pdb.LineNumberEntry);
- const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
- const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
- const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
- if (relative_address >= vaddr_start and relative_address < vaddr_end) {
+
+ const has_column = line_hdr.Flags.LF_HaveColumns;
+
+ if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
+ // All line entries are stored inside their line block by ascending start address.
+ // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address.
+ // This is done with a simple linear search.
+ var line_i: u32 = 0;
+ while (line_i < block_hdr.NumLines) : (line_i += 1) {
+ const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
+ line_index += @sizeOf(pdb.LineNumberEntry);
+
+ const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
+ if (relative_address <= vaddr_start) {
+ break;
+ }
+ }
+
+ // line_i == 0 would mean that no matching LineNumberEntry was found.
+ if (line_i > 0) {
const subsect_index = checksum_offset + block_hdr.NameIndex;
const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);
const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;
try di.pdb.string_table.seekTo(strtab_offset);
const source_file_name = try di.pdb.string_table.readNullTermString(allocator);
- const line = flags.Start;
+
+ const line_entry_idx = line_i - 1;
+
const column = if (has_column) blk: {
- line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
- line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i;
- const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]);
+ const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
+ const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx;
+ const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]);
break :blk col_num_entry.StartColumn;
} else 0;
+
+ const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry);
+ const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]);
+ const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
+
break :subsections LineInfo{
.allocator = allocator,
.file_name = source_file_name,
- .line = line,
+ .line = flags.Start,
.column = column,
};
}
}
- break :subsections null;
+ }
+
+ // Checking that we are not reading garbage after the (possibly) multiple block fragments.
+ if (line_index != subsection_end_index) {
+ return error.InvalidDebugInfo;
}
},
else => {},
@@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
- const signature = try modi.stream.readIntLe(u32);
+ const signature = try modi.stream.readIntLittle(u32);
if (signature != 4)
return error.InvalidDebugInfo;
@@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{
pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
switch (builtin.os) {
- builtin.Os.linux => return openSelfDebugInfoLinux(allocator),
+ builtin.Os.linux, builtin.Os.freebsd => return openSelfDebugInfoLinux(allocator),
builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),
builtin.Os.windows => return openSelfDebugInfoWindows(allocator),
else => return error.UnsupportedOperatingSystem,
@@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
const self_file = try os.openSelfExe();
defer self_file.close();
- const coff_obj = try allocator.createOne(coff.Coff);
+ const coff_obj = try allocator.create(coff.Coff);
coff_obj.* = coff.Coff{
.in_file = self_file,
.allocator = allocator,
@@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
const len = try di.coff.getPdbPath(path_buf[0..]);
const raw_path = path_buf[0..len];
- const path = try os.path.resolve(allocator, raw_path);
+ const path = try os.path.resolve(allocator, [][]const u8{raw_path});
try di.pdb.openFile(di.coff, path);
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
- const version = try pdb_stream.stream.readIntLe(u32);
- const signature = try pdb_stream.stream.readIntLe(u32);
- const age = try pdb_stream.stream.readIntLe(u32);
+ const version = try pdb_stream.stream.readIntLittle(u32);
+ const signature = try pdb_stream.stream.readIntLittle(u32);
+ const age = try pdb_stream.stream.readIntLittle(u32);
var guid: [16]u8 = undefined;
try pdb_stream.stream.readNoEof(guid[0..]);
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
@@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
// We validated the executable and pdb match.
const string_table_index = str_tab_index: {
- const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
+ const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
const name_bytes = try allocator.alloc(u8, name_bytes_len);
try pdb_stream.stream.readNoEof(name_bytes);
@@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
};
const bucket_list = try allocator.alloc(Bucket, present.len);
for (present) |_| {
- const name_offset = try pdb_stream.stream.readIntLe(u32);
- const name_index = try pdb_stream.stream.readIntLe(u32);
+ const name_offset = try pdb_stream.stream.readIntLittle(u32);
+ const name_index = try pdb_stream.stream.readIntLittle(u32);
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
if (mem.eql(u8, name, "/names")) {
break :str_tab_index name_index;
@@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
var sect_cont_offset: usize = 0;
if (section_contrib_size != 0) {
- const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));
+ const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
return error.InvalidDebugInfo;
sect_cont_offset += @sizeOf(u32);
@@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
}
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
- const num_words = try stream.readIntLe(u32);
+ const num_words = try stream.readIntLittle(u32);
var word_i: usize = 0;
var list = ArrayList(usize).init(allocator);
while (word_i != num_words) : (word_i += 1) {
- const word = try stream.readIntLe(u32);
+ const word = try stream.readIntLittle(u32);
var bit_i: u5 = 0;
while (true) : (bit_i += 1) {
if (word & (u32(1) << bit_i) != 0) {
@@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
}
}
}
- const sentinel = try allocator.createOne(macho.nlist_64);
+ const sentinel = try allocator.create(macho.nlist_64);
sentinel.* = macho.nlist_64{
.n_strx = 0,
.n_type = 36,
@@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) {
return self.ofiles.allocator;
}
},
- builtin.Os.windows => struct {
+ builtin.Os.uefi, builtin.Os.windows => struct {
pdb: pdb.Pdb,
coff: *coff.Coff,
sect_contribs: []pdb.SectionContribEntry,
modules: []Module,
},
- builtin.Os.linux => DwarfInfo,
- builtin.Os.freebsd => struct {},
+ builtin.Os.linux, builtin.Os.freebsd => DwarfInfo,
else => @compileError("Unsupported OS"),
};
@@ -1200,7 +1199,7 @@ const Constant = struct {
fn asUnsignedLe(self: *const Constant) !u64 {
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
if (self.signed) return error.InvalidDebugInfo;
- return mem.readInt(self.payload, u64, builtin.Endian.Little);
+ return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
}
};
@@ -1331,7 +1330,7 @@ const LineNumberProgram = struct {
return error.InvalidDebugInfo;
} else
self.include_dirs[file_entry.dir_index];
- const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
+ const file_name = try os.path.join(self.file_entries.allocator, [][]const u8{ dir_name, file_entry.file_name });
errdefer self.file_entries.allocator.free(file_name);
return LineInfo{
.line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,
@@ -1381,7 +1380,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
}
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
- const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
+ const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
return parseFormValueBlockLen(allocator, in_stream, block_len);
}
@@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
}
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
- return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
+ return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
}
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
- return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
+ return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
}
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
@@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
}
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
- const block_len = try in_stream.readIntLe(T);
+ const block_len = try in_stream.readIntLittle(T);
return parseFormValueRefLen(allocator, in_stream, block_len);
}
@@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
},
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
- DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
+ DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
@@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
continue;
}
- const version = try di.dwarf_in_stream.readInt(di.endian, u16);
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
// TODO support 3 and 5
if (version != 2 and version != 4) return error.InvalidDebugInfo;
- const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
+ const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
const minimum_instruction_length = try di.dwarf_in_stream.readByte();
@@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
return error.MissingDebugInfo;
},
DW.LNE_set_address => {
- const addr = try di.dwarf_in_stream.readInt(di.endian, usize);
+ const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
prog.address = addr;
},
DW.LNE_define_file => {
@@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
prog.address += inc_addr;
},
DW.LNS_fixed_advance_pc => {
- const arg = try di.dwarf_in_stream.readInt(di.endian, u16);
+ const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
prog.address += arg;
},
DW.LNS_set_prologue_end => {},
@@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
- const version = try di.dwarf_in_stream.readInt(di.endian, u16);
+ const version = try di.dwarf_in_stream.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
+ const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
const address_size = try di.dwarf_in_stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
@@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
- const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64));
+ const compile_unit_die = try di.allocator().create(Die);
+ compile_unit_die.* = try parseDie(di, abbrev_table, is_64);
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
@@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
if (di.debug_ranges) |debug_ranges| {
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
while (true) {
- const begin_addr = try di.dwarf_in_stream.readIntLe(usize);
- const end_addr = try di.dwarf_in_stream.readIntLe(usize);
+ const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
+ const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
if (begin_addr == 0 and end_addr == 0) {
break;
}
@@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
}
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
- const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);
+ // TODO https://github.com/ziglang/zig/issues/863
+ const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
ptr.* += @sizeOf(T);
return result;
}
@@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
}
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
- const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);
+ // TODO this code can be improved with https://github.com/ziglang/zig/issues/863
+ const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
ptr.* += 4;
- const result = mem.readIntLE(u64, ptr.*[0..8]);
+ const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
ptr.* += 8;
return result;
} else {
@@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
}
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
- const first_32_bits = try in_stream.readIntLe(u32);
+ const first_32_bits = try in_stream.readIntLittle(u32);
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
- return in_stream.readIntLe(u64);
+ return in_stream.readIntLittle(u64);
} else {
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
return u64(first_32_bits);
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 49f217bc8e..66026b1f29 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -6,6 +6,7 @@ const mem = std.mem;
const cstr = std.cstr;
const os = std.os;
const assert = std.debug.assert;
+const testing = std.testing;
const elf = std.elf;
const linux = os.linux;
const windows = os.windows;
@@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) {
};
pub const LinuxDynLib = struct {
- allocator: *mem.Allocator,
elf_lib: ElfLib,
fd: i32,
map_addr: usize,
@@ -27,7 +27,7 @@ pub const LinuxDynLib = struct {
/// 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 | linux.O_CLOEXEC);
+ const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
errdefer std.os.close(fd);
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
@@ -45,7 +45,6 @@ pub const LinuxDynLib = struct {
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,
@@ -208,7 +207,7 @@ test "dynamic_library" {
};
const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
- assert(err == error.FileNotFound);
+ testing.expect(err == error.FileNotFound);
return;
};
@panic("Expected error from function");
diff --git a/std/elf.zig b/std/elf.zig
index cf7c29b1e5..6a564c3283 100644
--- a/std/elf.zig
+++ b/std/elf.zig
@@ -412,7 +412,7 @@ pub const Elf = struct {
// skip over padding
try seekable_stream.seekForward(9);
- elf.file_type = switch (try in.readInt(elf.endian, u16)) {
+ elf.file_type = switch (try in.readInt(u16, elf.endian)) {
1 => FileType.Relocatable,
2 => FileType.Executable,
3 => FileType.Shared,
@@ -420,7 +420,7 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- elf.arch = switch (try in.readInt(elf.endian, u16)) {
+ elf.arch = switch (try in.readInt(u16, elf.endian)) {
0x02 => Arch.Sparc,
0x03 => Arch.x86,
0x08 => Arch.Mips,
@@ -433,32 +433,32 @@ pub const Elf = struct {
else => return error.InvalidFormat,
};
- const elf_version = try in.readInt(elf.endian, u32);
+ const elf_version = try in.readInt(u32, elf.endian);
if (elf_version != 1) return error.InvalidFormat;
if (elf.is_64) {
- elf.entry_addr = try in.readInt(elf.endian, u64);
- elf.program_header_offset = try in.readInt(elf.endian, u64);
- elf.section_header_offset = try in.readInt(elf.endian, u64);
+ elf.entry_addr = try in.readInt(u64, elf.endian);
+ elf.program_header_offset = try in.readInt(u64, elf.endian);
+ elf.section_header_offset = try in.readInt(u64, elf.endian);
} else {
- elf.entry_addr = u64(try in.readInt(elf.endian, u32));
- elf.program_header_offset = u64(try in.readInt(elf.endian, u32));
- elf.section_header_offset = u64(try in.readInt(elf.endian, u32));
+ elf.entry_addr = u64(try in.readInt(u32, elf.endian));
+ elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
+ elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
}
// skip over flags
try seekable_stream.seekForward(4);
- const header_size = try in.readInt(elf.endian, u16);
+ const header_size = try in.readInt(u16, elf.endian);
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
return error.InvalidFormat;
}
- const ph_entry_size = try in.readInt(elf.endian, u16);
- const ph_entry_count = try in.readInt(elf.endian, u16);
- const sh_entry_size = try in.readInt(elf.endian, u16);
- const sh_entry_count = try in.readInt(elf.endian, u16);
- elf.string_section_index = u64(try in.readInt(elf.endian, u16));
+ const ph_entry_size = try in.readInt(u16, elf.endian);
+ const ph_entry_count = try in.readInt(u16, elf.endian);
+ const sh_entry_size = try in.readInt(u16, elf.endian);
+ const sh_entry_count = try in.readInt(u16, elf.endian);
+ elf.string_section_index = u64(try in.readInt(u16, elf.endian));
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
@@ -481,32 +481,32 @@ pub const Elf = struct {
if (sh_entry_size != 64) return error.InvalidFormat;
for (elf.section_headers) |*elf_section| {
- elf_section.name = try in.readInt(elf.endian, u32);
- elf_section.sh_type = try in.readInt(elf.endian, u32);
- elf_section.flags = try in.readInt(elf.endian, u64);
- elf_section.addr = try in.readInt(elf.endian, u64);
- elf_section.offset = try in.readInt(elf.endian, u64);
- elf_section.size = try in.readInt(elf.endian, u64);
- elf_section.link = try in.readInt(elf.endian, u32);
- elf_section.info = try in.readInt(elf.endian, u32);
- elf_section.addr_align = try in.readInt(elf.endian, u64);
- elf_section.ent_size = try in.readInt(elf.endian, u64);
+ elf_section.name = try in.readInt(u32, elf.endian);
+ elf_section.sh_type = try in.readInt(u32, elf.endian);
+ elf_section.flags = try in.readInt(u64, elf.endian);
+ elf_section.addr = try in.readInt(u64, elf.endian);
+ elf_section.offset = try in.readInt(u64, elf.endian);
+ elf_section.size = try in.readInt(u64, elf.endian);
+ elf_section.link = try in.readInt(u32, elf.endian);
+ elf_section.info = try in.readInt(u32, elf.endian);
+ elf_section.addr_align = try in.readInt(u64, elf.endian);
+ elf_section.ent_size = try in.readInt(u64, elf.endian);
}
} else {
if (sh_entry_size != 40) return error.InvalidFormat;
for (elf.section_headers) |*elf_section| {
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
- elf_section.name = try in.readInt(elf.endian, u32);
- elf_section.sh_type = try in.readInt(elf.endian, u32);
- elf_section.flags = u64(try in.readInt(elf.endian, u32));
- elf_section.addr = u64(try in.readInt(elf.endian, u32));
- elf_section.offset = u64(try in.readInt(elf.endian, u32));
- elf_section.size = u64(try in.readInt(elf.endian, u32));
- elf_section.link = try in.readInt(elf.endian, u32);
- elf_section.info = try in.readInt(elf.endian, u32);
- elf_section.addr_align = u64(try in.readInt(elf.endian, u32));
- elf_section.ent_size = u64(try in.readInt(elf.endian, u32));
+ elf_section.name = try in.readInt(u32, elf.endian);
+ elf_section.sh_type = try in.readInt(u32, elf.endian);
+ elf_section.flags = u64(try in.readInt(u32, elf.endian));
+ elf_section.addr = u64(try in.readInt(u32, elf.endian));
+ elf_section.offset = u64(try in.readInt(u32, elf.endian));
+ elf_section.size = u64(try in.readInt(u32, elf.endian));
+ elf_section.link = try in.readInt(u32, elf.endian);
+ elf_section.info = try in.readInt(u32, elf.endian);
+ elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
+ elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
}
}
diff --git a/std/event/channel.zig b/std/event/channel.zig
index 133ce1c69c..4af9bf612b 100644
--- a/std/event/channel.zig
+++ b/std/event/channel.zig
@@ -1,6 +1,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const testing = std.testing;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
const Loop = std.event.Loop;
@@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type {
const buffer_nodes = try loop.allocator.alloc(T, capacity);
errdefer loop.allocator.free(buffer_nodes);
- const self = try loop.allocator.create(SelfChannel{
+ const self = try loop.allocator.create(SelfChannel);
+ self.* = SelfChannel{
.loop = loop,
.buffer_len = 0,
.buffer_nodes = buffer_nodes,
@@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type {
.or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
.get_count = 0,
.put_count = 0,
- });
+ };
errdefer loop.allocator.destroy(self);
return self;
@@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type {
}
test "std.event.Channel" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void {
const value1_promise = try async channel.get();
const value1 = await value1_promise;
- assert(value1 == 1234);
+ testing.expect(value1 == 1234);
const value2_promise = try async channel.get();
const value2 = await value2_promise;
- assert(value2 == 4567);
+ testing.expect(value2 == 4567);
const value3_promise = try async channel.getOrNull();
const value3 = await value3_promise;
- assert(value3 == null);
+ testing.expect(value3 == null);
const last_put = try async testPut(channel, 4444);
const value4 = await try async channel.getOrNull();
- assert(value4.? == 4444);
+ testing.expect(value4.? == 4444);
await last_put;
}
diff --git a/std/event/fs.zig b/std/event/fs.zig
index 1b8e1aa5dc..0e7482ec60 100644
--- a/std/event/fs.zig
+++ b/std/event/fs.zig
@@ -2,6 +2,7 @@ const builtin = @import("builtin");
const std = @import("../index.zig");
const event = std.event;
const assert = std.debug.assert;
+const testing = std.testing;
const os = std.os;
const mem = std.mem;
const posix = os.posix;
@@ -495,7 +496,7 @@ pub const CloseOperation = struct {
};
pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
- const self = try loop.allocator.createOne(CloseOperation);
+ const self = try loop.allocator.create(CloseOperation);
self.* = CloseOperation{
.loop = loop,
.os_data = switch (builtin.os) {
@@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type {
},
builtin.Os.windows => {
- const self = try loop.allocator.createOne(Self);
+ const self = try loop.allocator.create(Self);
errdefer loop.allocator.destroy(self);
self.* = Self{
.channel = channel,
@@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type {
},
builtin.Os.macosx, builtin.Os.freebsd => {
- const self = try loop.allocator.createOne(Self);
+ const self = try loop.allocator.create(Self);
errdefer loop.allocator.destroy(self);
self.* = Self{
@@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type {
}
async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
- const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);
+ const resolved_path = try os.path.resolve(self.channel.loop.allocator, [][]const u8{file_path});
var resolved_path_consumed = false;
defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
@@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type {
}
} else {
errdefer _ = self.os_data.dir_table.remove(dirname);
- const dir = try self.channel.loop.allocator.createOne(OsData.Dir);
+ const dir = try self.channel.loop.allocator.create(OsData.Dir);
errdefer self.channel.loop.allocator.destroy(dir);
dir.* = OsData.Dir{
@@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type {
const test_tmp_dir = "std_event_fs_test";
-test "write a file, watch it, write it again" {
- if (builtin.os == builtin.Os.windows) {
- // TODO this test is disabled on windows until the coroutine rewrite is finished.
- // https://github.com/ziglang/zig/issues/1363
- return error.SkipZigTest;
- }
- var da = std.heap.DirectAllocator.init();
- defer da.deinit();
-
- const allocator = &da.allocator;
-
- // TODO move this into event loop too
- try os.makePath(allocator, test_tmp_dir);
- defer os.deleteTree(allocator, test_tmp_dir) catch {};
-
- var loop: Loop = undefined;
- try loop.initMultiThreaded(allocator);
- defer loop.deinit();
-
- var result: anyerror!void = error.ResultNeverWritten;
- const handle = try async testFsWatchCantFail(&loop, &result);
- defer cancel handle;
-
- loop.run();
- return result;
-}
+// TODO this test is disabled until the coroutine rewrite is finished.
+//test "write a file, watch it, write it again" {
+// return error.SkipZigTest;
+// var da = std.heap.DirectAllocator.init();
+// defer da.deinit();
+//
+// const allocator = &da.allocator;
+//
+// // TODO move this into event loop too
+// try os.makePath(allocator, test_tmp_dir);
+// defer os.deleteTree(allocator, test_tmp_dir) catch {};
+//
+// var loop: Loop = undefined;
+// try loop.initMultiThreaded(allocator);
+// defer loop.deinit();
+//
+// var result: anyerror!void = error.ResultNeverWritten;
+// const handle = try async testFsWatchCantFail(&loop, &result);
+// defer cancel handle;
+//
+// loop.run();
+// return result;
+//}
async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
result.* = await (async testFsWatch(loop) catch unreachable);
}
async fn testFsWatch(loop: *Loop) !void {
- const file_path = try os.path.join(loop.allocator, test_tmp_dir, "file.txt");
+ const file_path = try os.path.join(loop.allocator, [][]const u8{ test_tmp_dir, "file.txt" });
defer loop.allocator.free(file_path);
const contents =
@@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void {
try await try async writeFile(loop, file_path, contents);
const read_contents = try await try async readFile(loop, file_path, 1024 * 1024);
- assert(mem.eql(u8, read_contents, contents));
+ testing.expectEqualSlices(u8, contents, read_contents);
// now watch the file
var watch = try Watch(void).create(loop, 0);
defer watch.destroy();
- assert((try await try async watch.addFile(file_path, {})) == null);
+ testing.expect((try await try async watch.addFile(file_path, {})) == null);
const ev = try async watch.channel.get();
var ev_consumed = false;
@@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void {
WatchEventId.Delete => @panic("wrong event"),
}
const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024);
- assert(mem.eql(u8, contents_updated,
+ testing.expectEqualSlices(u8,
\\line 1
\\lorem ipsum
- ));
+ , contents_updated);
// TODO test deleting the file and then re-adding it. we should get events for both
}
diff --git a/std/event/future.zig b/std/event/future.zig
index d61768b198..66acac5ad7 100644
--- a/std/event/future.zig
+++ b/std/event/future.zig
@@ -1,5 +1,6 @@
const std = @import("../index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type {
}
test "std.event.Future" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void {
const result = (await a) + (await b);
cancel c;
- assert(result == 12);
+ testing.expect(result == 12);
}
async fn waitOnFuture(future: *Future(i32)) i32 {
diff --git a/std/event/group.zig b/std/event/group.zig
index 9f2687a5b3..25e79640cb 100644
--- a/std/event/group.zig
+++ b/std/event/group.zig
@@ -4,7 +4,7 @@ const Lock = std.event.Lock;
const Loop = std.event.Loop;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
-const assert = std.debug.assert;
+const testing = std.testing;
/// ReturnType must be `void` or `E!void`
pub fn Group(comptime ReturnType: type) type {
@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {
/// Add a promise to the group. Thread-safe.
pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {
- const node = try self.lock.loop.allocator.create(Stack.Node{
+ const node = try self.lock.loop.allocator.create(Stack.Node);
+ node.* = Stack.Node{
.next = undefined,
.data = handle,
- });
+ };
self.alloc_stack.push(node);
}
@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {
}
test "std.event.Group" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void {
group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory");
group.call(increaseByTen, &count) catch @panic("memory");
await (async group.wait() catch @panic("memory"));
- assert(count == 11);
+ testing.expect(count == 11);
var another = Group(anyerror!void).init(loop);
another.add(async somethingElse() catch @panic("memory")) catch @panic("memory");
another.call(doSomethingThatFails) catch @panic("memory");
- std.debug.assertError(await (async another.wait() catch @panic("memory")), error.ItBroke);
+ testing.expectError(error.ItBroke, await (async another.wait() catch @panic("memory")));
}
async fn sleepALittle(count: *usize) void {
diff --git a/std/event/io.zig b/std/event/io.zig
index bb377a3b68..b11550f7aa 100644
--- a/std/event/io.zig
+++ b/std/event/io.zig
@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
if (amt_read < buf.len) return error.EndOfStream;
}
- pub async fn readIntLe(self: *Self, comptime T: type) !T {
- return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
+ pub async fn readIntLittle(self: *Self, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try await (async self.readNoEof(bytes[0..]) catch unreachable);
+ return mem.readIntLittle(T, &bytes);
}
pub async fn readIntBe(self: *Self, comptime T: type) !T {
- return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
- }
-
- pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try await (async self.readNoEof(bytes[0..]) catch unreachable);
- return mem.readInt(bytes, T, endian);
+ return mem.readIntBig(T, &bytes);
+ }
+
+ pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try await (async self.readNoEof(bytes[0..]) catch unreachable);
+ return mem.readInt(T, &bytes, endian);
}
pub async fn readStruct(self: *Self, comptime T: type) !T {
diff --git a/std/event/lock.zig b/std/event/lock.zig
index 46e0d13468..d6a246cee5 100644
--- a/std/event/lock.zig
+++ b/std/event/lock.zig
@@ -1,6 +1,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -122,6 +123,9 @@ pub const Lock = struct {
};
test "std.event.Lock" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -138,7 +142,7 @@ test "std.event.Lock" {
defer cancel handle;
loop.run();
- assert(mem.eql(i32, shared_test_data, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len));
+ testing.expectEqualSlices(i32, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len, shared_test_data);
}
async fn testLock(loop: *Loop, lock: *Lock) void {
diff --git a/std/event/loop.zig b/std/event/loop.zig
index 43965e8293..b92bf41982 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -1,6 +1,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -97,6 +98,7 @@ pub const Loop = struct {
/// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value.
pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
+ if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
const core_count = try os.cpuCount(allocator);
return self.initInternal(allocator, core_count);
}
@@ -201,6 +203,11 @@ pub const Loop = struct {
self.os_data.fs_thread.wait();
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
// writing 8 bytes to an eventfd cannot fail
@@ -301,6 +308,11 @@ pub const Loop = struct {
self.os_data.fs_thread.wait();
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
_ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
@@ -338,6 +350,11 @@ pub const Loop = struct {
self.available_eventfd_resume_nodes.push(eventfd_node);
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
var i: usize = 0;
@@ -845,6 +862,9 @@ pub const Loop = struct {
};
test "std.event.Loop - basic" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -858,6 +878,9 @@ test "std.event.Loop - basic" {
}
test "std.event.Loop - call" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -874,7 +897,7 @@ test "std.event.Loop - call" {
loop.run();
- assert(did_it);
+ testing.expect(did_it);
}
async fn testEventLoop() i32 {
@@ -883,6 +906,6 @@ async fn testEventLoop() i32 {
async fn testEventLoop2(h: promise->i32, did_it: *bool) void {
const value = await h;
- assert(value == 1234);
+ testing.expect(value == 1234);
did_it.* = true;
}
diff --git a/std/event/net.zig b/std/event/net.zig
index 6838704084..48461c3d81 100644
--- a/std/event/net.zig
+++ b/std/event/net.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const testing = std.testing;
const event = std.event;
const mem = std.mem;
const os = std.os;
@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
}
test "listen on a port, send bytes, receive bytes" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
if (builtin.os != builtin.Os.linux) {
// TODO build abstractions for other operating systems
return error.SkipZigTest;
@@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv
var buf: [512]u8 = undefined;
const amt_read = try socket_file.read(buf[0..]);
const msg = buf[0..amt_read];
- assert(mem.eql(u8, msg, "hello from server\n"));
+ testing.expect(mem.eql(u8, msg, "hello from server\n"));
server.close();
}
diff --git a/std/event/rwlock.zig b/std/event/rwlock.zig
index 5d48ea893e..26ccd12b73 100644
--- a/std/event/rwlock.zig
+++ b/std/event/rwlock.zig
@@ -1,6 +1,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -211,6 +212,9 @@ pub const RwLock = struct {
};
test "std.event.RwLock" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -228,7 +232,7 @@ test "std.event.RwLock" {
loop.run();
const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len;
- assert(mem.eql(i32, shared_test_data, expected_result));
+ testing.expectEqualSlices(i32, expected_result, shared_test_data);
}
async fn testLock(loop: *Loop, lock: *RwLock) void {
@@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void {
const handle = await lock_promise;
defer handle.release();
- assert(shared_test_index == 0);
- assert(shared_test_data[i] == @intCast(i32, shared_count));
+ testing.expect(shared_test_index == 0);
+ testing.expect(shared_test_data[i] == @intCast(i32, shared_count));
}
}
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index eda0bfae03..f006dfdbdc 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -2,7 +2,7 @@ const std = @import("../index.zig");
const math = std.math;
const debug = std.debug;
const assert = debug.assert;
-const assertError = debug.assertError;
+const testing = std.testing;
const mem = std.mem;
const builtin = @import("builtin");
const errol = @import("errol/index.zig");
@@ -117,7 +117,7 @@ pub fn formatType(
return output(context, @errorName(value));
}
switch (@typeInfo(T)) {
- builtin.TypeId.Int, builtin.TypeId.Float => {
+ builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
return formatValue(value, fmt, context, Errors, output);
},
builtin.TypeId.Void => {
@@ -236,6 +236,9 @@ pub fn formatType(
const casted_value = ([]const u8)(value);
return output(context, casted_value);
},
+ builtin.TypeInfo.Pointer.Size.C => {
+ return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
+ },
},
builtin.TypeId.Array => |info| {
if (info.child == u8) {
@@ -243,6 +246,9 @@ pub fn formatType(
}
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
},
+ builtin.TypeId.Fn => {
+ return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
+ },
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
}
}
@@ -268,11 +274,15 @@ fn formatValue(
}
}
- comptime var T = @typeOf(value);
+ const T = @typeOf(value);
switch (@typeId(T)) {
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
- else => unreachable,
+ builtin.TypeId.ComptimeInt => {
+ const Int = math.IntFittingRange(value, value);
+ return formatIntValue(Int(value), fmt, context, Errors, output);
+ },
+ else => comptime unreachable,
}
}
@@ -289,9 +299,10 @@ pub fn formatIntValue(
if (fmt.len > 0) {
switch (fmt[0]) {
'c' => {
- if (@typeOf(value) == u8) {
- if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
- return formatAsciiChar(value, context, Errors, output);
+ if (@typeOf(value).bit_count <= 8) {
+ if (fmt.len > 1)
+ @compileError("Unknown format character: " ++ []u8{fmt[1]});
+ return formatAsciiChar(u8(value), context, Errors, output);
}
},
'b' => {
@@ -580,7 +591,7 @@ pub fn formatFloatDecimal(
}
// Remaining fractional portion, zero-padding if insufficient.
- debug.assert(precision >= printed);
+ assert(precision >= printed);
if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
return;
@@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
}
test "fmt.parseInt" {
- assert((parseInt(i32, "-10", 10) catch unreachable) == -10);
- assert((parseInt(i32, "+10", 10) catch unreachable) == 10);
- assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
- assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
- assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
- assert((parseInt(u8, "255", 10) catch unreachable) == 255);
- assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
+ testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
+ testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
+ testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
+ testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
+ testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
+ testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
+ testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
}
const ParseUnsignedError = error{
@@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
return x;
}
-test "parseUnsigned" {
- assert((try parseUnsigned(u16, "050124", 10)) == 50124);
- assert((try parseUnsigned(u16, "65535", 10)) == 65535);
- assertError(parseUnsigned(u16, "65536", 10), error.Overflow);
+test "fmt.parseUnsigned" {
+ testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
+ testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
+ testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
- assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
- assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow);
+ testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
+ testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
- assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
+ testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
- assert((try parseUnsigned(u7, "1", 10)) == 1);
- assert((try parseUnsigned(u7, "1000", 2)) == 8);
+ testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
+ testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
- assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter);
- assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter);
+ testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
+ testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
- assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
+ testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
// these numbers should fit even though the radix itself doesn't fit in the destination type
- assert((try parseUnsigned(u1, "0", 10)) == 0);
- assert((try parseUnsigned(u1, "1", 10)) == 1);
- assertError(parseUnsigned(u1, "2", 10), error.Overflow);
- assert((try parseUnsigned(u1, "001", 16)) == 1);
- assert((try parseUnsigned(u2, "3", 16)) == 3);
- assertError(parseUnsigned(u2, "4", 16), error.Overflow);
+ testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
+ testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
+ testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
+ testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
+ testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
+ testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
+}
+
+pub const parseFloat = @import("parse_float.zig").parseFloat;
+
+test "fmt.parseFloat" {
+ _ = @import("parse_float.zig");
}
pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
@@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
test "buf print int" {
var buffer: [max_int_digits]u8 = undefined;
const buf = buffer[0..];
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42"));
- assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42"));
+ testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
}
fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 {
@@ -931,7 +948,7 @@ test "parse u64 digit too big" {
test "parse unsigned comptime" {
comptime {
- assert((try parseUnsigned(usize, "2", 10)) == 2);
+ testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
}
}
@@ -964,6 +981,23 @@ test "fmt.format" {
const value: u8 = 0b1100;
try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
}
+ {
+ var buf1: [32]u8 = undefined;
+ var context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
+ var res = buf1[0 .. buf1.len - context.remaining.len];
+ testing.expect(mem.eql(u8, res, "1234"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ testing.expect(mem.eql(u8, res, "a"));
+
+ context = BufPrintContext{ .remaining = buf1[0..] };
+ try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
+ res = buf1[0 .. buf1.len - context.remaining.len];
+ testing.expect(mem.eql(u8, res, "1100"));
+ }
{
const value: [3]u8 = "abc";
try testFmt("array: abc\n", "array: {}\n", value);
@@ -985,6 +1019,14 @@ test "fmt.format" {
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
}
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
+ }
+ {
+ const value = @intToPtr(fn () void, 0xdeadbeef);
+ try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
+ }
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
@@ -1020,19 +1062,19 @@ test "fmt.format" {
var buf1: [32]u8 = undefined;
const value: f32 = 1.34;
const result = try bufPrint(buf1[0..], "f32: {e}\n", value);
- assert(mem.eql(u8, result, "f32: 1.34000003e+00\n"));
+ testing.expect(mem.eql(u8, result, "f32: 1.34000003e+00\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f32 = 12.34;
const result = try bufPrint(buf1[0..], "f32: {e}\n", value);
- assert(mem.eql(u8, result, "f32: 1.23400001e+01\n"));
+ testing.expect(mem.eql(u8, result, "f32: 1.23400001e+01\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = -12.34e10;
const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
- assert(mem.eql(u8, result, "f64: -1.234e+11\n"));
+ testing.expect(mem.eql(u8, result, "f64: -1.234e+11\n"));
}
{
// This fails on release due to a minor rounding difference.
@@ -1042,26 +1084,26 @@ test "fmt.format" {
var buf1: [32]u8 = undefined;
const value: f64 = 9.999960e-40;
const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
- assert(mem.eql(u8, result, "f64: 9.99996e-40\n"));
+ testing.expect(mem.eql(u8, result, "f64: 9.99996e-40\n"));
}
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 1.409706e-42;
const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
- assert(mem.eql(u8, result, "f64: 1.40971e-42\n"));
+ testing.expect(mem.eql(u8, result, "f64: 1.40971e-42\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = @bitCast(f32, u32(814313563));
const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
- assert(mem.eql(u8, result, "f64: 1.00000e-09\n"));
+ testing.expect(mem.eql(u8, result, "f64: 1.00000e-09\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = @bitCast(f32, u32(1006632960));
const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
- assert(mem.eql(u8, result, "f64: 7.81250e-03\n"));
+ testing.expect(mem.eql(u8, result, "f64: 7.81250e-03\n"));
}
{
// libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
@@ -1069,47 +1111,47 @@ test "fmt.format" {
var buf1: [32]u8 = undefined;
const value: f64 = @bitCast(f32, u32(1203982400));
const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
- assert(mem.eql(u8, result, "f64: 1.00001e+05\n"));
+ testing.expect(mem.eql(u8, result, "f64: 1.00001e+05\n"));
}
{
var buf1: [32]u8 = undefined;
const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
- assert(mem.eql(u8, result, "f64: nan\n"));
+ testing.expect(mem.eql(u8, result, "f64: nan\n"));
}
if (builtin.arch != builtin.Arch.armv8) {
// negative nan is not defined by IEE 754,
// and ARM thus normalizes it to positive nan
var buf1: [32]u8 = undefined;
const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64);
- assert(mem.eql(u8, result, "f64: -nan\n"));
+ testing.expect(mem.eql(u8, result, "f64: -nan\n"));
}
{
var buf1: [32]u8 = undefined;
const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64);
- assert(mem.eql(u8, result, "f64: inf\n"));
+ testing.expect(mem.eql(u8, result, "f64: inf\n"));
}
{
var buf1: [32]u8 = undefined;
const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
- assert(mem.eql(u8, result, "f64: -inf\n"));
+ testing.expect(mem.eql(u8, result, "f64: -inf\n"));
}
{
var buf1: [64]u8 = undefined;
const value: f64 = 1.52314e+29;
const result = try bufPrint(buf1[0..], "f64: {.}\n", value);
- assert(mem.eql(u8, result, "f64: 152314000000000000000000000000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 152314000000000000000000000000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f32 = 1.1234;
const result = try bufPrint(buf1[0..], "f32: {.1}\n", value);
- assert(mem.eql(u8, result, "f32: 1.1\n"));
+ testing.expect(mem.eql(u8, result, "f32: 1.1\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f32 = 1234.567;
const result = try bufPrint(buf1[0..], "f32: {.2}\n", value);
- assert(mem.eql(u8, result, "f32: 1234.57\n"));
+ testing.expect(mem.eql(u8, result, "f32: 1234.57\n"));
}
{
var buf1: [32]u8 = undefined;
@@ -1117,92 +1159,92 @@ test "fmt.format" {
const result = try bufPrint(buf1[0..], "f32: {.4}\n", value);
// -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
// -11.12339... is rounded back up to -11.1234
- assert(mem.eql(u8, result, "f32: -11.1234\n"));
+ testing.expect(mem.eql(u8, result, "f32: -11.1234\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f32 = 91.12345;
const result = try bufPrint(buf1[0..], "f32: {.5}\n", value);
- assert(mem.eql(u8, result, "f32: 91.12345\n"));
+ testing.expect(mem.eql(u8, result, "f32: 91.12345\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 91.12345678901235;
const result = try bufPrint(buf1[0..], "f64: {.10}\n", value);
- assert(mem.eql(u8, result, "f64: 91.1234567890\n"));
+ testing.expect(mem.eql(u8, result, "f64: 91.1234567890\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 0.0;
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 5.700;
const result = try bufPrint(buf1[0..], "f64: {.0}\n", value);
- assert(mem.eql(u8, result, "f64: 6\n"));
+ testing.expect(mem.eql(u8, result, "f64: 6\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 9.999;
const result = try bufPrint(buf1[0..], "f64: {.1}\n", value);
- assert(mem.eql(u8, result, "f64: 10.0\n"));
+ testing.expect(mem.eql(u8, result, "f64: 10.0\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 1.0;
const result = try bufPrint(buf1[0..], "f64: {.3}\n", value);
- assert(mem.eql(u8, result, "f64: 1.000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 1.000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 0.0003;
const result = try bufPrint(buf1[0..], "f64: {.8}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00030000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00030000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 1.40130e-45;
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = 9.999960e-40;
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
}
// libc checks
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(916964781)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00001\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(925353389)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.00001\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(1036831278)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.10000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.10000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(1065353133)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 1.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 1.00000\n"));
}
{
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(1092616192)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 10.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 10.00000\n"));
}
// libc differences
{
@@ -1212,7 +1254,7 @@ test "fmt.format" {
// floats of the form x.yyyy25 on a precision point.
const value: f64 = f64(@bitCast(f32, u32(1015021568)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 0.01563\n"));
+ testing.expect(mem.eql(u8, result, "f64: 0.01563\n"));
}
// std-windows-x86_64-Debug-bare test case fails
{
@@ -1222,7 +1264,7 @@ test "fmt.format" {
var buf1: [32]u8 = undefined;
const value: f64 = f64(@bitCast(f32, u32(1518338049)));
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
- assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
+ testing.expect(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
}
//custom type format
{
@@ -1303,10 +1345,10 @@ test "fmt.format" {
var buf: [100]u8 = undefined;
const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
- debug.assert(mem.eql(u8, uu_result[0..3], "UU@"));
+ testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
- debug.assert(mem.eql(u8, uu_result[0..3], "EU@"));
+ testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
}
//enum format
{
@@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 {
}
test "fmt.trim" {
- assert(mem.eql(u8, "abc", trim("\n abc \t")));
- assert(mem.eql(u8, "", trim(" ")));
- assert(mem.eql(u8, "", trim("")));
- assert(mem.eql(u8, "abc", trim(" abc")));
- assert(mem.eql(u8, "abc", trim("abc ")));
+ testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
+ testing.expect(mem.eql(u8, "", trim(" ")));
+ testing.expect(mem.eql(u8, "", trim("")));
+ testing.expect(mem.eql(u8, "abc", trim(" abc")));
+ testing.expect(mem.eql(u8, "abc", trim("abc ")));
}
pub fn isWhiteSpace(byte: u8) bool {
diff --git a/std/fmt/parse_float.zig b/std/fmt/parse_float.zig
new file mode 100644
index 0000000000..de9619efe2
--- /dev/null
+++ b/std/fmt/parse_float.zig
@@ -0,0 +1,420 @@
+// Adapted from https://github.com/grzegorz-kraszewski/stringtofloat.
+
+// MIT License
+//
+// Copyright (c) 2016 Grzegorz Kraszewski
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+// Be aware that this implementation has the following limitations:
+//
+// - Is not round-trip accurate for all values
+// - Only supports round-to-zero
+// - Does not handle denormals
+
+const std = @import("../index.zig");
+
+const max_digits = 25;
+
+const f64_plus_zero: u64 = 0x0000000000000000;
+const f64_minus_zero: u64 = 0x8000000000000000;
+const f64_plus_infinity: u64 = 0x7FF0000000000000;
+const f64_minus_infinity: u64 = 0xFFF0000000000000;
+
+const Z96 = struct {
+ d0: u32,
+ d1: u32,
+ d2: u32,
+
+ // d = s >> 1
+ inline fn shiftRight1(d: *Z96, s: Z96) void {
+ d.d0 = (s.d0 >> 1) | ((s.d1 & 1) << 31);
+ d.d1 = (s.d1 >> 1) | ((s.d2 & 1) << 31);
+ d.d2 = s.d2 >> 1;
+ }
+
+ // d = s << 1
+ inline fn shiftLeft1(d: *Z96, s: Z96) void {
+ d.d2 = (s.d2 << 1) | ((s.d1 & (1 << 31)) >> 31);
+ d.d1 = (s.d1 << 1) | ((s.d0 & (1 << 31)) >> 31);
+ d.d0 = s.d0 << 1;
+ }
+
+ // d += s
+ inline fn add(d: *Z96, s: Z96) void {
+ var w = u64(d.d0) + u64(s.d0);
+ d.d0 = @truncate(u32, w);
+
+ w >>= 32;
+ w += u64(d.d1) + u64(s.d1);
+ d.d1 = @truncate(u32, w);
+
+ w >>= 32;
+ w += u64(d.d2) + u64(s.d2);
+ d.d2 = @truncate(u32, w);
+ }
+
+ // d -= s
+ inline fn sub(d: *Z96, s: Z96) void {
+ var w = u64(d.d0) -% u64(s.d0);
+ d.d0 = @truncate(u32, w);
+
+ w >>= 32;
+ w += u64(d.d1) -% u64(s.d1);
+ d.d1 = @truncate(u32, w);
+
+ w >>= 32;
+ w += u64(d.d2) -% u64(s.d2);
+ d.d2 = @truncate(u32, w);
+ }
+};
+
+const FloatRepr = struct {
+ negative: bool,
+ exponent: i32,
+ mantissa: u64,
+};
+
+fn convertRepr(comptime T: type, n: FloatRepr) T {
+ const mask28: u32 = 0xf << 28;
+
+ var s: Z96 = undefined;
+ var q: Z96 = undefined;
+ var r: Z96 = undefined;
+
+ s.d0 = @truncate(u32, n.mantissa);
+ s.d1 = @truncate(u32, n.mantissa >> 32);
+ s.d2 = 0;
+
+ var binary_exponent: u64 = 92;
+ var exp = n.exponent;
+
+ while (exp > 0) : (exp -= 1) {
+ q.shiftLeft1(s); // q = p << 1
+ r.shiftLeft1(q); // r = p << 2
+ s.shiftLeft1(r); // p = p << 3
+ q.add(s); // p = (p << 3) + (p << 1)
+
+ exp -= 1;
+
+ while (s.d2 & mask28 != 0) {
+ q.shiftRight1(s);
+ binary_exponent += 1;
+ s = q;
+ }
+ }
+
+ while (exp < 0) {
+ while (s.d2 & (1 << 31) == 0) {
+ q.shiftLeft1(s);
+ binary_exponent -= 1;
+ s = q;
+ }
+
+ q.d2 = s.d2 / 10;
+ r.d1 = s.d2 % 10;
+ r.d2 = (s.d1 >> 8) | (r.d1 << 24);
+ q.d1 = r.d2 / 10;
+ r.d1 = r.d2 % 10;
+ r.d2 = ((s.d1 & 0xff) << 16) | (s.d0 >> 16) | (r.d1 << 24);
+ r.d0 = r.d2 / 10;
+ r.d1 = r.d2 % 10;
+ q.d1 = (q.d1 << 8) | ((r.d0 & 0x00ff0000) >> 16);
+ q.d0 = r.d0 << 16;
+ r.d2 = (s.d0 *% 0xffff) | (r.d1 << 16);
+ q.d0 |= r.d2 / 10;
+ s = q;
+
+ exp += 1;
+ }
+
+ if (s.d0 != 0 or s.d1 != 0 or s.d2 != 0) {
+ while (s.d2 & mask28 == 0) {
+ q.shiftLeft1(s);
+ binary_exponent -= 1;
+ s = q;
+ }
+ }
+
+ binary_exponent += 1023;
+
+ const repr: u64 = blk: {
+ if (binary_exponent > 2046) {
+ break :blk if (n.negative) f64_minus_infinity else f64_plus_infinity;
+ } else if (binary_exponent < 1) {
+ break :blk if (n.negative) f64_minus_zero else f64_plus_zero;
+ } else if (s.d2 != 0) {
+ const binexs2 = u64(binary_exponent) << 52;
+ const rr = (u64(s.d2 & ~mask28) << 24) | ((u64(s.d1) + 128) >> 8) | binexs2;
+ break :blk if (n.negative) rr | (1 << 63) else rr;
+ } else {
+ break :blk 0;
+ }
+ };
+
+ const f = @bitCast(f64, repr);
+ return @floatCast(T, f);
+}
+
+const State = enum {
+ MaybeSign,
+ LeadingMantissaZeros,
+ LeadingFractionalZeros,
+ MantissaIntegral,
+ MantissaFractional,
+ ExponentSign,
+ LeadingExponentZeros,
+ Exponent,
+};
+
+const ParseResult = enum {
+ Ok,
+ PlusZero,
+ MinusZero,
+ PlusInf,
+ MinusInf,
+};
+
+inline fn isDigit(c: u8) bool {
+ return c >= '0' and c <= '9';
+}
+
+inline fn isSpace(c: u8) bool {
+ return (c >= 0x09 and c <= 0x13) or c == 0x20;
+}
+
+fn parseRepr(s: []const u8, n: *FloatRepr) !ParseResult {
+ var digit_index: usize = 0;
+ var negative = false;
+ var negative_exp = false;
+ var exponent: i32 = 0;
+
+ var state = State.MaybeSign;
+
+ var i: usize = 0;
+ loop: while (i < s.len) {
+ const c = s[i];
+
+ switch (state) {
+ State.MaybeSign => {
+ state = State.LeadingMantissaZeros;
+
+ if (c == '+') {
+ i += 1;
+ } else if (c == '-') {
+ n.negative = true;
+ i += 1;
+ } else if (isDigit(c) or c == '.') {
+ // continue
+ } else {
+ return error.InvalidCharacter;
+ }
+ },
+
+ State.LeadingMantissaZeros => {
+ if (c == '0') {
+ i += 1;
+ } else if (c == '.') {
+ i += 1;
+ state = State.LeadingFractionalZeros;
+ } else {
+ state = State.MantissaIntegral;
+ }
+ },
+
+ State.LeadingFractionalZeros => {
+ if (c == '0') {
+ i += 1;
+ if (n.exponent > std.math.minInt(i32)) {
+ n.exponent -= 1;
+ }
+ } else {
+ state = State.MantissaFractional;
+ }
+ },
+
+ State.MantissaIntegral => {
+ if (isDigit(c)) {
+ if (digit_index < max_digits) {
+ n.mantissa *%= 10;
+ n.mantissa += s[i] - '0';
+ digit_index += 1;
+ } else if (n.exponent < std.math.maxInt(i32)) {
+ n.exponent += 1;
+ }
+
+ i += 1;
+ } else if (c == '.') {
+ i += 1;
+ state = State.MantissaFractional;
+ } else {
+ state = State.MantissaFractional;
+ }
+ },
+
+ State.MantissaFractional => {
+ if (isDigit(c)) {
+ if (digit_index < max_digits) {
+ n.mantissa *%= 10;
+ n.mantissa += c - '0';
+ n.exponent -%= 1;
+ digit_index += 1;
+ }
+
+ i += 1;
+ } else if (c == 'e' or c == 'E') {
+ i += 1;
+ state = State.ExponentSign;
+ } else {
+ state = State.ExponentSign;
+ }
+ },
+
+ State.ExponentSign => {
+ if (c == '+') {
+ i += 1;
+ } else if (c == '-') {
+ negative_exp = true;
+ i += 1;
+ }
+
+ state = State.LeadingExponentZeros;
+ },
+
+ State.LeadingExponentZeros => {
+ if (c == '0') {
+ i += 1;
+ } else {
+ state = State.Exponent;
+ }
+ },
+
+ State.Exponent => {
+ if (isDigit(c)) {
+ if (exponent < std.math.maxInt(i32)) {
+ exponent *= 10;
+ exponent += @intCast(i32, c - '0');
+ }
+
+ i += 1;
+ } else {
+ return error.InvalidCharacter;
+ }
+ },
+ }
+ }
+
+ if (negative_exp) exponent = -exponent;
+ n.exponent += exponent;
+
+ if (n.mantissa == 0) {
+ return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero;
+ } else if (n.exponent > 309) {
+ return if (n.negative) ParseResult.MinusInf else ParseResult.PlusInf;
+ } else if (n.exponent < -328) {
+ return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero;
+ }
+
+ return ParseResult.Ok;
+}
+
+inline fn isLower(c: u8) bool {
+ return c -% 'a' < 26;
+}
+
+inline fn toUpper(c: u8) u8 {
+ return if (isLower(c)) (c & 0x5f) else c;
+}
+
+fn caseInEql(a: []const u8, b: []const u8) bool {
+ if (a.len != b.len) return false;
+
+ for (a) |_, i| {
+ if (toUpper(a[i]) != toUpper(b[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+pub fn parseFloat(comptime T: type, s: []const u8) !T {
+ if (s.len == 0) {
+ return error.InvalidCharacter;
+ }
+
+ if (caseInEql(s, "nan")) {
+ return std.math.nan(T);
+ } else if (caseInEql(s, "inf") or caseInEql(s, "+inf")) {
+ return std.math.inf(T);
+ } else if (caseInEql(s, "-inf")) {
+ return -std.math.inf(T);
+ }
+
+ var r = FloatRepr{
+ .negative = false,
+ .exponent = 0,
+ .mantissa = 0,
+ };
+
+ return switch (try parseRepr(s, &r)) {
+ ParseResult.Ok => convertRepr(T, r),
+ ParseResult.PlusZero => 0.0,
+ ParseResult.MinusZero => -T(0.0),
+ ParseResult.PlusInf => std.math.inf(T),
+ ParseResult.MinusInf => -std.math.inf(T),
+ };
+}
+
+test "fmt.parseFloat" {
+ const testing = std.testing;
+ const expect = testing.expect;
+ const expectEqual = testing.expectEqual;
+ const approxEq = std.math.approxEq;
+ const epsilon = 1e-7;
+
+ inline for ([]type{ f16, f32, f64, f128 }) |T| {
+ const Z = @IntType(false, T.bit_count);
+
+ testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
+ testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
+ testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc"));
+
+ expectEqual(try parseFloat(T, "0"), 0.0);
+ expectEqual((try parseFloat(T, "0")), 0.0);
+ expectEqual((try parseFloat(T, "+0")), 0.0);
+ expectEqual((try parseFloat(T, "-0")), 0.0);
+
+ expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon));
+ expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon));
+
+ expectEqual((try parseFloat(T, "1e-700")), 0);
+ expectEqual((try parseFloat(T, "1e+700")), std.math.inf(T));
+
+ expectEqual(@bitCast(Z, try parseFloat(T, "nAn")), @bitCast(Z, std.math.nan(T)));
+ expectEqual((try parseFloat(T, "inF")), std.math.inf(T));
+ expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T));
+
+ if (T != f16) {
+ expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon));
+ expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));
+ }
+ }
+}
diff --git a/std/hash/adler.zig b/std/hash/adler.zig
index 9c5966f89b..78f960367a 100644
--- a/std/hash/adler.zig
+++ b/std/hash/adler.zig
@@ -4,7 +4,7 @@
// https://github.com/madler/zlib/blob/master/adler32.c
const std = @import("../index.zig");
-const debug = std.debug;
+const testing = std.testing;
pub const Adler32 = struct {
const base = 65521;
@@ -89,19 +89,19 @@ pub const Adler32 = struct {
};
test "adler32 sanity" {
- debug.assert(Adler32.hash("a") == 0x620062);
- debug.assert(Adler32.hash("example") == 0xbc002ed);
+ testing.expect(Adler32.hash("a") == 0x620062);
+ testing.expect(Adler32.hash("example") == 0xbc002ed);
}
test "adler32 long" {
const long1 = []u8{1} ** 1024;
- debug.assert(Adler32.hash(long1[0..]) == 0x06780401);
+ testing.expect(Adler32.hash(long1[0..]) == 0x06780401);
const long2 = []u8{1} ** 1025;
- debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402);
+ testing.expect(Adler32.hash(long2[0..]) == 0x0a7a0402);
}
test "adler32 very long" {
const long = []u8{1} ** 5553;
- debug.assert(Adler32.hash(long[0..]) == 0x707f15b2);
+ testing.expect(Adler32.hash(long[0..]) == 0x707f15b2);
}
diff --git a/std/hash/crc.zig b/std/hash/crc.zig
index c4bd92884a..9bea358bf1 100644
--- a/std/hash/crc.zig
+++ b/std/hash/crc.zig
@@ -7,6 +7,7 @@
const std = @import("../index.zig");
const debug = std.debug;
+const testing = std.testing;
pub const Polynomial = struct {
const IEEE = 0xedb88320;
@@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
test "crc32 ieee" {
const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
- debug.assert(Crc32Ieee.hash("") == 0x00000000);
- debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
- debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
+ testing.expect(Crc32Ieee.hash("") == 0x00000000);
+ testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
+ testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
}
test "crc32 castagnoli" {
const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
- debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
- debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
- debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
+ testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
+ testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
+ testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
}
// half-byte lookup table implementation.
@@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
test "small crc32 ieee" {
const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
- debug.assert(Crc32Ieee.hash("") == 0x00000000);
- debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
- debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
+ testing.expect(Crc32Ieee.hash("") == 0x00000000);
+ testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
+ testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
}
test "small crc32 castagnoli" {
const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
- debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
- debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
- debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
+ testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
+ testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
+ testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
}
diff --git a/std/hash/fnv.zig b/std/hash/fnv.zig
index 9bb18f14b3..6876b636f6 100644
--- a/std/hash/fnv.zig
+++ b/std/hash/fnv.zig
@@ -5,7 +5,7 @@
// https://tools.ietf.org/html/draft-eastlake-fnv-14
const std = @import("../index.zig");
-const debug = std.debug;
+const testing = std.testing;
pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5);
pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);
@@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
}
test "fnv1a-32" {
- debug.assert(Fnv1a_32.hash("") == 0x811c9dc5);
- debug.assert(Fnv1a_32.hash("a") == 0xe40c292c);
- debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968);
+ testing.expect(Fnv1a_32.hash("") == 0x811c9dc5);
+ testing.expect(Fnv1a_32.hash("a") == 0xe40c292c);
+ testing.expect(Fnv1a_32.hash("foobar") == 0xbf9cf968);
}
test "fnv1a-64" {
- debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325);
- debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
- debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
+ testing.expect(Fnv1a_64.hash("") == 0xcbf29ce484222325);
+ testing.expect(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
+ testing.expect(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
}
test "fnv1a-128" {
- debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
- debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
+ testing.expect(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
+ testing.expect(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
}
diff --git a/std/hash/siphash.zig b/std/hash/siphash.zig
index 0fe958c38b..c9a6128d35 100644
--- a/std/hash/siphash.zig
+++ b/std/hash/siphash.zig
@@ -6,7 +6,8 @@
// https://131002.net/siphash/
const std = @import("../index.zig");
-const debug = std.debug;
+const assert = std.debug.assert;
+const testing = std.testing;
const math = std.math;
const mem = std.mem;
@@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
}
fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
- debug.assert(T == u64 or T == u128);
- debug.assert(c_rounds > 0 and d_rounds > 0);
+ assert(T == u64 or T == u128);
+ assert(c_rounds > 0 and d_rounds > 0);
return struct {
const Self = @This();
@@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
msg_len: u8,
pub fn init(key: []const u8) Self {
- debug.assert(key.len >= 16);
+ assert(key.len >= 16);
- const k0 = mem.readInt(key[0..8], u64, Endian.Little);
- const k1 = mem.readInt(key[8..16], u64, Endian.Little);
+ const k0 = mem.readIntSliceLittle(u64, key[0..8]);
+ const k1 = mem.readIntSliceLittle(u64, key[8..16]);
var d = Self{
.v0 = k0 ^ 0x736f6d6570736575,
@@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
}
fn round(d: *Self, b: []const u8) void {
- debug.assert(b.len == 8);
+ assert(b.len == 8);
- const m = mem.readInt(b[0..], u64, Endian.Little);
+ const m = mem.readIntSliceLittle(u64, b[0..]);
d.v3 ^= m;
comptime var i: usize = 0;
@@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
test "siphash64-2-4 sanity" {
- const vectors = [][]const u8{
+ const vectors = [][8]u8{
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
@@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" {
for (vectors) |vector, i| {
buffer[i] = @intCast(u8, i);
- const expected = mem.readInt(vector, u64, Endian.Little);
- debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
+ const expected = mem.readIntLittle(u64, &vector);
+ testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
}
}
test "siphash128-2-4 sanity" {
- const vectors = [][]const u8{
+ const vectors = [][16]u8{
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
@@ -314,7 +315,7 @@ test "siphash128-2-4 sanity" {
for (vectors) |vector, i| {
buffer[i] = @intCast(u8, i);
- const expected = mem.readInt(vector, u128, Endian.Little);
- debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
+ const expected = mem.readIntLittle(u128, &vector);
+ testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
}
}
diff --git a/std/hash_map.zig b/std/hash_map.zig
index 99237047e0..4519890bb7 100644
--- a/std/hash_map.zig
+++ b/std/hash_map.zig
@@ -1,6 +1,7 @@
const std = @import("index.zig");
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const math = std.math;
const mem = std.mem;
const Allocator = mem.Allocator;
@@ -342,37 +343,37 @@ test "basic hash map usage" {
var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
defer map.deinit();
- assert((try map.put(1, 11)) == null);
- assert((try map.put(2, 22)) == null);
- assert((try map.put(3, 33)) == null);
- assert((try map.put(4, 44)) == null);
- assert((try map.put(5, 55)) == null);
+ testing.expect((try map.put(1, 11)) == null);
+ testing.expect((try map.put(2, 22)) == null);
+ testing.expect((try map.put(3, 33)) == null);
+ testing.expect((try map.put(4, 44)) == null);
+ testing.expect((try map.put(5, 55)) == null);
- assert((try map.put(5, 66)).?.value == 55);
- assert((try map.put(5, 55)).?.value == 66);
+ testing.expect((try map.put(5, 66)).?.value == 55);
+ testing.expect((try map.put(5, 55)).?.value == 66);
const gop1 = try map.getOrPut(5);
- assert(gop1.found_existing == true);
- assert(gop1.kv.value == 55);
+ testing.expect(gop1.found_existing == true);
+ testing.expect(gop1.kv.value == 55);
gop1.kv.value = 77;
- assert(map.get(5).?.value == 77);
+ testing.expect(map.get(5).?.value == 77);
const gop2 = try map.getOrPut(99);
- assert(gop2.found_existing == false);
+ testing.expect(gop2.found_existing == false);
gop2.kv.value = 42;
- assert(map.get(99).?.value == 42);
+ testing.expect(map.get(99).?.value == 42);
const gop3 = try map.getOrPutValue(5, 5);
- assert(gop3.value == 77);
+ testing.expect(gop3.value == 77);
const gop4 = try map.getOrPutValue(100, 41);
- assert(gop4.value == 41);
+ testing.expect(gop4.value == 41);
- assert(map.contains(2));
- assert(map.get(2).?.value == 22);
+ testing.expect(map.contains(2));
+ testing.expect(map.get(2).?.value == 22);
_ = map.remove(2);
- assert(map.remove(2) == null);
- assert(map.get(2) == null);
+ testing.expect(map.remove(2) == null);
+ testing.expect(map.get(2) == null);
}
test "iterator hash map" {
@@ -382,9 +383,9 @@ test "iterator hash map" {
var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
defer reset_map.deinit();
- assert((try reset_map.put(1, 11)) == null);
- assert((try reset_map.put(2, 22)) == null);
- assert((try reset_map.put(3, 33)) == null);
+ testing.expect((try reset_map.put(1, 11)) == null);
+ testing.expect((try reset_map.put(2, 22)) == null);
+ testing.expect((try reset_map.put(3, 33)) == null);
var keys = []i32{
3,
@@ -400,26 +401,26 @@ test "iterator hash map" {
var it = reset_map.iterator();
var count: usize = 0;
while (it.next()) |next| {
- assert(next.key == keys[count]);
- assert(next.value == values[count]);
+ testing.expect(next.key == keys[count]);
+ testing.expect(next.value == values[count]);
count += 1;
}
- assert(count == 3);
- assert(it.next() == null);
+ testing.expect(count == 3);
+ testing.expect(it.next() == null);
it.reset();
count = 0;
while (it.next()) |next| {
- assert(next.key == keys[count]);
- assert(next.value == values[count]);
+ testing.expect(next.key == keys[count]);
+ testing.expect(next.value == values[count]);
count += 1;
if (count == 2) break;
}
it.reset();
var entry = it.next().?;
- assert(entry.key == keys[0]);
- assert(entry.value == values[0]);
+ testing.expect(entry.key == keys[0]);
+ testing.expect(entry.value == values[0]);
}
pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {
@@ -495,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
builtin.TypeId.Pointer => |info| switch (info.size) {
builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),
+ builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"),
builtin.TypeInfo.Pointer.Size.Slice => {
const interval = std.math.max(1, key.len / 256);
var i: usize = 0;
@@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),
builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),
+ builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),
builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),
builtin.TypeId.Union => @compileError("TODO auto hash for unions"),
builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),
@@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
builtin.TypeId.Pointer => |info| switch (info.size) {
builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),
+ builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"),
builtin.TypeInfo.Pointer.Size.Slice => {
if (a.len != b.len) return false;
for (a) |a_item, i| {
@@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),
builtin.TypeId.Union => @compileError("TODO auto eql for unions"),
builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),
+ builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),
}
}
diff --git a/std/heap.zig b/std/heap.zig
index 5c31d412cf..e7088150a8 100644
--- a/std/heap.zig
+++ b/std/heap.zig
@@ -1,6 +1,7 @@
const std = @import("index.zig");
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const mem = std.mem;
const os = std.os;
const builtin = @import("builtin");
@@ -66,7 +67,7 @@ pub const DirectAllocator = struct {
}
}
- fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
+ fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
switch (builtin.os) {
@@ -106,9 +107,7 @@ pub const DirectAllocator = struct {
};
const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
const root_addr = @ptrToInt(ptr);
- const rem = @rem(root_addr, alignment);
- const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
- const adjusted_addr = root_addr + march_forward_bytes;
+ const adjusted_addr = mem.alignForward(root_addr, alignment);
const record_addr = adjusted_addr + n;
@intToPtr(*align(1) usize, record_addr).* = root_addr;
return @intToPtr([*]u8, adjusted_addr)[0..n];
@@ -126,8 +125,7 @@ pub const DirectAllocator = struct {
const base_addr = @ptrToInt(old_mem.ptr);
const old_addr_end = base_addr + old_mem.len;
const new_addr_end = base_addr + new_size;
- const rem = @rem(new_addr_end, os.page_size);
- const new_addr_end_rounded = new_addr_end + if (rem == 0) 0 else (os.page_size - rem);
+ const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
if (old_addr_end > new_addr_end_rounded) {
_ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
}
@@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct {
fn free(allocator: *Allocator, bytes: []u8) void {}
};
-/// lock free
-pub const ThreadSafeFixedBufferAllocator = struct {
- allocator: Allocator,
- end_index: usize,
- buffer: []u8,
+pub const ThreadSafeFixedBufferAllocator = blk: {
+ if (builtin.single_threaded) {
+ break :blk FixedBufferAllocator;
+ } else {
+ /// lock free
+ break :blk struct {
+ allocator: Allocator,
+ end_index: usize,
+ buffer: []u8,
- pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator {
- return ThreadSafeFixedBufferAllocator{
- .allocator = Allocator{
- .allocFn = alloc,
- .reallocFn = realloc,
- .freeFn = free,
- },
- .buffer = buffer,
- .end_index = 0,
+ pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator {
+ return ThreadSafeFixedBufferAllocator{
+ .allocator = Allocator{
+ .allocFn = alloc,
+ .reallocFn = realloc,
+ .freeFn = free,
+ },
+ .buffer = buffer,
+ .end_index = 0,
+ };
+ }
+
+ fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
+ const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);
+ var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);
+ while (true) {
+ const addr = @ptrToInt(self.buffer.ptr) + end_index;
+ const rem = @rem(addr, alignment);
+ const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
+ const adjusted_index = end_index + march_forward_bytes;
+ const new_end_index = adjusted_index + n;
+ if (new_end_index > self.buffer.len) {
+ return error.OutOfMemory;
+ }
+ end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index];
+ }
+ }
+
+ fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
+ if (new_size <= old_mem.len) {
+ return old_mem[0..new_size];
+ } else {
+ const result = try alloc(allocator, new_size, alignment);
+ mem.copy(u8, result, old_mem);
+ return result;
+ }
+ }
+
+ fn free(allocator: *Allocator, bytes: []u8) void {}
};
}
-
- fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
- const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);
- var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);
- while (true) {
- const addr = @ptrToInt(self.buffer.ptr) + end_index;
- const rem = @rem(addr, alignment);
- const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
- const adjusted_index = end_index + march_forward_bytes;
- const new_end_index = adjusted_index + n;
- if (new_end_index > self.buffer.len) {
- return error.OutOfMemory;
- }
- end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index];
- }
- }
-
- fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
- if (new_size <= old_mem.len) {
- return old_mem[0..new_size];
- } else {
- const result = try alloc(allocator, new_size, alignment);
- mem.copy(u8, result, old_mem);
- return result;
- }
- }
-
- fn free(allocator: *Allocator, bytes: []u8) void {}
};
pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) {
@@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" {
var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);
- assert(slice0.len == 5);
+ testing.expect(slice0.len == 5);
var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);
- assert(slice1.ptr == slice0.ptr);
- assert(slice1.len == 10);
- debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory);
+ testing.expect(slice1.ptr == slice0.ptr);
+ testing.expect(slice1.len == 10);
+ testing.expectError(error.OutOfMemory, fixed_buffer_allocator.allocator.realloc(u8, slice1, 11));
}
// check that we don't re-use the memory if it's not the most recent block
{
@@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" {
slice0[1] = 2;
var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);
- assert(slice0.ptr != slice2.ptr);
- assert(slice1.ptr != slice2.ptr);
- assert(slice2[0] == 1);
- assert(slice2[1] == 2);
+ testing.expect(slice0.ptr != slice2.ptr);
+ testing.expect(slice1.ptr != slice2.ptr);
+ testing.expect(slice2[0] == 1);
+ testing.expect(slice2[1] == 2);
}
}
@@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" {
fn testAllocator(allocator: *mem.Allocator) !void {
var slice = try allocator.alloc(*i32, 100);
- assert(slice.len == 100);
+ testing.expect(slice.len == 100);
for (slice) |*item, i| {
- item.* = try allocator.create(@intCast(i32, i));
+ item.* = try allocator.create(i32);
+ item.*.* = @intCast(i32, i);
}
slice = try allocator.realloc(*i32, slice, 20000);
- assert(slice.len == 20000);
+ testing.expect(slice.len == 20000);
for (slice[0..100]) |item, i| {
- assert(item.* == @intCast(i32, i));
+ testing.expect(item.* == @intCast(i32, i));
allocator.destroy(item);
}
slice = try allocator.realloc(*i32, slice, 50);
- assert(slice.len == 50);
+ testing.expect(slice.len == 50);
slice = try allocator.realloc(*i32, slice, 25);
- assert(slice.len == 25);
+ testing.expect(slice.len == 25);
slice = try allocator.realloc(*i32, slice, 0);
- assert(slice.len == 0);
+ testing.expect(slice.len == 0);
slice = try allocator.realloc(*i32, slice, 10);
- assert(slice.len == 10);
+ testing.expect(slice.len == 10);
allocator.free(slice);
}
@@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void {
fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void {
// initial
var slice = try allocator.alignedAlloc(u8, alignment, 10);
- assert(slice.len == 10);
+ testing.expect(slice.len == 10);
// grow
slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
- assert(slice.len == 100);
+ testing.expect(slice.len == 100);
// shrink
slice = try allocator.alignedRealloc(u8, alignment, slice, 10);
- assert(slice.len == 10);
+ testing.expect(slice.len == 10);
// go to zero
slice = try allocator.alignedRealloc(u8, alignment, slice, 0);
- assert(slice.len == 0);
+ testing.expect(slice.len == 0);
// realloc from zero
slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
- assert(slice.len == 100);
+ testing.expect(slice.len == 100);
// shrink with shrink
slice = allocator.alignedShrink(u8, alignment, slice, 10);
- assert(slice.len == 10);
+ testing.expect(slice.len == 10);
// shrink to zero
slice = allocator.alignedShrink(u8, alignment, slice, 0);
- assert(slice.len == 0);
+ testing.expect(slice.len == 0);
}
fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void {
@@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
_ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);
var slice = try allocator.allocFn(allocator, 500, large_align);
- debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
+ testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
slice = try allocator.reallocFn(allocator, slice, 100, large_align);
- debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
+ testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
slice = try allocator.reallocFn(allocator, slice, 5000, large_align);
- debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
+ testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
slice = try allocator.reallocFn(allocator, slice, 10, large_align);
- debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
+ testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
slice = try allocator.reallocFn(allocator, slice, 20000, large_align);
- debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
+ testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
allocator.free(slice);
}
diff --git a/std/index.zig b/std/index.zig
index 55ad016bb1..9d9b7ee8d6 100644
--- a/std/index.zig
+++ b/std/index.zig
@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
pub const HashMap = @import("hash_map.zig").HashMap;
pub const LinkedList = @import("linked_list.zig").LinkedList;
pub const Mutex = @import("mutex.zig").Mutex;
+pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
pub const SpinLock = @import("spinlock.zig").SpinLock;
@@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig");
pub const heap = @import("heap.zig");
pub const io = @import("io.zig");
pub const json = @import("json.zig");
+pub const lazyInit = @import("lazy_init.zig").lazyInit;
pub const macho = @import("macho.zig");
pub const math = @import("math/index.zig");
-pub const meta = @import("meta/index.zig");
pub const mem = @import("mem.zig");
+pub const meta = @import("meta/index.zig");
pub const net = @import("net.zig");
pub const os = @import("os/index.zig");
pub const pdb = @import("pdb.zig");
pub const rand = @import("rand/index.zig");
pub const rb = @import("rb.zig");
pub const sort = @import("sort.zig");
+pub const testing = @import("testing.zig");
pub const unicode = @import("unicode.zig");
pub const zig = @import("zig/index.zig");
-pub const lazyInit = @import("lazy_init.zig").lazyInit;
-
test "std" {
// run tests from these
_ = @import("array_list.zig");
@@ -55,9 +56,10 @@ test "std" {
_ = @import("hash_map.zig");
_ = @import("linked_list.zig");
_ = @import("mutex.zig");
+ _ = @import("statically_initialized_mutex.zig");
_ = @import("segmented_list.zig");
_ = @import("spinlock.zig");
-
+
_ = @import("base64.zig");
_ = @import("build.zig");
_ = @import("c/index.zig");
@@ -66,24 +68,26 @@ test "std" {
_ = @import("cstr.zig");
_ = @import("debug/index.zig");
_ = @import("dwarf.zig");
+ _ = @import("dynamic_library.zig");
_ = @import("elf.zig");
_ = @import("empty.zig");
_ = @import("event.zig");
_ = @import("fmt/index.zig");
_ = @import("hash/index.zig");
+ _ = @import("heap.zig");
_ = @import("io.zig");
_ = @import("json.zig");
+ _ = @import("lazy_init.zig");
_ = @import("macho.zig");
_ = @import("math/index.zig");
- _ = @import("meta/index.zig");
_ = @import("mem.zig");
+ _ = @import("meta/index.zig");
_ = @import("net.zig");
- _ = @import("heap.zig");
_ = @import("os/index.zig");
- _ = @import("rand/index.zig");
_ = @import("pdb.zig");
+ _ = @import("rand/index.zig");
_ = @import("sort.zig");
+ _ = @import("testing.zig");
_ = @import("unicode.zig");
_ = @import("zig/index.zig");
- _ = @import("lazy_init.zig");
}
diff --git a/std/io.zig b/std/io.zig
index bdca2b03e8..f6e3790af6 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -8,9 +8,12 @@ const debug = std.debug;
const assert = debug.assert;
const os = std.os;
const mem = std.mem;
+const meta = std.meta;
+const trait = meta.trait;
const Buffer = std.Buffer;
const fmt = std.fmt;
const File = std.os.File;
+const testing = std.testing;
const is_posix = builtin.os != builtin.Os.windows;
const is_windows = builtin.os == builtin.Os.windows;
@@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type {
}
/// Reads a native-endian integer
- pub fn readIntNe(self: *Self, comptime T: type) !T {
- return self.readInt(builtin.endian, T);
- }
-
- pub fn readIntLe(self: *Self, comptime T: type) !T {
+ pub fn readIntNative(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readIntLE(T, bytes);
+ return mem.readIntNative(T, &bytes);
}
- pub fn readIntBe(self: *Self, comptime T: type) !T {
+ /// Reads a foreign-endian integer
+ pub fn readIntForeign(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readIntBE(T, bytes);
+ return mem.readIntForeign(T, &bytes);
}
- pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
+ pub fn readIntLittle(self: *Self, comptime T: type) !T {
var bytes: [@sizeOf(T)]u8 = undefined;
try self.readNoEof(bytes[0..]);
- return mem.readInt(bytes, T, endian);
+ return mem.readIntLittle(T, &bytes);
}
- pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
- assert(size <= @sizeOf(T));
- assert(size <= 8);
- var input_buf: [8]u8 = undefined;
- const input_slice = input_buf[0..size];
- try self.readNoEof(input_slice);
- return mem.readInt(input_slice, T, endian);
+ pub fn readIntBig(self: *Self, comptime T: type) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try self.readNoEof(bytes[0..]);
+ return mem.readIntBig(T, &bytes);
+ }
+
+ pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ try self.readNoEof(bytes[0..]);
+ return mem.readInt(T, &bytes, endian);
+ }
+
+ pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
+ assert(size <= @sizeOf(ReturnType));
+ var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
+ const bytes = bytes_buf[0..size];
+ try self.readNoEof(bytes);
+ return mem.readVarInt(ReturnType, bytes, endian);
}
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
@@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type {
}
/// Write a native-endian integer.
- pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
- return self.writeInt(builtin.endian, T, value);
- }
-
- pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {
+ pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeIntLE(T, &bytes, value);
+ mem.writeIntNative(T, &bytes, value);
return self.writeFn(self, bytes);
}
- pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {
+ /// Write a foreign-endian integer.
+ pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeIntBE(T, &bytes, value);
+ mem.writeIntForeign(T, &bytes, value);
return self.writeFn(self, bytes);
}
- pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {
+ pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
var bytes: [@sizeOf(T)]u8 = undefined;
- mem.writeInt(bytes[0..], value, endian);
+ mem.writeIntLittle(T, &bytes, value);
+ return self.writeFn(self, bytes);
+ }
+
+ pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ mem.writeIntBig(T, &bytes, value);
+ return self.writeFn(self, bytes);
+ }
+
+ pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
+ var bytes: [@sizeOf(T)]u8 = undefined;
+ mem.writeInt(T, &bytes, value, endian);
return self.writeFn(self, bytes);
}
};
@@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
const amt_buffered = self.end_index - self.start_index;
if (amt_buffered == 0) {
assert(self.end_index <= buffer_size);
- if (self.end_index == buffer_size) {
- // we can read more data from the unbuffered stream
- if (dest_space < buffer_size) {
- self.start_index = 0;
- self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
- } else {
- // asking for so much data that buffering is actually less efficient.
- // forward the request directly to the unbuffered stream
- const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
- return dest_index + amt_read;
- }
- } else {
- // reading from the unbuffered stream returned less than we asked for
- // so we cannot read any more data.
+ // Make sure the last read actually gave us some data
+ if (self.end_index == 0) {
+ // reading from the unbuffered stream returned nothing
+ // so we have nothing left to read.
return dest_index;
}
+ // we can read more data from the unbuffered stream
+ if (dest_space < buffer_size) {
+ self.start_index = 0;
+ self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
+ } else {
+ // asking for so much data that buffering is actually less efficient.
+ // forward the request directly to the unbuffered stream
+ const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
+ return dest_index + amt_read;
+ }
}
+
const copy_amount = math.min(dest_space, amt_buffered);
const copy_end_index = self.start_index + copy_amount;
mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
@@ -350,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
};
}
+test "io.BufferedInStream" {
+ const OneByteReadInStream = struct {
+ const Error = error{NoError};
+ const Stream = InStream(Error);
+
+ stream: Stream,
+ str: []const u8,
+ curr: usize,
+
+ fn init(str: []const u8) @This() {
+ return @This(){
+ .stream = Stream{ .readFn = readFn },
+ .str = str,
+ .curr = 0,
+ };
+ }
+
+ fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
+ const self = @fieldParentPtr(@This(), "stream", in_stream);
+ if (self.str.len <= self.curr or dest.len == 0)
+ return 0;
+
+ dest[0] = self.str[self.curr];
+ self.curr += 1;
+ return 1;
+ }
+ };
+
+ var buf: [100]u8 = undefined;
+ const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
+
+ const str = "This is a test";
+ var one_byte_stream = OneByteReadInStream.init(str);
+ var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream);
+ const stream = &buf_in_stream.stream;
+
+ const res = try stream.readAllAlloc(allocator, str.len + 1);
+ testing.expectEqualSlices(u8, str, res);
+}
+
/// Creates a stream which supports 'un-reading' data, so that it can be read again.
/// This makes look-ahead style parsing much easier.
pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
@@ -446,6 +507,153 @@ pub const SliceInStream = struct {
}
};
+/// Creates a stream which allows for reading bit fields from another stream
+pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
+ return struct {
+ const Self = @This();
+
+ in_stream: *Stream,
+ bit_buffer: u7,
+ bit_count: u3,
+ stream: Stream,
+
+ pub const Stream = InStream(Error);
+ const u8_bit_count = comptime meta.bitCount(u8);
+ const u7_bit_count = comptime meta.bitCount(u7);
+ const u4_bit_count = comptime meta.bitCount(u4);
+
+ pub fn init(in_stream: *Stream) Self {
+ return Self{
+ .in_stream = in_stream,
+ .bit_buffer = 0,
+ .bit_count = 0,
+ .stream = Stream{ .readFn = read },
+ };
+ }
+
+ /// Reads `bits` bits from the stream and returns a specified unsigned int type
+ /// containing them in the least significant end, returning an error if the
+ /// specified number of bits could not be read.
+ pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U {
+ var n: usize = undefined;
+ const result = try self.readBits(U, bits, &n);
+ if (n < bits) return error.EndOfStream;
+ return result;
+ }
+
+ /// Reads `bits` bits from the stream and returns a specified unsigned int type
+ /// containing them in the least significant end. The number of bits successfully
+ /// read is placed in `out_bits`, as reaching the end of the stream is not an error.
+ pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U {
+ comptime assert(trait.isUnsignedInt(U));
+
+ //by extending the buffer to a minimum of u8 we can cover a number of edge cases
+ // related to shifting and casting.
+ const u_bit_count = comptime meta.bitCount(U);
+ const buf_bit_count = bc: {
+ assert(u_bit_count >= bits);
+ break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
+ };
+ const Buf = @IntType(false, buf_bit_count);
+ const BufShift = math.Log2Int(Buf);
+
+ out_bits.* = usize(0);
+ if (U == u0 or bits == 0) return 0;
+ var out_buffer = Buf(0);
+
+ if (self.bit_count > 0) {
+ const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count;
+ const shift = u7_bit_count - n;
+ switch (endian) {
+ builtin.Endian.Big => {
+ out_buffer = Buf(self.bit_buffer >> shift);
+ self.bit_buffer <<= n;
+ },
+ builtin.Endian.Little => {
+ const value = (self.bit_buffer << shift) >> shift;
+ out_buffer = Buf(value);
+ self.bit_buffer >>= n;
+ },
+ }
+ self.bit_count -= n;
+ out_bits.* = n;
+ }
+ //at this point we know bit_buffer is empty
+
+ //copy bytes until we have enough bits, then leave the rest in bit_buffer
+ while (out_bits.* < bits) {
+ const n = bits - out_bits.*;
+ const next_byte = self.in_stream.readByte() catch |err| {
+ if (err == error.EndOfStream) {
+ return @intCast(U, out_buffer);
+ }
+ //@BUG: See #1810. Not sure if the bug is that I have to do this for some
+ // streams, or that I don't for streams with emtpy errorsets.
+ return @errSetCast(Error, err);
+ };
+
+ switch (endian) {
+ builtin.Endian.Big => {
+ if (n >= u8_bit_count) {
+ out_buffer <<= @intCast(u3, u8_bit_count - 1);
+ out_buffer <<= 1;
+ out_buffer |= Buf(next_byte);
+ out_bits.* += u8_bit_count;
+ continue;
+ }
+
+ const shift = @intCast(u3, u8_bit_count - n);
+ out_buffer <<= @intCast(BufShift, n);
+ out_buffer |= Buf(next_byte >> shift);
+ out_bits.* += n;
+ self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1));
+ self.bit_count = shift;
+ },
+ builtin.Endian.Little => {
+ if (n >= u8_bit_count) {
+ out_buffer |= Buf(next_byte) << @intCast(BufShift, out_bits.*);
+ out_bits.* += u8_bit_count;
+ continue;
+ }
+
+ const shift = @intCast(u3, u8_bit_count - n);
+ const value = (next_byte << shift) >> shift;
+ out_buffer |= Buf(value) << @intCast(BufShift, out_bits.*);
+ out_bits.* += n;
+ self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n));
+ self.bit_count = shift;
+ },
+ }
+ }
+
+ return @intCast(U, out_buffer);
+ }
+
+ pub fn alignToByte(self: *Self) void {
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+
+ pub fn read(self_stream: *Stream, buffer: []u8) Error!usize {
+ var self = @fieldParentPtr(Self, "stream", self_stream);
+
+ var out_bits: usize = undefined;
+ var out_bits_total = usize(0);
+ //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced
+ if (self.bit_count > 0) {
+ for (buffer) |*b, i| {
+ b.* = try self.readBits(u8, u8_bit_count, &out_bits);
+ out_bits_total += out_bits;
+ }
+ const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0);
+ return (out_bits_total / u8_bit_count) + incomplete_byte;
+ }
+
+ return self.in_stream.read(buffer);
+ }
+ };
+}
+
/// This is a simple OutStream that writes to a slice, and returns an error
/// when it runs out of space.
pub const SliceOutStream = struct {
@@ -498,7 +706,7 @@ test "io.SliceOutStream" {
const stream = &slice_stream.stream;
try stream.print("{}{}!", "Hello", "World");
- debug.assert(mem.eql(u8, "HelloWorld!", slice_stream.getWritten()));
+ testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten());
}
var null_out_stream_state = NullOutStream.init();
@@ -560,7 +768,7 @@ test "io.CountingOutStream" {
const bytes = "yay" ** 10000;
stream.write(bytes) catch unreachable;
- debug.assert(counting_stream.bytes_written == bytes.len);
+ testing.expect(counting_stream.bytes_written == bytes.len);
}
pub fn BufferedOutStream(comptime Error: type) type {
@@ -639,6 +847,135 @@ pub const BufferOutStream = struct {
}
};
+/// Creates a stream which allows for writing bit fields to another stream
+pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
+ return struct {
+ const Self = @This();
+
+ out_stream: *Stream,
+ bit_buffer: u8,
+ bit_count: u4,
+ stream: Stream,
+
+ pub const Stream = OutStream(Error);
+ const u8_bit_count = comptime meta.bitCount(u8);
+ const u4_bit_count = comptime meta.bitCount(u4);
+
+ pub fn init(out_stream: *Stream) Self {
+ return Self{
+ .out_stream = out_stream,
+ .bit_buffer = 0,
+ .bit_count = 0,
+ .stream = Stream{ .writeFn = write },
+ };
+ }
+
+ /// Write the specified number of bits to the stream from the least significant bits of
+ /// the specified unsigned int value. Bits will only be written to the stream when there
+ /// are enough to fill a byte.
+ pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
+ if (bits == 0) return;
+
+ const U = @typeOf(value);
+ comptime assert(trait.isUnsignedInt(U));
+
+ //by extending the buffer to a minimum of u8 we can cover a number of edge cases
+ // related to shifting and casting.
+ const u_bit_count = comptime meta.bitCount(U);
+ const buf_bit_count = bc: {
+ assert(u_bit_count >= bits);
+ break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
+ };
+ const Buf = @IntType(false, buf_bit_count);
+ const BufShift = math.Log2Int(Buf);
+
+ const buf_value = @intCast(Buf, value);
+
+ const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
+ var in_buffer = switch (endian) {
+ builtin.Endian.Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
+ builtin.Endian.Little => buf_value,
+ };
+ var in_bits = bits;
+
+ if (self.bit_count > 0) {
+ const bits_remaining = u8_bit_count - self.bit_count;
+ const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
+ switch (endian) {
+ builtin.Endian.Big => {
+ const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
+ const v = @intCast(u8, in_buffer >> shift);
+ self.bit_buffer |= v;
+ in_buffer <<= n;
+ },
+ builtin.Endian.Little => {
+ const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
+ self.bit_buffer |= v;
+ in_buffer >>= n;
+ },
+ }
+ self.bit_count += n;
+ in_bits -= n;
+
+ //if we didn't fill the buffer, it's because bits < bits_remaining;
+ if (self.bit_count != u8_bit_count) return;
+ try self.out_stream.writeByte(self.bit_buffer);
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+ //at this point we know bit_buffer is empty
+
+ //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
+ while (in_bits >= u8_bit_count) {
+ switch (endian) {
+ builtin.Endian.Big => {
+ const v = @intCast(u8, in_buffer >> high_byte_shift);
+ try self.out_stream.writeByte(v);
+ in_buffer <<= @intCast(u3, u8_bit_count - 1);
+ in_buffer <<= 1;
+ },
+ builtin.Endian.Little => {
+ const v = @truncate(u8, in_buffer);
+ try self.out_stream.writeByte(v);
+ in_buffer >>= @intCast(u3, u8_bit_count - 1);
+ in_buffer >>= 1;
+ },
+ }
+ in_bits -= u8_bit_count;
+ }
+
+ if (in_bits > 0) {
+ self.bit_count = @intCast(u4, in_bits);
+ self.bit_buffer = switch (endian) {
+ builtin.Endian.Big => @truncate(u8, in_buffer >> high_byte_shift),
+ builtin.Endian.Little => @truncate(u8, in_buffer),
+ };
+ }
+ }
+
+ /// Flush any remaining bits to the stream.
+ pub fn flushBits(self: *Self) Error!void {
+ if (self.bit_count == 0) return;
+ try self.out_stream.writeByte(self.bit_buffer);
+ self.bit_buffer = 0;
+ self.bit_count = 0;
+ }
+
+ pub fn write(self_stream: *Stream, buffer: []const u8) Error!void {
+ var self = @fieldParentPtr(Self, "stream", self_stream);
+
+ //@NOTE: I'm not sure this is a good idea, maybe flushBits should be forced
+ if (self.bit_count > 0) {
+ for (buffer) |b, i|
+ try self.writeBits(b, u8_bit_count);
+ return;
+ }
+
+ return self.out_stream.write(buffer);
+ }
+ };
+}
+
pub const BufferedAtomicFile = struct {
atomic_file: os.AtomicFile,
file_stream: os.File.OutStream,
@@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct {
pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
// TODO with well defined copy elision we don't need this allocation
- var self = try allocator.create(BufferedAtomicFile{
+ var self = try allocator.create(BufferedAtomicFile);
+ self.* = BufferedAtomicFile{
.atomic_file = undefined,
.file_stream = undefined,
.buffered_stream = undefined,
.allocator = allocator,
- });
+ };
errdefer allocator.destroy(self);
self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
@@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct {
}
};
-test "import io tests" {
- comptime {
- _ = @import("io_test.zig");
- }
-}
-
pub fn readLine(buf: *std.Buffer) ![]u8 {
var stdin = try getStdIn();
var stdin_stream = stdin.inStream();
@@ -721,10 +1053,10 @@ test "io.readLineFrom" {
);
const stream = &mem_stream.stream;
- debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
- debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
- debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
- debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
+ testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf));
+ testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf));
+ testing.expectError(error.EndOfStream, readLineFrom(stream, &buf));
+ testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice());
}
pub fn readLineSlice(slice: []u8) ![]u8 {
@@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" {
);
const stream = &mem_stream.stream;
- debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
- debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
+ testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]));
+ testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..]));
}
+
+/// Creates a deserializer that deserializes types from any stream.
+/// If `is_packed` is true, the data stream is treated as bit-packed,
+/// otherwise data is expected to be packed to the smallest byte.
+/// Types may implement a custom deserialization routine with a
+/// function named `deserialize` in the form of:
+/// pub fn deserialize(self: *Self, deserializer: var) !void
+/// which will be called when the deserializer is used to deserialize
+/// that type. It will pass a pointer to the type instance to deserialize
+/// into and a pointer to the deserializer struct.
+pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime Error: type) type {
+ return struct {
+ const Self = @This();
+
+ in_stream: if (is_packed) BitInStream(endian, Stream.Error) else *Stream,
+
+ pub const Stream = InStream(Error);
+
+ pub fn init(in_stream: *Stream) Self {
+ return Self{ .in_stream = switch (is_packed) {
+ true => BitInStream(endian, Stream.Error).init(in_stream),
+ else => in_stream,
+ } };
+ }
+
+ pub fn alignToByte(self: *Self) void {
+ if (!is_packed) return;
+ self.in_stream.alignToByte();
+ }
+
+ //@BUG: inferred error issue. See: #1386
+ fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
+ comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
+
+ const u8_bit_count = 8;
+ const t_bit_count = comptime meta.bitCount(T);
+
+ const U = @IntType(false, t_bit_count);
+ const Log2U = math.Log2Int(U);
+ const int_size = (U.bit_count + 7) / 8;
+
+ if (is_packed) {
+ const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
+ return @bitCast(T, result);
+ }
+
+ var buffer: [int_size]u8 = undefined;
+ const read_size = try self.in_stream.read(buffer[0..]);
+ if (read_size < int_size) return error.EndOfStream;
+
+ if (int_size == 1) {
+ if (t_bit_count == 8) return @bitCast(T, buffer[0]);
+ const PossiblySignedByte = @IntType(T.is_signed, 8);
+ return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
+ }
+
+ var result = U(0);
+ for (buffer) |byte, i| {
+ switch (endian) {
+ builtin.Endian.Big => {
+ result = (result << u8_bit_count) | byte;
+ },
+ builtin.Endian.Little => {
+ result |= U(byte) << @intCast(Log2U, u8_bit_count * i);
+ },
+ }
+ }
+
+ return @bitCast(T, result);
+ }
+
+ //@TODO: Replace this with @unionInit or whatever when it is added
+ // see: #1315
+ fn setTag(ptr: var, tag: var) void {
+ const T = @typeOf(ptr);
+ comptime assert(trait.isPtrTo(builtin.TypeId.Union)(T));
+ const U = meta.Child(T);
+
+ const info = @typeInfo(U).Union;
+ if (info.tag_type) |TagType| {
+ comptime assert(TagType == @typeOf(tag));
+
+ var ptr_tag = ptr: {
+ if (@alignOf(TagType) >= @alignOf(U)) break :ptr @ptrCast(*TagType, ptr);
+ const offset = comptime max: {
+ var max_field_size: comptime_int = 0;
+ for (info.fields) |field_info| {
+ const field_size = @sizeOf(field_info.field_type);
+ max_field_size = math.max(max_field_size, field_size);
+ }
+ break :max math.max(max_field_size, @alignOf(U));
+ };
+ break :ptr @intToPtr(*TagType, @ptrToInt(ptr) + offset);
+ };
+ ptr_tag.* = tag;
+ }
+ }
+
+ /// Deserializes and returns data of the specified type from the stream
+ pub fn deserialize(self: *Self, comptime T: type) !T {
+ var value: T = undefined;
+ try self.deserializeInto(&value);
+ return value;
+ }
+
+ /// Deserializes data into the type pointed to by `ptr`
+ pub fn deserializeInto(self: *Self, ptr: var) !void {
+ const T = @typeOf(ptr);
+ comptime assert(trait.is(builtin.TypeId.Pointer)(T));
+
+ if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) {
+ for (ptr) |*v|
+ try self.deserializeInto(v);
+ return;
+ }
+
+ comptime assert(trait.isSingleItemPtr(T));
+
+ const C = comptime meta.Child(T);
+ const child_type_id = @typeId(C);
+
+ //custom deserializer: fn(self: *Self, deserializer: var) !void
+ if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
+
+ if (comptime trait.isPacked(C) and !is_packed) {
+ var packed_deserializer = Deserializer(endian, true, Error).init(self.in_stream);
+ return packed_deserializer.deserializeInto(ptr);
+ }
+
+ switch (child_type_id) {
+ builtin.TypeId.Void => return,
+ builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
+ builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C),
+ builtin.TypeId.Struct => {
+ const info = @typeInfo(C).Struct;
+
+ inline for (info.fields) |*field_info| {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+
+ if (FieldType == void or FieldType == u0) continue;
+
+ //it doesn't make any sense to read pointers
+ if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
+ @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
+ @typeName(C) ++ " because it " ++ "is of pointer-type " ++
+ @typeName(FieldType) ++ ".");
+ }
+
+ try self.deserializeInto(&@field(ptr, name));
+ }
+ },
+ builtin.TypeId.Union => {
+ const info = @typeInfo(C).Union;
+ if (info.tag_type) |TagType| {
+ //we avoid duplicate iteration over the enum tags
+ // by getting the int directly and casting it without
+ // safety. If it is bad, it will be caught anyway.
+ const TagInt = @TagType(TagType);
+ const tag = try self.deserializeInt(TagInt);
+
+ {
+ @setRuntimeSafety(false);
+ //See: #1315
+ setTag(ptr, @intToEnum(TagType, tag));
+ }
+
+ inline for (info.fields) |field_info| {
+ if (field_info.enum_field.?.value == tag) {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+ @field(ptr, name) = FieldType(undefined);
+ try self.deserializeInto(&@field(ptr, name));
+ return;
+ }
+ }
+ //This is reachable if the enum data is bad
+ return error.InvalidEnumTag;
+ }
+ @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
+ " because it is an untagged union Use a custom deserialize().");
+ },
+ builtin.TypeId.Optional => {
+ const OC = comptime meta.Child(C);
+ const exists = (try self.deserializeInt(u1)) > 0;
+ if (!exists) {
+ ptr.* = null;
+ return;
+ }
+
+ //The way non-pointer optionals are implemented ensures a pointer to them
+ // will point to the value. The flag is stored at the end of that data.
+ var val_ptr = @ptrCast(*OC, ptr);
+ try self.deserializeInto(val_ptr);
+ //This bit ensures the null flag isn't set. Any actual copying should be
+ // optimized out... I hope.
+ ptr.* = val_ptr.*;
+ },
+ builtin.TypeId.Enum => {
+ var value = try self.deserializeInt(@TagType(C));
+ ptr.* = try meta.intToEnum(C, value);
+ },
+ else => {
+ @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented).");
+ },
+ }
+ }
+ };
+}
+
+/// Creates a serializer that serializes types to any stream.
+/// If `is_packed` is true, the data will be bit-packed into the stream.
+/// Note that the you must call `serializer.flush()` when you are done
+/// writing bit-packed data in order ensure any unwritten bits are committed.
+/// If `is_packed` is false, data is packed to the smallest byte. In the case
+/// of packed structs, the struct will written bit-packed and with the specified
+/// endianess, after which data will resume being written at the next byte boundary.
+/// Types may implement a custom serialization routine with a
+/// function named `serialize` in the form of:
+/// pub fn serialize(self: Self, serializer: var) !void
+/// which will be called when the serializer is used to serialize that type. It will
+/// pass a const pointer to the type instance to be serialized and a pointer
+/// to the serializer struct.
+pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, comptime Error: type) type {
+ return struct {
+ const Self = @This();
+
+ out_stream: if (is_packed) BitOutStream(endian, Stream.Error) else *Stream,
+
+ pub const Stream = OutStream(Error);
+
+ pub fn init(out_stream: *Stream) Self {
+ return Self{ .out_stream = switch (is_packed) {
+ true => BitOutStream(endian, Stream.Error).init(out_stream),
+ else => out_stream,
+ } };
+ }
+
+ /// Flushes any unwritten bits to the stream
+ pub fn flush(self: *Self) Error!void {
+ if (is_packed) return self.out_stream.flushBits();
+ }
+
+ fn serializeInt(self: *Self, value: var) Error!void {
+ const T = @typeOf(value);
+ comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
+
+ const t_bit_count = comptime meta.bitCount(T);
+ const u8_bit_count = comptime meta.bitCount(u8);
+
+ const U = @IntType(false, t_bit_count);
+ const Log2U = math.Log2Int(U);
+ const int_size = (U.bit_count + 7) / 8;
+
+ const u_value = @bitCast(U, value);
+
+ if (is_packed) return self.out_stream.writeBits(u_value, t_bit_count);
+
+ var buffer: [int_size]u8 = undefined;
+ if (int_size == 1) buffer[0] = u_value;
+
+ for (buffer) |*byte, i| {
+ const idx = switch (endian) {
+ builtin.Endian.Big => int_size - i - 1,
+ builtin.Endian.Little => i,
+ };
+ const shift = @intCast(Log2U, idx * u8_bit_count);
+ const v = u_value >> shift;
+ byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
+ }
+
+ try self.out_stream.write(buffer);
+ }
+
+ /// Serializes the passed value into the stream
+ pub fn serialize(self: *Self, value: var) Error!void {
+ const T = comptime @typeOf(value);
+
+ if (comptime trait.isIndexable(T)) {
+ for (value) |v|
+ try self.serialize(v);
+ return;
+ }
+
+ //custom serializer: fn(self: Self, serializer: var) !void
+ if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
+
+ if (comptime trait.isPacked(T) and !is_packed) {
+ var packed_serializer = Serializer(endian, true, Error).init(self.out_stream);
+ try packed_serializer.serialize(value);
+ try packed_serializer.flush();
+ return;
+ }
+
+ switch (@typeId(T)) {
+ builtin.TypeId.Void => return,
+ builtin.TypeId.Bool => try self.serializeInt(u1(@boolToInt(value))),
+ builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value),
+ builtin.TypeId.Struct => {
+ const info = @typeInfo(T);
+
+ inline for (info.Struct.fields) |*field_info| {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+
+ if (FieldType == void or FieldType == u0) continue;
+
+ //It doesn't make sense to write pointers
+ if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
+ @compileError("Will not " ++ "serialize field " ++ name ++
+ " of struct " ++ @typeName(T) ++ " because it " ++
+ "is of pointer-type " ++ @typeName(FieldType) ++ ".");
+ }
+ try self.serialize(@field(value, name));
+ }
+ },
+ builtin.TypeId.Union => {
+ const info = @typeInfo(T).Union;
+ if (info.tag_type) |TagType| {
+ const active_tag = meta.activeTag(value);
+ try self.serialize(active_tag);
+ //This inline loop is necessary because active_tag is a runtime
+ // value, but @field requires a comptime value. Our alternative
+ // is to check each field for a match
+ inline for (info.fields) |field_info| {
+ if (field_info.enum_field.?.value == @enumToInt(active_tag)) {
+ const name = field_info.name;
+ const FieldType = field_info.field_type;
+ try self.serialize(@field(value, name));
+ return;
+ }
+ }
+ unreachable;
+ }
+ @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
+ " because it is an untagged union Use a custom serialize().");
+ },
+ builtin.TypeId.Optional => {
+ if (value == null) {
+ try self.serializeInt(u1(@boolToInt(false)));
+ return;
+ }
+ try self.serializeInt(u1(@boolToInt(true)));
+
+ const OC = comptime meta.Child(T);
+
+ //The way non-pointer optionals are implemented ensures a pointer to them
+ // will point to the value. The flag is stored at the end of that data.
+ var val_ptr = @ptrCast(*const OC, &value);
+ try self.serialize(val_ptr.*);
+ },
+ builtin.TypeId.Enum => {
+ try self.serializeInt(@enumToInt(value));
+ },
+ else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."),
+ }
+ }
+ };
+}
+
+test "import io tests" {
+ comptime {
+ _ = @import("io_test.zig");
+ }
+}
+
diff --git a/std/io_test.zig b/std/io_test.zig
index 5224199527..fb6e0ae7e9 100644
--- a/std/io_test.zig
+++ b/std/io_test.zig
@@ -1,8 +1,10 @@
const std = @import("index.zig");
const io = std.io;
+const meta = std.meta;
+const trait = std.trait;
const DefaultPrng = std.rand.DefaultPrng;
-const assert = std.debug.assert;
-const assertError = std.debug.assertError;
+const expect = std.testing.expect;
+const expectError = std.testing.expectError;
const mem = std.mem;
const os = std.os;
const builtin = @import("builtin");
@@ -33,7 +35,7 @@ test "write a file, read it, then delete it" {
const file_size = try file.getEndPos();
const expected_file_size = "begin".len + data.len + "end".len;
- assert(file_size == expected_file_size);
+ expect(file_size == expected_file_size);
var file_in_stream = file.inStream();
var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
@@ -41,9 +43,9 @@ test "write a file, read it, then delete it" {
const contents = try st.readAllAlloc(allocator, 2 * 1024);
defer allocator.free(contents);
- assert(mem.eql(u8, contents[0.."begin".len], "begin"));
- assert(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
- assert(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
+ expect(mem.eql(u8, contents[0.."begin".len], "begin"));
+ expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
+ expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
}
try os.deleteFile(tmp_file_name);
}
@@ -59,7 +61,7 @@ test "BufferOutStream" {
const y: i32 = 1234;
try buf_stream.print("x: {}\ny: {}\n", x, y);
- assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
+ expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
}
test "SliceInStream" {
@@ -69,15 +71,15 @@ test "SliceInStream" {
var dest: [4]u8 = undefined;
var read = try ss.stream.read(dest[0..4]);
- assert(read == 4);
- assert(mem.eql(u8, dest[0..4], bytes[0..4]));
+ expect(read == 4);
+ expect(mem.eql(u8, dest[0..4], bytes[0..4]));
read = try ss.stream.read(dest[0..4]);
- assert(read == 3);
- assert(mem.eql(u8, dest[0..3], bytes[4..7]));
+ expect(read == 3);
+ expect(mem.eql(u8, dest[0..3], bytes[4..7]));
read = try ss.stream.read(dest[0..4]);
- assert(read == 0);
+ expect(read == 0);
}
test "PeekStream" {
@@ -91,26 +93,26 @@ test "PeekStream" {
ps.putBackByte(10);
var read = try ps.stream.read(dest[0..4]);
- assert(read == 4);
- assert(dest[0] == 10);
- assert(dest[1] == 9);
- assert(mem.eql(u8, dest[2..4], bytes[0..2]));
+ expect(read == 4);
+ expect(dest[0] == 10);
+ expect(dest[1] == 9);
+ expect(mem.eql(u8, dest[2..4], bytes[0..2]));
read = try ps.stream.read(dest[0..4]);
- assert(read == 4);
- assert(mem.eql(u8, dest[0..4], bytes[2..6]));
+ expect(read == 4);
+ expect(mem.eql(u8, dest[0..4], bytes[2..6]));
read = try ps.stream.read(dest[0..4]);
- assert(read == 2);
- assert(mem.eql(u8, dest[0..2], bytes[6..8]));
+ expect(read == 2);
+ expect(mem.eql(u8, dest[0..2], bytes[6..8]));
ps.putBackByte(11);
ps.putBackByte(12);
read = try ps.stream.read(dest[0..4]);
- assert(read == 2);
- assert(dest[0] == 12);
- assert(dest[1] == 11);
+ expect(read == 2);
+ expect(dest[0] == 12);
+ expect(dest[1] == 11);
}
test "SliceOutStream" {
@@ -118,17 +120,461 @@ test "SliceOutStream" {
var ss = io.SliceOutStream.init(buffer[0..]);
try ss.stream.write("Hello");
- assert(mem.eql(u8, ss.getWritten(), "Hello"));
+ expect(mem.eql(u8, ss.getWritten(), "Hello"));
try ss.stream.write("world");
- assert(mem.eql(u8, ss.getWritten(), "Helloworld"));
+ expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
- assertError(ss.stream.write("!"), error.OutOfSpace);
- assert(mem.eql(u8, ss.getWritten(), "Helloworld"));
+ expectError(error.OutOfSpace, ss.stream.write("!"));
+ expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
ss.reset();
- assert(ss.getWritten().len == 0);
+ expect(ss.getWritten().len == 0);
- assertError(ss.stream.write("Hello world!"), error.OutOfSpace);
- assert(mem.eql(u8, ss.getWritten(), "Hello worl"));
+ expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
+ expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
+}
+
+test "BitInStream" {
+ const mem_be = []u8{ 0b11001101, 0b00001011 };
+ const mem_le = []u8{ 0b00011101, 0b10010101 };
+
+ var mem_in_be = io.SliceInStream.init(mem_be[0..]);
+ const InError = io.SliceInStream.Error;
+ var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
+
+ var out_bits: usize = undefined;
+
+ expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
+ expect(out_bits == 1);
+ expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
+ expect(out_bits == 2);
+ expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
+ expect(out_bits == 3);
+ expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
+ expect(out_bits == 4);
+ expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
+ expect(out_bits == 5);
+ expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
+ expect(out_bits == 1);
+
+ mem_in_be.pos = 0;
+ bit_stream_be.bit_count = 0;
+ expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
+ expect(out_bits == 15);
+
+ mem_in_be.pos = 0;
+ bit_stream_be.bit_count = 0;
+ expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
+ expect(out_bits == 16);
+
+ _ = try bit_stream_be.readBits(u0, 0, &out_bits);
+
+ expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
+ expect(out_bits == 0);
+ expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
+
+ var mem_in_le = io.SliceInStream.init(mem_le[0..]);
+ var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
+
+ expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
+ expect(out_bits == 1);
+ expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
+ expect(out_bits == 2);
+ expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
+ expect(out_bits == 3);
+ expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
+ expect(out_bits == 4);
+ expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
+ expect(out_bits == 5);
+ expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
+ expect(out_bits == 1);
+
+ mem_in_le.pos = 0;
+ bit_stream_le.bit_count = 0;
+ expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
+ expect(out_bits == 15);
+
+ mem_in_le.pos = 0;
+ bit_stream_le.bit_count = 0;
+ expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
+ expect(out_bits == 16);
+
+ _ = try bit_stream_le.readBits(u0, 0, &out_bits);
+
+ expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
+ expect(out_bits == 0);
+ expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
+}
+
+test "BitOutStream" {
+ var mem_be = []u8{0} ** 2;
+ var mem_le = []u8{0} ** 2;
+
+ var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
+ const OutError = io.SliceOutStream.Error;
+ var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
+
+ try bit_stream_be.writeBits(u2(1), 1);
+ try bit_stream_be.writeBits(u5(2), 2);
+ try bit_stream_be.writeBits(u128(3), 3);
+ try bit_stream_be.writeBits(u8(4), 4);
+ try bit_stream_be.writeBits(u9(5), 5);
+ try bit_stream_be.writeBits(u1(1), 1);
+
+ expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
+
+ mem_out_be.pos = 0;
+
+ try bit_stream_be.writeBits(u15(0b110011010000101), 15);
+ try bit_stream_be.flushBits();
+ expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
+
+ mem_out_be.pos = 0;
+ try bit_stream_be.writeBits(u32(0b110011010000101), 16);
+ expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
+
+ try bit_stream_be.writeBits(u0(0), 0);
+
+ var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
+ var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
+
+ try bit_stream_le.writeBits(u2(1), 1);
+ try bit_stream_le.writeBits(u5(2), 2);
+ try bit_stream_le.writeBits(u128(3), 3);
+ try bit_stream_le.writeBits(u8(4), 4);
+ try bit_stream_le.writeBits(u9(5), 5);
+ try bit_stream_le.writeBits(u1(1), 1);
+
+ expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
+
+ mem_out_le.pos = 0;
+ try bit_stream_le.writeBits(u15(0b110011010000101), 15);
+ try bit_stream_le.flushBits();
+ expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
+
+ mem_out_le.pos = 0;
+ try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
+ expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
+
+ try bit_stream_le.writeBits(u0(0), 0);
+}
+
+test "BitStreams with File Stream" {
+ const tmp_file_name = "temp_test_file.txt";
+ {
+ var file = try os.File.openWrite(tmp_file_name);
+ defer file.close();
+
+ var file_out = file.outStream();
+ var file_out_stream = &file_out.stream;
+ const OutError = os.File.WriteError;
+ var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
+
+ try bit_stream.writeBits(u2(1), 1);
+ try bit_stream.writeBits(u5(2), 2);
+ try bit_stream.writeBits(u128(3), 3);
+ try bit_stream.writeBits(u8(4), 4);
+ try bit_stream.writeBits(u9(5), 5);
+ try bit_stream.writeBits(u1(1), 1);
+ try bit_stream.flushBits();
+ }
+ {
+ var file = try os.File.openRead(tmp_file_name);
+ defer file.close();
+
+ var file_in = file.inStream();
+ var file_in_stream = &file_in.stream;
+ const InError = os.File.ReadError;
+ var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
+
+ var out_bits: usize = undefined;
+
+ expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
+ expect(out_bits == 1);
+ expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
+ expect(out_bits == 2);
+ expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
+ expect(out_bits == 3);
+ expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
+ expect(out_bits == 4);
+ expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
+ expect(out_bits == 5);
+ expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
+ expect(out_bits == 1);
+
+ expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
+ }
+ try os.deleteFile(tmp_file_name);
+}
+
+fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
+ //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
+ const max_test_bitsize = 128;
+
+ const total_bytes = comptime blk: {
+ var bytes = 0;
+ comptime var i = 0;
+ while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
+ break :blk bytes * 2;
+ };
+
+ var data_mem: [total_bytes]u8 = undefined;
+ var out = io.SliceOutStream.init(data_mem[0..]);
+ const OutError = io.SliceOutStream.Error;
+ var out_stream = &out.stream;
+ var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
+
+ var in = io.SliceInStream.init(data_mem[0..]);
+ const InError = io.SliceInStream.Error;
+ var in_stream = &in.stream;
+ var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
+
+ comptime var i = 0;
+ inline while (i <= max_test_bitsize) : (i += 1) {
+ const U = @IntType(false, i);
+ const S = @IntType(true, i);
+ try serializer.serializeInt(U(i));
+ if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
+ }
+ try serializer.flush();
+
+ i = 0;
+ inline while (i <= max_test_bitsize) : (i += 1) {
+ const U = @IntType(false, i);
+ const S = @IntType(true, i);
+ const x = try deserializer.deserializeInt(U);
+ const y = try deserializer.deserializeInt(S);
+ expect(x == U(i));
+ if (i != 0) expect(y == S(-1)) else expect(y == 0);
+ }
+
+ const u8_bit_count = comptime meta.bitCount(u8);
+ //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
+ //and we have each for unsigned and signed, so * 2
+ const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
+ const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
+ const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
+
+ expect(in.pos == if (is_packed) total_packed_bytes else total_bytes);
+
+ //Verify that empty error set works with serializer.
+ //deserializer is covered by SliceInStream
+ const NullError = io.NullOutStream.Error;
+ var null_out = io.NullOutStream.init();
+ var null_out_stream = &null_out.stream;
+ var null_serializer = io.Serializer(endian, is_packed, NullError).init(null_out_stream);
+ try null_serializer.serialize(data_mem[0..]);
+ try null_serializer.flush();
+}
+
+test "Serializer/Deserializer Int" {
+ try testIntSerializerDeserializer(builtin.Endian.Big, false);
+ try testIntSerializerDeserializer(builtin.Endian.Little, false);
+ try testIntSerializerDeserializer(builtin.Endian.Big, true);
+ try testIntSerializerDeserializer(builtin.Endian.Little, true);
+}
+
+fn testIntSerializerDeserializerInfNaN(comptime endian: builtin.Endian,
+ comptime is_packed: bool) !void
+{
+ const mem_size = (16*2 + 32*2 + 64*2 + 128*2) / comptime meta.bitCount(u8);
+ var data_mem: [mem_size]u8 = undefined;
+
+ var out = io.SliceOutStream.init(data_mem[0..]);
+ const OutError = io.SliceOutStream.Error;
+ var out_stream = &out.stream;
+ var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
+
+ var in = io.SliceInStream.init(data_mem[0..]);
+ const InError = io.SliceInStream.Error;
+ var in_stream = &in.stream;
+ var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
+
+ //@TODO: isInf/isNan not currently implemented for f128.
+ try serializer.serialize(std.math.nan(f16));
+ try serializer.serialize(std.math.inf(f16));
+ try serializer.serialize(std.math.nan(f32));
+ try serializer.serialize(std.math.inf(f32));
+ try serializer.serialize(std.math.nan(f64));
+ try serializer.serialize(std.math.inf(f64));
+ //try serializer.serialize(std.math.nan(f128));
+ //try serializer.serialize(std.math.inf(f128));
+ const nan_check_f16 = try deserializer.deserialize(f16);
+ const inf_check_f16 = try deserializer.deserialize(f16);
+ const nan_check_f32 = try deserializer.deserialize(f32);
+ const inf_check_f32 = try deserializer.deserialize(f32);
+ const nan_check_f64 = try deserializer.deserialize(f64);
+ const inf_check_f64 = try deserializer.deserialize(f64);
+ //const nan_check_f128 = try deserializer.deserialize(f128);
+ //const inf_check_f128 = try deserializer.deserialize(f128);
+ expect(std.math.isNan(nan_check_f16));
+ expect(std.math.isInf(inf_check_f16));
+ expect(std.math.isNan(nan_check_f32));
+ expect(std.math.isInf(inf_check_f32));
+ expect(std.math.isNan(nan_check_f64));
+ expect(std.math.isInf(inf_check_f64));
+ //expect(std.math.isNan(nan_check_f128));
+ //expect(std.math.isInf(inf_check_f128));
+}
+
+test "Serializer/Deserializer Int: Inf/NaN" {
+ try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, false);
+ try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, false);
+ try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, true);
+ try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, true);
+}
+
+fn testAlternateSerializer(self: var, serializer: var) !void {
+ try serializer.serialize(self.f_f16);
+}
+
+fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
+ const ColorType = enum(u4) {
+ RGB8 = 1,
+ RA16 = 2,
+ R32 = 3,
+ };
+
+ const TagAlign = union(enum(u32)) {
+ A: u8,
+ B: u8,
+ C: u8,
+ };
+
+ const Color = union(ColorType) {
+ RGB8: struct {
+ r: u8,
+ g: u8,
+ b: u8,
+ a: u8,
+ },
+ RA16: struct {
+ r: u16,
+ a: u16,
+ },
+ R32: u32,
+ };
+
+ const PackedStruct = packed struct {
+ f_i3: i3,
+ f_u2: u2,
+ };
+
+
+
+ //to test custom serialization
+ const Custom = struct {
+ f_f16: f16,
+ f_unused_u32: u32,
+
+ pub fn deserialize(self: *@This(), deserializer: var) !void {
+ try deserializer.deserializeInto(&self.f_f16);
+ self.f_unused_u32 = 47;
+ }
+
+ pub const serialize = testAlternateSerializer;
+ };
+
+ const MyStruct = struct {
+ f_i3: i3,
+ f_u8: u8,
+ f_tag_align: TagAlign,
+ f_u24: u24,
+ f_i19: i19,
+ f_void: void,
+ f_f32: f32,
+ f_f128: f128,
+ f_packed_0: PackedStruct,
+ f_i7arr: [10]i7,
+ f_of64n: ?f64,
+ f_of64v: ?f64,
+ f_color_type: ColorType,
+ f_packed_1: PackedStruct,
+ f_custom: Custom,
+ f_color: Color,
+ };
+
+ const my_inst = MyStruct{
+ .f_i3 = -1,
+ .f_u8 = 8,
+ .f_tag_align = TagAlign{ .B = 148 },
+ .f_u24 = 24,
+ .f_i19 = 19,
+ .f_void = {},
+ .f_f32 = 32.32,
+ .f_f128 = 128.128,
+ .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
+ .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ .f_of64n = null,
+ .f_of64v = 64.64,
+ .f_color_type = ColorType.R32,
+ .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
+ .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
+ .f_color = Color{ .R32 = 123822 },
+ };
+
+ var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
+ var out = io.SliceOutStream.init(data_mem[0..]);
+ const OutError = io.SliceOutStream.Error;
+ var out_stream = &out.stream;
+ var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
+
+ var in = io.SliceInStream.init(data_mem[0..]);
+ const InError = io.SliceInStream.Error;
+ var in_stream = &in.stream;
+ var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
+
+ try serializer.serialize(my_inst);
+
+ const my_copy = try deserializer.deserialize(MyStruct);
+ expect(meta.eql(my_copy, my_inst));
+}
+
+test "Serializer/Deserializer generic" {
+ try testSerializerDeserializer(builtin.Endian.Big, false);
+ try testSerializerDeserializer(builtin.Endian.Little, false);
+ try testSerializerDeserializer(builtin.Endian.Big, true);
+ try testSerializerDeserializer(builtin.Endian.Little, true);
+}
+
+fn testBadData(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
+ const E = enum(u14) {
+ One = 1,
+ Two = 2,
+ };
+
+ const A = struct {
+ e: E,
+ };
+
+ const C = union(E) {
+ One: u14,
+ Two: f16,
+ };
+
+ var data_mem: [4]u8 = undefined;
+ var out = io.SliceOutStream.init(data_mem[0..]);
+ const OutError = io.SliceOutStream.Error;
+ var out_stream = &out.stream;
+ var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
+
+ var in = io.SliceInStream.init(data_mem[0..]);
+ const InError = io.SliceInStream.Error;
+ var in_stream = &in.stream;
+ var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
+
+ try serializer.serialize(u14(3));
+ expectError(error.InvalidEnumTag, deserializer.deserialize(A));
+ out.pos = 0;
+ try serializer.serialize(u14(3));
+ try serializer.serialize(u14(88));
+ expectError(error.InvalidEnumTag, deserializer.deserialize(C));
+}
+
+test "Deserializer bad data" {
+ try testBadData(builtin.Endian.Big, false);
+ try testBadData(builtin.Endian.Little, false);
+ try testBadData(builtin.Endian.Big, true);
+ try testBadData(builtin.Endian.Little, true);
}
diff --git a/std/json.zig b/std/json.zig
index 4d07d7b89d..dd053e7635 100644
--- a/std/json.zig
+++ b/std/json.zig
@@ -4,6 +4,7 @@
const std = @import("index.zig");
const debug = std.debug;
+const testing = std.testing;
const mem = std.mem;
const maxInt = std.math.maxInt;
@@ -960,7 +961,7 @@ test "json.token" {
checkNext(&p, Token.Id.ObjectEnd);
checkNext(&p, Token.Id.ObjectEnd);
- debug.assert((try p.next()) == null);
+ testing.expect((try p.next()) == null);
}
// Validate a JSON string. This does not limit number precision so a decoder may not necessarily
@@ -981,7 +982,7 @@ pub fn validate(s: []const u8) bool {
}
test "json.validate" {
- debug.assert(validate("{}"));
+ testing.expect(validate("{}"));
}
const Allocator = std.mem.Allocator;
@@ -1344,7 +1345,7 @@ pub const Parser = struct {
return if (token.number_is_integer)
Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
else
- @panic("TODO: fmt.parseFloat not yet implemented");
+ Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) };
}
};
@@ -1365,7 +1366,8 @@ test "json.parser.dynamic" {
\\ },
\\ "Animated" : false,
\\ "IDs": [116, 943, 234, 38793],
- \\ "ArrayOfObject": [{"n": "m"}]
+ \\ "ArrayOfObject": [{"n": "m"}],
+ \\ "double": 1.3412
\\ }
\\}
;
@@ -1378,20 +1380,23 @@ test "json.parser.dynamic" {
var image = root.Object.get("Image").?.value;
const width = image.Object.get("Width").?.value;
- debug.assert(width.Integer == 800);
+ testing.expect(width.Integer == 800);
const height = image.Object.get("Height").?.value;
- debug.assert(height.Integer == 600);
+ testing.expect(height.Integer == 600);
const title = image.Object.get("Title").?.value;
- debug.assert(mem.eql(u8, title.String, "View from 15th Floor"));
+ testing.expect(mem.eql(u8, title.String, "View from 15th Floor"));
const animated = image.Object.get("Animated").?.value;
- debug.assert(animated.Bool == false);
+ testing.expect(animated.Bool == false);
const array_of_object = image.Object.get("ArrayOfObject").?.value;
- debug.assert(array_of_object.Array.len == 1);
+ testing.expect(array_of_object.Array.len == 1);
const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
- debug.assert(mem.eql(u8, obj0.String, "m"));
+ testing.expect(mem.eql(u8, obj0.String, "m"));
+
+ const double = image.Object.get("double").?.value;
+ testing.expect(double.Float == 1.3412);
}
diff --git a/std/json_test.zig b/std/json_test.zig
index 9e19ec592a..edc50be8cb 100644
--- a/std/json_test.zig
+++ b/std/json_test.zig
@@ -6,15 +6,15 @@
const std = @import("index.zig");
fn ok(comptime s: []const u8) void {
- std.debug.assert(std.json.validate(s));
+ std.testing.expect(std.json.validate(s));
}
fn err(comptime s: []const u8) void {
- std.debug.assert(!std.json.validate(s));
+ std.testing.expect(!std.json.validate(s));
}
fn any(comptime s: []const u8) void {
- std.debug.assert(true);
+ std.testing.expect(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/std/lazy_init.zig b/std/lazy_init.zig
index f08c01e874..a09168786b 100644
--- a/std/lazy_init.zig
+++ b/std/lazy_init.zig
@@ -1,6 +1,7 @@
const std = @import("index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const testing = std.testing;
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -63,12 +64,12 @@ test "std.lazyInit" {
global_number.resolve();
}
if (global_number.get()) |x| {
- assert(x.* == 1234);
+ testing.expect(x.* == 1234);
} else {
@panic("bad");
}
if (global_number.get()) |x| {
- assert(x.* == 1234);
+ testing.expect(x.* == 1234);
} else {
@panic("bad");
}
@@ -80,6 +81,6 @@ test "std.lazyInit(void)" {
if (global_void.get()) |_| @panic("bad") else {
global_void.resolve();
}
- assert(global_void.get() != null);
- assert(global_void.get() != null);
+ testing.expect(global_void.get() != null);
+ testing.expect(global_void.get() != null);
}
diff --git a/std/linked_list.zig b/std/linked_list.zig
index c3db55b5a6..86e5cd056e 100644
--- a/std/linked_list.zig
+++ b/std/linked_list.zig
@@ -1,6 +1,7 @@
const std = @import("index.zig");
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const mem = std.mem;
const Allocator = mem.Allocator;
@@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type {
/// Returns:
/// A pointer to the new node.
pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
- return allocator.create(Node(undefined));
+ return allocator.create(Node);
}
/// Deallocate a node.
@@ -246,7 +247,7 @@ test "basic linked list test" {
var it = list.first;
var index: u32 = 1;
while (it) |node| : (it = node.next) {
- assert(node.data == index);
+ testing.expect(node.data == index);
index += 1;
}
}
@@ -256,7 +257,7 @@ test "basic linked list test" {
var it = list.last;
var index: u32 = 1;
while (it) |node| : (it = node.prev) {
- assert(node.data == (6 - index));
+ testing.expect(node.data == (6 - index));
index += 1;
}
}
@@ -265,9 +266,9 @@ test "basic linked list test" {
var last = list.pop(); // {2, 3, 4}
list.remove(three); // {2, 4}
- assert(list.first.?.data == 2);
- assert(list.last.?.data == 4);
- assert(list.len == 2);
+ testing.expect(list.first.?.data == 2);
+ testing.expect(list.last.?.data == 4);
+ testing.expect(list.len == 2);
}
test "linked list concatenation" {
@@ -294,18 +295,18 @@ test "linked list concatenation" {
list1.concatByMoving(&list2);
- assert(list1.last == five);
- assert(list1.len == 5);
- assert(list2.first == null);
- assert(list2.last == null);
- assert(list2.len == 0);
+ testing.expect(list1.last == five);
+ testing.expect(list1.len == 5);
+ testing.expect(list2.first == null);
+ testing.expect(list2.last == null);
+ testing.expect(list2.len == 0);
// Traverse forwards.
{
var it = list1.first;
var index: u32 = 1;
while (it) |node| : (it = node.next) {
- assert(node.data == index);
+ testing.expect(node.data == index);
index += 1;
}
}
@@ -315,7 +316,7 @@ test "linked list concatenation" {
var it = list1.last;
var index: u32 = 1;
while (it) |node| : (it = node.prev) {
- assert(node.data == (6 - index));
+ testing.expect(node.data == (6 - index));
index += 1;
}
}
@@ -328,7 +329,7 @@ test "linked list concatenation" {
var it = list2.first;
var index: u32 = 1;
while (it) |node| : (it = node.next) {
- assert(node.data == index);
+ testing.expect(node.data == index);
index += 1;
}
}
@@ -338,7 +339,7 @@ test "linked list concatenation" {
var it = list2.last;
var index: u32 = 1;
while (it) |node| : (it = node.prev) {
- assert(node.data == (6 - index));
+ testing.expect(node.data == (6 - index));
index += 1;
}
}
diff --git a/std/math/acos.zig b/std/math/acos.zig
index 54844e8f6e..734f7a8651 100644
--- a/std/math/acos.zig
+++ b/std/math/acos.zig
@@ -4,7 +4,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn acos(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -143,38 +143,38 @@ fn acos64(x: f64) f64 {
}
test "math.acos" {
- assert(acos(f32(0.0)) == acos32(0.0));
- assert(acos(f64(0.0)) == acos64(0.0));
+ expect(acos(f32(0.0)) == acos32(0.0));
+ expect(acos(f64(0.0)) == acos64(0.0));
}
test "math.acos32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
- assert(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));
- assert(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));
- assert(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));
- assert(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));
- assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
+ expect(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
+ expect(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));
+ expect(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));
+ expect(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));
+ expect(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));
+ expect(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
}
test "math.acos64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
- assert(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));
- assert(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));
- assert(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));
- assert(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));
- assert(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));
+ expect(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
+ expect(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));
+ expect(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));
+ expect(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));
+ expect(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));
+ expect(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));
}
test "math.acos32.special" {
- assert(math.isNan(acos32(-2)));
- assert(math.isNan(acos32(1.5)));
+ expect(math.isNan(acos32(-2)));
+ expect(math.isNan(acos32(1.5)));
}
test "math.acos64.special" {
- assert(math.isNan(acos64(-2)));
- assert(math.isNan(acos64(1.5)));
+ expect(math.isNan(acos64(-2)));
+ expect(math.isNan(acos64(1.5)));
}
diff --git a/std/math/acosh.zig b/std/math/acosh.zig
index 9be323e1f6..a9c4a908ef 100644
--- a/std/math/acosh.zig
+++ b/std/math/acosh.zig
@@ -6,7 +6,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn acosh(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 {
}
test "math.acosh" {
- assert(acosh(f32(1.5)) == acosh32(1.5));
- assert(acosh(f64(1.5)) == acosh64(1.5));
+ expect(acosh(f32(1.5)) == acosh32(1.5));
+ expect(acosh(f64(1.5)) == acosh64(1.5));
}
test "math.acosh32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
- assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
- assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
- assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
+ expect(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
+ expect(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
+ expect(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
+ expect(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
}
test "math.acosh64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
- assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
- assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
- assert(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));
+ expect(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
+ expect(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
+ expect(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
+ expect(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));
}
test "math.acosh32.special" {
- assert(math.isNan(acosh32(math.nan(f32))));
- assert(math.isSignalNan(acosh32(0.5)));
+ expect(math.isNan(acosh32(math.nan(f32))));
+ expect(math.isSignalNan(acosh32(0.5)));
}
test "math.acosh64.special" {
- assert(math.isNan(acosh64(math.nan(f64))));
- assert(math.isSignalNan(acosh64(0.5)));
+ expect(math.isNan(acosh64(math.nan(f64))));
+ expect(math.isSignalNan(acosh64(0.5)));
}
diff --git a/std/math/asin.zig b/std/math/asin.zig
index 30b3a57e32..c9dbdf704f 100644
--- a/std/math/asin.zig
+++ b/std/math/asin.zig
@@ -5,7 +5,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn asin(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -136,42 +136,42 @@ fn asin64(x: f64) f64 {
}
test "math.asin" {
- assert(asin(f32(0.0)) == asin32(0.0));
- assert(asin(f64(0.0)) == asin64(0.0));
+ expect(asin(f32(0.0)) == asin32(0.0));
+ expect(asin(f64(0.0)) == asin64(0.0));
}
test "math.asin32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));
- assert(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));
- assert(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));
- assert(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));
- assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
+ expect(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));
+ expect(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));
+ expect(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));
+ expect(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));
+ expect(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
}
test "math.asin64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));
- assert(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));
- assert(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));
- assert(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));
- assert(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));
+ expect(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));
+ expect(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));
+ expect(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));
+ expect(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));
+ expect(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));
}
test "math.asin32.special" {
- assert(asin32(0.0) == 0.0);
- assert(asin32(-0.0) == -0.0);
- assert(math.isNan(asin32(-2)));
- assert(math.isNan(asin32(1.5)));
+ expect(asin32(0.0) == 0.0);
+ expect(asin32(-0.0) == -0.0);
+ expect(math.isNan(asin32(-2)));
+ expect(math.isNan(asin32(1.5)));
}
test "math.asin64.special" {
- assert(asin64(0.0) == 0.0);
- assert(asin64(-0.0) == -0.0);
- assert(math.isNan(asin64(-2)));
- assert(math.isNan(asin64(1.5)));
+ expect(asin64(0.0) == 0.0);
+ expect(asin64(-0.0) == -0.0);
+ expect(math.isNan(asin64(-2)));
+ expect(math.isNan(asin64(1.5)));
}
diff --git a/std/math/asinh.zig b/std/math/asinh.zig
index 98892bcbcb..05bd8d008e 100644
--- a/std/math/asinh.zig
+++ b/std/math/asinh.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn asinh(x: var) @typeOf(x) {
@@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 {
}
test "math.asinh" {
- assert(asinh(f32(0.0)) == asinh32(0.0));
- assert(asinh(f64(0.0)) == asinh64(0.0));
+ expect(asinh(f32(0.0)) == asinh32(0.0));
+ expect(asinh(f64(0.0)) == asinh64(0.0));
}
test "math.asinh32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
- assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
- assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
- assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
- assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
- assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
+ expect(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
+ expect(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
+ expect(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
+ expect(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
+ expect(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
+ expect(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
}
test "math.asinh64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
- assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
- assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
- assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
- assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
- assert(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));
+ expect(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
+ expect(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
+ expect(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
+ expect(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
+ expect(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
+ expect(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));
}
test "math.asinh32.special" {
- assert(asinh32(0.0) == 0.0);
- assert(asinh32(-0.0) == -0.0);
- assert(math.isPositiveInf(asinh32(math.inf(f32))));
- assert(math.isNegativeInf(asinh32(-math.inf(f32))));
- assert(math.isNan(asinh32(math.nan(f32))));
+ expect(asinh32(0.0) == 0.0);
+ expect(asinh32(-0.0) == -0.0);
+ expect(math.isPositiveInf(asinh32(math.inf(f32))));
+ expect(math.isNegativeInf(asinh32(-math.inf(f32))));
+ expect(math.isNan(asinh32(math.nan(f32))));
}
test "math.asinh64.special" {
- assert(asinh64(0.0) == 0.0);
- assert(asinh64(-0.0) == -0.0);
- assert(math.isPositiveInf(asinh64(math.inf(f64))));
- assert(math.isNegativeInf(asinh64(-math.inf(f64))));
- assert(math.isNan(asinh64(math.nan(f64))));
+ expect(asinh64(0.0) == 0.0);
+ expect(asinh64(-0.0) == -0.0);
+ expect(math.isPositiveInf(asinh64(math.inf(f64))));
+ expect(math.isNegativeInf(asinh64(-math.inf(f64))));
+ expect(math.isNan(asinh64(math.nan(f64))));
}
diff --git a/std/math/atan.zig b/std/math/atan.zig
index 6ca94dd84a..72d17b4db2 100644
--- a/std/math/atan.zig
+++ b/std/math/atan.zig
@@ -5,7 +5,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn atan(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 {
}
test "math.atan" {
- assert(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));
- assert(atan(f64(0.2)) == atan64(0.2));
+ expect(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));
+ expect(atan(f64(0.2)) == atan64(0.2));
}
test "math.atan32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
- assert(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));
- assert(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));
- assert(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));
- assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
+ expect(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
+ expect(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));
+ expect(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));
+ expect(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));
+ expect(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
}
test "math.atan64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
- assert(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));
- assert(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));
- assert(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));
- assert(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));
+ expect(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
+ expect(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));
+ expect(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));
+ expect(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));
+ expect(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));
}
test "math.atan32.special" {
const epsilon = 0.000001;
- assert(atan32(0.0) == 0.0);
- assert(atan32(-0.0) == -0.0);
- assert(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));
+ expect(atan32(0.0) == 0.0);
+ expect(atan32(-0.0) == -0.0);
+ expect(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));
}
test "math.atan64.special" {
const epsilon = 0.000001;
- assert(atan64(0.0) == 0.0);
- assert(atan64(-0.0) == -0.0);
- assert(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));
+ expect(atan64(0.0) == 0.0);
+ expect(atan64(-0.0) == -0.0);
+ expect(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));
}
diff --git a/std/math/atan2.zig b/std/math/atan2.zig
index b3e45ba045..6e1f67cfbb 100644
--- a/std/math/atan2.zig
+++ b/std/math/atan2.zig
@@ -20,12 +20,12 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
-pub fn atan2(comptime T: type, x: T, y: T) T {
+pub fn atan2(comptime T: type, y: T, x: T) T {
return switch (T) {
- f32 => atan2_32(x, y),
- f64 => atan2_64(x, y),
+ f32 => atan2_32(y, x),
+ f64 => atan2_64(y, x),
else => @compileError("atan2 not implemented for " ++ @typeName(T)),
};
}
@@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 {
}
test "math.atan2" {
- assert(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));
- assert(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));
+ expect(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));
+ expect(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));
}
test "math.atan2_32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));
- assert(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon));
- assert(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon));
- assert(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon));
- assert(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon));
- assert(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));
- assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
+ expect(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon));
+ expect(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon));
+ expect(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon));
+ expect(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon));
+ expect(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));
+ expect(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
}
test "math.atan2_64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));
- assert(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon));
- assert(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon));
- assert(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon));
- assert(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon));
- assert(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));
- assert(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));
+ expect(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon));
+ expect(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon));
+ expect(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon));
+ expect(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon));
+ expect(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));
+ expect(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));
}
test "math.atan2_32.special" {
const epsilon = 0.000001;
- assert(math.isNan(atan2_32(1.0, math.nan(f32))));
- assert(math.isNan(atan2_32(math.nan(f32), 1.0)));
- assert(atan2_32(0.0, 5.0) == 0.0);
- assert(atan2_32(-0.0, 5.0) == -0.0);
- assert(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
- //assert(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
- assert(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon));
- assert(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon));
- assert(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon));
- assert(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon));
- assert(atan2_32(1.0, math.inf(f32)) == 0.0);
- assert(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon));
- assert(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon));
- assert(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon));
+ expect(math.isNan(atan2_32(1.0, math.nan(f32))));
+ expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
+ expect(atan2_32(0.0, 5.0) == 0.0);
+ expect(atan2_32(-0.0, 5.0) == -0.0);
+ expect(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
+ //expect(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
+ expect(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon));
+ expect(atan2_32(1.0, math.inf(f32)) == 0.0);
+ expect(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon));
+ expect(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon));
+ expect(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon));
}
test "math.atan2_64.special" {
const epsilon = 0.000001;
- assert(math.isNan(atan2_64(1.0, math.nan(f64))));
- assert(math.isNan(atan2_64(math.nan(f64), 1.0)));
- assert(atan2_64(0.0, 5.0) == 0.0);
- assert(atan2_64(-0.0, 5.0) == -0.0);
- assert(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
- //assert(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
- assert(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon));
- assert(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon));
- assert(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon));
- assert(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon));
- assert(atan2_64(1.0, math.inf(f64)) == 0.0);
- assert(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon));
- assert(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon));
- assert(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon));
- assert(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon));
+ expect(math.isNan(atan2_64(1.0, math.nan(f64))));
+ expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
+ expect(atan2_64(0.0, 5.0) == 0.0);
+ expect(atan2_64(-0.0, 5.0) == -0.0);
+ expect(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
+ //expect(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
+ expect(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon));
+ expect(atan2_64(1.0, math.inf(f64)) == 0.0);
+ expect(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon));
+ expect(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon));
+ expect(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon));
+ expect(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon));
}
diff --git a/std/math/atanh.zig b/std/math/atanh.zig
index c97855c234..f2feab0207 100644
--- a/std/math/atanh.zig
+++ b/std/math/atanh.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn atanh(x: var) @typeOf(x) {
@@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 {
}
test "math.atanh" {
- assert(atanh(f32(0.0)) == atanh_32(0.0));
- assert(atanh(f64(0.0)) == atanh_64(0.0));
+ expect(atanh(f32(0.0)) == atanh_32(0.0));
+ expect(atanh(f64(0.0)) == atanh_64(0.0));
}
test "math.atanh_32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
- assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
+ expect(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
+ expect(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
}
test "math.atanh_64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
- assert(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));
+ expect(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
+ expect(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));
}
test "math.atanh32.special" {
- assert(math.isPositiveInf(atanh_32(1)));
- assert(math.isNegativeInf(atanh_32(-1)));
- assert(math.isSignalNan(atanh_32(1.5)));
- assert(math.isSignalNan(atanh_32(-1.5)));
- assert(math.isNan(atanh_32(math.nan(f32))));
+ expect(math.isPositiveInf(atanh_32(1)));
+ expect(math.isNegativeInf(atanh_32(-1)));
+ expect(math.isSignalNan(atanh_32(1.5)));
+ expect(math.isSignalNan(atanh_32(-1.5)));
+ expect(math.isNan(atanh_32(math.nan(f32))));
}
test "math.atanh64.special" {
- assert(math.isPositiveInf(atanh_64(1)));
- assert(math.isNegativeInf(atanh_64(-1)));
- assert(math.isSignalNan(atanh_64(1.5)));
- assert(math.isSignalNan(atanh_64(-1.5)));
- assert(math.isNan(atanh_64(math.nan(f64))));
+ expect(math.isPositiveInf(atanh_64(1)));
+ expect(math.isNegativeInf(atanh_64(-1)));
+ expect(math.isSignalNan(atanh_64(1.5)));
+ expect(math.isSignalNan(atanh_64(-1.5)));
+ expect(math.isNan(atanh_64(math.nan(f64))));
}
diff --git a/std/math/big/int.zig b/std/math/big/int.zig
index cda2e1419f..f21e5df8aa 100644
--- a/std/math/big/int.zig
+++ b/std/math/big/int.zig
@@ -1,6 +1,7 @@
const std = @import("../../index.zig");
const builtin = @import("builtin");
const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const mem = std.mem;
const Allocator = mem.Allocator;
@@ -1086,44 +1087,40 @@ test "big.int comptime_int set" {
const result = Limb(s & maxInt(Limb));
s >>= Limb.bit_count / 2;
s >>= Limb.bit_count / 2;
- debug.assert(a.limbs[i] == result);
+ testing.expect(a.limbs[i] == result);
}
}
test "big.int comptime_int set negative" {
var a = try Int.initSet(al, -10);
- debug.assert(a.limbs[0] == 10);
- debug.assert(a.positive == false);
+ testing.expect(a.limbs[0] == 10);
+ testing.expect(a.positive == false);
}
test "big.int int set unaligned small" {
var a = try Int.initSet(al, u7(45));
- debug.assert(a.limbs[0] == 45);
- debug.assert(a.positive == true);
+ testing.expect(a.limbs[0] == 45);
+ testing.expect(a.positive == true);
}
test "big.int comptime_int to" {
const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab);
- debug.assert((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
+ testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
}
test "big.int sub-limb to" {
const a = try Int.initSet(al, 10);
- debug.assert((try a.to(u8)) == 10);
+ testing.expect((try a.to(u8)) == 10);
}
test "big.int to target too small error" {
const a = try Int.initSet(al, 0xffffffff);
- if (a.to(u8)) |_| {
- unreachable;
- } else |err| {
- debug.assert(err == error.TargetTooSmall);
- }
+ testing.expectError(error.TargetTooSmall, a.to(u8));
}
test "big.int norm1" {
@@ -1135,22 +1132,22 @@ test "big.int norm1" {
a.limbs[2] = 3;
a.limbs[3] = 0;
a.norm1(4);
- debug.assert(a.len == 3);
+ testing.expect(a.len == 3);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
a.norm1(3);
- debug.assert(a.len == 3);
+ testing.expect(a.len == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
a.norm1(2);
- debug.assert(a.len == 1);
+ testing.expect(a.len == 1);
a.limbs[0] = 0;
a.norm1(1);
- debug.assert(a.len == 1);
+ testing.expect(a.len == 1);
}
test "big.int normN" {
@@ -1162,144 +1159,144 @@ test "big.int normN" {
a.limbs[2] = 0;
a.limbs[3] = 0;
a.normN(4);
- debug.assert(a.len == 2);
+ testing.expect(a.len == 2);
a.limbs[0] = 1;
a.limbs[1] = 2;
a.limbs[2] = 3;
a.normN(3);
- debug.assert(a.len == 3);
+ testing.expect(a.len == 3);
a.limbs[0] = 0;
a.limbs[1] = 0;
a.limbs[2] = 0;
a.limbs[3] = 0;
a.normN(4);
- debug.assert(a.len == 1);
+ testing.expect(a.len == 1);
a.limbs[0] = 0;
a.normN(1);
- debug.assert(a.len == 1);
+ testing.expect(a.len == 1);
}
test "big.int parity" {
var a = try Int.init(al);
try a.set(0);
- debug.assert(a.isEven());
- debug.assert(!a.isOdd());
+ testing.expect(a.isEven());
+ testing.expect(!a.isOdd());
try a.set(7);
- debug.assert(!a.isEven());
- debug.assert(a.isOdd());
+ testing.expect(!a.isEven());
+ testing.expect(a.isOdd());
}
test "big.int bitcount + sizeInBase" {
var a = try Int.init(al);
try a.set(0b100);
- debug.assert(a.bitCountAbs() == 3);
- debug.assert(a.sizeInBase(2) >= 3);
- debug.assert(a.sizeInBase(10) >= 1);
+ testing.expect(a.bitCountAbs() == 3);
+ testing.expect(a.sizeInBase(2) >= 3);
+ testing.expect(a.sizeInBase(10) >= 1);
a.negate();
- debug.assert(a.bitCountAbs() == 3);
- debug.assert(a.sizeInBase(2) >= 4);
- debug.assert(a.sizeInBase(10) >= 2);
+ testing.expect(a.bitCountAbs() == 3);
+ testing.expect(a.sizeInBase(2) >= 4);
+ testing.expect(a.sizeInBase(10) >= 2);
try a.set(0xffffffff);
- debug.assert(a.bitCountAbs() == 32);
- debug.assert(a.sizeInBase(2) >= 32);
- debug.assert(a.sizeInBase(10) >= 10);
+ testing.expect(a.bitCountAbs() == 32);
+ testing.expect(a.sizeInBase(2) >= 32);
+ testing.expect(a.sizeInBase(10) >= 10);
try a.shiftLeft(a, 5000);
- debug.assert(a.bitCountAbs() == 5032);
- debug.assert(a.sizeInBase(2) >= 5032);
+ testing.expect(a.bitCountAbs() == 5032);
+ testing.expect(a.sizeInBase(2) >= 5032);
a.positive = false;
- debug.assert(a.bitCountAbs() == 5032);
- debug.assert(a.sizeInBase(2) >= 5033);
+ testing.expect(a.bitCountAbs() == 5032);
+ testing.expect(a.sizeInBase(2) >= 5033);
}
test "big.int bitcount/to" {
var a = try Int.init(al);
try a.set(0);
- debug.assert(a.bitCountTwosComp() == 0);
+ testing.expect(a.bitCountTwosComp() == 0);
// TODO: stack smashing
- // debug.assert((try a.to(u0)) == 0);
+ // testing.expect((try a.to(u0)) == 0);
// TODO: sigsegv
- // debug.assert((try a.to(i0)) == 0);
+ // testing.expect((try a.to(i0)) == 0);
try a.set(-1);
- debug.assert(a.bitCountTwosComp() == 1);
- debug.assert((try a.to(i1)) == -1);
+ testing.expect(a.bitCountTwosComp() == 1);
+ testing.expect((try a.to(i1)) == -1);
try a.set(-8);
- debug.assert(a.bitCountTwosComp() == 4);
- debug.assert((try a.to(i4)) == -8);
+ testing.expect(a.bitCountTwosComp() == 4);
+ testing.expect((try a.to(i4)) == -8);
try a.set(127);
- debug.assert(a.bitCountTwosComp() == 7);
- debug.assert((try a.to(u7)) == 127);
+ testing.expect(a.bitCountTwosComp() == 7);
+ testing.expect((try a.to(u7)) == 127);
try a.set(-128);
- debug.assert(a.bitCountTwosComp() == 8);
- debug.assert((try a.to(i8)) == -128);
+ testing.expect(a.bitCountTwosComp() == 8);
+ testing.expect((try a.to(i8)) == -128);
try a.set(-129);
- debug.assert(a.bitCountTwosComp() == 9);
- debug.assert((try a.to(i9)) == -129);
+ testing.expect(a.bitCountTwosComp() == 9);
+ testing.expect((try a.to(i9)) == -129);
}
test "big.int fits" {
var a = try Int.init(al);
try a.set(0);
- debug.assert(a.fits(u0));
- debug.assert(a.fits(i0));
+ testing.expect(a.fits(u0));
+ testing.expect(a.fits(i0));
try a.set(255);
- debug.assert(!a.fits(u0));
- debug.assert(!a.fits(u1));
- debug.assert(!a.fits(i8));
- debug.assert(a.fits(u8));
- debug.assert(a.fits(u9));
- debug.assert(a.fits(i9));
+ testing.expect(!a.fits(u0));
+ testing.expect(!a.fits(u1));
+ testing.expect(!a.fits(i8));
+ testing.expect(a.fits(u8));
+ testing.expect(a.fits(u9));
+ testing.expect(a.fits(i9));
try a.set(-128);
- debug.assert(!a.fits(i7));
- debug.assert(a.fits(i8));
- debug.assert(a.fits(i9));
- debug.assert(!a.fits(u9));
+ testing.expect(!a.fits(i7));
+ testing.expect(a.fits(i8));
+ testing.expect(a.fits(i9));
+ testing.expect(!a.fits(u9));
try a.set(0x1ffffffffeeeeeeee);
- debug.assert(!a.fits(u32));
- debug.assert(!a.fits(u64));
- debug.assert(a.fits(u65));
+ testing.expect(!a.fits(u32));
+ testing.expect(!a.fits(u64));
+ testing.expect(a.fits(u65));
}
test "big.int string set" {
var a = try Int.init(al);
try a.setString(10, "120317241209124781241290847124");
- debug.assert((try a.to(u128)) == 120317241209124781241290847124);
+ testing.expect((try a.to(u128)) == 120317241209124781241290847124);
}
test "big.int string negative" {
var a = try Int.init(al);
try a.setString(10, "-1023");
- debug.assert((try a.to(i32)) == -1023);
+ testing.expect((try a.to(i32)) == -1023);
}
test "big.int string set bad char error" {
var a = try Int.init(al);
- a.setString(10, "x") catch |err| debug.assert(err == error.InvalidCharForDigit);
+ testing.expectError(error.InvalidCharForDigit, a.setString(10, "x"));
}
test "big.int string set bad base error" {
var a = try Int.init(al);
- a.setString(45, "10") catch |err| debug.assert(err == error.InvalidBase);
+ testing.expectError(error.InvalidBase, a.setString(45, "10"));
}
test "big.int string to" {
@@ -1308,17 +1305,13 @@ test "big.int string to" {
const as = try a.toString(al, 10);
const es = "120317241209124781241290847124";
- debug.assert(mem.eql(u8, as, es));
+ testing.expect(mem.eql(u8, as, es));
}
test "big.int string to base base error" {
const a = try Int.initSet(al, 0xffffffff);
- if (a.toString(al, 45)) |_| {
- unreachable;
- } else |err| {
- debug.assert(err == error.InvalidBase);
- }
+ testing.expectError(error.InvalidBase, a.toString(al, 45));
}
test "big.int string to base 2" {
@@ -1327,7 +1320,7 @@ test "big.int string to base 2" {
const as = try a.toString(al, 2);
const es = "-1011";
- debug.assert(mem.eql(u8, as, es));
+ testing.expect(mem.eql(u8, as, es));
}
test "big.int string to base 16" {
@@ -1336,7 +1329,7 @@ test "big.int string to base 16" {
const as = try a.toString(al, 16);
const es = "efffffff00000001eeeeeeefaaaaaaab";
- debug.assert(mem.eql(u8, as, es));
+ testing.expect(mem.eql(u8, as, es));
}
test "big.int neg string to" {
@@ -1345,7 +1338,7 @@ test "big.int neg string to" {
const as = try a.toString(al, 10);
const es = "-123907434";
- debug.assert(mem.eql(u8, as, es));
+ testing.expect(mem.eql(u8, as, es));
}
test "big.int zero string to" {
@@ -1354,98 +1347,98 @@ test "big.int zero string to" {
const as = try a.toString(al, 10);
const es = "0";
- debug.assert(mem.eql(u8, as, es));
+ testing.expect(mem.eql(u8, as, es));
}
test "big.int clone" {
var a = try Int.initSet(al, 1234);
const b = try a.clone();
- debug.assert((try a.to(u32)) == 1234);
- debug.assert((try b.to(u32)) == 1234);
+ testing.expect((try a.to(u32)) == 1234);
+ testing.expect((try b.to(u32)) == 1234);
try a.set(77);
- debug.assert((try a.to(u32)) == 77);
- debug.assert((try b.to(u32)) == 1234);
+ testing.expect((try a.to(u32)) == 77);
+ testing.expect((try b.to(u32)) == 1234);
}
test "big.int swap" {
var a = try Int.initSet(al, 1234);
var b = try Int.initSet(al, 5678);
- debug.assert((try a.to(u32)) == 1234);
- debug.assert((try b.to(u32)) == 5678);
+ testing.expect((try a.to(u32)) == 1234);
+ testing.expect((try b.to(u32)) == 5678);
a.swap(&b);
- debug.assert((try a.to(u32)) == 5678);
- debug.assert((try b.to(u32)) == 1234);
+ testing.expect((try a.to(u32)) == 5678);
+ testing.expect((try b.to(u32)) == 1234);
}
test "big.int to negative" {
var a = try Int.initSet(al, -10);
- debug.assert((try a.to(i32)) == -10);
+ testing.expect((try a.to(i32)) == -10);
}
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);
+ testing.expect(a.cmpAbs(b) == 1);
+ testing.expect(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);
+ testing.expect(a.cmpAbs(b) == -1);
+ testing.expect(b.cmpAbs(a) == 1);
}
test "big.int compare different limb size" {
var a = try Int.initSet(al, maxInt(Limb) + 1);
var b = try Int.initSet(al, 1);
- debug.assert(a.cmpAbs(b) == 1);
- debug.assert(b.cmpAbs(a) == -1);
+ testing.expect(a.cmpAbs(b) == 1);
+ testing.expect(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);
+ testing.expect(a.cmpAbs(b) == 1);
+ testing.expect(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));
+ testing.expect(a.eqAbs(b));
+ testing.expect(!a.eq(b));
}
test "big.int abs" {
var a = try Int.initSet(al, -5);
a.abs();
- debug.assert((try a.to(u32)) == 5);
+ testing.expect((try a.to(u32)) == 5);
a.abs();
- debug.assert((try a.to(u32)) == 5);
+ testing.expect((try a.to(u32)) == 5);
}
test "big.int negate" {
var a = try Int.initSet(al, 5);
a.negate();
- debug.assert((try a.to(i32)) == -5);
+ testing.expect((try a.to(i32)) == -5);
a.negate();
- debug.assert((try a.to(i32)) == 5);
+ testing.expect((try a.to(i32)) == 5);
}
test "big.int add single-single" {
@@ -1455,7 +1448,7 @@ test "big.int add single-single" {
var c = try Int.init(al);
try c.add(a, b);
- debug.assert((try c.to(u32)) == 55);
+ testing.expect((try c.to(u32)) == 55);
}
test "big.int add multi-single" {
@@ -1465,10 +1458,10 @@ test "big.int add multi-single" {
var c = try Int.init(al);
try c.add(a, b);
- debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
+ testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
try c.add(b, a);
- debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
+ testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
}
test "big.int add multi-multi" {
@@ -1480,7 +1473,7 @@ test "big.int add multi-multi" {
var c = try Int.init(al);
try c.add(a, b);
- debug.assert((try c.to(u128)) == op1 + op2);
+ testing.expect((try c.to(u128)) == op1 + op2);
}
test "big.int add zero-zero" {
@@ -1490,7 +1483,7 @@ test "big.int add zero-zero" {
var c = try Int.init(al);
try c.add(a, b);
- debug.assert((try c.to(u32)) == 0);
+ testing.expect((try c.to(u32)) == 0);
}
test "big.int add alias multi-limb nonzero-zero" {
@@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" {
try a.add(a, b);
- debug.assert((try a.to(u128)) == op1);
+ testing.expect((try a.to(u128)) == op1);
}
test "big.int add sign" {
@@ -1512,16 +1505,16 @@ test "big.int add sign" {
const neg_two = try Int.initSet(al, -2);
try a.add(one, two);
- debug.assert((try a.to(i32)) == 3);
+ testing.expect((try a.to(i32)) == 3);
try a.add(neg_one, two);
- debug.assert((try a.to(i32)) == 1);
+ testing.expect((try a.to(i32)) == 1);
try a.add(one, neg_two);
- debug.assert((try a.to(i32)) == -1);
+ testing.expect((try a.to(i32)) == -1);
try a.add(neg_one, neg_two);
- debug.assert((try a.to(i32)) == -3);
+ testing.expect((try a.to(i32)) == -3);
}
test "big.int sub single-single" {
@@ -1531,7 +1524,7 @@ test "big.int sub single-single" {
var c = try Int.init(al);
try c.sub(a, b);
- debug.assert((try c.to(u32)) == 45);
+ testing.expect((try c.to(u32)) == 45);
}
test "big.int sub multi-single" {
@@ -1541,7 +1534,7 @@ test "big.int sub multi-single" {
var c = try Int.init(al);
try c.sub(a, b);
- debug.assert((try c.to(Limb)) == maxInt(Limb));
+ testing.expect((try c.to(Limb)) == maxInt(Limb));
}
test "big.int sub multi-multi" {
@@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" {
var c = try Int.init(al);
try c.sub(a, b);
- debug.assert((try c.to(u128)) == op1 - op2);
+ testing.expect((try c.to(u128)) == op1 - op2);
}
test "big.int sub equal" {
@@ -1564,7 +1557,7 @@ test "big.int sub equal" {
var c = try Int.init(al);
try c.sub(a, b);
- debug.assert((try c.to(u32)) == 0);
+ testing.expect((try c.to(u32)) == 0);
}
test "big.int sub sign" {
@@ -1576,19 +1569,19 @@ test "big.int sub sign" {
const neg_two = try Int.initSet(al, -2);
try a.sub(one, two);
- debug.assert((try a.to(i32)) == -1);
+ testing.expect((try a.to(i32)) == -1);
try a.sub(neg_one, two);
- debug.assert((try a.to(i32)) == -3);
+ testing.expect((try a.to(i32)) == -3);
try a.sub(one, neg_two);
- debug.assert((try a.to(i32)) == 3);
+ testing.expect((try a.to(i32)) == 3);
try a.sub(neg_one, neg_two);
- debug.assert((try a.to(i32)) == 1);
+ testing.expect((try a.to(i32)) == 1);
try a.sub(neg_two, neg_one);
- debug.assert((try a.to(i32)) == -1);
+ testing.expect((try a.to(i32)) == -1);
}
test "big.int mul single-single" {
@@ -1598,7 +1591,7 @@ test "big.int mul single-single" {
var c = try Int.init(al);
try c.mul(a, b);
- debug.assert((try c.to(u64)) == 250);
+ testing.expect((try c.to(u64)) == 250);
}
test "big.int mul multi-single" {
@@ -1608,7 +1601,7 @@ test "big.int mul multi-single" {
var c = try Int.init(al);
try c.mul(a, b);
- debug.assert((try c.to(DoubleLimb)) == 2 * maxInt(Limb));
+ testing.expect((try c.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul multi-multi" {
@@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" {
var c = try Int.init(al);
try c.mul(a, b);
- debug.assert((try c.to(u256)) == op1 * op2);
+ testing.expect((try c.to(u256)) == op1 * op2);
}
test "big.int mul alias r with a" {
@@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" {
try a.mul(a, b);
- debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
+ testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul alias r with b" {
@@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" {
try a.mul(b, a);
- debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
+ testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
}
test "big.int mul alias r with a and b" {
@@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" {
try a.mul(a, a);
- debug.assert((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb));
+ testing.expect((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb));
}
test "big.int mul a*0" {
@@ -1656,7 +1649,7 @@ test "big.int mul a*0" {
var c = try Int.init(al);
try c.mul(a, b);
- debug.assert((try c.to(u32)) == 0);
+ testing.expect((try c.to(u32)) == 0);
}
test "big.int mul 0*0" {
@@ -1666,7 +1659,7 @@ test "big.int mul 0*0" {
var c = try Int.init(al);
try c.mul(a, b);
- debug.assert((try c.to(u32)) == 0);
+ testing.expect((try c.to(u32)) == 0);
}
test "big.int div single-single no rem" {
@@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u32)) == 10);
- debug.assert((try r.to(u32)) == 0);
+ testing.expect((try q.to(u32)) == 10);
+ testing.expect((try r.to(u32)) == 0);
}
test "big.int div single-single with rem" {
@@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u32)) == 9);
- debug.assert((try r.to(u32)) == 4);
+ testing.expect((try q.to(u32)) == 9);
+ testing.expect((try r.to(u32)) == 4);
}
test "big.int div multi-single no rem" {
@@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u64)) == op1 / op2);
- debug.assert((try r.to(u64)) == 0);
+ testing.expect((try q.to(u64)) == op1 / op2);
+ testing.expect((try r.to(u64)) == 0);
}
test "big.int div multi-single with rem" {
@@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u64)) == op1 / op2);
- debug.assert((try r.to(u64)) == 3);
+ testing.expect((try q.to(u64)) == op1 / op2);
+ testing.expect((try r.to(u64)) == 3);
}
test "big.int div multi>2-single" {
@@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == op1 / op2);
- debug.assert((try r.to(u32)) == 0x3e4e);
+ testing.expect((try q.to(u128)) == op1 / op2);
+ testing.expect((try r.to(u32)) == 0x3e4e);
}
test "big.int div single-single q < r" {
@@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u64)) == 0);
- debug.assert((try r.to(u64)) == 0x0078f432);
+ testing.expect((try q.to(u64)) == 0);
+ testing.expect((try r.to(u64)) == 0x0078f432);
}
test "big.int div single-single q == r" {
@@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u64)) == 1);
- debug.assert((try r.to(u64)) == 0);
+ testing.expect((try q.to(u64)) == 1);
+ testing.expect((try r.to(u64)) == 0);
}
test "big.int div q=0 alias" {
@@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" {
try Int.divTrunc(&a, &b, a, b);
- debug.assert((try a.to(u64)) == 0);
- debug.assert((try b.to(u64)) == 3);
+ testing.expect((try a.to(u64)) == 0);
+ testing.expect((try b.to(u64)) == 3);
}
test "big.int div multi-multi q < r" {
@@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == 0);
- debug.assert((try r.to(u128)) == op1);
+ testing.expect((try q.to(u128)) == 0);
+ testing.expect((try r.to(u128)) == op1);
}
test "big.int div trunc single-single +/+" {
@@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" {
const eq = @divTrunc(u, v);
const er = @mod(u, v);
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single -/+" {
@@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" {
const eq = -1;
const er = -2;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single +/-" {
@@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" {
const eq = -1;
const er = 2;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div trunc single-single -/-" {
@@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" {
const eq = 1;
const er = -2;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single +/+" {
@@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" {
const eq = 1;
const er = 2;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single -/+" {
@@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" {
const eq = -2;
const er = 1;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single +/-" {
@@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" {
const eq = -2;
const er = -1;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div floor single-single -/-" {
@@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" {
const eq = 1;
const er = -2;
- debug.assert((try q.to(i32)) == eq);
- debug.assert((try r.to(i32)) == er);
+ testing.expect((try q.to(i32)) == eq);
+ testing.expect((try r.to(i32)) == er);
}
test "big.int div multi-multi with rem" {
@@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
- debug.assert((try r.to(u128)) == 0x28de0acacd806823638);
+ testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
+ testing.expect((try r.to(u128)) == 0x28de0acacd806823638);
}
test "big.int div multi-multi no rem" {
@@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
- debug.assert((try r.to(u128)) == 0);
+ testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
+ testing.expect((try r.to(u128)) == 0);
}
test "big.int div multi-multi (2 branch)" {
@@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == 0x10000000000000000);
- debug.assert((try r.to(u128)) == 0x44444443444444431111111111111111);
+ testing.expect((try q.to(u128)) == 0x10000000000000000);
+ testing.expect((try r.to(u128)) == 0x44444443444444431111111111111111);
}
test "big.int div multi-multi (3.1/3.3 branch)" {
@@ -1990,53 +1983,53 @@ test "big.int div multi-multi (3.1/3.3 branch)" {
var r = try Int.init(al);
try Int.divTrunc(&q, &r, a, b);
- debug.assert((try q.to(u128)) == 0xfffffffffffffffffff);
- debug.assert((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
+ testing.expect((try q.to(u128)) == 0xfffffffffffffffffff);
+ testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
}
test "big.int shift-right single" {
var a = try Int.initSet(al, 0xffff0000);
try a.shiftRight(a, 16);
- debug.assert((try a.to(u32)) == 0xffff);
+ testing.expect((try a.to(u32)) == 0xffff);
}
test "big.int shift-right multi" {
var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333);
try a.shiftRight(a, 67);
- debug.assert((try a.to(u64)) == 0x1fffe0001dddc222);
+ testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
}
test "big.int shift-left single" {
var a = try Int.initSet(al, 0xffff);
try a.shiftLeft(a, 16);
- debug.assert((try a.to(u64)) == 0xffff0000);
+ testing.expect((try a.to(u64)) == 0xffff0000);
}
test "big.int shift-left multi" {
var a = try Int.initSet(al, 0x1fffe0001dddc222);
try a.shiftLeft(a, 67);
- debug.assert((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
+ testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
}
test "big.int shift-right negative" {
var a = try Int.init(al);
try a.shiftRight(try Int.initSet(al, -20), 2);
- debug.assert((try a.to(i32)) == -20 >> 2);
+ testing.expect((try a.to(i32)) == -20 >> 2);
try a.shiftRight(try Int.initSet(al, -5), 10);
- debug.assert((try a.to(i32)) == -5 >> 10);
+ testing.expect((try a.to(i32)) == -5 >> 10);
}
test "big.int shift-left negative" {
var a = try Int.init(al);
try a.shiftRight(try Int.initSet(al, -10), 1232);
- debug.assert((try a.to(i32)) == -10 >> 1232);
+ testing.expect((try a.to(i32)) == -10 >> 1232);
}
test "big.int bitwise and simple" {
@@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" {
try a.bitAnd(a, b);
- debug.assert((try a.to(u64)) == 0xeeeeeeee00000000);
+ testing.expect((try a.to(u64)) == 0xeeeeeeee00000000);
}
test "big.int bitwise and multi-limb" {
@@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" {
try a.bitAnd(a, b);
- debug.assert((try a.to(u128)) == 0);
+ testing.expect((try a.to(u128)) == 0);
}
test "big.int bitwise xor simple" {
@@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" {
try a.bitXor(a, b);
- debug.assert((try a.to(u64)) == 0x1111111133333333);
+ testing.expect((try a.to(u64)) == 0x1111111133333333);
}
test "big.int bitwise xor multi-limb" {
@@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" {
try a.bitXor(a, b);
- debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));
+ testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));
}
test "big.int bitwise or simple" {
@@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" {
try a.bitOr(a, b);
- debug.assert((try a.to(u64)) == 0xffffffff33333333);
+ testing.expect((try a.to(u64)) == 0xffffffff33333333);
}
test "big.int bitwise or multi-limb" {
@@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" {
try a.bitOr(a, b);
// TODO: big.int.cpp or is wrong on multi-limb.
- debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));
+ testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));
}
test "big.int var args" {
var a = try Int.initSet(al, 5);
try a.add(a, try Int.initSet(al, 6));
- debug.assert((try a.to(u64)) == 11);
+ testing.expect((try a.to(u64)) == 11);
- debug.assert(a.cmp(try Int.initSet(al, 11)) == 0);
- debug.assert(a.cmp(try Int.initSet(al, 14)) <= 0);
+ testing.expect(a.cmp(try Int.initSet(al, 11)) == 0);
+ testing.expect(a.cmp(try Int.initSet(al, 14)) <= 0);
}
diff --git a/std/math/cbrt.zig b/std/math/cbrt.zig
index c067c5155a..957e026af4 100644
--- a/std/math/cbrt.zig
+++ b/std/math/cbrt.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn cbrt(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 {
}
test "math.cbrt" {
- assert(cbrt(f32(0.0)) == cbrt32(0.0));
- assert(cbrt(f64(0.0)) == cbrt64(0.0));
+ expect(cbrt(f32(0.0)) == cbrt32(0.0));
+ expect(cbrt(f64(0.0)) == cbrt64(0.0));
}
test "math.cbrt32" {
const epsilon = 0.000001;
- assert(cbrt32(0.0) == 0.0);
- assert(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));
- assert(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));
- assert(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));
- assert(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));
- assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
+ expect(cbrt32(0.0) == 0.0);
+ expect(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));
+ expect(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));
+ expect(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));
+ expect(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));
+ expect(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
}
test "math.cbrt64" {
const epsilon = 0.000001;
- assert(cbrt64(0.0) == 0.0);
- assert(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));
- assert(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));
- assert(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));
- assert(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));
- assert(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));
+ expect(cbrt64(0.0) == 0.0);
+ expect(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));
+ expect(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));
+ expect(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));
+ expect(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));
+ expect(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));
}
test "math.cbrt.special" {
- assert(cbrt32(0.0) == 0.0);
- assert(cbrt32(-0.0) == -0.0);
- assert(math.isPositiveInf(cbrt32(math.inf(f32))));
- assert(math.isNegativeInf(cbrt32(-math.inf(f32))));
- assert(math.isNan(cbrt32(math.nan(f32))));
+ expect(cbrt32(0.0) == 0.0);
+ expect(cbrt32(-0.0) == -0.0);
+ expect(math.isPositiveInf(cbrt32(math.inf(f32))));
+ expect(math.isNegativeInf(cbrt32(-math.inf(f32))));
+ expect(math.isNan(cbrt32(math.nan(f32))));
}
test "math.cbrt64.special" {
- assert(cbrt64(0.0) == 0.0);
- assert(cbrt64(-0.0) == -0.0);
- assert(math.isPositiveInf(cbrt64(math.inf(f64))));
- assert(math.isNegativeInf(cbrt64(-math.inf(f64))));
- assert(math.isNan(cbrt64(math.nan(f64))));
+ expect(cbrt64(0.0) == 0.0);
+ expect(cbrt64(-0.0) == -0.0);
+ expect(math.isPositiveInf(cbrt64(math.inf(f64))));
+ expect(math.isNegativeInf(cbrt64(-math.inf(f64))));
+ expect(math.isNan(cbrt64(math.nan(f64))));
}
diff --git a/std/math/ceil.zig b/std/math/ceil.zig
index 8a5221d862..5c6b98b2ca 100644
--- a/std/math/ceil.zig
+++ b/std/math/ceil.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn ceil(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 {
}
test "math.ceil" {
- assert(ceil(f32(0.0)) == ceil32(0.0));
- assert(ceil(f64(0.0)) == ceil64(0.0));
+ expect(ceil(f32(0.0)) == ceil32(0.0));
+ expect(ceil(f64(0.0)) == ceil64(0.0));
}
test "math.ceil32" {
- assert(ceil32(1.3) == 2.0);
- assert(ceil32(-1.3) == -1.0);
- assert(ceil32(0.2) == 1.0);
+ expect(ceil32(1.3) == 2.0);
+ expect(ceil32(-1.3) == -1.0);
+ expect(ceil32(0.2) == 1.0);
}
test "math.ceil64" {
- assert(ceil64(1.3) == 2.0);
- assert(ceil64(-1.3) == -1.0);
- assert(ceil64(0.2) == 1.0);
+ expect(ceil64(1.3) == 2.0);
+ expect(ceil64(-1.3) == -1.0);
+ expect(ceil64(0.2) == 1.0);
}
test "math.ceil32.special" {
- assert(ceil32(0.0) == 0.0);
- assert(ceil32(-0.0) == -0.0);
- assert(math.isPositiveInf(ceil32(math.inf(f32))));
- assert(math.isNegativeInf(ceil32(-math.inf(f32))));
- assert(math.isNan(ceil32(math.nan(f32))));
+ expect(ceil32(0.0) == 0.0);
+ expect(ceil32(-0.0) == -0.0);
+ expect(math.isPositiveInf(ceil32(math.inf(f32))));
+ expect(math.isNegativeInf(ceil32(-math.inf(f32))));
+ expect(math.isNan(ceil32(math.nan(f32))));
}
test "math.ceil64.special" {
- assert(ceil64(0.0) == 0.0);
- assert(ceil64(-0.0) == -0.0);
- assert(math.isPositiveInf(ceil64(math.inf(f64))));
- assert(math.isNegativeInf(ceil64(-math.inf(f64))));
- assert(math.isNan(ceil64(math.nan(f64))));
+ expect(ceil64(0.0) == 0.0);
+ expect(ceil64(-0.0) == -0.0);
+ expect(math.isPositiveInf(ceil64(math.inf(f64))));
+ expect(math.isNegativeInf(ceil64(-math.inf(f64))));
+ expect(math.isNan(ceil64(math.nan(f64))));
}
diff --git a/std/math/complex/abs.zig b/std/math/complex/abs.zig
index 4cd095c46b..245d67d4c5 100644
--- a/std/math/complex/abs.zig
+++ b/std/math/complex/abs.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -14,5 +14,5 @@ const epsilon = 0.0001;
test "complex.cabs" {
const a = Complex(f32).new(5, 3);
const c = abs(a);
- debug.assert(math.approxEq(f32, c, 5.83095, epsilon));
+ testing.expect(math.approxEq(f32, c, 5.83095, epsilon));
}
diff --git a/std/math/complex/acos.zig b/std/math/complex/acos.zig
index a5760b4ace..1b314bc31a 100644
--- a/std/math/complex/acos.zig
+++ b/std/math/complex/acos.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -16,6 +16,6 @@ test "complex.cacos" {
const a = Complex(f32).new(5, 3);
const c = acos(a);
- debug.assert(math.approxEq(f32, c.re, 0.546975, epsilon));
- debug.assert(math.approxEq(f32, c.im, -2.452914, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 0.546975, epsilon));
+ testing.expect(math.approxEq(f32, c.im, -2.452914, epsilon));
}
diff --git a/std/math/complex/acosh.zig b/std/math/complex/acosh.zig
index 8dd91b2836..0e4c0121f4 100644
--- a/std/math/complex/acosh.zig
+++ b/std/math/complex/acosh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -16,6 +16,6 @@ test "complex.cacosh" {
const a = Complex(f32).new(5, 3);
const c = acosh(a);
- debug.assert(math.approxEq(f32, c.re, 2.452914, epsilon));
- debug.assert(math.approxEq(f32, c.im, 0.546975, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 2.452914, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 0.546975, epsilon));
}
diff --git a/std/math/complex/arg.zig b/std/math/complex/arg.zig
index f24512ac73..be117a5940 100644
--- a/std/math/complex/arg.zig
+++ b/std/math/complex/arg.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -14,5 +14,5 @@ const epsilon = 0.0001;
test "complex.carg" {
const a = Complex(f32).new(5, 3);
const c = arg(a);
- debug.assert(math.approxEq(f32, c, 0.540420, epsilon));
+ testing.expect(math.approxEq(f32, c, 0.540420, epsilon));
}
diff --git a/std/math/complex/asin.zig b/std/math/complex/asin.zig
index 584a3a1a9b..cf802ea206 100644
--- a/std/math/complex/asin.zig
+++ b/std/math/complex/asin.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -22,6 +22,6 @@ test "complex.casin" {
const a = Complex(f32).new(5, 3);
const c = asin(a);
- debug.assert(math.approxEq(f32, c.re, 1.023822, epsilon));
- debug.assert(math.approxEq(f32, c.im, 2.452914, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 1.023822, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 2.452914, epsilon));
}
diff --git a/std/math/complex/asinh.zig b/std/math/complex/asinh.zig
index 0c4dc2b6e4..0386a636b0 100644
--- a/std/math/complex/asinh.zig
+++ b/std/math/complex/asinh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -17,6 +17,6 @@ test "complex.casinh" {
const a = Complex(f32).new(5, 3);
const c = asinh(a);
- debug.assert(math.approxEq(f32, c.re, 2.459831, epsilon));
- debug.assert(math.approxEq(f32, c.im, 0.533999, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 2.459831, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 0.533999, epsilon));
}
diff --git a/std/math/complex/atan.zig b/std/math/complex/atan.zig
index de60f2546d..8e60e58e43 100644
--- a/std/math/complex/atan.zig
+++ b/std/math/complex/atan.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -117,14 +117,14 @@ test "complex.catan32" {
const a = Complex(f32).new(5, 3);
const c = atan(a);
- debug.assert(math.approxEq(f32, c.re, 1.423679, epsilon));
- debug.assert(math.approxEq(f32, c.im, 0.086569, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 1.423679, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 0.086569, epsilon));
}
test "complex.catan64" {
const a = Complex(f64).new(5, 3);
const c = atan(a);
- debug.assert(math.approxEq(f64, c.re, 1.423679, epsilon));
- debug.assert(math.approxEq(f64, c.im, 0.086569, epsilon));
+ testing.expect(math.approxEq(f64, c.re, 1.423679, epsilon));
+ testing.expect(math.approxEq(f64, c.im, 0.086569, epsilon));
}
diff --git a/std/math/complex/atanh.zig b/std/math/complex/atanh.zig
index f70c741765..5b18fe1992 100644
--- a/std/math/complex/atanh.zig
+++ b/std/math/complex/atanh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -17,6 +17,6 @@ test "complex.catanh" {
const a = Complex(f32).new(5, 3);
const c = atanh(a);
- debug.assert(math.approxEq(f32, c.re, 0.146947, epsilon));
- debug.assert(math.approxEq(f32, c.im, 1.480870, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 0.146947, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 1.480870, epsilon));
}
diff --git a/std/math/complex/conj.zig b/std/math/complex/conj.zig
index ad3e8b5036..143543f9e7 100644
--- a/std/math/complex/conj.zig
+++ b/std/math/complex/conj.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -13,5 +13,5 @@ test "complex.conj" {
const a = Complex(f32).new(5, 3);
const c = a.conjugate();
- debug.assert(c.re == 5 and c.im == -3);
+ testing.expect(c.re == 5 and c.im == -3);
}
diff --git a/std/math/complex/cos.zig b/std/math/complex/cos.zig
index 96e4ffcdb0..658d19c3b6 100644
--- a/std/math/complex/cos.zig
+++ b/std/math/complex/cos.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -16,6 +16,6 @@ test "complex.ccos" {
const a = Complex(f32).new(5, 3);
const c = cos(a);
- debug.assert(math.approxEq(f32, c.re, 2.855815, epsilon));
- debug.assert(math.approxEq(f32, c.im, 9.606383, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 2.855815, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 9.606383, epsilon));
}
diff --git a/std/math/complex/cosh.zig b/std/math/complex/cosh.zig
index 91875a0c47..5ce10b03f8 100644
--- a/std/math/complex/cosh.zig
+++ b/std/math/complex/cosh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -152,14 +152,14 @@ test "complex.ccosh32" {
const a = Complex(f32).new(5, 3);
const c = cosh(a);
- debug.assert(math.approxEq(f32, c.re, -73.467300, epsilon));
- debug.assert(math.approxEq(f32, c.im, 10.471557, epsilon));
+ testing.expect(math.approxEq(f32, c.re, -73.467300, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 10.471557, epsilon));
}
test "complex.ccosh64" {
const a = Complex(f64).new(5, 3);
const c = cosh(a);
- debug.assert(math.approxEq(f64, c.re, -73.467300, epsilon));
- debug.assert(math.approxEq(f64, c.im, 10.471557, epsilon));
+ testing.expect(math.approxEq(f64, c.re, -73.467300, epsilon));
+ testing.expect(math.approxEq(f64, c.im, 10.471557, epsilon));
}
diff --git a/std/math/complex/exp.zig b/std/math/complex/exp.zig
index 0473f653b6..9ded698d08 100644
--- a/std/math/complex/exp.zig
+++ b/std/math/complex/exp.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -118,14 +118,14 @@ test "complex.cexp32" {
const a = Complex(f32).new(5, 3);
const c = exp(a);
- debug.assert(math.approxEq(f32, c.re, -146.927917, epsilon));
- debug.assert(math.approxEq(f32, c.im, 20.944065, epsilon));
+ testing.expect(math.approxEq(f32, c.re, -146.927917, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 20.944065, epsilon));
}
test "complex.cexp64" {
const a = Complex(f64).new(5, 3);
const c = exp(a);
- debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon));
- debug.assert(math.approxEq(f64, c.im, 20.944065, epsilon));
+ testing.expect(math.approxEq(f64, c.re, -146.927917, epsilon));
+ testing.expect(math.approxEq(f64, c.im, 20.944065, epsilon));
}
diff --git a/std/math/complex/index.zig b/std/math/complex/index.zig
index 171c4c5829..ffbf14d83e 100644
--- a/std/math/complex/index.zig
+++ b/std/math/complex/index.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
pub const abs = @import("abs.zig").abs;
@@ -97,7 +97,7 @@ test "complex.add" {
const b = Complex(f32).new(2, 7);
const c = a.add(b);
- debug.assert(c.re == 7 and c.im == 10);
+ testing.expect(c.re == 7 and c.im == 10);
}
test "complex.sub" {
@@ -105,7 +105,7 @@ test "complex.sub" {
const b = Complex(f32).new(2, 7);
const c = a.sub(b);
- debug.assert(c.re == 3 and c.im == -4);
+ testing.expect(c.re == 3 and c.im == -4);
}
test "complex.mul" {
@@ -113,7 +113,7 @@ test "complex.mul" {
const b = Complex(f32).new(2, 7);
const c = a.mul(b);
- debug.assert(c.re == -11 and c.im == 41);
+ testing.expect(c.re == -11 and c.im == 41);
}
test "complex.div" {
@@ -121,7 +121,7 @@ test "complex.div" {
const b = Complex(f32).new(2, 7);
const c = a.div(b);
- debug.assert(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and
+ testing.expect(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and
math.approxEq(f32, c.im, f32(-29) / 53, epsilon));
}
@@ -129,14 +129,14 @@ test "complex.conjugate" {
const a = Complex(f32).new(5, 3);
const c = a.conjugate();
- debug.assert(c.re == 5 and c.im == -3);
+ testing.expect(c.re == 5 and c.im == -3);
}
test "complex.reciprocal" {
const a = Complex(f32).new(5, 3);
const c = a.reciprocal();
- debug.assert(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and
+ testing.expect(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and
math.approxEq(f32, c.im, f32(-3) / 34, epsilon));
}
@@ -144,7 +144,7 @@ test "complex.magnitude" {
const a = Complex(f32).new(5, 3);
const c = a.magnitude();
- debug.assert(math.approxEq(f32, c, 5.83095, epsilon));
+ testing.expect(math.approxEq(f32, c, 5.83095, epsilon));
}
test "complex.cmath" {
diff --git a/std/math/complex/log.zig b/std/math/complex/log.zig
index a4a1d1664f..360bb7d21e 100644
--- a/std/math/complex/log.zig
+++ b/std/math/complex/log.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -18,6 +18,6 @@ test "complex.clog" {
const a = Complex(f32).new(5, 3);
const c = log(a);
- debug.assert(math.approxEq(f32, c.re, 1.763180, epsilon));
- debug.assert(math.approxEq(f32, c.im, 0.540419, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 1.763180, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 0.540419, epsilon));
}
diff --git a/std/math/complex/pow.zig b/std/math/complex/pow.zig
index edf68653b6..bd625626c8 100644
--- a/std/math/complex/pow.zig
+++ b/std/math/complex/pow.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -17,6 +17,6 @@ test "complex.cpow" {
const b = Complex(f32).new(2.3, -1.3);
const c = pow(Complex(f32), a, b);
- debug.assert(math.approxEq(f32, c.re, 58.049110, epsilon));
- debug.assert(math.approxEq(f32, c.im, -101.003433, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 58.049110, epsilon));
+ testing.expect(math.approxEq(f32, c.im, -101.003433, epsilon));
}
diff --git a/std/math/complex/proj.zig b/std/math/complex/proj.zig
index b6c4cc046e..d31006129e 100644
--- a/std/math/complex/proj.zig
+++ b/std/math/complex/proj.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -20,5 +20,5 @@ test "complex.cproj" {
const a = Complex(f32).new(5, 3);
const c = proj(a);
- debug.assert(c.re == 5 and c.im == 3);
+ testing.expect(c.re == 5 and c.im == 3);
}
diff --git a/std/math/complex/sin.zig b/std/math/complex/sin.zig
index d32b771d3b..9d54ab0969 100644
--- a/std/math/complex/sin.zig
+++ b/std/math/complex/sin.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -17,6 +17,6 @@ test "complex.csin" {
const a = Complex(f32).new(5, 3);
const c = sin(a);
- debug.assert(math.approxEq(f32, c.re, -9.654126, epsilon));
- debug.assert(math.approxEq(f32, c.im, 2.841692, epsilon));
+ testing.expect(math.approxEq(f32, c.re, -9.654126, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 2.841692, epsilon));
}
diff --git a/std/math/complex/sinh.zig b/std/math/complex/sinh.zig
index dc19a0ba1b..469ea6067a 100644
--- a/std/math/complex/sinh.zig
+++ b/std/math/complex/sinh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -151,14 +151,14 @@ test "complex.csinh32" {
const a = Complex(f32).new(5, 3);
const c = sinh(a);
- debug.assert(math.approxEq(f32, c.re, -73.460617, epsilon));
- debug.assert(math.approxEq(f32, c.im, 10.472508, epsilon));
+ testing.expect(math.approxEq(f32, c.re, -73.460617, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 10.472508, epsilon));
}
test "complex.csinh64" {
const a = Complex(f64).new(5, 3);
const c = sinh(a);
- debug.assert(math.approxEq(f64, c.re, -73.460617, epsilon));
- debug.assert(math.approxEq(f64, c.im, 10.472508, epsilon));
+ testing.expect(math.approxEq(f64, c.re, -73.460617, epsilon));
+ testing.expect(math.approxEq(f64, c.im, 10.472508, epsilon));
}
diff --git a/std/math/complex/sqrt.zig b/std/math/complex/sqrt.zig
index 47367816f7..60f6061baa 100644
--- a/std/math/complex/sqrt.zig
+++ b/std/math/complex/sqrt.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -125,14 +125,14 @@ test "complex.csqrt32" {
const a = Complex(f32).new(5, 3);
const c = sqrt(a);
- debug.assert(math.approxEq(f32, c.re, 2.327117, epsilon));
- debug.assert(math.approxEq(f32, c.im, 0.644574, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 2.327117, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 0.644574, epsilon));
}
test "complex.csqrt64" {
const a = Complex(f64).new(5, 3);
const c = sqrt(a);
- debug.assert(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));
- debug.assert(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));
+ testing.expect(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));
+ testing.expect(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));
}
diff --git a/std/math/complex/tan.zig b/std/math/complex/tan.zig
index 4ea5182fa7..db34580598 100644
--- a/std/math/complex/tan.zig
+++ b/std/math/complex/tan.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -17,6 +17,6 @@ test "complex.ctan" {
const a = Complex(f32).new(5, 3);
const c = tan(a);
- debug.assert(math.approxEq(f32, c.re, -0.002708233, epsilon));
- debug.assert(math.approxEq(f32, c.im, 1.004165, epsilon));
+ testing.expect(math.approxEq(f32, c.re, -0.002708233, epsilon));
+ testing.expect(math.approxEq(f32, c.im, 1.004165, epsilon));
}
diff --git a/std/math/complex/tanh.zig b/std/math/complex/tanh.zig
index e48d438783..03ab431312 100644
--- a/std/math/complex/tanh.zig
+++ b/std/math/complex/tanh.zig
@@ -1,5 +1,5 @@
const std = @import("../../index.zig");
-const debug = std.debug;
+const testing = std.testing;
const math = std.math;
const cmath = math.complex;
const Complex = cmath.Complex;
@@ -100,14 +100,14 @@ test "complex.ctanh32" {
const a = Complex(f32).new(5, 3);
const c = tanh(a);
- debug.assert(math.approxEq(f32, c.re, 0.999913, epsilon));
- debug.assert(math.approxEq(f32, c.im, -0.000025, epsilon));
+ testing.expect(math.approxEq(f32, c.re, 0.999913, epsilon));
+ testing.expect(math.approxEq(f32, c.im, -0.000025, epsilon));
}
test "complex.ctanh64" {
const a = Complex(f64).new(5, 3);
const c = tanh(a);
- debug.assert(math.approxEq(f64, c.re, 0.999913, epsilon));
- debug.assert(math.approxEq(f64, c.im, -0.000025, epsilon));
+ testing.expect(math.approxEq(f64, c.re, 0.999913, epsilon));
+ testing.expect(math.approxEq(f64, c.im, -0.000025, epsilon));
}
diff --git a/std/math/copysign.zig b/std/math/copysign.zig
index 4c6e333d6c..dbf8f6e1ef 100644
--- a/std/math/copysign.zig
+++ b/std/math/copysign.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn copysign(comptime T: type, x: T, y: T) T {
@@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 {
}
test "math.copysign" {
- assert(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
- assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
- assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
+ expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
+ expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
+ expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
}
test "math.copysign16" {
- assert(copysign16(5.0, 1.0) == 5.0);
- assert(copysign16(5.0, -1.0) == -5.0);
- assert(copysign16(-5.0, -1.0) == -5.0);
- assert(copysign16(-5.0, 1.0) == 5.0);
+ expect(copysign16(5.0, 1.0) == 5.0);
+ expect(copysign16(5.0, -1.0) == -5.0);
+ expect(copysign16(-5.0, -1.0) == -5.0);
+ expect(copysign16(-5.0, 1.0) == 5.0);
}
test "math.copysign32" {
- assert(copysign32(5.0, 1.0) == 5.0);
- assert(copysign32(5.0, -1.0) == -5.0);
- assert(copysign32(-5.0, -1.0) == -5.0);
- assert(copysign32(-5.0, 1.0) == 5.0);
+ expect(copysign32(5.0, 1.0) == 5.0);
+ expect(copysign32(5.0, -1.0) == -5.0);
+ expect(copysign32(-5.0, -1.0) == -5.0);
+ expect(copysign32(-5.0, 1.0) == 5.0);
}
test "math.copysign64" {
- assert(copysign64(5.0, 1.0) == 5.0);
- assert(copysign64(5.0, -1.0) == -5.0);
- assert(copysign64(-5.0, -1.0) == -5.0);
- assert(copysign64(-5.0, 1.0) == 5.0);
+ expect(copysign64(5.0, 1.0) == 5.0);
+ expect(copysign64(5.0, -1.0) == -5.0);
+ expect(copysign64(-5.0, -1.0) == -5.0);
+ expect(copysign64(-5.0, 1.0) == 5.0);
}
diff --git a/std/math/cos.zig b/std/math/cos.zig
index b6a2fbffe6..7783ddc09b 100644
--- a/std/math/cos.zig
+++ b/std/math/cos.zig
@@ -6,7 +6,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn cos(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 {
}
test "math.cos" {
- assert(cos(f32(0.0)) == cos32(0.0));
- assert(cos(f64(0.0)) == cos64(0.0));
+ expect(cos(f32(0.0)) == cos32(0.0));
+ expect(cos(f64(0.0)) == cos64(0.0));
}
test "math.cos32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
- assert(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
- assert(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
- assert(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
- assert(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
- assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
+ expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
+ expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
+ expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
+ expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
+ expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
+ expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
}
test "math.cos64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
- assert(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
- assert(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
- assert(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
- assert(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
- assert(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
+ expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
+ expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
+ expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
+ expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
+ expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
+ expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
}
test "math.cos32.special" {
- assert(math.isNan(cos32(math.inf(f32))));
- assert(math.isNan(cos32(-math.inf(f32))));
- assert(math.isNan(cos32(math.nan(f32))));
+ expect(math.isNan(cos32(math.inf(f32))));
+ expect(math.isNan(cos32(-math.inf(f32))));
+ expect(math.isNan(cos32(math.nan(f32))));
}
test "math.cos64.special" {
- assert(math.isNan(cos64(math.inf(f64))));
- assert(math.isNan(cos64(-math.inf(f64))));
- assert(math.isNan(cos64(math.nan(f64))));
+ expect(math.isNan(cos64(math.inf(f64))));
+ expect(math.isNan(cos64(-math.inf(f64))));
+ expect(math.isNan(cos64(math.nan(f64))));
}
diff --git a/std/math/cosh.zig b/std/math/cosh.zig
index 77e02855fd..57c5eef828 100644
--- a/std/math/cosh.zig
+++ b/std/math/cosh.zig
@@ -8,7 +8,7 @@ const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
const expo2 = @import("expo2.zig").expo2;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn cosh(x: var) @typeOf(x) {
@@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 {
}
test "math.cosh" {
- assert(cosh(f32(1.5)) == cosh32(1.5));
- assert(cosh(f64(1.5)) == cosh64(1.5));
+ expect(cosh(f32(1.5)) == cosh32(1.5));
+ expect(cosh(f64(1.5)) == cosh64(1.5));
}
test "math.cosh32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
- assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
- assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
- assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
+ expect(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
+ expect(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
+ expect(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
+ expect(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
}
test "math.cosh64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
- assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
- assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
- assert(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));
+ expect(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
+ expect(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
+ expect(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
+ expect(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));
}
test "math.cosh32.special" {
- assert(cosh32(0.0) == 1.0);
- assert(cosh32(-0.0) == 1.0);
- assert(math.isPositiveInf(cosh32(math.inf(f32))));
- assert(math.isPositiveInf(cosh32(-math.inf(f32))));
- assert(math.isNan(cosh32(math.nan(f32))));
+ expect(cosh32(0.0) == 1.0);
+ expect(cosh32(-0.0) == 1.0);
+ expect(math.isPositiveInf(cosh32(math.inf(f32))));
+ expect(math.isPositiveInf(cosh32(-math.inf(f32))));
+ expect(math.isNan(cosh32(math.nan(f32))));
}
test "math.cosh64.special" {
- assert(cosh64(0.0) == 1.0);
- assert(cosh64(-0.0) == 1.0);
- assert(math.isPositiveInf(cosh64(math.inf(f64))));
- assert(math.isPositiveInf(cosh64(-math.inf(f64))));
- assert(math.isNan(cosh64(math.nan(f64))));
+ expect(cosh64(0.0) == 1.0);
+ expect(cosh64(-0.0) == 1.0);
+ expect(math.isPositiveInf(cosh64(math.inf(f64))));
+ expect(math.isPositiveInf(cosh64(-math.inf(f64))));
+ expect(math.isNan(cosh64(math.nan(f64))));
}
diff --git a/std/math/exp2.zig b/std/math/exp2.zig
index 3d8e5d692e..ba0001a09a 100644
--- a/std/math/exp2.zig
+++ b/std/math/exp2.zig
@@ -5,7 +5,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn exp2(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 {
}
test "math.exp2" {
- assert(exp2(f32(0.8923)) == exp2_32(0.8923));
- assert(exp2(f64(0.8923)) == exp2_64(0.8923));
+ expect(exp2(f32(0.8923)) == exp2_32(0.8923));
+ expect(exp2(f64(0.8923)) == exp2_64(0.8923));
}
test "math.exp2_32" {
const epsilon = 0.000001;
- assert(exp2_32(0.0) == 1.0);
- assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
- assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
- assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
- assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
+ expect(exp2_32(0.0) == 1.0);
+ expect(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
+ expect(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
+ expect(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
+ expect(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
}
test "math.exp2_64" {
const epsilon = 0.000001;
- assert(exp2_64(0.0) == 1.0);
- assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
- assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
- assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
+ expect(exp2_64(0.0) == 1.0);
+ expect(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
+ expect(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
+ expect(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
}
test "math.exp2_32.special" {
- assert(math.isPositiveInf(exp2_32(math.inf(f32))));
- assert(math.isNan(exp2_32(math.nan(f32))));
+ expect(math.isPositiveInf(exp2_32(math.inf(f32))));
+ expect(math.isNan(exp2_32(math.nan(f32))));
}
test "math.exp2_64.special" {
- assert(math.isPositiveInf(exp2_64(math.inf(f64))));
- assert(math.isNan(exp2_64(math.nan(f64))));
+ expect(math.isPositiveInf(exp2_64(math.inf(f64))));
+ expect(math.isNan(exp2_64(math.nan(f64))));
}
diff --git a/std/math/expm1.zig b/std/math/expm1.zig
index 6729417f60..ba00ec2561 100644
--- a/std/math/expm1.zig
+++ b/std/math/expm1.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn expm1(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 {
}
test "math.exp1m" {
- assert(expm1(f32(0.0)) == expm1_32(0.0));
- assert(expm1(f64(0.0)) == expm1_64(0.0));
+ expect(expm1(f32(0.0)) == expm1_32(0.0));
+ expect(expm1(f64(0.0)) == expm1_64(0.0));
}
test "math.expm1_32" {
const epsilon = 0.000001;
- assert(expm1_32(0.0) == 0.0);
- assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
- assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
- assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
+ expect(expm1_32(0.0) == 0.0);
+ expect(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
+ expect(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
+ expect(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
}
test "math.expm1_64" {
const epsilon = 0.000001;
- assert(expm1_64(0.0) == 0.0);
- assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
- assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
- assert(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));
+ expect(expm1_64(0.0) == 0.0);
+ expect(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
+ expect(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
+ expect(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));
}
test "math.expm1_32.special" {
const epsilon = 0.000001;
- assert(math.isPositiveInf(expm1_32(math.inf(f32))));
- assert(expm1_32(-math.inf(f32)) == -1.0);
- assert(math.isNan(expm1_32(math.nan(f32))));
+ expect(math.isPositiveInf(expm1_32(math.inf(f32))));
+ expect(expm1_32(-math.inf(f32)) == -1.0);
+ expect(math.isNan(expm1_32(math.nan(f32))));
}
test "math.expm1_64.special" {
const epsilon = 0.000001;
- assert(math.isPositiveInf(expm1_64(math.inf(f64))));
- assert(expm1_64(-math.inf(f64)) == -1.0);
- assert(math.isNan(expm1_64(math.nan(f64))));
+ expect(math.isPositiveInf(expm1_64(math.inf(f64))));
+ expect(expm1_64(-math.inf(f64)) == -1.0);
+ expect(math.isNan(expm1_64(math.nan(f64))));
}
diff --git a/std/math/fabs.zig b/std/math/fabs.zig
index 443010ac7f..a605f4f33f 100644
--- a/std/math/fabs.zig
+++ b/std/math/fabs.zig
@@ -5,7 +5,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn fabs(x: var) @typeOf(x) {
@@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {
f16 => fabs16(x),
f32 => fabs32(x),
f64 => fabs64(x),
+ f128 => fabs128(x),
else => @compileError("fabs not implemented for " ++ @typeName(T)),
};
}
@@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 {
return @bitCast(f64, u);
}
+fn fabs128(x: f128) f128 {
+ var u = @bitCast(u128, x);
+ u &= maxInt(u128) >> 1;
+ return @bitCast(f128, u);
+}
+
test "math.fabs" {
- assert(fabs(f16(1.0)) == fabs16(1.0));
- assert(fabs(f32(1.0)) == fabs32(1.0));
- assert(fabs(f64(1.0)) == fabs64(1.0));
+ expect(fabs(f16(1.0)) == fabs16(1.0));
+ expect(fabs(f32(1.0)) == fabs32(1.0));
+ expect(fabs(f64(1.0)) == fabs64(1.0));
+ expect(fabs(f128(1.0)) == fabs128(1.0));
}
test "math.fabs16" {
- assert(fabs16(1.0) == 1.0);
- assert(fabs16(-1.0) == 1.0);
+ expect(fabs16(1.0) == 1.0);
+ expect(fabs16(-1.0) == 1.0);
}
test "math.fabs32" {
- assert(fabs32(1.0) == 1.0);
- assert(fabs32(-1.0) == 1.0);
+ expect(fabs32(1.0) == 1.0);
+ expect(fabs32(-1.0) == 1.0);
}
test "math.fabs64" {
- assert(fabs64(1.0) == 1.0);
- assert(fabs64(-1.0) == 1.0);
+ expect(fabs64(1.0) == 1.0);
+ expect(fabs64(-1.0) == 1.0);
+}
+
+test "math.fabs128" {
+ expect(fabs128(1.0) == 1.0);
+ expect(fabs128(-1.0) == 1.0);
}
test "math.fabs16.special" {
- assert(math.isPositiveInf(fabs(math.inf(f16))));
- assert(math.isPositiveInf(fabs(-math.inf(f16))));
- assert(math.isNan(fabs(math.nan(f16))));
+ expect(math.isPositiveInf(fabs(math.inf(f16))));
+ expect(math.isPositiveInf(fabs(-math.inf(f16))));
+ expect(math.isNan(fabs(math.nan(f16))));
}
test "math.fabs32.special" {
- assert(math.isPositiveInf(fabs(math.inf(f32))));
- assert(math.isPositiveInf(fabs(-math.inf(f32))));
- assert(math.isNan(fabs(math.nan(f32))));
+ expect(math.isPositiveInf(fabs(math.inf(f32))));
+ expect(math.isPositiveInf(fabs(-math.inf(f32))));
+ expect(math.isNan(fabs(math.nan(f32))));
}
test "math.fabs64.special" {
- assert(math.isPositiveInf(fabs(math.inf(f64))));
- assert(math.isPositiveInf(fabs(-math.inf(f64))));
- assert(math.isNan(fabs(math.nan(f64))));
+ expect(math.isPositiveInf(fabs(math.inf(f64))));
+ expect(math.isPositiveInf(fabs(-math.inf(f64))));
+ expect(math.isNan(fabs(math.nan(f64))));
+}
+
+test "math.fabs128.special" {
+ expect(math.isPositiveInf(fabs(math.inf(f128))));
+ expect(math.isPositiveInf(fabs(-math.inf(f128))));
+ expect(math.isNan(fabs(math.nan(f128))));
}
diff --git a/std/math/floor.zig b/std/math/floor.zig
index 6ce462b10f..c7c12e37ba 100644
--- a/std/math/floor.zig
+++ b/std/math/floor.zig
@@ -5,7 +5,7 @@
// - floor(nan) = nan
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const std = @import("../index.zig");
const math = std.math;
@@ -117,49 +117,49 @@ fn floor64(x: f64) f64 {
}
test "math.floor" {
- assert(floor(f16(1.3)) == floor16(1.3));
- assert(floor(f32(1.3)) == floor32(1.3));
- assert(floor(f64(1.3)) == floor64(1.3));
+ expect(floor(f16(1.3)) == floor16(1.3));
+ expect(floor(f32(1.3)) == floor32(1.3));
+ expect(floor(f64(1.3)) == floor64(1.3));
}
test "math.floor16" {
- assert(floor16(1.3) == 1.0);
- assert(floor16(-1.3) == -2.0);
- assert(floor16(0.2) == 0.0);
+ expect(floor16(1.3) == 1.0);
+ expect(floor16(-1.3) == -2.0);
+ expect(floor16(0.2) == 0.0);
}
test "math.floor32" {
- assert(floor32(1.3) == 1.0);
- assert(floor32(-1.3) == -2.0);
- assert(floor32(0.2) == 0.0);
+ expect(floor32(1.3) == 1.0);
+ expect(floor32(-1.3) == -2.0);
+ expect(floor32(0.2) == 0.0);
}
test "math.floor64" {
- assert(floor64(1.3) == 1.0);
- assert(floor64(-1.3) == -2.0);
- assert(floor64(0.2) == 0.0);
+ expect(floor64(1.3) == 1.0);
+ expect(floor64(-1.3) == -2.0);
+ expect(floor64(0.2) == 0.0);
}
test "math.floor16.special" {
- assert(floor16(0.0) == 0.0);
- assert(floor16(-0.0) == -0.0);
- assert(math.isPositiveInf(floor16(math.inf(f16))));
- assert(math.isNegativeInf(floor16(-math.inf(f16))));
- assert(math.isNan(floor16(math.nan(f16))));
+ expect(floor16(0.0) == 0.0);
+ expect(floor16(-0.0) == -0.0);
+ expect(math.isPositiveInf(floor16(math.inf(f16))));
+ expect(math.isNegativeInf(floor16(-math.inf(f16))));
+ expect(math.isNan(floor16(math.nan(f16))));
}
test "math.floor32.special" {
- assert(floor32(0.0) == 0.0);
- assert(floor32(-0.0) == -0.0);
- assert(math.isPositiveInf(floor32(math.inf(f32))));
- assert(math.isNegativeInf(floor32(-math.inf(f32))));
- assert(math.isNan(floor32(math.nan(f32))));
+ expect(floor32(0.0) == 0.0);
+ expect(floor32(-0.0) == -0.0);
+ expect(math.isPositiveInf(floor32(math.inf(f32))));
+ expect(math.isNegativeInf(floor32(-math.inf(f32))));
+ expect(math.isNan(floor32(math.nan(f32))));
}
test "math.floor64.special" {
- assert(floor64(0.0) == 0.0);
- assert(floor64(-0.0) == -0.0);
- assert(math.isPositiveInf(floor64(math.inf(f64))));
- assert(math.isNegativeInf(floor64(-math.inf(f64))));
- assert(math.isNan(floor64(math.nan(f64))));
+ expect(floor64(0.0) == 0.0);
+ expect(floor64(-0.0) == -0.0);
+ expect(math.isPositiveInf(floor64(math.inf(f64))));
+ expect(math.isNegativeInf(floor64(-math.inf(f64))));
+ expect(math.isNan(floor64(math.nan(f64))));
}
diff --git a/std/math/fma.zig b/std/math/fma.zig
index 21faf4118d..b084cf3cbd 100644
--- a/std/math/fma.zig
+++ b/std/math/fma.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn fma(comptime T: type, x: T, y: T, z: T) T {
return switch (T) {
@@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
}
test "math.fma" {
- assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));
- assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));
+ expect(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));
+ expect(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));
}
test "math.fma32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));
- assert(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon));
- assert(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon));
- assert(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon));
- assert(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon));
- assert(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon));
- assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
+ expect(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));
+ expect(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon));
+ expect(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon));
+ expect(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon));
+ expect(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon));
+ expect(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon));
+ expect(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
}
test "math.fma64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));
- assert(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon));
- assert(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon));
- assert(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon));
- assert(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon));
- assert(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon));
- assert(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
+ expect(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));
+ expect(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon));
+ expect(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon));
+ expect(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon));
+ expect(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon));
+ expect(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon));
+ expect(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
}
diff --git a/std/math/frexp.zig b/std/math/frexp.zig
index dfc790fdd9..35f3e081a9 100644
--- a/std/math/frexp.zig
+++ b/std/math/frexp.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
fn frexp_result(comptime T: type) type {
return struct {
@@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result {
test "math.frexp" {
const a = frexp(f32(1.3));
const b = frexp32(1.3);
- assert(a.significand == b.significand and a.exponent == b.exponent);
+ expect(a.significand == b.significand and a.exponent == b.exponent);
const c = frexp(f64(1.3));
const d = frexp64(1.3);
- assert(c.significand == d.significand and c.exponent == d.exponent);
+ expect(c.significand == d.significand and c.exponent == d.exponent);
}
test "math.frexp32" {
@@ -115,10 +115,10 @@ test "math.frexp32" {
var r: frexp32_result = undefined;
r = frexp32(1.3);
- assert(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1);
+ expect(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1);
r = frexp32(78.0234);
- assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);
+ expect(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);
}
test "math.frexp64" {
@@ -126,46 +126,46 @@ test "math.frexp64" {
var r: frexp64_result = undefined;
r = frexp64(1.3);
- assert(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1);
+ expect(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1);
r = frexp64(78.0234);
- assert(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7);
+ expect(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7);
}
test "math.frexp32.special" {
var r: frexp32_result = undefined;
r = frexp32(0.0);
- assert(r.significand == 0.0 and r.exponent == 0);
+ expect(r.significand == 0.0 and r.exponent == 0);
r = frexp32(-0.0);
- assert(r.significand == -0.0 and r.exponent == 0);
+ expect(r.significand == -0.0 and r.exponent == 0);
r = frexp32(math.inf(f32));
- assert(math.isPositiveInf(r.significand) and r.exponent == 0);
+ expect(math.isPositiveInf(r.significand) and r.exponent == 0);
r = frexp32(-math.inf(f32));
- assert(math.isNegativeInf(r.significand) and r.exponent == 0);
+ expect(math.isNegativeInf(r.significand) and r.exponent == 0);
r = frexp32(math.nan(f32));
- assert(math.isNan(r.significand));
+ expect(math.isNan(r.significand));
}
test "math.frexp64.special" {
var r: frexp64_result = undefined;
r = frexp64(0.0);
- assert(r.significand == 0.0 and r.exponent == 0);
+ expect(r.significand == 0.0 and r.exponent == 0);
r = frexp64(-0.0);
- assert(r.significand == -0.0 and r.exponent == 0);
+ expect(r.significand == -0.0 and r.exponent == 0);
r = frexp64(math.inf(f64));
- assert(math.isPositiveInf(r.significand) and r.exponent == 0);
+ expect(math.isPositiveInf(r.significand) and r.exponent == 0);
r = frexp64(-math.inf(f64));
- assert(math.isNegativeInf(r.significand) and r.exponent == 0);
+ expect(math.isNegativeInf(r.significand) and r.exponent == 0);
r = frexp64(math.nan(f64));
- assert(math.isNan(r.significand));
+ expect(math.isNan(r.significand));
}
diff --git a/std/math/hypot.zig b/std/math/hypot.zig
index a63657a621..dea11e0a61 100644
--- a/std/math/hypot.zig
+++ b/std/math/hypot.zig
@@ -7,7 +7,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn hypot(comptime T: type, x: T, y: T) T {
@@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 {
}
test "math.hypot" {
- assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
- assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
+ expect(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
+ expect(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
}
test "math.hypot32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
- assert(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));
- assert(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));
- assert(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));
- assert(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));
- assert(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));
- assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
+ expect(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
+ expect(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));
+ expect(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));
+ expect(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));
+ expect(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));
+ expect(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));
+ expect(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
}
test "math.hypot64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
- assert(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));
- assert(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));
- assert(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));
- assert(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));
- assert(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));
- assert(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));
+ expect(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
+ expect(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));
+ expect(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));
+ expect(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));
+ expect(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));
+ expect(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));
+ expect(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));
}
test "math.hypot32.special" {
- assert(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));
- assert(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));
- assert(math.isPositiveInf(hypot32(0.0, math.inf(f32))));
- assert(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));
- assert(math.isNan(hypot32(math.nan(f32), 0.0)));
- assert(math.isNan(hypot32(0.0, math.nan(f32))));
+ expect(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));
+ expect(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));
+ expect(math.isPositiveInf(hypot32(0.0, math.inf(f32))));
+ expect(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));
+ expect(math.isNan(hypot32(math.nan(f32), 0.0)));
+ expect(math.isNan(hypot32(0.0, math.nan(f32))));
}
test "math.hypot64.special" {
- assert(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));
- assert(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));
- assert(math.isPositiveInf(hypot64(0.0, math.inf(f64))));
- assert(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));
- assert(math.isNan(hypot64(math.nan(f64), 0.0)));
- assert(math.isNan(hypot64(0.0, math.nan(f64))));
+ expect(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));
+ expect(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));
+ expect(math.isPositiveInf(hypot64(0.0, math.inf(f64))));
+ expect(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));
+ expect(math.isNan(hypot64(math.nan(f64), 0.0)));
+ expect(math.isNan(hypot64(0.0, math.nan(f64))));
}
diff --git a/std/math/ilogb.zig b/std/math/ilogb.zig
index e6bdb14012..e7b6485357 100644
--- a/std/math/ilogb.zig
+++ b/std/math/ilogb.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
@@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 {
}
test "math.ilogb" {
- assert(ilogb(f32(0.2)) == ilogb32(0.2));
- assert(ilogb(f64(0.2)) == ilogb64(0.2));
+ expect(ilogb(f32(0.2)) == ilogb32(0.2));
+ expect(ilogb(f64(0.2)) == ilogb64(0.2));
}
test "math.ilogb32" {
- assert(ilogb32(0.0) == fp_ilogb0);
- assert(ilogb32(0.5) == -1);
- assert(ilogb32(0.8923) == -1);
- assert(ilogb32(10.0) == 3);
- assert(ilogb32(-123984) == 16);
- assert(ilogb32(2398.23) == 11);
+ expect(ilogb32(0.0) == fp_ilogb0);
+ expect(ilogb32(0.5) == -1);
+ expect(ilogb32(0.8923) == -1);
+ expect(ilogb32(10.0) == 3);
+ expect(ilogb32(-123984) == 16);
+ expect(ilogb32(2398.23) == 11);
}
test "math.ilogb64" {
- assert(ilogb64(0.0) == fp_ilogb0);
- assert(ilogb64(0.5) == -1);
- assert(ilogb64(0.8923) == -1);
- assert(ilogb64(10.0) == 3);
- assert(ilogb64(-123984) == 16);
- assert(ilogb64(2398.23) == 11);
+ expect(ilogb64(0.0) == fp_ilogb0);
+ expect(ilogb64(0.5) == -1);
+ expect(ilogb64(0.8923) == -1);
+ expect(ilogb64(10.0) == 3);
+ expect(ilogb64(-123984) == 16);
+ expect(ilogb64(2398.23) == 11);
}
test "math.ilogb32.special" {
- assert(ilogb32(math.inf(f32)) == maxInt(i32));
- assert(ilogb32(-math.inf(f32)) == maxInt(i32));
- assert(ilogb32(0.0) == minInt(i32));
- assert(ilogb32(math.nan(f32)) == maxInt(i32));
+ expect(ilogb32(math.inf(f32)) == maxInt(i32));
+ expect(ilogb32(-math.inf(f32)) == maxInt(i32));
+ expect(ilogb32(0.0) == minInt(i32));
+ expect(ilogb32(math.nan(f32)) == maxInt(i32));
}
test "math.ilogb64.special" {
- assert(ilogb64(math.inf(f64)) == maxInt(i32));
- assert(ilogb64(-math.inf(f64)) == maxInt(i32));
- assert(ilogb64(0.0) == minInt(i32));
- assert(ilogb64(math.nan(f64)) == maxInt(i32));
+ expect(ilogb64(math.inf(f64)) == maxInt(i32));
+ expect(ilogb64(-math.inf(f64)) == maxInt(i32));
+ expect(ilogb64(0.0) == minInt(i32));
+ expect(ilogb64(math.nan(f64)) == maxInt(i32));
}
diff --git a/std/math/index.zig b/std/math/index.zig
index 83bd2310d0..20648139b8 100644
--- a/std/math/index.zig
+++ b/std/math/index.zig
@@ -2,10 +2,18 @@ const builtin = @import("builtin");
const std = @import("../index.zig");
const TypeId = builtin.TypeId;
const assert = std.debug.assert;
+const testing = std.testing;
pub const e = 2.71828182845904523536028747135266249775724709369995;
pub const pi = 3.14159265358979323846264338327950288419716939937510;
+// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
+pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
+pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
+pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
+pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
+pub const f128_toint = 1.0 / f128_epsilon;
+
// float.h details
pub const f64_true_min = 4.94065645841246544177e-324;
pub const f64_min = 2.2250738585072014e-308;
@@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64);
pub const inf_u64 = u64(0x7FF << 52);
pub const inf_f64 = @bitCast(f64, inf_u64);
+pub const nan_u128 = u128(0x7fff0000000000000000000000000001);
+pub const nan_f128 = @bitCast(f128, nan_u128);
+
+pub const inf_u128 = u128(0x7fff0000000000000000000000000000);
+pub const inf_f128 = @bitCast(f128, inf_u128);
+
pub const nan = @import("nan.zig").nan;
pub const snan = @import("nan.zig").snan;
pub const inf = @import("inf.zig").inf;
@@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) {
}
test "math.min" {
- assert(min(i32(-1), i32(2)) == -1);
+ testing.expect(min(i32(-1), i32(2)) == -1);
}
pub fn max(x: var, y: var) @typeOf(x + y) {
@@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) {
}
test "math.max" {
- assert(max(i32(-1), i32(2)) == 2);
+ testing.expect(max(i32(-1), i32(2)) == 2);
}
pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) {
@@ -286,10 +300,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T {
}
test "math.shl" {
- assert(shl(u8, 0b11111111, usize(3)) == 0b11111000);
- assert(shl(u8, 0b11111111, usize(8)) == 0);
- assert(shl(u8, 0b11111111, usize(9)) == 0);
- assert(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
+ testing.expect(shl(u8, 0b11111111, usize(3)) == 0b11111000);
+ testing.expect(shl(u8, 0b11111111, usize(8)) == 0);
+ testing.expect(shl(u8, 0b11111111, usize(9)) == 0);
+ testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
}
/// Shifts right. Overflowed bits are truncated.
@@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T {
}
test "math.shr" {
- assert(shr(u8, 0b11111111, usize(3)) == 0b00011111);
- assert(shr(u8, 0b11111111, usize(8)) == 0);
- assert(shr(u8, 0b11111111, usize(9)) == 0);
- assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
+ testing.expect(shr(u8, 0b11111111, usize(3)) == 0b00011111);
+ testing.expect(shr(u8, 0b11111111, usize(8)) == 0);
+ testing.expect(shr(u8, 0b11111111, usize(9)) == 0);
+ testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
}
/// Rotates right. Only unsigned values can be rotated.
@@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T {
}
test "math.rotr" {
- assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
- assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
- assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
- assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
- assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
+ testing.expect(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
+ testing.expect(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
+ testing.expect(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
+ testing.expect(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
+ testing.expect(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
}
/// Rotates left. Only unsigned values can be rotated.
@@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T {
}
test "math.rotl" {
- assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
- assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
- assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
- assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
- assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
+ testing.expect(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
+ testing.expect(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
+ testing.expect(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
+ testing.expect(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
+ testing.expect(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
}
pub fn Log2Int(comptime T: type) type {
@@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
return u0;
}
const is_signed = from < 0;
- const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement
+ const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
const base = log2(largest_positive_integer);
const upper = (1 << base) - 1;
var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
@@ -382,50 +396,50 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
}
test "math.IntFittingRange" {
- assert(IntFittingRange(0, 0) == u0);
- assert(IntFittingRange(0, 1) == u1);
- assert(IntFittingRange(0, 2) == u2);
- assert(IntFittingRange(0, 3) == u2);
- assert(IntFittingRange(0, 4) == u3);
- assert(IntFittingRange(0, 7) == u3);
- assert(IntFittingRange(0, 8) == u4);
- assert(IntFittingRange(0, 9) == u4);
- assert(IntFittingRange(0, 15) == u4);
- assert(IntFittingRange(0, 16) == u5);
- assert(IntFittingRange(0, 17) == u5);
- assert(IntFittingRange(0, 4095) == u12);
- assert(IntFittingRange(2000, 4095) == u12);
- assert(IntFittingRange(0, 4096) == u13);
- assert(IntFittingRange(2000, 4096) == u13);
- assert(IntFittingRange(0, 4097) == u13);
- assert(IntFittingRange(2000, 4097) == u13);
- assert(IntFittingRange(0, 123456789123456798123456789) == u87);
- assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
+ testing.expect(IntFittingRange(0, 0) == u0);
+ testing.expect(IntFittingRange(0, 1) == u1);
+ testing.expect(IntFittingRange(0, 2) == u2);
+ testing.expect(IntFittingRange(0, 3) == u2);
+ testing.expect(IntFittingRange(0, 4) == u3);
+ testing.expect(IntFittingRange(0, 7) == u3);
+ testing.expect(IntFittingRange(0, 8) == u4);
+ testing.expect(IntFittingRange(0, 9) == u4);
+ testing.expect(IntFittingRange(0, 15) == u4);
+ testing.expect(IntFittingRange(0, 16) == u5);
+ testing.expect(IntFittingRange(0, 17) == u5);
+ testing.expect(IntFittingRange(0, 4095) == u12);
+ testing.expect(IntFittingRange(2000, 4095) == u12);
+ testing.expect(IntFittingRange(0, 4096) == u13);
+ testing.expect(IntFittingRange(2000, 4096) == u13);
+ testing.expect(IntFittingRange(0, 4097) == u13);
+ testing.expect(IntFittingRange(2000, 4097) == u13);
+ testing.expect(IntFittingRange(0, 123456789123456798123456789) == u87);
+ testing.expect(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
- assert(IntFittingRange(-1, -1) == i1);
- assert(IntFittingRange(-1, 0) == i1);
- assert(IntFittingRange(-1, 1) == i2);
- assert(IntFittingRange(-2, -2) == i2);
- assert(IntFittingRange(-2, -1) == i2);
- assert(IntFittingRange(-2, 0) == i2);
- assert(IntFittingRange(-2, 1) == i2);
- assert(IntFittingRange(-2, 2) == i3);
- assert(IntFittingRange(-1, 2) == i3);
- assert(IntFittingRange(-1, 3) == i3);
- assert(IntFittingRange(-1, 4) == i4);
- assert(IntFittingRange(-1, 7) == i4);
- assert(IntFittingRange(-1, 8) == i5);
- assert(IntFittingRange(-1, 9) == i5);
- assert(IntFittingRange(-1, 15) == i5);
- assert(IntFittingRange(-1, 16) == i6);
- assert(IntFittingRange(-1, 17) == i6);
- assert(IntFittingRange(-1, 4095) == i13);
- assert(IntFittingRange(-4096, 4095) == i13);
- assert(IntFittingRange(-1, 4096) == i14);
- assert(IntFittingRange(-4097, 4095) == i14);
- assert(IntFittingRange(-1, 4097) == i14);
- assert(IntFittingRange(-1, 123456789123456798123456789) == i88);
- assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
+ testing.expect(IntFittingRange(-1, -1) == i1);
+ testing.expect(IntFittingRange(-1, 0) == i1);
+ testing.expect(IntFittingRange(-1, 1) == i2);
+ testing.expect(IntFittingRange(-2, -2) == i2);
+ testing.expect(IntFittingRange(-2, -1) == i2);
+ testing.expect(IntFittingRange(-2, 0) == i2);
+ testing.expect(IntFittingRange(-2, 1) == i2);
+ testing.expect(IntFittingRange(-2, 2) == i3);
+ testing.expect(IntFittingRange(-1, 2) == i3);
+ testing.expect(IntFittingRange(-1, 3) == i3);
+ testing.expect(IntFittingRange(-1, 4) == i4);
+ testing.expect(IntFittingRange(-1, 7) == i4);
+ testing.expect(IntFittingRange(-1, 8) == i5);
+ testing.expect(IntFittingRange(-1, 9) == i5);
+ testing.expect(IntFittingRange(-1, 15) == i5);
+ testing.expect(IntFittingRange(-1, 16) == i6);
+ testing.expect(IntFittingRange(-1, 17) == i6);
+ testing.expect(IntFittingRange(-1, 4095) == i13);
+ testing.expect(IntFittingRange(-4096, 4095) == i13);
+ testing.expect(IntFittingRange(-1, 4096) == i14);
+ testing.expect(IntFittingRange(-4097, 4095) == i14);
+ testing.expect(IntFittingRange(-1, 4097) == i14);
+ testing.expect(IntFittingRange(-1, 123456789123456798123456789) == i88);
+ testing.expect(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
}
test "math overflow functions" {
@@ -434,10 +448,10 @@ test "math overflow functions" {
}
fn testOverflow() void {
- assert((mul(i32, 3, 4) catch unreachable) == 12);
- assert((add(i32, 3, 4) catch unreachable) == 7);
- assert((sub(i32, 3, 4) catch unreachable) == -1);
- assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
+ testing.expect((mul(i32, 3, 4) catch unreachable) == 12);
+ testing.expect((add(i32, 3, 4) catch unreachable) == 7);
+ testing.expect((sub(i32, 3, 4) catch unreachable) == -1);
+ testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
}
pub fn absInt(x: var) !@typeOf(x) {
@@ -458,8 +472,8 @@ test "math.absInt" {
comptime testAbsInt();
}
fn testAbsInt() void {
- assert((absInt(i32(-10)) catch unreachable) == 10);
- assert((absInt(i32(10)) catch unreachable) == 10);
+ testing.expect((absInt(i32(-10)) catch unreachable) == 10);
+ testing.expect((absInt(i32(10)) catch unreachable) == 10);
}
pub const absFloat = @import("fabs.zig").fabs;
@@ -476,13 +490,13 @@ test "math.divTrunc" {
comptime testDivTrunc();
}
fn testDivTrunc() void {
- assert((divTrunc(i32, 5, 3) catch unreachable) == 1);
- assert((divTrunc(i32, -5, 3) catch unreachable) == -1);
- if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
- if (divTrunc(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
+ testing.expect((divTrunc(i32, 5, 3) catch unreachable) == 1);
+ testing.expect((divTrunc(i32, -5, 3) catch unreachable) == -1);
+ testing.expectError(error.DivisionByZero, divTrunc(i8, -5, 0));
+ testing.expectError(error.Overflow, divTrunc(i8, -128, -1));
- assert((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);
- assert((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
+ testing.expect((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);
+ testing.expect((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
}
pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
@@ -497,13 +511,13 @@ test "math.divFloor" {
comptime testDivFloor();
}
fn testDivFloor() void {
- assert((divFloor(i32, 5, 3) catch unreachable) == 1);
- assert((divFloor(i32, -5, 3) catch unreachable) == -2);
- if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
- if (divFloor(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
+ testing.expect((divFloor(i32, 5, 3) catch unreachable) == 1);
+ testing.expect((divFloor(i32, -5, 3) catch unreachable) == -2);
+ testing.expectError(error.DivisionByZero, divFloor(i8, -5, 0));
+ testing.expectError(error.Overflow, divFloor(i8, -128, -1));
- assert((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);
- assert((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
+ testing.expect((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);
+ testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
}
pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
@@ -520,15 +534,15 @@ test "math.divExact" {
comptime testDivExact();
}
fn testDivExact() void {
- assert((divExact(i32, 10, 5) catch unreachable) == 2);
- assert((divExact(i32, -10, 5) catch unreachable) == -2);
- if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
- if (divExact(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
- if (divExact(i32, 5, 2)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);
+ testing.expect((divExact(i32, 10, 5) catch unreachable) == 2);
+ testing.expect((divExact(i32, -10, 5) catch unreachable) == -2);
+ testing.expectError(error.DivisionByZero, divExact(i8, -5, 0));
+ testing.expectError(error.Overflow, divExact(i8, -128, -1));
+ testing.expectError(error.UnexpectedRemainder, divExact(i32, 5, 2));
- assert((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);
- assert((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0);
- if (divExact(f32, 5.0, 2.0)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);
+ testing.expect((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);
+ testing.expect((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0);
+ testing.expectError(error.UnexpectedRemainder, divExact(f32, 5.0, 2.0));
}
pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
@@ -543,15 +557,15 @@ test "math.mod" {
comptime testMod();
}
fn testMod() void {
- assert((mod(i32, -5, 3) catch unreachable) == 1);
- assert((mod(i32, 5, 3) catch unreachable) == 2);
- if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
- if (mod(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
+ testing.expect((mod(i32, -5, 3) catch unreachable) == 1);
+ testing.expect((mod(i32, 5, 3) catch unreachable) == 2);
+ testing.expectError(error.NegativeDenominator, mod(i32, 10, -1));
+ testing.expectError(error.DivisionByZero, mod(i32, 10, 0));
- assert((mod(f32, -5, 3) catch unreachable) == 1);
- assert((mod(f32, 5, 3) catch unreachable) == 2);
- if (mod(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
- if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
+ testing.expect((mod(f32, -5, 3) catch unreachable) == 1);
+ testing.expect((mod(f32, 5, 3) catch unreachable) == 2);
+ testing.expectError(error.NegativeDenominator, mod(f32, 10, -1));
+ testing.expectError(error.DivisionByZero, mod(f32, 10, 0));
}
pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
@@ -566,15 +580,15 @@ test "math.rem" {
comptime testRem();
}
fn testRem() void {
- assert((rem(i32, -5, 3) catch unreachable) == -2);
- assert((rem(i32, 5, 3) catch unreachable) == 2);
- if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
- if (rem(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
+ testing.expect((rem(i32, -5, 3) catch unreachable) == -2);
+ testing.expect((rem(i32, 5, 3) catch unreachable) == 2);
+ testing.expectError(error.NegativeDenominator, rem(i32, 10, -1));
+ testing.expectError(error.DivisionByZero, rem(i32, 10, 0));
- assert((rem(f32, -5, 3) catch unreachable) == -2);
- assert((rem(f32, 5, 3) catch unreachable) == 2);
- if (rem(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
- if (rem(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
+ testing.expect((rem(f32, -5, 3) catch unreachable) == -2);
+ testing.expect((rem(f32, 5, 3) catch unreachable) == 2);
+ testing.expectError(error.NegativeDenominator, rem(f32, 10, -1));
+ testing.expectError(error.DivisionByZero, rem(f32, 10, 0));
}
/// Returns the absolute value of the integer parameter.
@@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
}
test "math.absCast" {
- assert(absCast(i32(-999)) == 999);
- assert(@typeOf(absCast(i32(-999))) == u32);
+ testing.expect(absCast(i32(-999)) == 999);
+ testing.expect(@typeOf(absCast(i32(-999))) == u32);
- assert(absCast(i32(999)) == 999);
- assert(@typeOf(absCast(i32(999))) == u32);
+ testing.expect(absCast(i32(999)) == 999);
+ testing.expect(@typeOf(absCast(i32(999))) == u32);
- assert(absCast(i32(minInt(i32))) == -minInt(i32));
- assert(@typeOf(absCast(i32(minInt(i32)))) == u32);
+ testing.expect(absCast(i32(minInt(i32))) == -minInt(i32));
+ testing.expect(@typeOf(absCast(i32(minInt(i32)))) == u32);
}
/// Returns the negation of the integer parameter.
@@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
}
test "math.negateCast" {
- assert((negateCast(u32(999)) catch unreachable) == -999);
- assert(@typeOf(negateCast(u32(999)) catch unreachable) == i32);
+ testing.expect((negateCast(u32(999)) catch unreachable) == -999);
+ testing.expect(@typeOf(negateCast(u32(999)) catch unreachable) == i32);
- assert((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32));
- assert(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32);
+ testing.expect((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32));
+ testing.expect(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32);
- if (negateCast(u32(maxInt(i32) + 10))) |_| unreachable else |err| assert(err == error.Overflow);
+ testing.expectError(error.Overflow, negateCast(u32(maxInt(i32) + 10)));
}
/// Cast an integer to a different integer type. If the value doesn't fit,
@@ -635,13 +649,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) {
}
test "math.cast" {
- if (cast(u8, u32(300))) |_| @panic("fail") else |err| assert(err == error.Overflow);
- if (cast(i8, i32(-200))) |_| @panic("fail") else |err| assert(err == error.Overflow);
- if (cast(u8, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);
- if (cast(u64, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);
+ testing.expectError(error.Overflow, cast(u8, u32(300)));
+ testing.expectError(error.Overflow, cast(i8, i32(-200)));
+ testing.expectError(error.Overflow, cast(u8, i8(-1)));
+ testing.expectError(error.Overflow, cast(u64, i8(-1)));
- assert((try cast(u8, u32(255))) == u8(255));
- assert(@typeOf(try cast(u8, u32(255))) == u8);
+ testing.expect((try cast(u8, u32(255))) == u8(255));
+ testing.expect(@typeOf(try cast(u8, u32(255))) == u8);
}
pub const AlignCastError = error{UnalignedMemory};
@@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
}
test "std.math.log2_int_ceil" {
- assert(log2_int_ceil(u32, 1) == 0);
- assert(log2_int_ceil(u32, 2) == 1);
- assert(log2_int_ceil(u32, 3) == 2);
- assert(log2_int_ceil(u32, 4) == 2);
- assert(log2_int_ceil(u32, 5) == 3);
- assert(log2_int_ceil(u32, 6) == 3);
- assert(log2_int_ceil(u32, 7) == 3);
- assert(log2_int_ceil(u32, 8) == 3);
- assert(log2_int_ceil(u32, 9) == 4);
- assert(log2_int_ceil(u32, 10) == 4);
+ testing.expect(log2_int_ceil(u32, 1) == 0);
+ testing.expect(log2_int_ceil(u32, 2) == 1);
+ testing.expect(log2_int_ceil(u32, 3) == 2);
+ testing.expect(log2_int_ceil(u32, 4) == 2);
+ testing.expect(log2_int_ceil(u32, 5) == 3);
+ testing.expect(log2_int_ceil(u32, 6) == 3);
+ testing.expect(log2_int_ceil(u32, 7) == 3);
+ testing.expect(log2_int_ceil(u32, 8) == 3);
+ testing.expect(log2_int_ceil(u32, 9) == 4);
+ testing.expect(log2_int_ceil(u32, 10) == 4);
}
fn testFloorPowerOfTwo() void {
- assert(floorPowerOfTwo(u32, 63) == 32);
- assert(floorPowerOfTwo(u32, 64) == 64);
- assert(floorPowerOfTwo(u32, 65) == 64);
- assert(floorPowerOfTwo(u4, 7) == 4);
- assert(floorPowerOfTwo(u4, 8) == 8);
- assert(floorPowerOfTwo(u4, 9) == 8);
+ testing.expect(floorPowerOfTwo(u32, 63) == 32);
+ testing.expect(floorPowerOfTwo(u32, 64) == 64);
+ testing.expect(floorPowerOfTwo(u32, 65) == 64);
+ testing.expect(floorPowerOfTwo(u4, 7) == 4);
+ testing.expect(floorPowerOfTwo(u4, 8) == 8);
+ testing.expect(floorPowerOfTwo(u4, 9) == 8);
}
pub fn lossyCast(comptime T: type, value: var) T {
@@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T {
test "math.f64_min" {
const f64_min_u64 = 0x0010000000000000;
const fmin: f64 = f64_min;
- assert(@bitCast(u64, fmin) == f64_min_u64);
+ testing.expect(@bitCast(u64, fmin) == f64_min_u64);
}
pub fn maxInt(comptime T: type) comptime_int {
@@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int {
}
test "minInt and maxInt" {
- assert(maxInt(u0) == 0);
- assert(maxInt(u1) == 1);
- assert(maxInt(u8) == 255);
- assert(maxInt(u16) == 65535);
- assert(maxInt(u32) == 4294967295);
- assert(maxInt(u64) == 18446744073709551615);
+ testing.expect(maxInt(u0) == 0);
+ testing.expect(maxInt(u1) == 1);
+ testing.expect(maxInt(u8) == 255);
+ testing.expect(maxInt(u16) == 65535);
+ testing.expect(maxInt(u32) == 4294967295);
+ testing.expect(maxInt(u64) == 18446744073709551615);
+ testing.expect(maxInt(u128) == 340282366920938463463374607431768211455);
- assert(maxInt(i0) == 0);
- assert(maxInt(i1) == 0);
- assert(maxInt(i8) == 127);
- assert(maxInt(i16) == 32767);
- assert(maxInt(i32) == 2147483647);
- assert(maxInt(i63) == 4611686018427387903);
- assert(maxInt(i64) == 9223372036854775807);
+ testing.expect(maxInt(i0) == 0);
+ testing.expect(maxInt(i1) == 0);
+ testing.expect(maxInt(i8) == 127);
+ testing.expect(maxInt(i16) == 32767);
+ testing.expect(maxInt(i32) == 2147483647);
+ testing.expect(maxInt(i63) == 4611686018427387903);
+ testing.expect(maxInt(i64) == 9223372036854775807);
+ testing.expect(maxInt(i128) == 170141183460469231731687303715884105727);
- assert(minInt(u0) == 0);
- assert(minInt(u1) == 0);
- assert(minInt(u8) == 0);
- assert(minInt(u16) == 0);
- assert(minInt(u32) == 0);
- assert(minInt(u63) == 0);
- assert(minInt(u64) == 0);
+ testing.expect(minInt(u0) == 0);
+ testing.expect(minInt(u1) == 0);
+ testing.expect(minInt(u8) == 0);
+ testing.expect(minInt(u16) == 0);
+ testing.expect(minInt(u32) == 0);
+ testing.expect(minInt(u63) == 0);
+ testing.expect(minInt(u64) == 0);
+ testing.expect(minInt(u128) == 0);
- assert(minInt(i0) == 0);
- assert(minInt(i1) == -1);
- assert(minInt(i8) == -128);
- assert(minInt(i16) == -32768);
- assert(minInt(i32) == -2147483648);
- assert(minInt(i63) == -4611686018427387904);
- assert(minInt(i64) == -9223372036854775808);
+ testing.expect(minInt(i0) == 0);
+ testing.expect(minInt(i1) == -1);
+ testing.expect(minInt(i8) == -128);
+ testing.expect(minInt(i16) == -32768);
+ testing.expect(minInt(i32) == -2147483648);
+ testing.expect(minInt(i63) == -4611686018427387904);
+ testing.expect(minInt(i64) == -9223372036854775808);
+ testing.expect(minInt(i128) == -170141183460469231731687303715884105728);
}
test "max value type" {
@@ -775,5 +793,5 @@ test "max value type" {
// u32 would not work. But since the value is a number literal,
// it works fine.
const x: u32 = maxInt(i32);
- assert(x == 2147483647);
+ testing.expect(x == 2147483647);
}
diff --git a/std/math/inf.zig b/std/math/inf.zig
index 62f5ef7c0d..fb7a3489c5 100644
--- a/std/math/inf.zig
+++ b/std/math/inf.zig
@@ -3,9 +3,10 @@ const math = std.math;
pub fn inf(comptime T: type) T {
return switch (T) {
- f16 => @bitCast(f16, math.inf_u16),
- f32 => @bitCast(f32, math.inf_u32),
- f64 => @bitCast(f64, math.inf_u64),
+ f16 => math.inf_f16,
+ f32 => math.inf_f32,
+ f64 => math.inf_f64,
+ f128 => math.inf_f128,
else => @compileError("inf not implemented for " ++ @typeName(T)),
};
}
diff --git a/std/math/isfinite.zig b/std/math/isfinite.zig
index bdfdff8f9f..bf1c9ac63c 100644
--- a/std/math/isfinite.zig
+++ b/std/math/isfinite.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn isFinite(x: var) bool {
@@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool {
}
test "math.isFinite" {
- assert(isFinite(f16(0.0)));
- assert(isFinite(f16(-0.0)));
- assert(isFinite(f32(0.0)));
- assert(isFinite(f32(-0.0)));
- assert(isFinite(f64(0.0)));
- assert(isFinite(f64(-0.0)));
- assert(!isFinite(math.inf(f16)));
- assert(!isFinite(-math.inf(f16)));
- assert(!isFinite(math.inf(f32)));
- assert(!isFinite(-math.inf(f32)));
- assert(!isFinite(math.inf(f64)));
- assert(!isFinite(-math.inf(f64)));
+ expect(isFinite(f16(0.0)));
+ expect(isFinite(f16(-0.0)));
+ expect(isFinite(f32(0.0)));
+ expect(isFinite(f32(-0.0)));
+ expect(isFinite(f64(0.0)));
+ expect(isFinite(f64(-0.0)));
+ expect(!isFinite(math.inf(f16)));
+ expect(!isFinite(-math.inf(f16)));
+ expect(!isFinite(math.inf(f32)));
+ expect(!isFinite(-math.inf(f32)));
+ expect(!isFinite(math.inf(f64)));
+ expect(!isFinite(-math.inf(f64)));
}
diff --git a/std/math/isinf.zig b/std/math/isinf.zig
index 93f66cc870..b1e3f7795e 100644
--- a/std/math/isinf.zig
+++ b/std/math/isinf.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn isInf(x: var) bool {
@@ -18,6 +18,10 @@ pub fn isInf(x: var) bool {
const bits = @bitCast(u64, x);
return bits & (maxInt(u64) >> 1) == (0x7FF << 52);
},
+ f128 => {
+ const bits = @bitCast(u128, x);
+ return bits & (maxInt(u128) >> 1) == (0x7FFF << 112);
+ },
else => {
@compileError("isInf not implemented for " ++ @typeName(T));
},
@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {
f64 => {
return @bitCast(u64, x) == 0x7FF << 52;
},
+ f128 => {
+ return @bitCast(u128, x) == 0x7FFF << 112;
+ },
else => {
@compileError("isPositiveInf not implemented for " ++ @typeName(T));
},
@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {
f64 => {
return @bitCast(u64, x) == 0xFFF << 52;
},
+ f128 => {
+ return @bitCast(u128, x) == 0xFFFF << 112;
+ },
else => {
@compileError("isNegativeInf not implemented for " ++ @typeName(T));
},
@@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool {
}
test "math.isInf" {
- assert(!isInf(f16(0.0)));
- assert(!isInf(f16(-0.0)));
- assert(!isInf(f32(0.0)));
- assert(!isInf(f32(-0.0)));
- assert(!isInf(f64(0.0)));
- assert(!isInf(f64(-0.0)));
- assert(isInf(math.inf(f16)));
- assert(isInf(-math.inf(f16)));
- assert(isInf(math.inf(f32)));
- assert(isInf(-math.inf(f32)));
- assert(isInf(math.inf(f64)));
- assert(isInf(-math.inf(f64)));
+ expect(!isInf(f16(0.0)));
+ expect(!isInf(f16(-0.0)));
+ expect(!isInf(f32(0.0)));
+ expect(!isInf(f32(-0.0)));
+ expect(!isInf(f64(0.0)));
+ expect(!isInf(f64(-0.0)));
+ expect(!isInf(f128(0.0)));
+ expect(!isInf(f128(-0.0)));
+ expect(isInf(math.inf(f16)));
+ expect(isInf(-math.inf(f16)));
+ expect(isInf(math.inf(f32)));
+ expect(isInf(-math.inf(f32)));
+ expect(isInf(math.inf(f64)));
+ expect(isInf(-math.inf(f64)));
+ expect(isInf(math.inf(f128)));
+ expect(isInf(-math.inf(f128)));
}
test "math.isPositiveInf" {
- assert(!isPositiveInf(f16(0.0)));
- assert(!isPositiveInf(f16(-0.0)));
- assert(!isPositiveInf(f32(0.0)));
- assert(!isPositiveInf(f32(-0.0)));
- assert(!isPositiveInf(f64(0.0)));
- assert(!isPositiveInf(f64(-0.0)));
- assert(isPositiveInf(math.inf(f16)));
- assert(!isPositiveInf(-math.inf(f16)));
- assert(isPositiveInf(math.inf(f32)));
- assert(!isPositiveInf(-math.inf(f32)));
- assert(isPositiveInf(math.inf(f64)));
- assert(!isPositiveInf(-math.inf(f64)));
+ expect(!isPositiveInf(f16(0.0)));
+ expect(!isPositiveInf(f16(-0.0)));
+ expect(!isPositiveInf(f32(0.0)));
+ expect(!isPositiveInf(f32(-0.0)));
+ expect(!isPositiveInf(f64(0.0)));
+ expect(!isPositiveInf(f64(-0.0)));
+ expect(!isPositiveInf(f128(0.0)));
+ expect(!isPositiveInf(f128(-0.0)));
+ expect(isPositiveInf(math.inf(f16)));
+ expect(!isPositiveInf(-math.inf(f16)));
+ expect(isPositiveInf(math.inf(f32)));
+ expect(!isPositiveInf(-math.inf(f32)));
+ expect(isPositiveInf(math.inf(f64)));
+ expect(!isPositiveInf(-math.inf(f64)));
+ expect(isPositiveInf(math.inf(f128)));
+ expect(!isPositiveInf(-math.inf(f128)));
}
test "math.isNegativeInf" {
- assert(!isNegativeInf(f16(0.0)));
- assert(!isNegativeInf(f16(-0.0)));
- assert(!isNegativeInf(f32(0.0)));
- assert(!isNegativeInf(f32(-0.0)));
- assert(!isNegativeInf(f64(0.0)));
- assert(!isNegativeInf(f64(-0.0)));
- assert(!isNegativeInf(math.inf(f16)));
- assert(isNegativeInf(-math.inf(f16)));
- assert(!isNegativeInf(math.inf(f32)));
- assert(isNegativeInf(-math.inf(f32)));
- assert(!isNegativeInf(math.inf(f64)));
- assert(isNegativeInf(-math.inf(f64)));
+ expect(!isNegativeInf(f16(0.0)));
+ expect(!isNegativeInf(f16(-0.0)));
+ expect(!isNegativeInf(f32(0.0)));
+ expect(!isNegativeInf(f32(-0.0)));
+ expect(!isNegativeInf(f64(0.0)));
+ expect(!isNegativeInf(f64(-0.0)));
+ expect(!isNegativeInf(f128(0.0)));
+ expect(!isNegativeInf(f128(-0.0)));
+ expect(!isNegativeInf(math.inf(f16)));
+ expect(isNegativeInf(-math.inf(f16)));
+ expect(!isNegativeInf(math.inf(f32)));
+ expect(isNegativeInf(-math.inf(f32)));
+ expect(!isNegativeInf(math.inf(f64)));
+ expect(isNegativeInf(-math.inf(f64)));
+ expect(!isNegativeInf(math.inf(f128)));
+ expect(isNegativeInf(-math.inf(f128)));
}
diff --git a/std/math/isnan.zig b/std/math/isnan.zig
index a2cb85b4f7..e8b03a1e34 100644
--- a/std/math/isnan.zig
+++ b/std/math/isnan.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn isNan(x: var) bool {
@@ -18,6 +18,10 @@ pub fn isNan(x: var) bool {
const bits = @bitCast(u64, x);
return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);
},
+ f128 => {
+ const bits = @bitCast(u128, x);
+ return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112);
+ },
else => {
@compileError("isNan not implemented for " ++ @typeName(T));
},
@@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool {
}
test "math.isNan" {
- assert(isNan(math.nan(f16)));
- assert(isNan(math.nan(f32)));
- assert(isNan(math.nan(f64)));
- assert(!isNan(f16(1.0)));
- assert(!isNan(f32(1.0)));
- assert(!isNan(f64(1.0)));
+ expect(isNan(math.nan(f16)));
+ expect(isNan(math.nan(f32)));
+ expect(isNan(math.nan(f64)));
+ expect(isNan(math.nan(f128)));
+ expect(!isNan(f16(1.0)));
+ expect(!isNan(f32(1.0)));
+ expect(!isNan(f64(1.0)));
+ expect(!isNan(f128(1.0)));
}
diff --git a/std/math/isnormal.zig b/std/math/isnormal.zig
index cc088e46a0..2c57aea7a9 100644
--- a/std/math/isnormal.zig
+++ b/std/math/isnormal.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn isNormal(x: var) bool {
@@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool {
}
test "math.isNormal" {
- assert(!isNormal(math.nan(f16)));
- assert(!isNormal(math.nan(f32)));
- assert(!isNormal(math.nan(f64)));
- assert(!isNormal(f16(0)));
- assert(!isNormal(f32(0)));
- assert(!isNormal(f64(0)));
- assert(isNormal(f16(1.0)));
- assert(isNormal(f32(1.0)));
- assert(isNormal(f64(1.0)));
+ expect(!isNormal(math.nan(f16)));
+ expect(!isNormal(math.nan(f32)));
+ expect(!isNormal(math.nan(f64)));
+ expect(!isNormal(f16(0)));
+ expect(!isNormal(f32(0)));
+ expect(!isNormal(f64(0)));
+ expect(isNormal(f16(1.0)));
+ expect(isNormal(f32(1.0)));
+ expect(isNormal(f64(1.0)));
}
diff --git a/std/math/ln.zig b/std/math/ln.zig
index a560fee8ec..257ce8054f 100644
--- a/std/math/ln.zig
+++ b/std/math/ln.zig
@@ -7,7 +7,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
@@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 {
}
test "math.ln" {
- assert(ln(f32(0.2)) == ln_32(0.2));
- assert(ln(f64(0.2)) == ln_64(0.2));
+ expect(ln(f32(0.2)) == ln_32(0.2));
+ expect(ln(f64(0.2)) == ln_64(0.2));
}
test "math.ln32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));
- assert(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));
- assert(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));
- assert(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));
- assert(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));
- assert(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));
+ expect(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));
+ expect(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));
+ expect(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));
+ expect(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));
+ expect(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));
+ expect(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));
}
test "math.ln64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));
- assert(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));
- assert(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));
- assert(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));
- assert(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));
- assert(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));
+ expect(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));
+ expect(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));
+ expect(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));
+ expect(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));
+ expect(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));
+ expect(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));
}
test "math.ln32.special" {
- assert(math.isPositiveInf(ln_32(math.inf(f32))));
- assert(math.isNegativeInf(ln_32(0.0)));
- assert(math.isNan(ln_32(-1.0)));
- assert(math.isNan(ln_32(math.nan(f32))));
+ expect(math.isPositiveInf(ln_32(math.inf(f32))));
+ expect(math.isNegativeInf(ln_32(0.0)));
+ expect(math.isNan(ln_32(-1.0)));
+ expect(math.isNan(ln_32(math.nan(f32))));
}
test "math.ln64.special" {
- assert(math.isPositiveInf(ln_64(math.inf(f64))));
- assert(math.isNegativeInf(ln_64(0.0)));
- assert(math.isNan(ln_64(-1.0)));
- assert(math.isNan(ln_64(math.nan(f64))));
+ expect(math.isPositiveInf(ln_64(math.inf(f64))));
+ expect(math.isNegativeInf(ln_64(0.0)));
+ expect(math.isNan(ln_64(-1.0)));
+ expect(math.isNan(ln_64(math.nan(f64))));
}
diff --git a/std/math/log.zig b/std/math/log.zig
index 20b6d055e8..21cffcc078 100644
--- a/std/math/log.zig
+++ b/std/math/log.zig
@@ -2,7 +2,7 @@ const std = @import("../index.zig");
const math = std.math;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn log(comptime T: type, base: T, x: T) T {
if (base == 2) {
@@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T {
}
test "math.log integer" {
- assert(log(u8, 2, 0x1) == 0);
- assert(log(u8, 2, 0x2) == 1);
- assert(log(i16, 2, 0x72) == 6);
- assert(log(u32, 2, 0xFFFFFF) == 23);
- assert(log(u64, 2, 0x7FF0123456789ABC) == 62);
+ expect(log(u8, 2, 0x1) == 0);
+ expect(log(u8, 2, 0x2) == 1);
+ expect(log(i16, 2, 0x72) == 6);
+ expect(log(u32, 2, 0xFFFFFF) == 23);
+ expect(log(u64, 2, 0x7FF0123456789ABC) == 62);
}
test "math.log float" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));
- assert(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));
- assert(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));
+ expect(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));
+ expect(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));
+ expect(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));
}
test "math.log float_special" {
- assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974)));
- assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974)));
+ expect(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974)));
+ expect(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974)));
- assert(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993)));
- assert(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));
+ expect(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993)));
+ expect(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));
}
diff --git a/std/math/log10.zig b/std/math/log10.zig
index 2b53d8a6ae..8055f71280 100644
--- a/std/math/log10.zig
+++ b/std/math/log10.zig
@@ -7,7 +7,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const testing = std.testing;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
@@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 {
}
test "math.log10" {
- assert(log10(f32(0.2)) == log10_32(0.2));
- assert(log10(f64(0.2)) == log10_64(0.2));
+ testing.expect(log10(f32(0.2)) == log10_32(0.2));
+ testing.expect(log10(f64(0.2)) == log10_64(0.2));
}
test "math.log10_32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
- assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
- assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
- assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
- assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
- assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
+ testing.expect(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
}
test "math.log10_64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
- assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
- assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
- assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
- assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
- assert(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
+ testing.expect(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));
}
test "math.log10_32.special" {
- assert(math.isPositiveInf(log10_32(math.inf(f32))));
- assert(math.isNegativeInf(log10_32(0.0)));
- assert(math.isNan(log10_32(-1.0)));
- assert(math.isNan(log10_32(math.nan(f32))));
+ testing.expect(math.isPositiveInf(log10_32(math.inf(f32))));
+ testing.expect(math.isNegativeInf(log10_32(0.0)));
+ testing.expect(math.isNan(log10_32(-1.0)));
+ testing.expect(math.isNan(log10_32(math.nan(f32))));
}
test "math.log10_64.special" {
- assert(math.isPositiveInf(log10_64(math.inf(f64))));
- assert(math.isNegativeInf(log10_64(0.0)));
- assert(math.isNan(log10_64(-1.0)));
- assert(math.isNan(log10_64(math.nan(f64))));
+ testing.expect(math.isPositiveInf(log10_64(math.inf(f64))));
+ testing.expect(math.isNegativeInf(log10_64(0.0)));
+ testing.expect(math.isNan(log10_64(-1.0)));
+ testing.expect(math.isNan(log10_64(math.nan(f64))));
}
diff --git a/std/math/log1p.zig b/std/math/log1p.zig
index 903fceac05..257e7b90d4 100644
--- a/std/math/log1p.zig
+++ b/std/math/log1p.zig
@@ -9,7 +9,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn log1p(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 {
}
test "math.log1p" {
- assert(log1p(f32(0.0)) == log1p_32(0.0));
- assert(log1p(f64(0.0)) == log1p_64(0.0));
+ expect(log1p(f32(0.0)) == log1p_32(0.0));
+ expect(log1p(f64(0.0)) == log1p_64(0.0));
}
test "math.log1p_32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
- assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
- assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
- assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
- assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
- assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
+ expect(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
+ expect(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
+ expect(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
+ expect(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
+ expect(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
+ expect(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
}
test "math.log1p_64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
- assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
- assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
- assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
- assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
- assert(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));
+ expect(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
+ expect(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
+ expect(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
+ expect(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
+ expect(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
+ expect(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));
}
test "math.log1p_32.special" {
- assert(math.isPositiveInf(log1p_32(math.inf(f32))));
- assert(log1p_32(0.0) == 0.0);
- assert(log1p_32(-0.0) == -0.0);
- assert(math.isNegativeInf(log1p_32(-1.0)));
- assert(math.isNan(log1p_32(-2.0)));
- assert(math.isNan(log1p_32(math.nan(f32))));
+ expect(math.isPositiveInf(log1p_32(math.inf(f32))));
+ expect(log1p_32(0.0) == 0.0);
+ expect(log1p_32(-0.0) == -0.0);
+ expect(math.isNegativeInf(log1p_32(-1.0)));
+ expect(math.isNan(log1p_32(-2.0)));
+ expect(math.isNan(log1p_32(math.nan(f32))));
}
test "math.log1p_64.special" {
- assert(math.isPositiveInf(log1p_64(math.inf(f64))));
- assert(log1p_64(0.0) == 0.0);
- assert(log1p_64(-0.0) == -0.0);
- assert(math.isNegativeInf(log1p_64(-1.0)));
- assert(math.isNan(log1p_64(-2.0)));
- assert(math.isNan(log1p_64(math.nan(f64))));
+ expect(math.isPositiveInf(log1p_64(math.inf(f64))));
+ expect(log1p_64(0.0) == 0.0);
+ expect(log1p_64(-0.0) == -0.0);
+ expect(math.isNegativeInf(log1p_64(-1.0)));
+ expect(math.isNan(log1p_64(-2.0)));
+ expect(math.isNan(log1p_64(math.nan(f64))));
}
diff --git a/std/math/log2.zig b/std/math/log2.zig
index 555c0bdf18..1bb51bf9f9 100644
--- a/std/math/log2.zig
+++ b/std/math/log2.zig
@@ -7,7 +7,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
@@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 {
}
test "math.log2" {
- assert(log2(f32(0.2)) == log2_32(0.2));
- assert(log2(f64(0.2)) == log2_64(0.2));
+ expect(log2(f32(0.2)) == log2_32(0.2));
+ expect(log2(f64(0.2)) == log2_64(0.2));
}
test "math.log2_32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
- assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
- assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
- assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
- assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
+ expect(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
+ expect(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
+ expect(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
+ expect(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
+ expect(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
}
test "math.log2_64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
- assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
- assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
- assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
- assert(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));
+ expect(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
+ expect(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
+ expect(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
+ expect(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
+ expect(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));
}
test "math.log2_32.special" {
- assert(math.isPositiveInf(log2_32(math.inf(f32))));
- assert(math.isNegativeInf(log2_32(0.0)));
- assert(math.isNan(log2_32(-1.0)));
- assert(math.isNan(log2_32(math.nan(f32))));
+ expect(math.isPositiveInf(log2_32(math.inf(f32))));
+ expect(math.isNegativeInf(log2_32(0.0)));
+ expect(math.isNan(log2_32(-1.0)));
+ expect(math.isNan(log2_32(math.nan(f32))));
}
test "math.log2_64.special" {
- assert(math.isPositiveInf(log2_64(math.inf(f64))));
- assert(math.isNegativeInf(log2_64(0.0)));
- assert(math.isNan(log2_64(-1.0)));
- assert(math.isNan(log2_64(math.nan(f64))));
+ expect(math.isPositiveInf(log2_64(math.inf(f64))));
+ expect(math.isNegativeInf(log2_64(0.0)));
+ expect(math.isNan(log2_64(-1.0)));
+ expect(math.isNan(log2_64(math.nan(f64))));
}
diff --git a/std/math/modf.zig b/std/math/modf.zig
index 0f619f25bc..2dadda76a9 100644
--- a/std/math/modf.zig
+++ b/std/math/modf.zig
@@ -5,7 +5,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
fn modf_result(comptime T: type) type {
@@ -119,11 +119,11 @@ test "math.modf" {
const a = modf(f32(1.0));
const b = modf32(1.0);
// NOTE: No struct comparison on generic return type function? non-named, makes sense, but still.
- assert(a.ipart == b.ipart and a.fpart == b.fpart);
+ expect(a.ipart == b.ipart and a.fpart == b.fpart);
const c = modf(f64(1.0));
const d = modf64(1.0);
- assert(a.ipart == b.ipart and a.fpart == b.fpart);
+ expect(a.ipart == b.ipart and a.fpart == b.fpart);
}
test "math.modf32" {
@@ -131,24 +131,24 @@ test "math.modf32" {
var r: modf32_result = undefined;
r = modf32(1.0);
- assert(math.approxEq(f32, r.ipart, 1.0, epsilon));
- assert(math.approxEq(f32, r.fpart, 0.0, epsilon));
+ expect(math.approxEq(f32, r.ipart, 1.0, epsilon));
+ expect(math.approxEq(f32, r.fpart, 0.0, epsilon));
r = modf32(2.545);
- assert(math.approxEq(f32, r.ipart, 2.0, epsilon));
- assert(math.approxEq(f32, r.fpart, 0.545, epsilon));
+ expect(math.approxEq(f32, r.ipart, 2.0, epsilon));
+ expect(math.approxEq(f32, r.fpart, 0.545, epsilon));
r = modf32(3.978123);
- assert(math.approxEq(f32, r.ipart, 3.0, epsilon));
- assert(math.approxEq(f32, r.fpart, 0.978123, epsilon));
+ expect(math.approxEq(f32, r.ipart, 3.0, epsilon));
+ expect(math.approxEq(f32, r.fpart, 0.978123, epsilon));
r = modf32(43874.3);
- assert(math.approxEq(f32, r.ipart, 43874, epsilon));
- assert(math.approxEq(f32, r.fpart, 0.300781, epsilon));
+ expect(math.approxEq(f32, r.ipart, 43874, epsilon));
+ expect(math.approxEq(f32, r.fpart, 0.300781, epsilon));
r = modf32(1234.340780);
- assert(math.approxEq(f32, r.ipart, 1234, epsilon));
- assert(math.approxEq(f32, r.fpart, 0.340820, epsilon));
+ expect(math.approxEq(f32, r.ipart, 1234, epsilon));
+ expect(math.approxEq(f32, r.fpart, 0.340820, epsilon));
}
test "math.modf64" {
@@ -156,48 +156,48 @@ test "math.modf64" {
var r: modf64_result = undefined;
r = modf64(1.0);
- assert(math.approxEq(f64, r.ipart, 1.0, epsilon));
- assert(math.approxEq(f64, r.fpart, 0.0, epsilon));
+ expect(math.approxEq(f64, r.ipart, 1.0, epsilon));
+ expect(math.approxEq(f64, r.fpart, 0.0, epsilon));
r = modf64(2.545);
- assert(math.approxEq(f64, r.ipart, 2.0, epsilon));
- assert(math.approxEq(f64, r.fpart, 0.545, epsilon));
+ expect(math.approxEq(f64, r.ipart, 2.0, epsilon));
+ expect(math.approxEq(f64, r.fpart, 0.545, epsilon));
r = modf64(3.978123);
- assert(math.approxEq(f64, r.ipart, 3.0, epsilon));
- assert(math.approxEq(f64, r.fpart, 0.978123, epsilon));
+ expect(math.approxEq(f64, r.ipart, 3.0, epsilon));
+ expect(math.approxEq(f64, r.fpart, 0.978123, epsilon));
r = modf64(43874.3);
- assert(math.approxEq(f64, r.ipart, 43874, epsilon));
- assert(math.approxEq(f64, r.fpart, 0.3, epsilon));
+ expect(math.approxEq(f64, r.ipart, 43874, epsilon));
+ expect(math.approxEq(f64, r.fpart, 0.3, epsilon));
r = modf64(1234.340780);
- assert(math.approxEq(f64, r.ipart, 1234, epsilon));
- assert(math.approxEq(f64, r.fpart, 0.340780, epsilon));
+ expect(math.approxEq(f64, r.ipart, 1234, epsilon));
+ expect(math.approxEq(f64, r.fpart, 0.340780, epsilon));
}
test "math.modf32.special" {
var r: modf32_result = undefined;
r = modf32(math.inf(f32));
- assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
+ expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
r = modf32(-math.inf(f32));
- assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
+ expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
r = modf32(math.nan(f32));
- assert(math.isNan(r.ipart) and math.isNan(r.fpart));
+ expect(math.isNan(r.ipart) and math.isNan(r.fpart));
}
test "math.modf64.special" {
var r: modf64_result = undefined;
r = modf64(math.inf(f64));
- assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
+ expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
r = modf64(-math.inf(f64));
- assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
+ expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
r = modf64(math.nan(f64));
- assert(math.isNan(r.ipart) and math.isNan(r.fpart));
+ expect(math.isNan(r.ipart) and math.isNan(r.fpart));
}
diff --git a/std/math/nan.zig b/std/math/nan.zig
index 2cbcbee81b..d3ad43da23 100644
--- a/std/math/nan.zig
+++ b/std/math/nan.zig
@@ -2,9 +2,10 @@ const math = @import("index.zig");
pub fn nan(comptime T: type) T {
return switch (T) {
- f16 => @bitCast(f16, math.nan_u16),
- f32 => @bitCast(f32, math.nan_u32),
- f64 => @bitCast(f64, math.nan_u64),
+ f16 => math.nan_f16,
+ f32 => math.nan_f32,
+ f64 => math.nan_f64,
+ f128 => math.nan_f128,
else => @compileError("nan not implemented for " ++ @typeName(T)),
};
}
diff --git a/std/math/pow.zig b/std/math/pow.zig
index 39a2bfa9f7..f037f66d7e 100644
--- a/std/math/pow.zig
+++ b/std/math/pow.zig
@@ -24,7 +24,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
// This implementation is taken from the go stlib, musl is a bit more complex.
pub fn pow(comptime T: type, x: T, y: T) T {
@@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool {
test "math.pow" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon));
- assert(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon));
- assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));
- assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
- assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
- assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
+ expect(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon));
+ expect(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon));
+ expect(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));
+ expect(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
+ expect(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
+ expect(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
- assert(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));
- assert(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));
- assert(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon));
- assert(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));
- assert(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));
- assert(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));
+ expect(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));
+ expect(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));
+ expect(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon));
+ expect(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));
+ expect(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));
+ expect(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));
}
test "math.pow.special" {
const epsilon = 0.000001;
- assert(pow(f32, 4, 0.0) == 1.0);
- assert(pow(f32, 7, -0.0) == 1.0);
- assert(pow(f32, 45, 1.0) == 45);
- assert(pow(f32, -45, 1.0) == -45);
- assert(math.isNan(pow(f32, math.nan(f32), 5.0)));
- assert(math.isNan(pow(f32, 5.0, math.nan(f32))));
- assert(math.isPositiveInf(pow(f32, 0.0, -1.0)));
- //assert(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
- assert(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));
- assert(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));
- assert(pow(f32, 0.0, math.inf(f32)) == 0.0);
- assert(pow(f32, -0.0, math.inf(f32)) == 0.0);
- assert(math.isPositiveInf(pow(f32, 0.0, -2.0)));
- assert(math.isPositiveInf(pow(f32, -0.0, -2.0)));
- assert(pow(f32, 0.0, 1.0) == 0.0);
- assert(pow(f32, -0.0, 1.0) == -0.0);
- assert(pow(f32, 0.0, 2.0) == 0.0);
- assert(pow(f32, -0.0, 2.0) == 0.0);
- assert(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon));
- assert(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon));
- assert(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));
- assert(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));
- assert(pow(f32, 1.2, -math.inf(f32)) == 0.0);
- assert(pow(f32, -1.2, -math.inf(f32)) == 0.0);
- assert(pow(f32, 0.2, math.inf(f32)) == 0.0);
- assert(pow(f32, -0.2, math.inf(f32)) == 0.0);
- assert(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));
- assert(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));
- assert(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));
- assert(pow(f32, math.inf(f32), -1.0) == 0.0);
- //assert(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0?
- assert(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));
- assert(math.isNan(pow(f32, -1.0, 1.2)));
- assert(math.isNan(pow(f32, -12.4, 78.5)));
+ expect(pow(f32, 4, 0.0) == 1.0);
+ expect(pow(f32, 7, -0.0) == 1.0);
+ expect(pow(f32, 45, 1.0) == 45);
+ expect(pow(f32, -45, 1.0) == -45);
+ expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
+ expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
+ expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
+ //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
+ expect(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));
+ expect(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));
+ expect(pow(f32, 0.0, math.inf(f32)) == 0.0);
+ expect(pow(f32, -0.0, math.inf(f32)) == 0.0);
+ expect(math.isPositiveInf(pow(f32, 0.0, -2.0)));
+ expect(math.isPositiveInf(pow(f32, -0.0, -2.0)));
+ expect(pow(f32, 0.0, 1.0) == 0.0);
+ expect(pow(f32, -0.0, 1.0) == -0.0);
+ expect(pow(f32, 0.0, 2.0) == 0.0);
+ expect(pow(f32, -0.0, 2.0) == 0.0);
+ expect(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon));
+ expect(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon));
+ expect(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));
+ expect(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));
+ expect(pow(f32, 1.2, -math.inf(f32)) == 0.0);
+ expect(pow(f32, -1.2, -math.inf(f32)) == 0.0);
+ expect(pow(f32, 0.2, math.inf(f32)) == 0.0);
+ expect(pow(f32, -0.2, math.inf(f32)) == 0.0);
+ expect(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));
+ expect(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));
+ expect(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));
+ expect(pow(f32, math.inf(f32), -1.0) == 0.0);
+ //expect(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0?
+ expect(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));
+ expect(math.isNan(pow(f32, -1.0, 1.2)));
+ expect(math.isNan(pow(f32, -12.4, 78.5)));
}
diff --git a/std/math/powi.zig b/std/math/powi.zig
index 13c09b192e..9c2a4a4965 100644
--- a/std/math/powi.zig
+++ b/std/math/powi.zig
@@ -12,7 +12,7 @@ const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
const assert = std.debug.assert;
-const assertError = std.debug.assertError;
+const testing = std.testing;
// This implementation is based on that from the rust stlib
pub fn powi(comptime T: type, x: T, y: T) (error{
@@ -103,75 +103,75 @@ pub fn powi(comptime T: type, x: T, y: T) (error{
}
test "math.powi" {
- assertError(powi(i8, -66, 6), error.Underflow);
- assertError(powi(i16, -13, 13), error.Underflow);
- assertError(powi(i32, -32, 21), error.Underflow);
- assertError(powi(i64, -24, 61), error.Underflow);
- assertError(powi(i17, -15, 15), error.Underflow);
- assertError(powi(i42, -6, 40), error.Underflow);
+ testing.expectError(error.Underflow, powi(i8, -66, 6));
+ testing.expectError(error.Underflow, powi(i16, -13, 13));
+ testing.expectError(error.Underflow, powi(i32, -32, 21));
+ testing.expectError(error.Underflow, powi(i64, -24, 61));
+ testing.expectError(error.Underflow, powi(i17, -15, 15));
+ testing.expectError(error.Underflow, powi(i42, -6, 40));
- assert((try powi(i8, -5, 3)) == -125);
- assert((try powi(i16, -16, 3)) == -4096);
- assert((try powi(i32, -91, 3)) == -753571);
- assert((try powi(i64, -36, 6)) == 2176782336);
- assert((try powi(i17, -2, 15)) == -32768);
- assert((try powi(i42, -5, 7)) == -78125);
+ testing.expect((try powi(i8, -5, 3)) == -125);
+ testing.expect((try powi(i16, -16, 3)) == -4096);
+ testing.expect((try powi(i32, -91, 3)) == -753571);
+ testing.expect((try powi(i64, -36, 6)) == 2176782336);
+ testing.expect((try powi(i17, -2, 15)) == -32768);
+ testing.expect((try powi(i42, -5, 7)) == -78125);
- assert((try powi(u8, 6, 2)) == 36);
- assert((try powi(u16, 5, 4)) == 625);
- assert((try powi(u32, 12, 6)) == 2985984);
- assert((try powi(u64, 34, 2)) == 1156);
- assert((try powi(u17, 16, 3)) == 4096);
- assert((try powi(u42, 34, 6)) == 1544804416);
+ testing.expect((try powi(u8, 6, 2)) == 36);
+ testing.expect((try powi(u16, 5, 4)) == 625);
+ testing.expect((try powi(u32, 12, 6)) == 2985984);
+ testing.expect((try powi(u64, 34, 2)) == 1156);
+ testing.expect((try powi(u17, 16, 3)) == 4096);
+ testing.expect((try powi(u42, 34, 6)) == 1544804416);
- assertError(powi(i8, 120, 7), error.Overflow);
- assertError(powi(i16, 73, 15), error.Overflow);
- assertError(powi(i32, 23, 31), error.Overflow);
- assertError(powi(i64, 68, 61), error.Overflow);
- assertError(powi(i17, 15, 15), error.Overflow);
- assertError(powi(i42, 121312, 41), error.Overflow);
+ testing.expectError(error.Overflow, powi(i8, 120, 7));
+ testing.expectError(error.Overflow, powi(i16, 73, 15));
+ testing.expectError(error.Overflow, powi(i32, 23, 31));
+ testing.expectError(error.Overflow, powi(i64, 68, 61));
+ testing.expectError(error.Overflow, powi(i17, 15, 15));
+ testing.expectError(error.Overflow, powi(i42, 121312, 41));
- assertError(powi(u8, 123, 7), error.Overflow);
- assertError(powi(u16, 2313, 15), error.Overflow);
- assertError(powi(u32, 8968, 31), error.Overflow);
- assertError(powi(u64, 2342, 63), error.Overflow);
- assertError(powi(u17, 2723, 16), error.Overflow);
- assertError(powi(u42, 8234, 41), error.Overflow);
+ testing.expectError(error.Overflow, powi(u8, 123, 7));
+ testing.expectError(error.Overflow, powi(u16, 2313, 15));
+ testing.expectError(error.Overflow, powi(u32, 8968, 31));
+ testing.expectError(error.Overflow, powi(u64, 2342, 63));
+ testing.expectError(error.Overflow, powi(u17, 2723, 16));
+ testing.expectError(error.Overflow, powi(u42, 8234, 41));
}
test "math.powi.special" {
- assertError(powi(i8, -2, 8), error.Underflow);
- assertError(powi(i16, -2, 16), error.Underflow);
- assertError(powi(i32, -2, 32), error.Underflow);
- assertError(powi(i64, -2, 64), error.Underflow);
- assertError(powi(i17, -2, 17), error.Underflow);
- assertError(powi(i42, -2, 42), error.Underflow);
+ testing.expectError(error.Underflow, powi(i8, -2, 8));
+ testing.expectError(error.Underflow, powi(i16, -2, 16));
+ testing.expectError(error.Underflow, powi(i32, -2, 32));
+ testing.expectError(error.Underflow, powi(i64, -2, 64));
+ testing.expectError(error.Underflow, powi(i17, -2, 17));
+ testing.expectError(error.Underflow, powi(i42, -2, 42));
- assert((try powi(i8, -1, 3)) == -1);
- assert((try powi(i16, -1, 2)) == 1);
- assert((try powi(i32, -1, 16)) == 1);
- assert((try powi(i64, -1, 6)) == 1);
- assert((try powi(i17, -1, 15)) == -1);
- assert((try powi(i42, -1, 7)) == -1);
+ testing.expect((try powi(i8, -1, 3)) == -1);
+ testing.expect((try powi(i16, -1, 2)) == 1);
+ testing.expect((try powi(i32, -1, 16)) == 1);
+ testing.expect((try powi(i64, -1, 6)) == 1);
+ testing.expect((try powi(i17, -1, 15)) == -1);
+ testing.expect((try powi(i42, -1, 7)) == -1);
- assert((try powi(u8, 1, 2)) == 1);
- assert((try powi(u16, 1, 4)) == 1);
- assert((try powi(u32, 1, 6)) == 1);
- assert((try powi(u64, 1, 2)) == 1);
- assert((try powi(u17, 1, 3)) == 1);
- assert((try powi(u42, 1, 6)) == 1);
+ testing.expect((try powi(u8, 1, 2)) == 1);
+ testing.expect((try powi(u16, 1, 4)) == 1);
+ testing.expect((try powi(u32, 1, 6)) == 1);
+ testing.expect((try powi(u64, 1, 2)) == 1);
+ testing.expect((try powi(u17, 1, 3)) == 1);
+ testing.expect((try powi(u42, 1, 6)) == 1);
- assertError(powi(i8, 2, 7), error.Overflow);
- assertError(powi(i16, 2, 15), error.Overflow);
- assertError(powi(i32, 2, 31), error.Overflow);
- assertError(powi(i64, 2, 63), error.Overflow);
- assertError(powi(i17, 2, 16), error.Overflow);
- assertError(powi(i42, 2, 41), error.Overflow);
+ testing.expectError(error.Overflow, powi(i8, 2, 7));
+ testing.expectError(error.Overflow, powi(i16, 2, 15));
+ testing.expectError(error.Overflow, powi(i32, 2, 31));
+ testing.expectError(error.Overflow, powi(i64, 2, 63));
+ testing.expectError(error.Overflow, powi(i17, 2, 16));
+ testing.expectError(error.Overflow, powi(i42, 2, 41));
- assertError(powi(u8, 2, 8), error.Overflow);
- assertError(powi(u16, 2, 16), error.Overflow);
- assertError(powi(u32, 2, 32), error.Overflow);
- assertError(powi(u64, 2, 64), error.Overflow);
- assertError(powi(u17, 2, 17), error.Overflow);
- assertError(powi(u42, 2, 42), error.Overflow);
+ testing.expectError(error.Overflow, powi(u8, 2, 8));
+ testing.expectError(error.Overflow, powi(u16, 2, 16));
+ testing.expectError(error.Overflow, powi(u32, 2, 32));
+ testing.expectError(error.Overflow, powi(u64, 2, 64));
+ testing.expectError(error.Overflow, powi(u17, 2, 17));
+ testing.expectError(error.Overflow, powi(u42, 2, 42));
}
diff --git a/std/math/round.zig b/std/math/round.zig
index 4fe35365c8..7346b703c9 100644
--- a/std/math/round.zig
+++ b/std/math/round.zig
@@ -5,7 +5,7 @@
// - round(nan) = nan
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const std = @import("../index.zig");
const math = std.math;
@@ -85,36 +85,36 @@ fn round64(x_: f64) f64 {
}
test "math.round" {
- assert(round(f32(1.3)) == round32(1.3));
- assert(round(f64(1.3)) == round64(1.3));
+ expect(round(f32(1.3)) == round32(1.3));
+ expect(round(f64(1.3)) == round64(1.3));
}
test "math.round32" {
- assert(round32(1.3) == 1.0);
- assert(round32(-1.3) == -1.0);
- assert(round32(0.2) == 0.0);
- assert(round32(1.8) == 2.0);
+ expect(round32(1.3) == 1.0);
+ expect(round32(-1.3) == -1.0);
+ expect(round32(0.2) == 0.0);
+ expect(round32(1.8) == 2.0);
}
test "math.round64" {
- assert(round64(1.3) == 1.0);
- assert(round64(-1.3) == -1.0);
- assert(round64(0.2) == 0.0);
- assert(round64(1.8) == 2.0);
+ expect(round64(1.3) == 1.0);
+ expect(round64(-1.3) == -1.0);
+ expect(round64(0.2) == 0.0);
+ expect(round64(1.8) == 2.0);
}
test "math.round32.special" {
- assert(round32(0.0) == 0.0);
- assert(round32(-0.0) == -0.0);
- assert(math.isPositiveInf(round32(math.inf(f32))));
- assert(math.isNegativeInf(round32(-math.inf(f32))));
- assert(math.isNan(round32(math.nan(f32))));
+ expect(round32(0.0) == 0.0);
+ expect(round32(-0.0) == -0.0);
+ expect(math.isPositiveInf(round32(math.inf(f32))));
+ expect(math.isNegativeInf(round32(-math.inf(f32))));
+ expect(math.isNan(round32(math.nan(f32))));
}
test "math.round64.special" {
- assert(round64(0.0) == 0.0);
- assert(round64(-0.0) == -0.0);
- assert(math.isPositiveInf(round64(math.inf(f64))));
- assert(math.isNegativeInf(round64(-math.inf(f64))));
- assert(math.isNan(round64(math.nan(f64))));
+ expect(round64(0.0) == 0.0);
+ expect(round64(-0.0) == -0.0);
+ expect(math.isPositiveInf(round64(math.inf(f64))));
+ expect(math.isNegativeInf(round64(-math.inf(f64))));
+ expect(math.isNan(round64(math.nan(f64))));
}
diff --git a/std/math/scalbn.zig b/std/math/scalbn.zig
index f72c7e866f..d37a8659a9 100644
--- a/std/math/scalbn.zig
+++ b/std/math/scalbn.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn scalbn(x: var, n: i32) @typeOf(x) {
const T = @typeOf(x);
@@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 {
}
test "math.scalbn" {
- assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
- assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
+ expect(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
+ expect(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
}
test "math.scalbn32" {
- assert(scalbn32(1.5, 4) == 24.0);
+ expect(scalbn32(1.5, 4) == 24.0);
}
test "math.scalbn64" {
- assert(scalbn64(1.5, 4) == 24.0);
+ expect(scalbn64(1.5, 4) == 24.0);
}
diff --git a/std/math/signbit.zig b/std/math/signbit.zig
index 8c6829dfcd..728f651aec 100644
--- a/std/math/signbit.zig
+++ b/std/math/signbit.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn signbit(x: var) bool {
const T = @typeOf(x);
@@ -28,22 +28,22 @@ fn signbit64(x: f64) bool {
}
test "math.signbit" {
- assert(signbit(f16(4.0)) == signbit16(4.0));
- assert(signbit(f32(4.0)) == signbit32(4.0));
- assert(signbit(f64(4.0)) == signbit64(4.0));
+ expect(signbit(f16(4.0)) == signbit16(4.0));
+ expect(signbit(f32(4.0)) == signbit32(4.0));
+ expect(signbit(f64(4.0)) == signbit64(4.0));
}
test "math.signbit16" {
- assert(!signbit16(4.0));
- assert(signbit16(-3.0));
+ expect(!signbit16(4.0));
+ expect(signbit16(-3.0));
}
test "math.signbit32" {
- assert(!signbit32(4.0));
- assert(signbit32(-3.0));
+ expect(!signbit32(4.0));
+ expect(signbit32(-3.0));
}
test "math.signbit64" {
- assert(!signbit64(4.0));
- assert(signbit64(-3.0));
+ expect(!signbit64(4.0));
+ expect(signbit64(-3.0));
}
diff --git a/std/math/sin.zig b/std/math/sin.zig
index 15b2f9f17a..5ade6636c7 100644
--- a/std/math/sin.zig
+++ b/std/math/sin.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn sin(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 {
}
test "math.sin" {
- assert(sin(f32(0.0)) == sin32(0.0));
- assert(sin(f64(0.0)) == sin64(0.0));
- assert(comptime (math.sin(f64(2))) == math.sin(f64(2)));
+ expect(sin(f32(0.0)) == sin32(0.0));
+ expect(sin(f64(0.0)) == sin64(0.0));
+ expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
}
test "math.sin32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
- assert(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
- assert(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
- assert(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
- assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
+ expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
+ expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
+ expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
+ expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
}
test "math.sin64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
- assert(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
- assert(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
- assert(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
- assert(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
+ expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
+ expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
+ expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
+ expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
+ expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
}
test "math.sin32.special" {
- assert(sin32(0.0) == 0.0);
- assert(sin32(-0.0) == -0.0);
- assert(math.isNan(sin32(math.inf(f32))));
- assert(math.isNan(sin32(-math.inf(f32))));
- assert(math.isNan(sin32(math.nan(f32))));
+ expect(sin32(0.0) == 0.0);
+ expect(sin32(-0.0) == -0.0);
+ expect(math.isNan(sin32(math.inf(f32))));
+ expect(math.isNan(sin32(-math.inf(f32))));
+ expect(math.isNan(sin32(math.nan(f32))));
}
test "math.sin64.special" {
- assert(sin64(0.0) == 0.0);
- assert(sin64(-0.0) == -0.0);
- assert(math.isNan(sin64(math.inf(f64))));
- assert(math.isNan(sin64(-math.inf(f64))));
- assert(math.isNan(sin64(math.nan(f64))));
+ expect(sin64(0.0) == 0.0);
+ expect(sin64(-0.0) == -0.0);
+ expect(math.isNan(sin64(math.inf(f64))));
+ expect(math.isNan(sin64(-math.inf(f64))));
+ expect(math.isNan(sin64(math.nan(f64))));
}
diff --git a/std/math/sinh.zig b/std/math/sinh.zig
index 733b89754a..95924ba55a 100644
--- a/std/math/sinh.zig
+++ b/std/math/sinh.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const expo2 = @import("expo2.zig").expo2;
const maxInt = std.math.maxInt;
@@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 {
}
test "math.sinh" {
- assert(sinh(f32(1.5)) == sinh32(1.5));
- assert(sinh(f64(1.5)) == sinh64(1.5));
+ expect(sinh(f32(1.5)) == sinh32(1.5));
+ expect(sinh(f64(1.5)) == sinh64(1.5));
}
test "math.sinh32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
- assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
- assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
+ expect(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
+ expect(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
+ expect(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
}
test "math.sinh64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
- assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
- assert(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));
+ expect(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
+ expect(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
+ expect(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));
}
test "math.sinh32.special" {
- assert(sinh32(0.0) == 0.0);
- assert(sinh32(-0.0) == -0.0);
- assert(math.isPositiveInf(sinh32(math.inf(f32))));
- assert(math.isNegativeInf(sinh32(-math.inf(f32))));
- assert(math.isNan(sinh32(math.nan(f32))));
+ expect(sinh32(0.0) == 0.0);
+ expect(sinh32(-0.0) == -0.0);
+ expect(math.isPositiveInf(sinh32(math.inf(f32))));
+ expect(math.isNegativeInf(sinh32(-math.inf(f32))));
+ expect(math.isNan(sinh32(math.nan(f32))));
}
test "math.sinh64.special" {
- assert(sinh64(0.0) == 0.0);
- assert(sinh64(-0.0) == -0.0);
- assert(math.isPositiveInf(sinh64(math.inf(f64))));
- assert(math.isNegativeInf(sinh64(-math.inf(f64))));
- assert(math.isNan(sinh64(math.nan(f64))));
+ expect(sinh64(0.0) == 0.0);
+ expect(sinh64(-0.0) == -0.0);
+ expect(math.isPositiveInf(sinh64(math.inf(f64))));
+ expect(math.isNegativeInf(sinh64(-math.inf(f64))));
+ expect(math.isNan(sinh64(math.nan(f64))));
}
diff --git a/std/math/sqrt.zig b/std/math/sqrt.zig
index 4300f20f5a..9996b44b20 100644
--- a/std/math/sqrt.zig
+++ b/std/math/sqrt.zig
@@ -7,7 +7,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
@@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ
}
test "math.sqrt" {
- assert(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
- assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
- assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
+ expect(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
+ expect(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
+ expect(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
}
test "math.sqrt16" {
const epsilon = 0.000001;
- assert(@sqrt(f16, 0.0) == 0.0);
- assert(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
- assert(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
- assert(@sqrt(f16, 4.0) == 2.0);
- assert(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
- assert(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
- assert(@sqrt(f16, 64.0) == 8.0);
- assert(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
- assert(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
+ expect(@sqrt(f16, 0.0) == 0.0);
+ expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
+ expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
+ expect(@sqrt(f16, 4.0) == 2.0);
+ expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
+ expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
+ expect(@sqrt(f16, 64.0) == 8.0);
+ expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
+ expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
}
test "math.sqrt32" {
const epsilon = 0.000001;
- assert(@sqrt(f32, 0.0) == 0.0);
- assert(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
- assert(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
- assert(@sqrt(f32, 4.0) == 2.0);
- assert(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
- assert(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
- assert(@sqrt(f32, 64.0) == 8.0);
- assert(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
- assert(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
+ expect(@sqrt(f32, 0.0) == 0.0);
+ expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
+ expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
+ expect(@sqrt(f32, 4.0) == 2.0);
+ expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
+ expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
+ expect(@sqrt(f32, 64.0) == 8.0);
+ expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
+ expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
}
test "math.sqrt64" {
const epsilon = 0.000001;
- assert(@sqrt(f64, 0.0) == 0.0);
- assert(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
- assert(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
- assert(@sqrt(f64, 4.0) == 2.0);
- assert(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
- assert(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
- assert(@sqrt(f64, 64.0) == 8.0);
- assert(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
- assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
+ expect(@sqrt(f64, 0.0) == 0.0);
+ expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
+ expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
+ expect(@sqrt(f64, 4.0) == 2.0);
+ expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
+ expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
+ expect(@sqrt(f64, 64.0) == 8.0);
+ expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
+ expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
}
test "math.sqrt16.special" {
- assert(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
- assert(@sqrt(f16, 0.0) == 0.0);
- assert(@sqrt(f16, -0.0) == -0.0);
- assert(math.isNan(@sqrt(f16, -1.0)));
- assert(math.isNan(@sqrt(f16, math.nan(f16))));
+ expect(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
+ expect(@sqrt(f16, 0.0) == 0.0);
+ expect(@sqrt(f16, -0.0) == -0.0);
+ expect(math.isNan(@sqrt(f16, -1.0)));
+ expect(math.isNan(@sqrt(f16, math.nan(f16))));
}
test "math.sqrt32.special" {
- assert(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
- assert(@sqrt(f32, 0.0) == 0.0);
- assert(@sqrt(f32, -0.0) == -0.0);
- assert(math.isNan(@sqrt(f32, -1.0)));
- assert(math.isNan(@sqrt(f32, math.nan(f32))));
+ expect(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
+ expect(@sqrt(f32, 0.0) == 0.0);
+ expect(@sqrt(f32, -0.0) == -0.0);
+ expect(math.isNan(@sqrt(f32, -1.0)));
+ expect(math.isNan(@sqrt(f32, math.nan(f32))));
}
test "math.sqrt64.special" {
- assert(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
- assert(@sqrt(f64, 0.0) == 0.0);
- assert(@sqrt(f64, -0.0) == -0.0);
- assert(math.isNan(@sqrt(f64, -1.0)));
- assert(math.isNan(@sqrt(f64, math.nan(f64))));
+ expect(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
+ expect(@sqrt(f64, 0.0) == 0.0);
+ expect(@sqrt(f64, -0.0) == -0.0);
+ expect(math.isNan(@sqrt(f64, -1.0)));
+ expect(math.isNan(@sqrt(f64, math.nan(f64))));
}
fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
@@ -127,10 +127,10 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
}
test "math.sqrt_int" {
- assert(sqrt_int(u32, 3) == 1);
- assert(sqrt_int(u32, 4) == 2);
- assert(sqrt_int(u32, 5) == 2);
- assert(sqrt_int(u32, 8) == 2);
- assert(sqrt_int(u32, 9) == 3);
- assert(sqrt_int(u32, 10) == 3);
+ expect(sqrt_int(u32, 3) == 1);
+ expect(sqrt_int(u32, 4) == 2);
+ expect(sqrt_int(u32, 5) == 2);
+ expect(sqrt_int(u32, 8) == 2);
+ expect(sqrt_int(u32, 9) == 3);
+ expect(sqrt_int(u32, 10) == 3);
}
diff --git a/std/math/tan.zig b/std/math/tan.zig
index a71a17e625..ec43092320 100644
--- a/std/math/tan.zig
+++ b/std/math/tan.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
pub fn tan(x: var) @typeOf(x) {
const T = @typeOf(x);
@@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 {
}
test "math.tan" {
- assert(tan(f32(0.0)) == tan32(0.0));
- assert(tan(f64(0.0)) == tan64(0.0));
+ expect(tan(f32(0.0)) == tan32(0.0));
+ expect(tan(f64(0.0)) == tan64(0.0));
}
test "math.tan32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
- assert(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
- assert(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
- assert(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
- assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
+ expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
+ expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
+ expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
+ expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
+ expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
}
test "math.tan64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
- assert(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
- assert(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
- assert(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
- assert(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
+ expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
+ expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
+ expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
+ expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
+ expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
}
test "math.tan32.special" {
- assert(tan32(0.0) == 0.0);
- assert(tan32(-0.0) == -0.0);
- assert(math.isNan(tan32(math.inf(f32))));
- assert(math.isNan(tan32(-math.inf(f32))));
- assert(math.isNan(tan32(math.nan(f32))));
+ expect(tan32(0.0) == 0.0);
+ expect(tan32(-0.0) == -0.0);
+ expect(math.isNan(tan32(math.inf(f32))));
+ expect(math.isNan(tan32(-math.inf(f32))));
+ expect(math.isNan(tan32(math.nan(f32))));
}
test "math.tan64.special" {
- assert(tan64(0.0) == 0.0);
- assert(tan64(-0.0) == -0.0);
- assert(math.isNan(tan64(math.inf(f64))));
- assert(math.isNan(tan64(-math.inf(f64))));
- assert(math.isNan(tan64(math.nan(f64))));
+ expect(tan64(0.0) == 0.0);
+ expect(tan64(-0.0) == -0.0);
+ expect(math.isNan(tan64(math.inf(f64))));
+ expect(math.isNan(tan64(-math.inf(f64))));
+ expect(math.isNan(tan64(math.nan(f64))));
}
diff --git a/std/math/tanh.zig b/std/math/tanh.zig
index faeb2641cc..a35449a053 100644
--- a/std/math/tanh.zig
+++ b/std/math/tanh.zig
@@ -7,7 +7,7 @@
const builtin = @import("builtin");
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const expo2 = @import("expo2.zig").expo2;
const maxInt = std.math.maxInt;
@@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 {
}
test "math.tanh" {
- assert(tanh(f32(1.5)) == tanh32(1.5));
- assert(tanh(f64(1.5)) == tanh64(1.5));
+ expect(tanh(f32(1.5)) == tanh32(1.5));
+ expect(tanh(f64(1.5)) == tanh64(1.5));
}
test "math.tanh32" {
const epsilon = 0.000001;
- assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
- assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
- assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
- assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
- assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
+ expect(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
+ expect(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
+ expect(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
+ expect(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
+ expect(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
}
test "math.tanh64" {
const epsilon = 0.000001;
- assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
- assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
- assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
- assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
- assert(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));
+ expect(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
+ expect(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
+ expect(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
+ expect(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
+ expect(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));
}
test "math.tanh32.special" {
- assert(tanh32(0.0) == 0.0);
- assert(tanh32(-0.0) == -0.0);
- assert(tanh32(math.inf(f32)) == 1.0);
- assert(tanh32(-math.inf(f32)) == -1.0);
- assert(math.isNan(tanh32(math.nan(f32))));
+ expect(tanh32(0.0) == 0.0);
+ expect(tanh32(-0.0) == -0.0);
+ expect(tanh32(math.inf(f32)) == 1.0);
+ expect(tanh32(-math.inf(f32)) == -1.0);
+ expect(math.isNan(tanh32(math.nan(f32))));
}
test "math.tanh64.special" {
- assert(tanh64(0.0) == 0.0);
- assert(tanh64(-0.0) == -0.0);
- assert(tanh64(math.inf(f64)) == 1.0);
- assert(tanh64(-math.inf(f64)) == -1.0);
- assert(math.isNan(tanh64(math.nan(f64))));
+ expect(tanh64(0.0) == 0.0);
+ expect(tanh64(-0.0) == -0.0);
+ expect(tanh64(math.inf(f64)) == 1.0);
+ expect(tanh64(-math.inf(f64)) == -1.0);
+ expect(math.isNan(tanh64(math.nan(f64))));
}
diff --git a/std/math/trunc.zig b/std/math/trunc.zig
index bb309a1e24..8c91ccc568 100644
--- a/std/math/trunc.zig
+++ b/std/math/trunc.zig
@@ -6,7 +6,7 @@
const std = @import("../index.zig");
const math = std.math;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
pub fn trunc(x: var) @typeOf(x) {
@@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 {
}
test "math.trunc" {
- assert(trunc(f32(1.3)) == trunc32(1.3));
- assert(trunc(f64(1.3)) == trunc64(1.3));
+ expect(trunc(f32(1.3)) == trunc32(1.3));
+ expect(trunc(f64(1.3)) == trunc64(1.3));
}
test "math.trunc32" {
- assert(trunc32(1.3) == 1.0);
- assert(trunc32(-1.3) == -1.0);
- assert(trunc32(0.2) == 0.0);
+ expect(trunc32(1.3) == 1.0);
+ expect(trunc32(-1.3) == -1.0);
+ expect(trunc32(0.2) == 0.0);
}
test "math.trunc64" {
- assert(trunc64(1.3) == 1.0);
- assert(trunc64(-1.3) == -1.0);
- assert(trunc64(0.2) == 0.0);
+ expect(trunc64(1.3) == 1.0);
+ expect(trunc64(-1.3) == -1.0);
+ expect(trunc64(0.2) == 0.0);
}
test "math.trunc32.special" {
- assert(trunc32(0.0) == 0.0); // 0x3F800000
- assert(trunc32(-0.0) == -0.0);
- assert(math.isPositiveInf(trunc32(math.inf(f32))));
- assert(math.isNegativeInf(trunc32(-math.inf(f32))));
- assert(math.isNan(trunc32(math.nan(f32))));
+ expect(trunc32(0.0) == 0.0); // 0x3F800000
+ expect(trunc32(-0.0) == -0.0);
+ expect(math.isPositiveInf(trunc32(math.inf(f32))));
+ expect(math.isNegativeInf(trunc32(-math.inf(f32))));
+ expect(math.isNan(trunc32(math.nan(f32))));
}
test "math.trunc64.special" {
- assert(trunc64(0.0) == 0.0);
- assert(trunc64(-0.0) == -0.0);
- assert(math.isPositiveInf(trunc64(math.inf(f64))));
- assert(math.isNegativeInf(trunc64(-math.inf(f64))));
- assert(math.isNan(trunc64(math.nan(f64))));
+ expect(trunc64(0.0) == 0.0);
+ expect(trunc64(-0.0) == -0.0);
+ expect(math.isPositiveInf(trunc64(math.inf(f64))));
+ expect(math.isNegativeInf(trunc64(-math.inf(f64))));
+ expect(math.isNan(trunc64(math.nan(f64))));
}
diff --git a/std/mem.zig b/std/mem.zig
index 9914a08e65..39b9701754 100644
--- a/std/mem.zig
+++ b/std/mem.zig
@@ -6,6 +6,7 @@ const builtin = @import("builtin");
const mem = @This();
const meta = std.meta;
const trait = meta.trait;
+const testing = std.testing;
pub const Allocator = struct {
pub const Error = error{OutOfMemory};
@@ -36,20 +37,9 @@ pub const Allocator = struct {
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
freeFn: fn (self: *Allocator, old_mem: []u8) void,
- /// Call `destroy` with the result
- /// TODO this is deprecated. use createOne instead
- pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) {
- const T = @typeOf(init);
- if (@sizeOf(T) == 0) return &(T{});
- const slice = try self.alloc(T, 1);
- const ptr = &slice[0];
- ptr.* = init;
- return ptr;
- }
-
/// Call `destroy` with the result.
/// Returns undefined memory.
- pub fn createOne(self: *Allocator, comptime T: type) Error!*T {
+ pub fn create(self: *Allocator, comptime T: type) Error!*T {
if (@sizeOf(T) == 0) return &(T{});
const slice = try self.alloc(T, 1);
return &slice[0];
@@ -192,7 +182,7 @@ test "mem.secureZero" {
set(u8, a[0..], 0);
secureZero(u8, b[0..]);
- assert(eql(u8, a[0..], b[0..]));
+ testing.expectEqualSlices(u8, a[0..], b[0..]);
}
pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
@@ -221,11 +211,11 @@ pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
}
test "mem.compare" {
- assert(compare(u8, "abcd", "bee") == Compare.LessThan);
- assert(compare(u8, "abc", "abc") == Compare.Equal);
- assert(compare(u8, "abc", "abc0") == Compare.LessThan);
- assert(compare(u8, "", "") == Compare.Equal);
- assert(compare(u8, "", "a") == Compare.LessThan);
+ testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
+ testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
+ testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
+ testing.expect(compare(u8, "", "") == Compare.Equal);
+ testing.expect(compare(u8, "", "a") == Compare.LessThan);
}
/// Returns true if lhs < rhs, false otherwise
@@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
}
test "mem.lessThan" {
- assert(lessThan(u8, "abcd", "bee"));
- assert(!lessThan(u8, "abc", "abc"));
- assert(lessThan(u8, "abc", "abc0"));
- assert(!lessThan(u8, "", ""));
- assert(lessThan(u8, "", "a"));
+ testing.expect(lessThan(u8, "abcd", "bee"));
+ testing.expect(!lessThan(u8, "abc", "abc"));
+ testing.expect(lessThan(u8, "abc", "abc0"));
+ testing.expect(!lessThan(u8, "", ""));
+ testing.expect(lessThan(u8, "", "a"));
}
/// Compares two slices and returns whether they are equal.
@@ -307,10 +297,10 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co
}
test "mem.trim" {
- assert(eql(u8, trimLeft(u8, " foo\n ", " \n"), "foo\n "));
- assert(eql(u8, trimRight(u8, " foo\n ", " \n"), " foo"));
- assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo"));
- assert(eql(u8, trim(u8, "foo", " \n"), "foo"));
+ testing.expectEqualSlices(u8, "foo\n ", trimLeft(u8, " foo\n ", " \n"));
+ testing.expectEqualSlices(u8, " foo", trimRight(u8, " foo\n ", " \n"));
+ testing.expectEqualSlices(u8, "foo", trim(u8, " foo\n ", " \n"));
+ testing.expectEqualSlices(u8, "foo", trim(u8, "foo", " \n"));
}
/// Linear search for the index of a scalar value inside a slice.
@@ -391,31 +381,27 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee
}
test "mem.indexOf" {
- assert(indexOf(u8, "one two three four", "four").? == 14);
- assert(lastIndexOf(u8, "one two three two four", "two").? == 14);
- assert(indexOf(u8, "one two three four", "gour") == null);
- assert(lastIndexOf(u8, "one two three four", "gour") == null);
- assert(indexOf(u8, "foo", "foo").? == 0);
- assert(lastIndexOf(u8, "foo", "foo").? == 0);
- assert(indexOf(u8, "foo", "fool") == null);
- assert(lastIndexOf(u8, "foo", "lfoo") == null);
- assert(lastIndexOf(u8, "foo", "fool") == null);
+ testing.expect(indexOf(u8, "one two three four", "four").? == 14);
+ testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14);
+ testing.expect(indexOf(u8, "one two three four", "gour") == null);
+ testing.expect(lastIndexOf(u8, "one two three four", "gour") == null);
+ testing.expect(indexOf(u8, "foo", "foo").? == 0);
+ testing.expect(lastIndexOf(u8, "foo", "foo").? == 0);
+ testing.expect(indexOf(u8, "foo", "fool") == null);
+ testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);
+ testing.expect(lastIndexOf(u8, "foo", "fool") == null);
- assert(indexOf(u8, "foo foo", "foo").? == 0);
- assert(lastIndexOf(u8, "foo foo", "foo").? == 4);
- assert(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
- assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);
+ testing.expect(indexOf(u8, "foo foo", "foo").? == 0);
+ testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
+ testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
+ testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2);
}
/// Reads an integer from memory with size equal to bytes.len.
/// T specifies the return type, which must be large enough to store
/// the result.
-/// See also ::readIntBE or ::readIntLE.
-pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
- if (T.bit_count == 8) {
- return bytes[0];
- }
- var result: T = 0;
+pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
+ var result: ReturnType = 0;
switch (endian) {
builtin.Endian.Big => {
for (bytes) |b| {
@@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
}
},
builtin.Endian.Little => {
- const ShiftType = math.Log2Int(T);
+ const ShiftType = math.Log2Int(ReturnType);
for (bytes) |b, index| {
- result = result | (T(b) << @intCast(ShiftType, index * 8));
+ result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
}
},
}
return result;
}
-/// Reads a big-endian int of type T from bytes.
-/// bytes.len must be exactly @sizeOf(T).
-pub fn readIntBE(comptime T: type, bytes: []const u8) T {
- if (T.is_signed) {
- return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
- }
- assert(bytes.len == @sizeOf(T));
- if (T == u8) return bytes[0];
- var result: T = 0;
- {
- comptime var i = 0;
- inline while (i < @sizeOf(T)) : (i += 1) {
- result = (result << 8) | T(bytes[i]);
- }
- }
- return result;
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+/// Assumes the endianness of memory is native. This means the function can
+/// simply pointer cast memory.
+pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
+ return @ptrCast(*align(1) const T, bytes).*;
}
-/// Reads a little-endian int of type T from bytes.
-/// bytes.len must be exactly @sizeOf(T).
-pub fn readIntLE(comptime T: type, bytes: []const u8) T {
- if (T.is_signed) {
- return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
- }
- assert(bytes.len == @sizeOf(T));
- if (T == u8) return bytes[0];
- var result: T = 0;
- {
- comptime var i = 0;
- inline while (i < @sizeOf(T)) : (i += 1) {
- result |= T(bytes[i]) << i * 8;
- }
- }
- return result;
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+/// Assumes the endianness of memory is foreign, so it must byte-swap.
+pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
+ return @bswap(T, readIntNative(T, bytes));
}
-test "readIntBE/LE" {
- assert(readIntBE(u0, []u8{}) == 0x0);
- assert(readIntLE(u0, []u8{}) == 0x0);
+pub const readIntLittle = switch (builtin.endian) {
+ builtin.Endian.Little => readIntNative,
+ builtin.Endian.Big => readIntForeign,
+};
- assert(readIntBE(u8, []u8{0x32}) == 0x32);
- assert(readIntLE(u8, []u8{0x12}) == 0x12);
+pub const readIntBig = switch (builtin.endian) {
+ builtin.Endian.Little => readIntForeign,
+ builtin.Endian.Big => readIntNative,
+};
- assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234);
- assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412);
-
- assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
- assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
-
- assert(readIntBE(i8, []u8{0xff}) == -1);
- assert(readIntLE(i8, []u8{0xfe}) == -2);
-
- assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3);
- assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4);
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// The bit count of T must be evenly divisible by 8.
+/// Assumes the endianness of memory is native. This means the function can
+/// simply pointer cast memory.
+pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
+ const n = @divExact(T.bit_count, 8);
+ assert(bytes.len >= n);
+ // TODO https://github.com/ziglang/zig/issues/863
+ return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr));
}
-/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
-/// to fill the entire buffer provided.
-/// value must be an integer.
-pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
- const uint = @IntType(false, @typeOf(value).bit_count);
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// The bit count of T must be evenly divisible by 8.
+/// Assumes the endianness of memory is foreign, so it must byte-swap.
+pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
+ return @bswap(T, readIntSliceNative(T, bytes));
+}
+
+pub const readIntSliceLittle = switch (builtin.endian) {
+ builtin.Endian.Little => readIntSliceNative,
+ builtin.Endian.Big => readIntSliceForeign,
+};
+
+pub const readIntSliceBig = switch (builtin.endian) {
+ builtin.Endian.Little => readIntSliceForeign,
+ builtin.Endian.Big => readIntSliceNative,
+};
+
+/// Reads an integer from memory with bit count specified by T.
+/// The bit count of T must be evenly divisible by 8.
+/// This function cannot fail and cannot cause undefined behavior.
+pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T {
+ if (endian == builtin.endian) {
+ return readIntNative(T, bytes);
+ } else {
+ return readIntForeign(T, bytes);
+ }
+}
+
+/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
+/// and ignores extra bytes.
+/// The bit count of T must be evenly divisible by 8.
+pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
+ const n = @divExact(T.bit_count, 8);
+ assert(bytes.len >= n);
+ // TODO https://github.com/ziglang/zig/issues/863
+ return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian);
+}
+
+test "comptime read/write int" {
+ comptime {
+ var bytes: [2]u8 = undefined;
+ std.mem.writeIntLittle(u16, &bytes, 0x1234);
+ const result = std.mem.readIntBig(u16, &bytes);
+ testing.expect(result == 0x3412);
+ }
+ comptime {
+ var bytes: [2]u8 = undefined;
+ std.mem.writeIntBig(u16, &bytes, 0x1234);
+ const result = std.mem.readIntLittle(u16, &bytes);
+ testing.expect(result == 0x3412);
+ }
+}
+
+test "readIntBig and readIntLittle" {
+ testing.expect(readIntSliceBig(u0, []u8{}) == 0x0);
+ testing.expect(readIntSliceLittle(u0, []u8{}) == 0x0);
+
+ testing.expect(readIntSliceBig(u8, []u8{0x32}) == 0x32);
+ testing.expect(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
+
+ testing.expect(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
+ testing.expect(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
+
+ testing.expect(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
+ testing.expect(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
+
+ testing.expect(readIntSliceBig(i8, []u8{0xff}) == -1);
+ testing.expect(readIntSliceLittle(i8, []u8{0xfe}) == -2);
+
+ testing.expect(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
+ testing.expect(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
+}
+
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, and
+/// accepts any integer bit width.
+/// This function stores in native endian, which means it is implemented as a simple
+/// memory store.
+pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {
+ @ptrCast(*align(1) T, buf).* = value;
+}
+
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, but
+/// the integer bit width must be divisible by 8.
+/// This function stores in foreign endian, which means it does a @bswap first.
+pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
+ writeIntNative(T, buf, @bswap(T, value));
+}
+
+pub const writeIntLittle = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntNative,
+ builtin.Endian.Big => writeIntForeign,
+};
+
+pub const writeIntBig = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntForeign,
+ builtin.Endian.Big => writeIntNative,
+};
+
+/// Writes an integer to memory, storing it in twos-complement.
+/// This function always succeeds, has defined behavior for all inputs, but
+/// the integer bit width must be divisible by 8.
+pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {
+ if (endian == builtin.endian) {
+ return writeIntNative(T, buffer, value);
+ } else {
+ return writeIntForeign(T, buffer, value);
+ }
+}
+
+/// Writes a twos-complement little-endian integer to memory.
+/// Asserts that buf.len >= T.bit_count / 8.
+/// The bit count of T must be divisible by 8.
+/// Any extra bytes in buffer after writing the integer are set to zero. To
+/// avoid the branch to check for extra buffer bytes, use writeIntLittle
+/// instead.
+pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
+ assert(buffer.len >= @divExact(T.bit_count, 8));
+
+ // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
+ const uint = @IntType(false, T.bit_count);
var bits = @truncate(uint, value);
- switch (endian) {
- builtin.Endian.Big => {
- var index: usize = buf.len;
- while (index != 0) {
- index -= 1;
-
- buf[index] = @truncate(u8, bits);
- bits >>= 8;
- }
- },
- builtin.Endian.Little => {
- for (buf) |*b| {
- b.* = @truncate(u8, bits);
- bits >>= 8;
- }
- },
- }
- assert(bits == 0);
-}
-
-pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
- assert(T.bit_count % 8 == 0);
- const uint = @IntType(false, T.bit_count);
- if (uint == u0) {
- return;
- }
- var bits = @bitCast(uint, value);
- if (uint == u8) {
- buf[0] = bits;
- return;
- }
- var index: usize = buf.len;
- while (index != 0) {
- index -= 1;
-
- buf[index] = @truncate(u8, bits);
- bits >>= 8;
- }
- assert(bits == 0);
-}
-
-pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
- assert(T.bit_count % 8 == 0);
- const uint = @IntType(false, T.bit_count);
- if (uint == u0) {
- return;
- }
- var bits = @bitCast(uint, value);
- if (uint == u8) {
- buf[0] = bits;
- return;
- }
- for (buf) |*b| {
+ for (buffer) |*b| {
b.* = @truncate(u8, bits);
bits >>= 8;
}
- assert(bits == 0);
}
-test "writeIntBE/LE" {
+/// Writes a twos-complement big-endian integer to memory.
+/// Asserts that buffer.len >= T.bit_count / 8.
+/// The bit count of T must be divisible by 8.
+/// Any extra bytes in buffer before writing the integer are set to zero. To
+/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
+pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
+ assert(buffer.len >= @divExact(T.bit_count, 8));
+
+ // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
+ const uint = @IntType(false, T.bit_count);
+ var bits = @truncate(uint, value);
+ var index: usize = buffer.len;
+ while (index != 0) {
+ index -= 1;
+ buffer[index] = @truncate(u8, bits);
+ bits >>= 8;
+ }
+}
+
+pub const writeIntSliceNative = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntSliceLittle,
+ builtin.Endian.Big => writeIntSliceBig,
+};
+
+pub const writeIntSliceForeign = switch (builtin.endian) {
+ builtin.Endian.Little => writeIntSliceBig,
+ builtin.Endian.Big => writeIntSliceLittle,
+};
+
+/// Writes a twos-complement integer to memory, with the specified endianness.
+/// Asserts that buf.len >= T.bit_count / 8.
+/// The bit count of T must be evenly divisible by 8.
+/// Any extra bytes in buffer not part of the integer are set to zero, with
+/// respect to endianness. To avoid the branch to check for extra buffer bytes,
+/// use writeInt instead.
+pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
+ comptime assert(T.bit_count % 8 == 0);
+ switch (endian) {
+ builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value),
+ builtin.Endian.Big => return writeIntSliceBig(T, buffer, value),
+ }
+}
+
+test "writeIntBig and writeIntLittle" {
var buf0: [0]u8 = undefined;
var buf1: [1]u8 = undefined;
var buf2: [2]u8 = undefined;
var buf9: [9]u8 = undefined;
- writeIntBE(u0, &buf0, 0x0);
- assert(eql_slice_u8(buf0[0..], []u8{}));
- writeIntLE(u0, &buf0, 0x0);
- assert(eql_slice_u8(buf0[0..], []u8{}));
+ writeIntBig(u0, &buf0, 0x0);
+ testing.expect(eql_slice_u8(buf0[0..], []u8{}));
+ writeIntLittle(u0, &buf0, 0x0);
+ testing.expect(eql_slice_u8(buf0[0..], []u8{}));
- writeIntBE(u8, &buf1, 0x12);
- assert(eql_slice_u8(buf1[0..], []u8{0x12}));
- writeIntLE(u8, &buf1, 0x34);
- assert(eql_slice_u8(buf1[0..], []u8{0x34}));
+ writeIntBig(u8, &buf1, 0x12);
+ testing.expect(eql_slice_u8(buf1[0..], []u8{0x12}));
+ writeIntLittle(u8, &buf1, 0x34);
+ testing.expect(eql_slice_u8(buf1[0..], []u8{0x34}));
- writeIntBE(u16, &buf2, 0x1234);
- assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
- writeIntLE(u16, &buf2, 0x5678);
- assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
+ writeIntBig(u16, &buf2, 0x1234);
+ testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
+ writeIntLittle(u16, &buf2, 0x5678);
+ testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
- writeIntBE(u72, &buf9, 0x123456789abcdef024);
- assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
- writeIntLE(u72, &buf9, 0xfedcba9876543210ec);
- assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
+ writeIntBig(u72, &buf9, 0x123456789abcdef024);
+ testing.expect(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
+ writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
+ testing.expect(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
- writeIntBE(i8, &buf1, -1);
- assert(eql_slice_u8(buf1[0..], []u8{0xff}));
- writeIntLE(i8, &buf1, -2);
- assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
+ writeIntBig(i8, &buf1, -1);
+ testing.expect(eql_slice_u8(buf1[0..], []u8{0xff}));
+ writeIntLittle(i8, &buf1, -2);
+ testing.expect(eql_slice_u8(buf1[0..], []u8{0xfe}));
- writeIntBE(i16, &buf2, -3);
- assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
- writeIntLE(i16, &buf2, -4);
- assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
+ writeIntBig(i16, &buf2, -3);
+ testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
+ writeIntLittle(i16, &buf2, -4);
+ testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
}
pub fn hash_slice_u8(k: []const u8) u32 {
@@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
}
/// Returns an iterator that iterates over the slices of `buffer` that are not
-/// any of the bytes in `split_bytes`.
-/// split(" abc def ghi ", " ")
+/// any of the bytes in `delimiter_bytes`.
+/// tokenize(" abc def ghi ", " ")
/// Will return slices for "abc", "def", "ghi", null, in that order.
-pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
- return SplitIterator{
+/// If `buffer` is empty, the iterator will return null.
+/// If `delimiter_bytes` does not exist in buffer,
+/// the iterator will return `buffer`, null, in that order.
+/// See also the related function `separate`.
+pub fn tokenize(buffer: []const u8, delimiter_bytes: []const u8) TokenIterator {
+ return TokenIterator{
.index = 0,
.buffer = buffer,
- .split_bytes = split_bytes,
+ .delimiter_bytes = delimiter_bytes,
};
}
-test "mem.split" {
- var it = split(" abc def ghi ", " ");
- assert(eql(u8, it.next().?, "abc"));
- assert(eql(u8, it.next().?, "def"));
- assert(eql(u8, it.next().?, "ghi"));
- assert(it.next() == null);
+test "mem.tokenize" {
+ var it = tokenize(" abc def ghi ", " ");
+ testing.expect(eql(u8, it.next().?, "abc"));
+ testing.expect(eql(u8, it.next().?, "def"));
+ testing.expect(eql(u8, it.next().?, "ghi"));
+ testing.expect(it.next() == null);
+
+ it = tokenize("..\\bob", "\\");
+ testing.expect(eql(u8, it.next().?, ".."));
+ testing.expect(eql(u8, "..", "..\\bob"[0..it.index]));
+ testing.expect(eql(u8, it.next().?, "bob"));
+ testing.expect(it.next() == null);
+
+ it = tokenize("//a/b", "/");
+ testing.expect(eql(u8, it.next().?, "a"));
+ testing.expect(eql(u8, it.next().?, "b"));
+ testing.expect(eql(u8, "//a/b", "//a/b"[0..it.index]));
+ testing.expect(it.next() == null);
+
+ it = tokenize("|", "|");
+ testing.expect(it.next() == null);
+
+ it = tokenize("", "|");
+ testing.expect(it.next() == null);
+
+ it = tokenize("hello", "");
+ testing.expect(eql(u8, it.next().?, "hello"));
+ testing.expect(it.next() == null);
+
+ it = tokenize("hello", " ");
+ testing.expect(eql(u8, it.next().?, "hello"));
+ testing.expect(it.next() == null);
+}
+
+test "mem.tokenize (multibyte)" {
+ var it = tokenize("a|b,c/d e", " /,|");
+ testing.expect(eql(u8, it.next().?, "a"));
+ testing.expect(eql(u8, it.next().?, "b"));
+ testing.expect(eql(u8, it.next().?, "c"));
+ testing.expect(eql(u8, it.next().?, "d"));
+ testing.expect(eql(u8, it.next().?, "e"));
+ testing.expect(it.next() == null);
+}
+
+/// Returns an iterator that iterates over the slices of `buffer` that
+/// are separated by bytes in `delimiter`.
+/// separate("abc|def||ghi", "|")
+/// will return slices for "abc", "def", "", "ghi", null, in that order.
+/// If `delimiter` does not exist in buffer,
+/// the iterator will return `buffer`, null, in that order.
+/// The delimiter length must not be zero.
+/// See also the related function `tokenize`.
+/// It is planned to rename this function to `split` before 1.0.0, like this:
+/// pub fn split(buffer: []const u8, delimiter: []const u8) SplitIterator {
+pub fn separate(buffer: []const u8, delimiter: []const u8) SplitIterator {
+ assert(delimiter.len != 0);
+ return SplitIterator{
+ .index = 0,
+ .buffer = buffer,
+ .delimiter = delimiter,
+ };
+}
+
+test "mem.separate" {
+ var it = separate("abc|def||ghi", "|");
+ testing.expect(eql(u8, it.next().?, "abc"));
+ testing.expect(eql(u8, it.next().?, "def"));
+ testing.expect(eql(u8, it.next().?, ""));
+ testing.expect(eql(u8, it.next().?, "ghi"));
+ testing.expect(it.next() == null);
+
+ it = separate("", "|");
+ testing.expect(eql(u8, it.next().?, ""));
+ testing.expect(it.next() == null);
+
+ it = separate("|", "|");
+ testing.expect(eql(u8, it.next().?, ""));
+ testing.expect(eql(u8, it.next().?, ""));
+ testing.expect(it.next() == null);
+
+ it = separate("hello", " ");
+ testing.expect(eql(u8, it.next().?, "hello"));
+ testing.expect(it.next() == null);
+}
+
+test "mem.separate (multibyte)" {
+ var it = separate("a, b ,, c, d, e", ", ");
+ testing.expect(eql(u8, it.next().?, "a"));
+ testing.expect(eql(u8, it.next().?, "b ,"));
+ testing.expect(eql(u8, it.next().?, "c"));
+ testing.expect(eql(u8, it.next().?, "d"));
+ testing.expect(eql(u8, it.next().?, "e"));
+ testing.expect(it.next() == null);
}
pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
@@ -628,8 +796,8 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool
}
test "mem.startsWith" {
- assert(startsWith(u8, "Bob", "Bo"));
- assert(!startsWith(u8, "Needle in haystack", "haystack"));
+ testing.expect(startsWith(u8, "Bob", "Bo"));
+ testing.expect(!startsWith(u8, "Needle in haystack", "haystack"));
}
pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
@@ -637,16 +805,17 @@ pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
}
test "mem.endsWith" {
- assert(endsWith(u8, "Needle in haystack", "haystack"));
- assert(!endsWith(u8, "Bob", "Bo"));
+ testing.expect(endsWith(u8, "Needle in haystack", "haystack"));
+ testing.expect(!endsWith(u8, "Bob", "Bo"));
}
-pub const SplitIterator = struct {
+pub const TokenIterator = struct {
buffer: []const u8,
- split_bytes: []const u8,
+ delimiter_bytes: []const u8,
index: usize,
- pub fn next(self: *SplitIterator) ?[]const u8 {
+ /// Returns a slice of the next token, or null if tokenization is complete.
+ pub fn next(self: *TokenIterator) ?[]const u8 {
// move to beginning of token
while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
const start = self.index;
@@ -662,16 +831,16 @@ pub const SplitIterator = struct {
}
/// Returns a slice of the remaining bytes. Does not affect iterator state.
- pub fn rest(self: *const SplitIterator) []const u8 {
+ pub fn rest(self: TokenIterator) []const u8 {
// move to beginning of token
var index: usize = self.index;
while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
return self.buffer[index..];
}
- fn isSplitByte(self: *const SplitIterator, byte: u8) bool {
- for (self.split_bytes) |split_byte| {
- if (byte == split_byte) {
+ fn isSplitByte(self: TokenIterator, byte: u8) bool {
+ for (self.delimiter_bytes) |delimiter_byte| {
+ if (byte == delimiter_byte) {
return true;
}
}
@@ -679,48 +848,72 @@ pub const SplitIterator = struct {
}
};
-/// Naively combines a series of strings with a separator.
-/// Allocates memory for the result, which must be freed by the caller.
-pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
- comptime assert(strings.len >= 1);
- var total_strings_len: usize = strings.len; // 1 sep per string
- {
- comptime var string_i = 0;
- inline while (string_i < strings.len) : (string_i += 1) {
- const arg = ([]const u8)(strings[string_i]);
- total_strings_len += arg.len;
- }
+pub const SplitIterator = struct {
+ buffer: []const u8,
+ index: ?usize,
+ delimiter: []const u8,
+
+ /// Returns a slice of the next field, or null if splitting is complete.
+ pub fn next(self: *SplitIterator) ?[]const u8 {
+ const start = self.index orelse return null;
+ const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
+ self.index = delim_start + self.delimiter.len;
+ break :blk delim_start;
+ } else blk: {
+ self.index = null;
+ break :blk self.buffer.len;
+ };
+ return self.buffer[start..end];
}
- const buf = try allocator.alloc(u8, total_strings_len);
+ /// Returns a slice of the remaining bytes. Does not affect iterator state.
+ pub fn rest(self: SplitIterator) []const u8 {
+ const end = self.buffer.len;
+ const start = self.index orelse end;
+ return self.buffer[start..end];
+ }
+};
+
+/// Naively combines a series of slices with a separator.
+/// Allocates memory for the result, which must be freed by the caller.
+pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 {
+ if (slices.len == 0) return (([*]u8)(undefined))[0..0];
+
+ const total_len = blk: {
+ var sum: usize = separator.len * (slices.len - 1);
+ for (slices) |slice|
+ sum += slice.len;
+ break :blk sum;
+ };
+
+ const buf = try allocator.alloc(u8, total_len);
errdefer allocator.free(buf);
- var buf_index: usize = 0;
- comptime var string_i = 0;
- inline while (true) {
- const arg = ([]const u8)(strings[string_i]);
- string_i += 1;
- copy(u8, buf[buf_index..], arg);
- buf_index += arg.len;
- if (string_i >= strings.len) break;
- if (buf[buf_index - 1] != sep) {
- buf[buf_index] = sep;
- buf_index += 1;
- }
+ copy(u8, buf, slices[0]);
+ var buf_index: usize = slices[0].len;
+ for (slices[1..]) |slice| {
+ copy(u8, buf[buf_index..], separator);
+ buf_index += separator.len;
+ copy(u8, buf[buf_index..], slice);
+ buf_index += slice.len;
}
- return allocator.shrink(u8, buf, buf_index);
+ // No need for shrink since buf is exactly the correct size.
+ return buf;
}
test "mem.join" {
- assert(eql(u8, try join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));
- assert(eql(u8, try join(debug.global_allocator, ',', "a"), "a"));
+ var buf: [1024]u8 = undefined;
+ const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
+ testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "b", "c" }), "a,b,c"));
+ testing.expect(eql(u8, try join(a, ",", [][]const u8{"a"}), "a"));
+ testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c"));
}
test "testStringEquality" {
- assert(eql(u8, "abcd", "abcd"));
- assert(!eql(u8, "abcdef", "abZdef"));
- assert(!eql(u8, "abcdefg", "abcdef"));
+ testing.expect(eql(u8, "abcd", "abcd"));
+ testing.expect(!eql(u8, "abcdef", "abZdef"));
+ testing.expect(!eql(u8, "abcdefg", "abcdef"));
}
test "testReadInt" {
@@ -735,12 +928,12 @@ fn testReadIntImpl() void {
0x56,
0x78,
};
- assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
- assert(readIntBE(u32, bytes) == 0x12345678);
- assert(readIntBE(i32, bytes) == 0x12345678);
- assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
- assert(readIntLE(u32, bytes) == 0x78563412);
- assert(readIntLE(i32, bytes) == 0x78563412);
+ testing.expect(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
+ testing.expect(readIntBig(u32, &bytes) == 0x12345678);
+ testing.expect(readIntBig(i32, &bytes) == 0x12345678);
+ testing.expect(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
+ testing.expect(readIntLittle(u32, &bytes) == 0x78563412);
+ testing.expect(readIntLittle(i32, &bytes) == 0x78563412);
}
{
const buf = []u8{
@@ -749,8 +942,8 @@ fn testReadIntImpl() void {
0x12,
0x34,
};
- const answer = readInt(buf, u64, builtin.Endian.Big);
- assert(answer == 0x00001234);
+ const answer = readInt(u32, &buf, builtin.Endian.Big);
+ testing.expect(answer == 0x00001234);
}
{
const buf = []u8{
@@ -759,30 +952,42 @@ fn testReadIntImpl() void {
0x00,
0x00,
};
- const answer = readInt(buf, u64, builtin.Endian.Little);
- assert(answer == 0x00003412);
+ const answer = readInt(u32, &buf, builtin.Endian.Little);
+ testing.expect(answer == 0x00003412);
}
{
const bytes = []u8{
0xff,
0xfe,
};
- assert(readIntBE(u16, bytes) == 0xfffe);
- assert(readIntBE(i16, bytes) == -0x0002);
- assert(readIntLE(u16, bytes) == 0xfeff);
- assert(readIntLE(i16, bytes) == -0x0101);
+ testing.expect(readIntBig(u16, &bytes) == 0xfffe);
+ testing.expect(readIntBig(i16, &bytes) == -0x0002);
+ testing.expect(readIntLittle(u16, &bytes) == 0xfeff);
+ testing.expect(readIntLittle(i16, &bytes) == -0x0101);
}
}
-test "testWriteInt" {
+test "std.mem.writeIntSlice" {
testWriteIntImpl();
comptime testWriteIntImpl();
}
fn testWriteIntImpl() void {
var bytes: [8]u8 = undefined;
- writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
+ testing.expect(eql(u8, bytes, []u8{
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ }));
+
+ writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
+ testing.expect(eql(u8, bytes, []u8{
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ }));
+
+ writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
+ testing.expect(eql(u8, bytes, []u8{
0x12,
0x34,
0x56,
@@ -793,8 +998,8 @@ fn testWriteIntImpl() void {
0xBE,
}));
- writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
+ testing.expect(eql(u8, bytes, []u8{
0x12,
0x34,
0x56,
@@ -805,8 +1010,8 @@ fn testWriteIntImpl() void {
0xBE,
}));
- writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
+ testing.expect(eql(u8, bytes, []u8{
0x00,
0x00,
0x00,
@@ -817,8 +1022,8 @@ fn testWriteIntImpl() void {
0x78,
}));
- writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
+ testing.expect(eql(u8, bytes, []u8{
0x12,
0x34,
0x56,
@@ -829,8 +1034,8 @@ fn testWriteIntImpl() void {
0x00,
}));
- writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
+ testing.expect(eql(u8, bytes, []u8{
0x00,
0x00,
0x00,
@@ -841,8 +1046,8 @@ fn testWriteIntImpl() void {
0x34,
}));
- writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
- assert(eql(u8, bytes, []u8{
+ writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
+ testing.expect(eql(u8, bytes, []u8{
0x34,
0x12,
0x00,
@@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T {
}
test "mem.min" {
- assert(min(u8, "abcdefg") == 'a');
+ testing.expect(min(u8, "abcdefg") == 'a');
}
pub fn max(comptime T: type, slice: []const T) T {
@@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T {
}
test "mem.max" {
- assert(max(u8, "abcdefg") == 'g');
+ testing.expect(max(u8, "abcdefg") == 'g');
}
pub fn swap(comptime T: type, a: *T, b: *T) void {
@@ -903,7 +1108,7 @@ test "std.mem.reverse" {
};
reverse(i32, arr[0..]);
- assert(eql(i32, arr, []i32{
+ testing.expect(eql(i32, arr, []i32{
4,
2,
1,
@@ -930,7 +1135,7 @@ test "std.mem.rotate" {
};
rotate(i32, arr[0..], 2);
- assert(eql(i32, arr, []i32{
+ testing.expect(eql(i32, arr, []i32{
1,
2,
4,
@@ -939,29 +1144,52 @@ test "std.mem.rotate" {
}));
}
-// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
-// endian-casting the pointer and then dereferencing
-
-pub fn endianSwapIfLe(comptime T: type, x: T) T {
- return endianSwapIf(builtin.Endian.Little, T, x);
+/// Converts a little-endian integer to host endianness.
+pub fn littleToNative(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => x,
+ builtin.Endian.Big => @bswap(T, x),
+ };
}
-pub fn endianSwapIfBe(comptime T: type, x: T) T {
- return endianSwapIf(builtin.Endian.Big, T, x);
+/// Converts a big-endian integer to host endianness.
+pub fn bigToNative(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => @bswap(T, x),
+ builtin.Endian.Big => x,
+ };
}
-pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
- return if (builtin.endian == endian) endianSwap(T, x) else x;
+/// Converts an integer from specified endianness to host endianness.
+pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
+ return switch (endianness_of_x) {
+ builtin.Endian.Little => littleToNative(T, x),
+ builtin.Endian.Big => bigToNative(T, x),
+ };
}
-pub fn endianSwap(comptime T: type, x: T) T {
- var buf: [@sizeOf(T)]u8 = undefined;
- mem.writeInt(buf[0..], x, builtin.Endian.Little);
- return mem.readInt(buf, T, builtin.Endian.Big);
+/// Converts an integer which has host endianness to the desired endianness.
+pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
+ return switch (desired_endianness) {
+ builtin.Endian.Little => nativeToLittle(T, x),
+ builtin.Endian.Big => nativeToBig(T, x),
+ };
}
-test "std.mem.endianSwap" {
- assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
+/// Converts an integer which has host endianness to little endian.
+pub fn nativeToLittle(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => x,
+ builtin.Endian.Big => @bswap(T, x),
+ };
+}
+
+/// Converts an integer which has host endianness to big endian.
+pub fn nativeToBig(comptime T: type, x: T) T {
+ return switch (builtin.endian) {
+ builtin.Endian.Little => @bswap(T, x),
+ builtin.Endian.Big => x,
+ };
}
fn AsBytesReturnType(comptime P: type) type {
@@ -989,12 +1217,12 @@ test "std.mem.asBytes" {
builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
};
- debug.assert(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
+ testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
var codeface = u32(0xC0DEFACE);
for (asBytes(&codeface).*) |*b|
b.* = 0;
- debug.assert(codeface == 0);
+ testing.expect(codeface == 0);
const S = packed struct {
a: u8,
@@ -1009,7 +1237,7 @@ test "std.mem.asBytes" {
.c = 0xDE,
.d = 0xA1,
};
- debug.assert(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
+ testing.expect(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
}
///Given any value, returns a copy of its bytes in an array.
@@ -1020,14 +1248,14 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {
test "std.mem.toBytes" {
var my_bytes = toBytes(u32(0x12345678));
switch (builtin.endian) {
- builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
- builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
+ builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
+ builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
}
my_bytes[0] = '\x99';
switch (builtin.endian) {
- builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
- builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
+ builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
+ builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
}
}
@@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" {
builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
};
- debug.assert(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
+ testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
var codeface_bytes = switch (builtin.endian) {
builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
};
var codeface = bytesAsValue(u32, &codeface_bytes);
- debug.assert(codeface.* == 0xC0DEFACE);
+ testing.expect(codeface.* == 0xC0DEFACE);
codeface.* = 0;
for (codeface_bytes) |b|
- debug.assert(b == 0);
+ testing.expect(b == 0);
const S = packed struct {
a: u8,
@@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" {
};
const inst_bytes = "\xBE\xEF\xDE\xA1";
const inst2 = bytesAsValue(S, &inst_bytes);
- debug.assert(meta.eql(inst, inst2.*));
+ testing.expect(meta.eql(inst, inst2.*));
}
///Given a pointer to an array of bytes, returns a value of the specified type backed by a
@@ -1098,7 +1326,7 @@ test "std.mem.bytesToValue" {
};
const deadbeef = bytesToValue(u32, deadbeef_bytes);
- debug.assert(deadbeef == u32(0xDEADBEEF));
+ testing.expect(deadbeef == u32(0xDEADBEEF));
}
fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
@@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) {
- debug.assert(start + length <= ptr.*.len);
+ assert(start + length <= ptr.*.len);
const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length);
const T = meta.Child(meta.Child(@typeOf(ptr)));
@@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
test "std.mem.subArrayPtr" {
const a1 = "abcdef";
const sub1 = subArrayPtr(&a1, 2, 3);
- debug.assert(std.mem.eql(u8, sub1.*, "cde"));
+ testing.expect(std.mem.eql(u8, sub1.*, "cde"));
var a2 = "abcdef";
var sub2 = subArrayPtr(&a2, 2, 3);
- debug.assert(std.mem.eql(u8, sub2, "cde"));
+ testing.expect(std.mem.eql(u8, sub2, "cde"));
sub2[1] = 'X';
- debug.assert(std.mem.eql(u8, a2, "abcXef"));
+ testing.expect(std.mem.eql(u8, a2, "abcXef"));
+}
+
+/// Round an address up to the nearest aligned address
+pub fn alignForward(addr: usize, alignment: usize) usize {
+ return (addr + alignment - 1) & ~(alignment - 1);
+}
+
+test "std.mem.alignForward" {
+ testing.expect(alignForward(1, 1) == 1);
+ testing.expect(alignForward(2, 1) == 2);
+ testing.expect(alignForward(1, 2) == 2);
+ testing.expect(alignForward(2, 2) == 2);
+ testing.expect(alignForward(3, 2) == 4);
+ testing.expect(alignForward(4, 2) == 4);
+ testing.expect(alignForward(7, 8) == 8);
+ testing.expect(alignForward(8, 8) == 8);
+ testing.expect(alignForward(9, 8) == 16);
+ testing.expect(alignForward(15, 8) == 16);
+ testing.expect(alignForward(16, 8) == 16);
+ testing.expect(alignForward(17, 8) == 24);
}
diff --git a/std/meta/index.zig b/std/meta/index.zig
index 69a3097288..652e2d39ec 100644
--- a/std/meta/index.zig
+++ b/std/meta/index.zig
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
const debug = std.debug;
const mem = std.mem;
const math = std.math;
+const testing = std.testing;
pub const trait = @import("trait.zig");
@@ -64,16 +65,16 @@ test "std.meta.tagName" {
var u2a = U2{ .C = 0 };
var u2b = U2{ .D = 0 };
- debug.assert(mem.eql(u8, tagName(E1.A), "A"));
- debug.assert(mem.eql(u8, tagName(E1.B), "B"));
- debug.assert(mem.eql(u8, tagName(E2.C), "C"));
- debug.assert(mem.eql(u8, tagName(E2.D), "D"));
- debug.assert(mem.eql(u8, tagName(error.E), "E"));
- debug.assert(mem.eql(u8, tagName(error.F), "F"));
- debug.assert(mem.eql(u8, tagName(u1g), "G"));
- debug.assert(mem.eql(u8, tagName(u1h), "H"));
- debug.assert(mem.eql(u8, tagName(u2a), "C"));
- debug.assert(mem.eql(u8, tagName(u2b), "D"));
+ testing.expect(mem.eql(u8, tagName(E1.A), "A"));
+ testing.expect(mem.eql(u8, tagName(E1.B), "B"));
+ testing.expect(mem.eql(u8, tagName(E2.C), "C"));
+ testing.expect(mem.eql(u8, tagName(E2.D), "D"));
+ testing.expect(mem.eql(u8, tagName(error.E), "E"));
+ testing.expect(mem.eql(u8, tagName(error.F), "F"));
+ testing.expect(mem.eql(u8, tagName(u1g), "G"));
+ testing.expect(mem.eql(u8, tagName(u1h), "H"));
+ testing.expect(mem.eql(u8, tagName(u2a), "C"));
+ testing.expect(mem.eql(u8, tagName(u2b), "D"));
}
pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
@@ -90,12 +91,12 @@ test "std.meta.stringToEnum" {
A,
B,
};
- debug.assert(E1.A == stringToEnum(E1, "A").?);
- debug.assert(E1.B == stringToEnum(E1, "B").?);
- debug.assert(null == stringToEnum(E1, "C"));
+ testing.expect(E1.A == stringToEnum(E1, "A").?);
+ testing.expect(E1.B == stringToEnum(E1, "B").?);
+ testing.expect(null == stringToEnum(E1, "C"));
}
-pub fn bitCount(comptime T: type) u32 {
+pub fn bitCount(comptime T: type) comptime_int {
return switch (@typeInfo(T)) {
TypeId.Int => |info| info.bits,
TypeId.Float => |info| info.bits,
@@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 {
}
test "std.meta.bitCount" {
- debug.assert(bitCount(u8) == 8);
- debug.assert(bitCount(f32) == 32);
+ testing.expect(bitCount(u8) == 8);
+ testing.expect(bitCount(f32) == 32);
}
-pub fn alignment(comptime T: type) u29 {
+pub fn alignment(comptime T: type) comptime_int {
//@alignOf works on non-pointer types
const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
return @typeInfo(P).Pointer.alignment;
}
test "std.meta.alignment" {
- debug.assert(alignment(u8) == 1);
- debug.assert(alignment(*align(1) u8) == 1);
- debug.assert(alignment(*align(2) u8) == 2);
- debug.assert(alignment([]align(1) u8) == 1);
- debug.assert(alignment([]align(2) u8) == 2);
+ testing.expect(alignment(u8) == 1);
+ testing.expect(alignment(*align(1) u8) == 1);
+ testing.expect(alignment(*align(2) u8) == 2);
+ testing.expect(alignment([]align(1) u8) == 1);
+ testing.expect(alignment([]align(2) u8) == 2);
}
pub fn Child(comptime T: type) type {
@@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type {
}
test "std.meta.Child" {
- debug.assert(Child([1]u8) == u8);
- debug.assert(Child(*u8) == u8);
- debug.assert(Child([]u8) == u8);
- debug.assert(Child(?u8) == u8);
- debug.assert(Child(promise->u8) == u8);
+ testing.expect(Child([1]u8) == u8);
+ testing.expect(Child(*u8) == u8);
+ testing.expect(Child([]u8) == u8);
+ testing.expect(Child(?u8) == u8);
+ testing.expect(Child(promise->u8) == u8);
}
pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
@@ -172,15 +173,15 @@ test "std.meta.containerLayout" {
a: u8,
};
- debug.assert(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);
- debug.assert(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);
- debug.assert(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);
- debug.assert(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);
- debug.assert(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);
- debug.assert(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);
- debug.assert(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);
- debug.assert(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);
- debug.assert(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
+ testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);
+ testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);
+ testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);
+ testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);
+ testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);
+ testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);
+ testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);
+ testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);
+ testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
}
pub fn definitions(comptime T: type) []TypeInfo.Definition {
@@ -214,8 +215,8 @@ test "std.meta.definitions" {
};
inline for (defs) |def| {
- debug.assert(def.len == 1);
- debug.assert(comptime mem.eql(u8, def[0].name, "a"));
+ testing.expect(def.len == 1);
+ testing.expect(comptime mem.eql(u8, def[0].name, "a"));
}
}
@@ -250,8 +251,8 @@ test "std.meta.definitionInfo" {
};
inline for (infos) |info| {
- debug.assert(comptime mem.eql(u8, info.name, "a"));
- debug.assert(!info.is_pub);
+ testing.expect(comptime mem.eql(u8, info.name, "a"));
+ testing.expect(!info.is_pub);
}
}
@@ -288,16 +289,16 @@ test "std.meta.fields" {
const sf = comptime fields(S1);
const uf = comptime fields(U1);
- debug.assert(e1f.len == 1);
- debug.assert(e2f.len == 1);
- debug.assert(sf.len == 1);
- debug.assert(uf.len == 1);
- debug.assert(mem.eql(u8, e1f[0].name, "A"));
- debug.assert(mem.eql(u8, e2f[0].name, "A"));
- debug.assert(mem.eql(u8, sf[0].name, "a"));
- debug.assert(mem.eql(u8, uf[0].name, "a"));
- debug.assert(comptime sf[0].field_type == u8);
- debug.assert(comptime uf[0].field_type == u8);
+ testing.expect(e1f.len == 1);
+ testing.expect(e2f.len == 1);
+ testing.expect(sf.len == 1);
+ testing.expect(uf.len == 1);
+ testing.expect(mem.eql(u8, e1f[0].name, "A"));
+ testing.expect(mem.eql(u8, e2f[0].name, "A"));
+ testing.expect(mem.eql(u8, sf[0].name, "a"));
+ testing.expect(mem.eql(u8, uf[0].name, "a"));
+ testing.expect(comptime sf[0].field_type == u8);
+ testing.expect(comptime uf[0].field_type == u8);
}
pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {
@@ -332,12 +333,12 @@ test "std.meta.fieldInfo" {
const sf = comptime fieldInfo(S1, "a");
const uf = comptime fieldInfo(U1, "a");
- debug.assert(mem.eql(u8, e1f.name, "A"));
- debug.assert(mem.eql(u8, e2f.name, "A"));
- debug.assert(mem.eql(u8, sf.name, "a"));
- debug.assert(mem.eql(u8, uf.name, "a"));
- debug.assert(comptime sf.field_type == u8);
- debug.assert(comptime uf.field_type == u8);
+ testing.expect(mem.eql(u8, e1f.name, "A"));
+ testing.expect(mem.eql(u8, e2f.name, "A"));
+ testing.expect(mem.eql(u8, sf.name, "a"));
+ testing.expect(mem.eql(u8, uf.name, "a"));
+ testing.expect(comptime sf.field_type == u8);
+ testing.expect(comptime uf.field_type == u8);
}
pub fn TagType(comptime T: type) type {
@@ -358,8 +359,8 @@ test "std.meta.TagType" {
D: u16,
};
- debug.assert(TagType(E) == u8);
- debug.assert(TagType(U) == E);
+ testing.expect(TagType(E) == u8);
+ testing.expect(TagType(U) == E);
}
///Returns the active tag of a tagged union
@@ -380,10 +381,37 @@ test "std.meta.activeTag" {
};
var u = U{ .Int = 32 };
- debug.assert(activeTag(u) == UE.Int);
+ testing.expect(activeTag(u) == UE.Int);
u = U{ .Float = 112.9876 };
- debug.assert(activeTag(u) == UE.Float);
+ testing.expect(activeTag(u) == UE.Float);
+}
+
+///Given a tagged union type, and an enum, return the type of the union
+/// field corresponding to the enum tag.
+pub fn TagPayloadType(comptime U: type, tag: var) type {
+ const Tag = @typeOf(tag);
+ testing.expect(trait.is(builtin.TypeId.Union)(U));
+ testing.expect(trait.is(builtin.TypeId.Enum)(Tag));
+
+ const info = @typeInfo(U).Union;
+
+ inline for (info.fields) |field_info| {
+ if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type;
+ }
+ unreachable;
+}
+
+test "std.meta.TagPayloadType" {
+ const Event = union(enum) {
+ Moved: struct {
+ from: i32,
+ to: i32,
+ },
+ };
+ const MovedEvent = TagPayloadType(Event, Event.Moved);
+ var e: Event = undefined;
+ testing.expect(MovedEvent == @typeOf(e.Moved));
}
///Compares two of any type for equality. Containers are compared on a field-by-field basis,
@@ -435,10 +463,18 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
builtin.TypeId.Pointer => {
const info = @typeInfo(T).Pointer;
switch (info.size) {
- builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b,
+ builtin.TypeInfo.Pointer.Size.One,
+ builtin.TypeInfo.Pointer.Size.Many,
+ builtin.TypeInfo.Pointer.Size.C,
+ => return a == b,
builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
}
},
+ builtin.TypeId.Optional => {
+ if (a == null and b == null) return true;
+ if (a == null or b == null) return false;
+ return eql(a.?, b.?);
+ },
else => return a == b,
}
}
@@ -452,7 +488,7 @@ test "std.meta.eql" {
const U = union(enum) {
s: S,
- f: f32,
+ f: ?f32,
};
const s_1 = S{
@@ -477,19 +513,19 @@ test "std.meta.eql" {
const u_2 = U{ .s = s_1 };
const u_3 = U{ .f = 24 };
- debug.assert(eql(s_1, s_3));
- debug.assert(eql(&s_1, &s_1));
- debug.assert(!eql(&s_1, &s_3));
- debug.assert(eql(u_1, u_3));
- debug.assert(!eql(u_1, u_2));
+ testing.expect(eql(s_1, s_3));
+ testing.expect(eql(&s_1, &s_1));
+ testing.expect(!eql(&s_1, &s_3));
+ testing.expect(eql(u_1, u_3));
+ testing.expect(!eql(u_1, u_2));
var a1 = "abcdef";
var a2 = "abcdef";
var a3 = "ghijkl";
- debug.assert(eql(a1, a2));
- debug.assert(!eql(a1, a3));
- debug.assert(!eql(a1[0..], a2[0..]));
+ testing.expect(eql(a1, a2));
+ testing.expect(!eql(a1, a3));
+ testing.expect(!eql(a1[0..], a2[0..]));
const EU = struct {
fn tst(err: bool) !u8 {
@@ -498,9 +534,9 @@ test "std.meta.eql" {
}
};
- debug.assert(eql(EU.tst(true), EU.tst(true)));
- debug.assert(eql(EU.tst(false), EU.tst(false)));
- debug.assert(!eql(EU.tst(false), EU.tst(true)));
+ testing.expect(eql(EU.tst(true), EU.tst(true)));
+ testing.expect(eql(EU.tst(false), EU.tst(false)));
+ testing.expect(!eql(EU.tst(false), EU.tst(true)));
}
test "intToEnum with error return" {
@@ -514,9 +550,9 @@ test "intToEnum with error return" {
var zero: u8 = 0;
var one: u16 = 1;
- debug.assert(intToEnum(E1, zero) catch unreachable == E1.A);
- debug.assert(intToEnum(E2, one) catch unreachable == E2.B);
- debug.assertError(intToEnum(E1, one), error.InvalidEnumTag);
+ testing.expect(intToEnum(E1, zero) catch unreachable == E1.A);
+ testing.expect(intToEnum(E2, one) catch unreachable == E2.B);
+ testing.expectError(error.InvalidEnumTag, intToEnum(E1, one));
}
pub const IntToEnumError = error{InvalidEnumTag};
diff --git a/std/meta/trait.zig b/std/meta/trait.zig
index caf7f1be04..7fca5f4dcd 100644
--- a/std/meta/trait.zig
+++ b/std/meta/trait.zig
@@ -2,6 +2,7 @@ const std = @import("../index.zig");
const builtin = @import("builtin");
const mem = std.mem;
const debug = std.debug;
+const testing = std.testing;
const warn = debug.warn;
const meta = @import("index.zig");
@@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" {
hasField("x"),
hasField("y"),
});
- debug.assert(isVector(Vector2));
- debug.assert(!isVector(u8));
+ testing.expect(isVector(Vector2));
+ testing.expect(!isVector(u8));
}
///
@@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" {
const value = u8(16);
};
- debug.assert(hasDef("value")(TestStruct));
- debug.assert(!hasDef("value")(TestStructFail));
- debug.assert(!hasDef("value")(*TestStruct));
- debug.assert(!hasDef("value")(**TestStructFail));
- debug.assert(!hasDef("x")(TestStruct));
- debug.assert(!hasDef("value")(u8));
+ testing.expect(hasDef("value")(TestStruct));
+ testing.expect(!hasDef("value")(TestStructFail));
+ testing.expect(!hasDef("value")(*TestStruct));
+ testing.expect(!hasDef("value")(**TestStructFail));
+ testing.expect(!hasDef("x")(TestStruct));
+ testing.expect(!hasDef("value")(u8));
}
///
@@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" {
pub fn useless() void {}
};
- debug.assert(hasFn("useless")(TestStruct));
- debug.assert(!hasFn("append")(TestStruct));
- debug.assert(!hasFn("useless")(u8));
+ testing.expect(hasFn("useless")(TestStruct));
+ testing.expect(!hasFn("append")(TestStruct));
+ testing.expect(!hasFn("useless")(u8));
}
///
@@ -143,11 +144,11 @@ test "std.meta.trait.hasField" {
value: u32,
};
- debug.assert(hasField("value")(TestStruct));
- debug.assert(!hasField("value")(*TestStruct));
- debug.assert(!hasField("x")(TestStruct));
- debug.assert(!hasField("x")(**TestStruct));
- debug.assert(!hasField("value")(u8));
+ testing.expect(hasField("value")(TestStruct));
+ testing.expect(!hasField("value")(*TestStruct));
+ testing.expect(!hasField("x")(TestStruct));
+ testing.expect(!hasField("x")(**TestStruct));
+ testing.expect(!hasField("value")(u8));
}
///
@@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn {
}
test "std.meta.trait.is" {
- debug.assert(is(builtin.TypeId.Int)(u8));
- debug.assert(!is(builtin.TypeId.Int)(f32));
- debug.assert(is(builtin.TypeId.Pointer)(*u8));
- debug.assert(is(builtin.TypeId.Void)(void));
- debug.assert(!is(builtin.TypeId.Optional)(anyerror));
+ testing.expect(is(builtin.TypeId.Int)(u8));
+ testing.expect(!is(builtin.TypeId.Int)(f32));
+ testing.expect(is(builtin.TypeId.Pointer)(*u8));
+ testing.expect(is(builtin.TypeId.Void)(void));
+ testing.expect(!is(builtin.TypeId.Optional)(anyerror));
}
///
@@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
}
test "std.meta.trait.isPtrTo" {
- debug.assert(!isPtrTo(builtin.TypeId.Struct)(struct {}));
- debug.assert(isPtrTo(builtin.TypeId.Struct)(*struct {}));
- debug.assert(!isPtrTo(builtin.TypeId.Struct)(**struct {}));
+ testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {}));
+ testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {}));
+ testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {}));
}
///////////Strait trait Fns
@@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" {
const TestExStruct = extern struct {};
const TestStruct = struct {};
- debug.assert(isExtern(TestExStruct));
- debug.assert(!isExtern(TestStruct));
- debug.assert(!isExtern(u8));
+ testing.expect(isExtern(TestExStruct));
+ testing.expect(!isExtern(TestStruct));
+ testing.expect(!isExtern(u8));
}
///
@@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" {
const TestPStruct = packed struct {};
const TestStruct = struct {};
- debug.assert(isPacked(TestPStruct));
- debug.assert(!isPacked(TestStruct));
- debug.assert(!isPacked(u8));
+ testing.expect(isPacked(TestPStruct));
+ testing.expect(!isPacked(TestStruct));
+ testing.expect(!isPacked(u8));
+}
+
+///
+pub fn isUnsignedInt(comptime T: type) bool {
+ return switch (@typeId(T)) {
+ builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
+ else => false,
+ };
+}
+
+test "isUnsignedInt" {
+ testing.expect(isUnsignedInt(u32) == true);
+ testing.expect(isUnsignedInt(comptime_int) == false);
+ testing.expect(isUnsignedInt(i64) == false);
+ testing.expect(isUnsignedInt(f64) == false);
+}
+
+///
+pub fn isSignedInt(comptime T: type) bool {
+ return switch (@typeId(T)) {
+ builtin.TypeId.ComptimeInt => true,
+ builtin.TypeId.Int => @typeInfo(T).Int.is_signed,
+ else => false,
+ };
+}
+
+test "isSignedInt" {
+ testing.expect(isSignedInt(u32) == false);
+ testing.expect(isSignedInt(comptime_int) == true);
+ testing.expect(isSignedInt(i64) == true);
+ testing.expect(isSignedInt(f64) == false);
}
///
@@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool {
test "std.meta.trait.isSingleItemPtr" {
const array = []u8{0} ** 10;
- debug.assert(isSingleItemPtr(@typeOf(&array[0])));
- debug.assert(!isSingleItemPtr(@typeOf(array)));
- debug.assert(!isSingleItemPtr(@typeOf(array[0..1])));
+ testing.expect(isSingleItemPtr(@typeOf(&array[0])));
+ testing.expect(!isSingleItemPtr(@typeOf(array)));
+ testing.expect(!isSingleItemPtr(@typeOf(array[0..1])));
}
///
@@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool {
test "std.meta.trait.isManyItemPtr" {
const array = []u8{0} ** 10;
const mip = @ptrCast([*]const u8, &array[0]);
- debug.assert(isManyItemPtr(@typeOf(mip)));
- debug.assert(!isManyItemPtr(@typeOf(array)));
- debug.assert(!isManyItemPtr(@typeOf(array[0..1])));
+ testing.expect(isManyItemPtr(@typeOf(mip)));
+ testing.expect(!isManyItemPtr(@typeOf(array)));
+ testing.expect(!isManyItemPtr(@typeOf(array[0..1])));
}
///
@@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool {
test "std.meta.trait.isSlice" {
const array = []u8{0} ** 10;
- debug.assert(isSlice(@typeOf(array[0..])));
- debug.assert(!isSlice(@typeOf(array)));
- debug.assert(!isSlice(@typeOf(&array[0])));
+ testing.expect(isSlice(@typeOf(array[0..])));
+ testing.expect(!isSlice(@typeOf(array)));
+ testing.expect(!isSlice(@typeOf(&array[0])));
}
///
@@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" {
const array = []u8{0} ** 10;
const slice = array[0..];
- debug.assert(isIndexable(@typeOf(array)));
- debug.assert(isIndexable(@typeOf(&array)));
- debug.assert(isIndexable(@typeOf(slice)));
- debug.assert(!isIndexable(meta.Child(@typeOf(slice))));
+ testing.expect(isIndexable(@typeOf(array)));
+ testing.expect(isIndexable(@typeOf(&array)));
+ testing.expect(isIndexable(@typeOf(slice)));
+ testing.expect(!isIndexable(meta.Child(@typeOf(slice))));
}
///
@@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" {
number: u8,
};
- debug.assert(isNumber(u32));
- debug.assert(isNumber(f32));
- debug.assert(isNumber(u64));
- debug.assert(isNumber(@typeOf(102)));
- debug.assert(isNumber(@typeOf(102.123)));
- debug.assert(!isNumber([]u8));
- debug.assert(!isNumber(NotANumber));
+ testing.expect(isNumber(u32));
+ testing.expect(isNumber(f32));
+ testing.expect(isNumber(u64));
+ testing.expect(isNumber(@typeOf(102)));
+ testing.expect(isNumber(@typeOf(102.123)));
+ testing.expect(!isNumber([]u8));
+ testing.expect(!isNumber(NotANumber));
}
///
@@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool {
test "std.meta.trait.isConstPtr" {
var t = u8(0);
const c = u8(0);
- debug.assert(isConstPtr(*const @typeOf(t)));
- debug.assert(isConstPtr(@typeOf(&c)));
- debug.assert(!isConstPtr(*@typeOf(t)));
- debug.assert(!isConstPtr(@typeOf(6)));
+ testing.expect(isConstPtr(*const @typeOf(t)));
+ testing.expect(isConstPtr(@typeOf(&c)));
+ testing.expect(!isConstPtr(*@typeOf(t)));
+ testing.expect(!isConstPtr(@typeOf(6)));
}
///
@@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" {
B,
};
- debug.assert(isContainer(TestStruct));
- debug.assert(isContainer(TestUnion));
- debug.assert(isContainer(TestEnum));
- debug.assert(!isContainer(u8));
+ testing.expect(isContainer(TestStruct));
+ testing.expect(isContainer(TestUnion));
+ testing.expect(isContainer(TestEnum));
+ testing.expect(!isContainer(u8));
}
diff --git a/std/mutex.zig b/std/mutex.zig
index e35bd81bc4..a13b1c06c7 100644
--- a/std/mutex.zig
+++ b/std/mutex.zig
@@ -2,77 +2,127 @@ const std = @import("index.zig");
const builtin = @import("builtin");
const AtomicOrder = builtin.AtomicOrder;
const AtomicRmwOp = builtin.AtomicRmwOp;
-const assert = std.debug.assert;
+const testing = std.testing;
const SpinLock = std.SpinLock;
const linux = std.os.linux;
+const windows = std.os.windows;
/// Lock may be held only once. If the same thread
/// tries to acquire the same mutex twice, it deadlocks.
+/// This type must be initialized at runtime, and then deinitialized when no
+/// longer needed, to free resources.
+/// If you need static initialization, use std.StaticallyInitializedMutex.
/// The Linux implementation is based on mutex3 from
/// https://www.akkadia.org/drepper/futex.pdf
-pub const Mutex = struct {
- /// 0: unlocked
- /// 1: locked, no waiters
- /// 2: locked, one or more waiters
- linux_lock: @typeOf(linux_lock_init),
+/// When an application is built in single threaded release mode, all the functions are
+/// no-ops. In single threaded debug mode, there is deadlock detection.
+pub const Mutex = if (builtin.single_threaded)
+ struct {
+ lock: @typeOf(lock_init),
- /// TODO better implementation than spin lock
- spin_lock: @typeOf(spin_lock_init),
+ const lock_init = if (std.debug.runtime_safety) false else {};
- const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};
- const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};
+ pub const Held = struct {
+ mutex: *Mutex,
- pub const Held = struct {
- mutex: *Mutex,
+ pub fn release(self: Held) void {
+ if (std.debug.runtime_safety) {
+ self.mutex.lock = false;
+ }
+ }
+ };
+ pub fn init() Mutex {
+ return Mutex{ .lock = lock_init };
+ }
+ pub fn deinit(self: *Mutex) void {}
- pub fn release(self: Held) void {
- if (builtin.os == builtin.Os.linux) {
- const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
+ pub fn acquire(self: *Mutex) Held {
+ if (std.debug.runtime_safety and self.lock) {
+ @panic("deadlock detected");
+ }
+ return Held{ .mutex = self };
+ }
+ }
+else switch (builtin.os) {
+ builtin.Os.linux => struct {
+ /// 0: unlocked
+ /// 1: locked, no waiters
+ /// 2: locked, one or more waiters
+ lock: i32,
+
+ pub const Held = struct {
+ mutex: *Mutex,
+
+ pub fn release(self: Held) void {
+ const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
if (c != 1) {
- _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
- const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
+ _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
+ const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
switch (linux.getErrno(rc)) {
0 => {},
linux.EINVAL => unreachable,
else => unreachable,
}
}
- } else {
- SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
}
- }
- };
-
- pub fn init() Mutex {
- return Mutex{
- .linux_lock = linux_lock_init,
- .spin_lock = spin_lock_init,
};
- }
- pub fn acquire(self: *Mutex) Held {
- if (builtin.os == builtin.Os.linux) {
- var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
+ pub fn init() Mutex {
+ return Mutex{ .lock = 0 };
+ }
+
+ pub fn deinit(self: *Mutex) void {}
+
+ pub fn acquire(self: *Mutex) Held {
+ var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
return Held{ .mutex = self };
if (c != 2)
- c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
+ c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
while (c != 0) {
- const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
+ const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
switch (linux.getErrno(rc)) {
0, linux.EINTR, linux.EAGAIN => {},
linux.EINVAL => unreachable,
else => unreachable,
}
- c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
+ c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
}
- } else {
- _ = self.spin_lock.acquire();
+ return Held{ .mutex = self };
}
- return Held{ .mutex = self };
- }
+ },
+ // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
+ // better implementation of this. The problem is we need the init() function to have access to
+ // the address of the CRITICAL_SECTION, and then have it not move.
+ builtin.Os.windows => std.StaticallyInitializedMutex,
+ else => struct {
+ /// TODO better implementation than spin lock.
+ /// When changing this, one must also change the corresponding
+ /// std.StaticallyInitializedMutex code, since it aliases this type,
+ /// under the assumption that it works both statically and at runtime.
+ lock: SpinLock,
+
+ pub const Held = struct {
+ mutex: *Mutex,
+
+ pub fn release(self: Held) void {
+ SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock });
+ }
+ };
+
+ pub fn init() Mutex {
+ return Mutex{ .lock = SpinLock.init() };
+ }
+
+ pub fn deinit(self: *Mutex) void {}
+
+ pub fn acquire(self: *Mutex) Held {
+ _ = self.lock.acquire();
+ return Held{ .mutex = self };
+ }
+ },
};
-const Context = struct {
+const TestContext = struct {
mutex: *Mutex,
data: i128,
@@ -90,25 +140,32 @@ test "std.Mutex" {
var a = &fixed_buffer_allocator.allocator;
var mutex = Mutex.init();
- var context = Context{
+ defer mutex.deinit();
+
+ var context = TestContext{
.mutex = &mutex,
.data = 0,
};
- const thread_count = 10;
- var threads: [thread_count]*std.os.Thread = undefined;
- for (threads) |*t| {
- t.* = try std.os.spawnThread(&context, worker);
- }
- for (threads) |t|
- t.wait();
+ if (builtin.single_threaded) {
+ worker(&context);
+ testing.expect(context.data == TestContext.incr_count);
+ } else {
+ const thread_count = 10;
+ var threads: [thread_count]*std.os.Thread = undefined;
+ for (threads) |*t| {
+ t.* = try std.os.spawnThread(&context, worker);
+ }
+ for (threads) |t|
+ t.wait();
- std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);
+ testing.expect(context.data == thread_count * TestContext.incr_count);
+ }
}
-fn worker(ctx: *Context) void {
+fn worker(ctx: *TestContext) void {
var i: usize = 0;
- while (i != Context.incr_count) : (i += 1) {
+ while (i != TestContext.incr_count) : (i += 1) {
const held = ctx.mutex.acquire();
defer held.release();
diff --git a/std/net.zig b/std/net.zig
index 006a9d4ac5..968c1f019f 100644
--- a/std/net.zig
+++ b/std/net.zig
@@ -23,7 +23,7 @@ pub const Address = struct {
.os_addr = posix.sockaddr{
.in = posix.sockaddr_in{
.family = posix.AF_INET,
- .port = std.mem.endianSwapIfLe(u16, _port),
+ .port = mem.nativeToBig(u16, _port),
.addr = ip4,
.zero = []u8{0} ** 8,
},
@@ -37,7 +37,7 @@ pub const Address = struct {
.os_addr = posix.sockaddr{
.in6 = posix.sockaddr_in6{
.family = posix.AF_INET6,
- .port = std.mem.endianSwapIfLe(u16, _port),
+ .port = mem.nativeToBig(u16, _port),
.flowinfo = 0,
.addr = ip6.addr,
.scope_id = ip6.scope_id,
@@ -47,7 +47,7 @@ pub const Address = struct {
}
pub fn port(self: Address) u16 {
- return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
+ return mem.bigToNative(u16, self.os_addr.in.port);
}
pub fn initPosix(addr: posix.sockaddr) Address {
@@ -57,12 +57,12 @@ pub const Address = struct {
pub fn format(self: *const Address, out_stream: var) !void {
switch (self.os_addr.in.family) {
posix.AF_INET => {
- const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
+ const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
},
posix.AF_INET6 => {
- const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);
+ const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
},
else => try out_stream.write("(unrecognized address family)"),
@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
}
test "std.net.parseIp4" {
- assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
+ assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001));
testParseIp4Fail("256.0.0.1", error.Overflow);
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
diff --git a/std/os/child_process.zig b/std/os/child_process.zig
index c8865bfacd..1da0b3492b 100644
--- a/std/os/child_process.zig
+++ b/std/os/child_process.zig
@@ -7,7 +7,6 @@ const posix = os.posix;
const windows = os.windows;
const mem = std.mem;
const debug = std.debug;
-const assert = debug.assert;
const BufMap = std.BufMap;
const Buffer = std.Buffer;
const builtin = @import("builtin");
@@ -88,7 +87,8 @@ pub const ChildProcess = struct {
/// First argument in argv is the executable.
/// On success must call deinit.
pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess {
- const child = try allocator.create(ChildProcess{
+ const child = try allocator.create(ChildProcess);
+ child.* = ChildProcess{
.allocator = allocator,
.argv = argv,
.pid = undefined,
@@ -109,7 +109,7 @@ pub const ChildProcess = struct {
.stdin_behavior = StdIo.Inherit,
.stdout_behavior = StdIo.Inherit,
.stderr_behavior = StdIo.Inherit,
- });
+ };
errdefer allocator.destroy(child);
return child;
}
@@ -573,7 +573,7 @@ pub const ChildProcess = struct {
// to match posix semantics
const app_name = x: {
if (self.cwd) |cwd| {
- const resolved = try os.path.resolve(self.allocator, cwd, self.argv[0]);
+ const resolved = try os.path.resolve(self.allocator, [][]const u8{ cwd, self.argv[0] });
defer self.allocator.free(resolved);
break :x try cstr.addNullByte(self.allocator, resolved);
} else {
@@ -594,12 +594,12 @@ pub const ChildProcess = struct {
const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
defer self.allocator.free(PATH);
- var it = mem.split(PATH, ";");
+ var it = mem.tokenize(PATH, ";");
while (it.next()) |search_path| {
- const joined_path = try os.path.join(self.allocator, search_path, app_name);
+ const joined_path = try os.path.join(self.allocator, [][]const u8{ search_path, app_name });
defer self.allocator.free(joined_path);
- const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, app_name);
+ const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path);
defer self.allocator.free(joined_path_w);
if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| {
@@ -609,6 +609,9 @@ pub const ChildProcess = struct {
} else {
return err;
}
+ } else {
+ // Every other error would have been returned earlier.
+ return error.FileNotFound;
}
};
@@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
fn writeIntFd(fd: i32, value: ErrInt) !void {
const stream = &os.File.openHandle(fd).outStream().stream;
- stream.writeIntNe(ErrInt, value) catch return error.SystemResources;
+ stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
const stream = &os.File.openHandle(fd).inStream().stream;
- return stream.readIntNe(ErrInt) catch return error.SystemResources;
+ return stream.readIntNative(ErrInt) catch return error.SystemResources;
}
diff --git a/std/os/darwin.zig b/std/os/darwin.zig
index c64ce807b6..3e883abbab 100644
--- a/std/os/darwin.zig
+++ b/std/os/darwin.zig
@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) 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),
+ @ptrCast(?*c_void, address),
length,
@bitCast(c_int, @intCast(c_uint, prot)),
@bitCast(c_int, c_uint(flags)),
diff --git a/std/os/freebsd/index.zig b/std/os/freebsd/index.zig
index 75389fc403..48c0ea5b1e 100644
--- a/std/os/freebsd/index.zig
+++ b/std/os/freebsd/index.zig
@@ -1,16 +1,20 @@
-const assert = @import("../debug.zig").assert;
const builtin = @import("builtin");
-const arch = switch (builtin.arch) {
- builtin.Arch.x86_64 => @import("x86_64.zig"),
- else => @compileError("unsupported arch"),
-};
-pub use @import("syscall.zig");
+
pub use @import("errno.zig");
const std = @import("../../index.zig");
const c = std.c;
+
+const assert = std.debug.assert;
+const maxInt = std.math.maxInt;
pub const Kevent = c.Kevent;
+pub const CTL_KERN = 1;
+pub const CTL_DEBUG = 5;
+
+pub const KERN_PROC = 14; // struct: process entries
+pub const KERN_PROC_PATHNAME = 12; // path to executable
+
pub const PATH_MAX = 1024;
pub const STDIN_FILENO = 0;
@@ -22,7 +26,22 @@ pub const PROT_READ = 1;
pub const PROT_WRITE = 2;
pub const PROT_EXEC = 4;
-pub const MAP_FAILED = @maxValue(usize);
+pub const CLOCK_REALTIME = 0;
+pub const CLOCK_VIRTUAL = 1;
+pub const CLOCK_PROF = 2;
+pub const CLOCK_MONOTONIC = 4;
+pub const CLOCK_UPTIME = 5;
+pub const CLOCK_UPTIME_PRECISE = 7;
+pub const CLOCK_UPTIME_FAST = 8;
+pub const CLOCK_REALTIME_PRECISE = 9;
+pub const CLOCK_REALTIME_FAST = 10;
+pub const CLOCK_MONOTONIC_PRECISE = 11;
+pub const CLOCK_MONOTONIC_FAST = 12;
+pub const CLOCK_SECOND = 13;
+pub const CLOCK_THREAD_CPUTIME_ID = 14;
+pub const CLOCK_PROCESS_CPUTIME_ID = 15;
+
+pub const MAP_FAILED = maxInt(usize);
pub const MAP_SHARED = 0x0001;
pub const MAP_PRIVATE = 0x0002;
pub const MAP_FIXED = 0x0010;
@@ -94,26 +113,33 @@ pub const SIGLIBRT = 33;
pub const SIGRTMIN = 65;
pub const SIGRTMAX = 126;
-pub const O_RDONLY = 0o0;
-pub const O_WRONLY = 0o1;
-pub const O_RDWR = 0o2;
-pub const O_ACCMODE = 0o3;
+// access function
+pub const F_OK = 0; // test for existence of file
+pub const X_OK = 1; // test for execute or search permission
+pub const W_OK = 2; // test for write permission
+pub const R_OK = 4; // test for read permission
-pub const O_CREAT = 0o100;
-pub const O_EXCL = 0o200;
-pub const O_NOCTTY = 0o400;
-pub const O_TRUNC = 0o1000;
-pub const O_APPEND = 0o2000;
-pub const O_NONBLOCK = 0o4000;
+
+pub const O_RDONLY = 0x0000;
+pub const O_WRONLY = 0x0001;
+pub const O_RDWR = 0x0002;
+pub const O_ACCMODE = 0x0003;
+
+pub const O_CREAT = 0x0200;
+pub const O_EXCL = 0x0800;
+pub const O_NOCTTY = 0x8000;
+pub const O_TRUNC = 0x0400;
+pub const O_APPEND = 0x0008;
+pub const O_NONBLOCK = 0x0004;
pub const O_DSYNC = 0o10000;
-pub const O_SYNC = 0o4010000;
+pub const O_SYNC = 0x0080;
pub const O_RSYNC = 0o4010000;
pub const O_DIRECTORY = 0o200000;
-pub const O_NOFOLLOW = 0o400000;
-pub const O_CLOEXEC = 0o2000000;
+pub const O_NOFOLLOW = 0x0100;
+pub const O_CLOEXEC = 0x00100000;
-pub const O_ASYNC = 0o20000;
-pub const O_DIRECT = 0o40000;
+pub const O_ASYNC = 0x0040;
+pub const O_DIRECT = 0x00010000;
pub const O_LARGEFILE = 0;
pub const O_NOATIME = 0o1000000;
pub const O_PATH = 0o10000000;
@@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5;
pub const SOCK_CLOEXEC = 0x10000000;
pub const SOCK_NONBLOCK = 0x20000000;
-// TODO: From here
pub const PROTO_ip = 0o000;
pub const PROTO_icmp = 0o001;
pub const PROTO_igmp = 0o002;
@@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438;
pub const TIOCGPTLCK = 0x80045439;
pub const TIOCGEXCL = 0x80045440;
+pub const sockaddr = c.sockaddr;
+pub const sockaddr_in = c.sockaddr_in;
+pub const sockaddr_in6 = c.sockaddr_in6;
+
fn unsigned(s: i32) u32 {
return @bitCast(u32, s);
}
@@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize {
}
pub fn dup2(old: i32, new: i32) usize {
- return arch.syscall2(SYS_dup2, @intCast(usize, old), @intCast(usize, new));
+ return errnoWrap(c.dup2(old, new));
}
pub fn chdir(path: [*]const u8) usize {
- return arch.syscall1(SYS_chdir, @ptrToInt(path));
+ return errnoWrap(c.chdir(path));
}
pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
- return arch.syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
+ return errnoWrap(c.execve(path, argv, envp));
}
pub fn fork() usize {
- return arch.syscall0(SYS_fork);
+ return errnoWrap(c.fork());
+}
+
+pub fn access(path: [*]const u8, mode: u32) usize {
+ return errnoWrap(c.access(path, mode));
}
pub fn getcwd(buf: [*]u8, size: usize) usize {
- return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size);
+ return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
}
pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
- return arch.syscall3(SYS_getdents, @intCast(usize, fd), @ptrToInt(dirp), count);
+ return errnoWrap(@bitCast(isize, c.getdents(fd, drip, count)));
+}
+
+pub fn getdirentries(fd: i32, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize {
+ return errnoWrap(@bitCast(isize, c.getdirentries(fd, buf_ptr, buf_len, basep)));
+}
+
+pub fn realpath(noalias filename: [*]const u8, noalias resolved_name: [*]u8) usize {
+ return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
}
pub fn isatty(fd: i32) bool {
- var wsz: winsize = undefined;
- return arch.syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+ return c.isatty(fd) != 0;
}
pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
- return arch.syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+ return errnoWrap(c.readlink(path, buf_ptr, buf_len));
}
pub fn mkdir(path: [*]const u8, mode: u32) usize {
- return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);
+ return errnoWrap(c.mkdir(path, mode));
}
-pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize {
- return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
+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, @intCast(c_uint, prot)),
+ @bitCast(c_int, c_uint(flags)),
+ fd,
+ offset,
+ );
+ const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
+ return errnoWrap(isize_result);
}
pub fn munmap(address: usize, length: usize) usize {
- return arch.syscall2(SYS_munmap, address, length);
+ return errnoWrap(c.munmap(@intToPtr(*c_void, address), length));
}
-pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
- return arch.syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
+pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
+ return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
}
pub fn rmdir(path: [*]const u8) usize {
- return arch.syscall1(SYS_rmdir, @ptrToInt(path));
+ return errnoWrap(c.rmdir(path));
}
pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
- return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
+ return errnoWrap(c.symlink(existing, new));
}
-pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
- return arch.syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize {
+ return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset));
}
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize {
- return arch.syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+ return errnoWrap(c.preadv(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset));
}
pub fn pipe(fd: *[2]i32) usize {
return pipe2(fd, 0);
}
-pub fn pipe2(fd: *[2]i32, flags: usize) usize {
- return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);
+pub fn pipe2(fd: *[2]i32, flags: u32) usize {
+ comptime assert(i32.bit_count == c_int.bit_count);
+ return errnoWrap(c.pipe2(@ptrCast(*[2]c_int, fd), flags));
}
-pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
- return arch.syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
+pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
+ return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
}
-pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
- return arch.syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
+ return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset));
}
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize {
- return arch.syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+ return errnoWrap(c.pwritev(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset));
}
pub fn rename(old: [*]const u8, new: [*]const u8) usize {
- return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
+ return errnoWrap(c.rename(old, new));
}
-pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
- return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);
+pub fn open(path: [*]const u8, flags: u32, mode: usize) usize {
+ return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
}
pub fn create(path: [*]const u8, perm: usize) usize {
@@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize {
}
pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
- return arch.syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
+ return errnoWrap(c.openat(@bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode));
}
pub fn close(fd: i32) usize {
- return arch.syscall1(SYS_close, @intCast(usize, fd));
+ return errnoWrap(c.close(fd));
}
-pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
- return arch.syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
+pub fn lseek(fd: i32, offset: isize, whence: c_int) usize {
+ return errnoWrap(c.lseek(fd, offset, whence));
}
-pub fn exit(status: i32) noreturn {
- _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));
- unreachable;
-}
-
-pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
- return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
+pub fn exit(code: i32) noreturn {
+ c.exit(code);
}
pub fn kill(pid: i32, sig: i32) usize {
- return arch.syscall2(SYS_kill, @bitCast(usize, @intCast(isize, pid)), @intCast(usize, sig));
+ return errnoWrap(c.kill(pid, sig));
}
pub fn unlink(path: [*]const u8) usize {
- return arch.syscall1(SYS_unlink, @ptrToInt(path));
+ return errnoWrap(c.unlink(path));
}
-pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
- return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
+pub fn waitpid(pid: i32, status: *i32, options: u32) usize {
+ comptime assert(i32.bit_count == c_int.bit_count);
+ return errnoWrap(c.waitpid(pid, @ptrCast(*c_int, status), @bitCast(c_int, options)));
}
pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
- return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
+ return errnoWrap(c.nanosleep(req, rem));
+}
+
+pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
+ return errnoWrap(c.clock_gettime(clk_id, tp));
+}
+
+pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
+ return errnoWrap(c.clock_getres(clk_id, tp));
}
pub fn setuid(uid: u32) usize {
- return arch.syscall1(SYS_setuid, uid);
+ return errnoWrap(c.setuid(uid));
}
pub fn setgid(gid: u32) usize {
- return arch.syscall1(SYS_setgid, gid);
+ return errnoWrap(c.setgid(gid));
}
pub fn setreuid(ruid: u32, euid: u32) usize {
- return arch.syscall2(SYS_setreuid, ruid, euid);
+ return errnoWrap(c.setreuid(ruid, euid));
}
pub fn setregid(rgid: u32, egid: u32) usize {
- return arch.syscall2(SYS_setregid, rgid, egid);
+ return errnoWrap(c.setregid(rgid, egid));
}
-pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
- // TODO: Implement
- return 0;
-}
+const NSIG = 32;
-pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
- // TODO: Implement
- return 0;
-}
-
-const NSIG = 65;
-const sigset_t = [128 / @sizeOf(usize)]usize;
-const all_mask = []usize{@maxValue(usize)};
-const app_mask = []usize{0xfffffffc7fffffff};
-
-/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
-pub const Sigaction = struct {
- // TODO: Adjust to use freebsd struct layout
- handler: extern fn (i32) void,
- mask: sigset_t,
- flags: u32,
-};
-
-pub const SIG_ERR = @intToPtr(extern fn (i32) void, @maxValue(usize));
+pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
-pub const empty_sigset = []usize{0} ** sigset_t.len;
+
+/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
+pub const Sigaction = extern struct {
+ /// signal handler
+ __sigaction_u: extern union {
+ __sa_handler: extern fn (i32) void,
+ __sa_sigaction: extern fn (i32, *__siginfo, usize) void,
+ },
+
+ /// see signal options
+ sa_flags: u32,
+
+ /// signal mask to apply
+ sa_mask: sigset_t,
+};
+
+pub const _SIG_WORDS = 4;
+pub const _SIG_MAXSIG = 128;
+
+pub inline fn _SIG_IDX(sig: usize) usize {
+ return sig - 1;
+}
+pub inline fn _SIG_WORD(sig: usize) usize {
+ return_SIG_IDX(sig) >> 5;
+}
+pub inline fn _SIG_BIT(sig: usize) usize {
+ return 1 << (_SIG_IDX(sig) & 31);
+}
+pub inline fn _SIG_VALID(sig: usize) usize {
+ return sig <= _SIG_MAXSIG and sig > 0;
+}
+
+pub const sigset_t = extern struct {
+ __bits: [_SIG_WORDS]u32,
+};
pub fn raise(sig: i32) usize {
- // TODO implement, see linux equivalent for what we want to try and do
- return 0;
+ return errnoWrap(c.raise(sig));
}
-fn blockAllSignals(set: *sigset_t) void {
- // TODO implement
+pub const Stat = c.Stat;
+pub const dirent = c.dirent;
+pub const timespec = c.timespec;
+
+pub fn fstat(fd: i32, buf: *c.Stat) usize {
+ return errnoWrap(c.fstat(fd, buf));
}
-
-fn blockAppSignals(set: *sigset_t) void {
- // TODO implement
-}
-
-fn restoreSignals(set: *sigset_t) void {
- // TODO implement
-}
-
-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));
-}
-
-pub fn sigismember(set: *const sigset_t, sig: u6) bool {
- const s = sig - 1;
- return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
-}
-
-pub const Stat = arch.Stat;
-pub const timespec = arch.timespec;
-
-pub fn fstat(fd: i32, stat_buf: *Stat) usize {
- return arch.syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
-}
-
pub const iovec = extern struct {
iov_base: [*]u8,
iov_len: usize,
@@ -760,10 +804,12 @@ pub const iovec_const = extern struct {
iov_len: usize,
};
+// TODO avoid libc dependency
pub fn kqueue() usize {
return errnoWrap(c.kqueue());
}
+// TODO avoid libc dependency
pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {
return errnoWrap(c.kevent(
kq,
@@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout:
));
}
+// TODO avoid libc dependency
pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
}
+// TODO avoid libc dependency
pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
}
+// TODO avoid libc dependency
pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
}
+// TODO avoid libc dependency
+
/// Takes the return value from a syscall and formats it back in the way
/// that the kernel represents it to libc. Errno was a mistake, let's make
/// it go away forever.
diff --git a/std/os/freebsd/syscall.zig b/std/os/freebsd/syscall.zig
deleted file mode 100644
index 6cdd71de3b..0000000000
--- a/std/os/freebsd/syscall.zig
+++ /dev/null
@@ -1,493 +0,0 @@
-pub const SYS_syscall = 0;
-pub const SYS_exit = 1;
-pub const SYS_fork = 2;
-pub const SYS_read = 3;
-pub const SYS_write = 4;
-pub const SYS_open = 5;
-pub const SYS_close = 6;
-pub const SYS_wait4 = 7;
-// 8 is old creat
-pub const SYS_link = 9;
-pub const SYS_unlink = 10;
-// 11 is obsolete execv
-pub const SYS_chdir = 12;
-pub const SYS_fchdir = 13;
-pub const SYS_freebsd11_mknod = 14;
-pub const SYS_chmod = 15;
-pub const SYS_chown = 16;
-pub const SYS_break = 17;
-// 18 is freebsd4 getfsstat
-// 19 is old lseek
-pub const SYS_getpid = 20;
-pub const SYS_mount = 21;
-pub const SYS_unmount = 22;
-pub const SYS_setuid = 23;
-pub const SYS_getuid = 24;
-pub const SYS_geteuid = 25;
-pub const SYS_ptrace = 26;
-pub const SYS_recvmsg = 27;
-pub const SYS_sendmsg = 28;
-pub const SYS_recvfrom = 29;
-pub const SYS_accept = 30;
-pub const SYS_getpeername = 31;
-pub const SYS_getsockname = 32;
-pub const SYS_access = 33;
-pub const SYS_chflags = 34;
-pub const SYS_fchflags = 35;
-pub const SYS_sync = 36;
-pub const SYS_kill = 37;
-// 38 is old stat
-pub const SYS_getppid = 39;
-// 40 is old lstat
-pub const SYS_dup = 41;
-pub const SYS_freebsd10_pipe = 42;
-pub const SYS_getegid = 43;
-pub const SYS_profil = 44;
-pub const SYS_ktrace = 45;
-// 46 is old sigaction
-pub const SYS_getgid = 47;
-// 48 is old sigprocmask
-pub const SYS_getlogin = 49;
-pub const SYS_setlogin = 50;
-pub const SYS_acct = 51;
-// 52 is old sigpending
-pub const SYS_sigaltstack = 53;
-pub const SYS_ioctl = 54;
-pub const SYS_reboot = 55;
-pub const SYS_revoke = 56;
-pub const SYS_symlink = 57;
-pub const SYS_readlink = 58;
-pub const SYS_execve = 59;
-pub const SYS_umask = 60;
-pub const SYS_chroot = 61;
-// 62 is old fstat
-// 63 is old getkerninfo
-// 64 is old getpagesize
-pub const SYS_msync = 65;
-pub const SYS_vfork = 66;
-// 67 is obsolete vread
-// 68 is obsolete vwrite
-// 69 is obsolete sbrk (still present on some platforms)
-pub const SYS_sstk = 70;
-// 71 is old mmap
-pub const SYS_vadvise = 72;
-pub const SYS_munmap = 73;
-pub const SYS_mprotect = 74;
-pub const SYS_madvise = 75;
-// 76 is obsolete vhangup
-// 77 is obsolete vlimit
-pub const SYS_mincore = 78;
-pub const SYS_getgroups = 79;
-pub const SYS_setgroups = 80;
-pub const SYS_getpgrp = 81;
-pub const SYS_setpgid = 82;
-pub const SYS_setitimer = 83;
-// 84 is old wait
-pub const SYS_swapon = 85;
-pub const SYS_getitimer = 86;
-// 87 is old gethostname
-// 88 is old sethostname
-pub const SYS_getdtablesize = 89;
-pub const SYS_dup2 = 90;
-pub const SYS_fcntl = 92;
-pub const SYS_select = 93;
-pub const SYS_fsync = 95;
-pub const SYS_setpriority = 96;
-pub const SYS_socket = 97;
-pub const SYS_connect = 98;
-// 99 is old accept
-pub const SYS_getpriority = 100;
-// 101 is old send
-// 102 is old recv
-// 103 is old sigreturn
-pub const SYS_bind = 104;
-pub const SYS_setsockopt = 105;
-pub const SYS_listen = 106;
-// 107 is obsolete vtimes
-// 108 is old sigvec
-// 109 is old sigblock
-// 110 is old sigsetmask
-// 111 is old sigsuspend
-// 112 is old sigstack
-// 113 is old recvmsg
-// 114 is old sendmsg
-// 115 is obsolete vtrace
-pub const SYS_gettimeofday = 116;
-pub const SYS_getrusage = 117;
-pub const SYS_getsockopt = 118;
-pub const SYS_readv = 120;
-pub const SYS_writev = 121;
-pub const SYS_settimeofday = 122;
-pub const SYS_fchown = 123;
-pub const SYS_fchmod = 124;
-// 125 is old recvfrom
-pub const SYS_setreuid = 126;
-pub const SYS_setregid = 127;
-pub const SYS_rename = 128;
-// 129 is old truncate
-// 130 is old ftruncate
-pub const SYS_flock = 131;
-pub const SYS_mkfifo = 132;
-pub const SYS_sendto = 133;
-pub const SYS_shutdown = 134;
-pub const SYS_socketpair = 135;
-pub const SYS_mkdir = 136;
-pub const SYS_rmdir = 137;
-pub const SYS_utimes = 138;
-// 139 is obsolete 4.2 sigreturn
-pub const SYS_adjtime = 140;
-// 141 is old getpeername
-// 142 is old gethostid
-// 143 is old sethostid
-// 144 is old getrlimit
-// 145 is old setrlimit
-// 146 is old killpg
-pub const SYS_setsid = 147;
-pub const SYS_quotactl = 148;
-// 149 is old quota
-// 150 is old getsockname
-pub const SYS_nlm_syscall = 154;
-pub const SYS_nfssvc = 155;
-// 156 is old getdirentries
-// 157 is freebsd4 statfs
-// 158 is freebsd4 fstatfs
-pub const SYS_lgetfh = 160;
-pub const SYS_getfh = 161;
-// 162 is freebsd4 getdomainname
-// 163 is freebsd4 setdomainname
-// 164 is freebsd4 uname
-pub const SYS_sysarch = 165;
-pub const SYS_rtprio = 166;
-pub const SYS_semsys = 169;
-pub const SYS_msgsys = 170;
-pub const SYS_shmsys = 171;
-// 173 is freebsd6 pread
-// 174 is freebsd6 pwrite
-pub const SYS_setfib = 175;
-pub const SYS_ntp_adjtime = 176;
-pub const SYS_setgid = 181;
-pub const SYS_setegid = 182;
-pub const SYS_seteuid = 183;
-// 184 is obsolete lfs_bmapv
-// 185 is obsolete lfs_markv
-// 186 is obsolete lfs_segclean
-// 187 is obsolete lfs_segwait
-pub const SYS_freebsd11_stat = 188;
-pub const SYS_freebsd11_fstat = 189;
-pub const SYS_freebsd11_lstat = 190;
-pub const SYS_pathconf = 191;
-pub const SYS_fpathconf = 192;
-pub const SYS_getrlimit = 194;
-pub const SYS_setrlimit = 195;
-pub const SYS_freebsd11_getdirentries = 196;
-// 197 is freebsd6 mmap
-pub const SYS___syscall = 198;
-// 199 is freebsd6 lseek
-// 200 is freebsd6 truncate
-// 201 is freebsd6 ftruncate
-pub const SYS___sysctl = 202;
-pub const SYS_mlock = 203;
-pub const SYS_munlock = 204;
-pub const SYS_undelete = 205;
-pub const SYS_futimes = 206;
-pub const SYS_getpgid = 207;
-pub const SYS_poll = 209;
-pub const SYS_freebsd7___semctl = 220;
-pub const SYS_semget = 221;
-pub const SYS_semop = 222;
-pub const SYS_freebsd7_msgctl = 224;
-pub const SYS_msgget = 225;
-pub const SYS_msgsnd = 226;
-pub const SYS_msgrcv = 227;
-pub const SYS_shmat = 228;
-pub const SYS_freebsd7_shmctl = 229;
-pub const SYS_shmdt = 230;
-pub const SYS_shmget = 231;
-pub const SYS_clock_gettime = 232;
-pub const SYS_clock_settime = 233;
-pub const SYS_clock_getres = 234;
-pub const SYS_ktimer_create = 235;
-pub const SYS_ktimer_delete = 236;
-pub const SYS_ktimer_settime = 237;
-pub const SYS_ktimer_gettime = 238;
-pub const SYS_ktimer_getoverrun = 239;
-pub const SYS_nanosleep = 240;
-pub const SYS_ffclock_getcounter = 241;
-pub const SYS_ffclock_setestimate = 242;
-pub const SYS_ffclock_getestimate = 243;
-pub const SYS_clock_nanosleep = 244;
-pub const SYS_clock_getcpuclockid2 = 247;
-pub const SYS_ntp_gettime = 248;
-pub const SYS_minherit = 250;
-pub const SYS_rfork = 251;
-// 252 is obsolete openbsd_poll
-pub const SYS_issetugid = 253;
-pub const SYS_lchown = 254;
-pub const SYS_aio_read = 255;
-pub const SYS_aio_write = 256;
-pub const SYS_lio_listio = 257;
-pub const SYS_freebsd11_getdents = 272;
-pub const SYS_lchmod = 274;
-// 275 is obsolete netbsd_lchown
-pub const SYS_lutimes = 276;
-// 277 is obsolete netbsd_msync
-pub const SYS_freebsd11_nstat = 278;
-pub const SYS_freebsd11_nfstat = 279;
-pub const SYS_freebsd11_nlstat = 280;
-pub const SYS_preadv = 289;
-pub const SYS_pwritev = 290;
-// 297 is freebsd4 fhstatfs
-pub const SYS_fhopen = 298;
-pub const SYS_freebsd11_fhstat = 299;
-pub const SYS_modnext = 300;
-pub const SYS_modstat = 301;
-pub const SYS_modfnext = 302;
-pub const SYS_modfind = 303;
-pub const SYS_kldload = 304;
-pub const SYS_kldunload = 305;
-pub const SYS_kldfind = 306;
-pub const SYS_kldnext = 307;
-pub const SYS_kldstat = 308;
-pub const SYS_kldfirstmod = 309;
-pub const SYS_getsid = 310;
-pub const SYS_setresuid = 311;
-pub const SYS_setresgid = 312;
-// 313 is obsolete signanosleep
-pub const SYS_aio_return = 314;
-pub const SYS_aio_suspend = 315;
-pub const SYS_aio_cancel = 316;
-pub const SYS_aio_error = 317;
-// 318 is freebsd6 aio_read
-// 319 is freebsd6 aio_write
-// 320 is freebsd6 lio_listio
-pub const SYS_yield = 321;
-// 322 is obsolete thr_sleep
-// 323 is obsolete thr_wakeup
-pub const SYS_mlockall = 324;
-pub const SYS_munlockall = 325;
-pub const SYS___getcwd = 326;
-pub const SYS_sched_setparam = 327;
-pub const SYS_sched_getparam = 328;
-pub const SYS_sched_setscheduler = 329;
-pub const SYS_sched_getscheduler = 330;
-pub const SYS_sched_yield = 331;
-pub const SYS_sched_get_priority_max = 332;
-pub const SYS_sched_get_priority_min = 333;
-pub const SYS_sched_rr_get_interval = 334;
-pub const SYS_utrace = 335;
-// 336 is freebsd4 sendfile
-pub const SYS_kldsym = 337;
-pub const SYS_jail = 338;
-pub const SYS_nnpfs_syscall = 339;
-pub const SYS_sigprocmask = 340;
-pub const SYS_sigsuspend = 341;
-// 342 is freebsd4 sigaction
-pub const SYS_sigpending = 343;
-// 344 is freebsd4 sigreturn
-pub const SYS_sigtimedwait = 345;
-pub const SYS_sigwaitinfo = 346;
-pub const SYS___acl_get_file = 347;
-pub const SYS___acl_set_file = 348;
-pub const SYS___acl_get_fd = 349;
-pub const SYS___acl_set_fd = 350;
-pub const SYS___acl_delete_file = 351;
-pub const SYS___acl_delete_fd = 352;
-pub const SYS___acl_aclcheck_file = 353;
-pub const SYS___acl_aclcheck_fd = 354;
-pub const SYS_extattrctl = 355;
-pub const SYS_extattr_set_file = 356;
-pub const SYS_extattr_get_file = 357;
-pub const SYS_extattr_delete_file = 358;
-pub const SYS_aio_waitcomplete = 359;
-pub const SYS_getresuid = 360;
-pub const SYS_getresgid = 361;
-pub const SYS_kqueue = 362;
-pub const SYS_freebsd11_kevent = 363;
-// 364 is obsolete __cap_get_proc
-// 365 is obsolete __cap_set_proc
-// 366 is obsolete __cap_get_fd
-// 367 is obsolete __cap_get_file
-// 368 is obsolete __cap_set_fd
-// 369 is obsolete __cap_set_file
-pub const SYS_extattr_set_fd = 371;
-pub const SYS_extattr_get_fd = 372;
-pub const SYS_extattr_delete_fd = 373;
-pub const SYS___setugid = 374;
-pub const SYS_eaccess = 376;
-pub const SYS_afs3_syscall = 377;
-pub const SYS_nmount = 378;
-// 379 is obsolete kse_exit
-// 380 is obsolete kse_wakeup
-// 381 is obsolete kse_create
-// 382 is obsolete kse_thr_interrupt
-// 383 is obsolete kse_release
-pub const SYS___mac_get_proc = 384;
-pub const SYS___mac_set_proc = 385;
-pub const SYS___mac_get_fd = 386;
-pub const SYS___mac_get_file = 387;
-pub const SYS___mac_set_fd = 388;
-pub const SYS___mac_set_file = 389;
-pub const SYS_kenv = 390;
-pub const SYS_lchflags = 391;
-pub const SYS_uuidgen = 392;
-pub const SYS_sendfile = 393;
-pub const SYS_mac_syscall = 394;
-pub const SYS_freebsd11_getfsstat = 395;
-pub const SYS_freebsd11_statfs = 396;
-pub const SYS_freebsd11_fstatfs = 397;
-pub const SYS_freebsd11_fhstatfs = 398;
-pub const SYS_ksem_close = 400;
-pub const SYS_ksem_post = 401;
-pub const SYS_ksem_wait = 402;
-pub const SYS_ksem_trywait = 403;
-pub const SYS_ksem_init = 404;
-pub const SYS_ksem_open = 405;
-pub const SYS_ksem_unlink = 406;
-pub const SYS_ksem_getvalue = 407;
-pub const SYS_ksem_destroy = 408;
-pub const SYS___mac_get_pid = 409;
-pub const SYS___mac_get_link = 410;
-pub const SYS___mac_set_link = 411;
-pub const SYS_extattr_set_link = 412;
-pub const SYS_extattr_get_link = 413;
-pub const SYS_extattr_delete_link = 414;
-pub const SYS___mac_execve = 415;
-pub const SYS_sigaction = 416;
-pub const SYS_sigreturn = 417;
-pub const SYS_getcontext = 421;
-pub const SYS_setcontext = 422;
-pub const SYS_swapcontext = 423;
-pub const SYS_swapoff = 424;
-pub const SYS___acl_get_link = 425;
-pub const SYS___acl_set_link = 426;
-pub const SYS___acl_delete_link = 427;
-pub const SYS___acl_aclcheck_link = 428;
-pub const SYS_sigwait = 429;
-pub const SYS_thr_create = 430;
-pub const SYS_thr_exit = 431;
-pub const SYS_thr_self = 432;
-pub const SYS_thr_kill = 433;
-pub const SYS_jail_attach = 436;
-pub const SYS_extattr_list_fd = 437;
-pub const SYS_extattr_list_file = 438;
-pub const SYS_extattr_list_link = 439;
-// 440 is obsolete kse_switchin
-pub const SYS_ksem_timedwait = 441;
-pub const SYS_thr_suspend = 442;
-pub const SYS_thr_wake = 443;
-pub const SYS_kldunloadf = 444;
-pub const SYS_audit = 445;
-pub const SYS_auditon = 446;
-pub const SYS_getauid = 447;
-pub const SYS_setauid = 448;
-pub const SYS_getaudit = 449;
-pub const SYS_setaudit = 450;
-pub const SYS_getaudit_addr = 451;
-pub const SYS_setaudit_addr = 452;
-pub const SYS_auditctl = 453;
-pub const SYS__umtx_op = 454;
-pub const SYS_thr_new = 455;
-pub const SYS_sigqueue = 456;
-pub const SYS_kmq_open = 457;
-pub const SYS_kmq_setattr = 458;
-pub const SYS_kmq_timedreceive = 459;
-pub const SYS_kmq_timedsend = 460;
-pub const SYS_kmq_notify = 461;
-pub const SYS_kmq_unlink = 462;
-pub const SYS_abort2 = 463;
-pub const SYS_thr_set_name = 464;
-pub const SYS_aio_fsync = 465;
-pub const SYS_rtprio_thread = 466;
-pub const SYS_sctp_peeloff = 471;
-pub const SYS_sctp_generic_sendmsg = 472;
-pub const SYS_sctp_generic_sendmsg_iov = 473;
-pub const SYS_sctp_generic_recvmsg = 474;
-pub const SYS_pread = 475;
-pub const SYS_pwrite = 476;
-pub const SYS_mmap = 477;
-pub const SYS_lseek = 478;
-pub const SYS_truncate = 479;
-pub const SYS_ftruncate = 480;
-pub const SYS_thr_kill2 = 481;
-pub const SYS_shm_open = 482;
-pub const SYS_shm_unlink = 483;
-pub const SYS_cpuset = 484;
-pub const SYS_cpuset_setid = 485;
-pub const SYS_cpuset_getid = 486;
-pub const SYS_cpuset_getaffinity = 487;
-pub const SYS_cpuset_setaffinity = 488;
-pub const SYS_faccessat = 489;
-pub const SYS_fchmodat = 490;
-pub const SYS_fchownat = 491;
-pub const SYS_fexecve = 492;
-pub const SYS_freebsd11_fstatat = 493;
-pub const SYS_futimesat = 494;
-pub const SYS_linkat = 495;
-pub const SYS_mkdirat = 496;
-pub const SYS_mkfifoat = 497;
-pub const SYS_freebsd11_mknodat = 498;
-pub const SYS_openat = 499;
-pub const SYS_readlinkat = 500;
-pub const SYS_renameat = 501;
-pub const SYS_symlinkat = 502;
-pub const SYS_unlinkat = 503;
-pub const SYS_posix_openpt = 504;
-pub const SYS_gssd_syscall = 505;
-pub const SYS_jail_get = 506;
-pub const SYS_jail_set = 507;
-pub const SYS_jail_remove = 508;
-pub const SYS_closefrom = 509;
-pub const SYS___semctl = 510;
-pub const SYS_msgctl = 511;
-pub const SYS_shmctl = 512;
-pub const SYS_lpathconf = 513;
-// 514 is obsolete cap_new
-pub const SYS___cap_rights_get = 515;
-pub const SYS_cap_enter = 516;
-pub const SYS_cap_getmode = 517;
-pub const SYS_pdfork = 518;
-pub const SYS_pdkill = 519;
-pub const SYS_pdgetpid = 520;
-pub const SYS_pselect = 522;
-pub const SYS_getloginclass = 523;
-pub const SYS_setloginclass = 524;
-pub const SYS_rctl_get_racct = 525;
-pub const SYS_rctl_get_rules = 526;
-pub const SYS_rctl_get_limits = 527;
-pub const SYS_rctl_add_rule = 528;
-pub const SYS_rctl_remove_rule = 529;
-pub const SYS_posix_fallocate = 530;
-pub const SYS_posix_fadvise = 531;
-pub const SYS_wait6 = 532;
-pub const SYS_cap_rights_limit = 533;
-pub const SYS_cap_ioctls_limit = 534;
-pub const SYS_cap_ioctls_get = 535;
-pub const SYS_cap_fcntls_limit = 536;
-pub const SYS_cap_fcntls_get = 537;
-pub const SYS_bindat = 538;
-pub const SYS_connectat = 539;
-pub const SYS_chflagsat = 540;
-pub const SYS_accept4 = 541;
-pub const SYS_pipe2 = 542;
-pub const SYS_aio_mlock = 543;
-pub const SYS_procctl = 544;
-pub const SYS_ppoll = 545;
-pub const SYS_futimens = 546;
-pub const SYS_utimensat = 547;
-// 548 is obsolete numa_getaffinity
-// 549 is obsolete numa_setaffinity
-pub const SYS_fdatasync = 550;
-pub const SYS_fstat = 551;
-pub const SYS_fstatat = 552;
-pub const SYS_fhstat = 553;
-pub const SYS_getdirentries = 554;
-pub const SYS_statfs = 555;
-pub const SYS_fstatfs = 556;
-pub const SYS_getfsstat = 557;
-pub const SYS_fhstatfs = 558;
-pub const SYS_mknodat = 559;
-pub const SYS_kevent = 560;
-pub const SYS_cpuset_getdomain = 561;
-pub const SYS_cpuset_setdomain = 562;
-pub const SYS_getrandom = 563;
-pub const SYS_MAXSYSCALL = 564;
diff --git a/std/os/freebsd/x86_64.zig b/std/os/freebsd/x86_64.zig
deleted file mode 100644
index 20a6710596..0000000000
--- a/std/os/freebsd/x86_64.zig
+++ /dev/null
@@ -1,136 +0,0 @@
-const freebsd = @import("index.zig");
-const socklen_t = freebsd.socklen_t;
-const iovec = freebsd.iovec;
-
-pub const SYS_sbrk = 69;
-
-pub fn syscall0(number: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall1(number: usize, arg1: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1),
- [arg2] "{rsi}" (arg2)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1),
- [arg2] "{rsi}" (arg2),
- [arg3] "{rdx}" (arg3)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1),
- [arg2] "{rsi}" (arg2),
- [arg3] "{rdx}" (arg3),
- [arg4] "{r10}" (arg4)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1),
- [arg2] "{rsi}" (arg2),
- [arg3] "{rdx}" (arg3),
- [arg4] "{r10}" (arg4),
- [arg5] "{r8}" (arg5)
- : "rcx", "r11"
- );
-}
-
-pub fn syscall6(
- number: usize,
- arg1: usize,
- arg2: usize,
- arg3: usize,
- arg4: usize,
- arg5: usize,
- arg6: usize,
-) usize {
- return asm volatile ("syscall"
- : [ret] "={rax}" (-> usize)
- : [number] "{rax}" (number),
- [arg1] "{rdi}" (arg1),
- [arg2] "{rsi}" (arg2),
- [arg3] "{rdx}" (arg3),
- [arg4] "{r10}" (arg4),
- [arg5] "{r8}" (arg5),
- [arg6] "{r9}" (arg6)
- : "rcx", "r11"
- );
-}
-
-pub nakedcc fn restore_rt() void {
- asm volatile ("syscall"
- :
- : [number] "{rax}" (usize(SYS_rt_sigreturn))
- : "rcx", "r11"
- );
-}
-
-pub const msghdr = extern struct {
- msg_name: &u8,
- msg_namelen: socklen_t,
- msg_iov: &iovec,
- msg_iovlen: i32,
- __pad1: i32,
- msg_control: &u8,
- msg_controllen: socklen_t,
- __pad2: socklen_t,
- msg_flags: i32,
-};
-
-/// Renamed to Stat to not conflict with the stat function.
-pub const Stat = extern struct {
- dev: u64,
- ino: u64,
- nlink: usize,
-
- mode: u32,
- uid: u32,
- gid: u32,
- __pad0: u32,
- rdev: u64,
- size: i64,
- blksize: isize,
- blocks: i64,
-
- atim: timespec,
- mtim: timespec,
- ctim: timespec,
- __unused: [3]isize,
-};
-
-pub const timespec = extern struct {
- tv_sec: isize,
- tv_nsec: isize,
-};
diff --git a/std/os/get_app_data_dir.zig b/std/os/get_app_data_dir.zig
index ae133bb4b1..f5e0b78eec 100644
--- a/std/os/get_app_data_dir.zig
+++ b/std/os/get_app_data_dir.zig
@@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
error.OutOfMemory => return error.OutOfMemory,
};
defer allocator.free(global_dir);
- return os.path.join(allocator, global_dir, appname);
+ return os.path.join(allocator, [][]const u8{ global_dir, appname });
},
os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
else => return error.AppDataDirUnavailable,
@@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
- return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
+ return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname });
},
builtin.Os.linux, builtin.Os.freebsd => {
const home_dir = os.getEnvPosix("HOME") orelse {
// TODO look in /etc/passwd
return error.AppDataDirUnavailable;
};
- return os.path.join(allocator, home_dir, ".local", "share", appname);
+ return os.path.join(allocator, [][]const u8{ home_dir, ".local", "share", appname });
},
else => @compileError("Unsupported OS"),
}
@@ -67,4 +67,3 @@ test "std.os.getAppDataDir" {
// We can't actually validate the result
_ = getAppDataDir(allocator, "zig") catch return;
}
-
diff --git a/std/os/index.zig b/std/os/index.zig
index 15be08c689..f52c12c2b6 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) {
};
const os = @This();
+comptime {
+ assert(@import("std") == std); // You have to run the std lib tests with --override-std-dir
+}
+
test "std.os" {
_ = @import("child_process.zig");
_ = @import("darwin.zig");
@@ -18,6 +22,7 @@ test "std.os" {
_ = @import("test.zig");
_ = @import("time.zig");
_ = @import("windows/index.zig");
+ _ = @import("uefi.zig");
_ = @import("get_app_data_dir.zig");
}
@@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig");
pub const linux = @import("linux/index.zig");
pub const freebsd = @import("freebsd/index.zig");
pub const zen = @import("zen.zig");
+pub const uefi = @import("uefi.zig");
+
pub const posix = switch (builtin.os) {
Os.linux => linux,
Os.macosx, Os.ios => darwin,
@@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) {
Os.zen => zen,
else => @compileError("Unsupported OS"),
};
+
pub const net = @import("net.zig");
pub const ChildProcess = @import("child_process.zig").ChildProcess;
@@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const c = std.c;
@@ -103,7 +112,7 @@ const math = std.math;
/// library implementation.
pub fn getRandomBytes(buf: []u8) !void {
switch (builtin.os) {
- Os.linux, Os.freebsd => while (true) {
+ Os.linux => while (true) {
// TODO check libc version and potentially call c.getrandom.
// See #397
const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
@@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void {
else => return unexpectedErrorPosix(errno),
}
},
- Os.macosx, Os.ios => return getRandomBytesDevURandom(buf),
+ Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf),
Os.windows => {
// Call RtlGenRandom() instead of CryptGetRandom() on Windows
// https://github.com/rust-lang-nursery/rand/issues/111
@@ -164,7 +173,7 @@ test "os.getRandomBytes" {
try getRandomBytes(buf_b[0..]);
// Check if random (not 100% conclusive)
- assert(!mem.eql(u8, buf_a, buf_b));
+ testing.expect(!mem.eql(u8, buf_a, buf_b));
}
/// Raises a signal in the current kernel thread, ending its execution.
@@ -187,6 +196,10 @@ pub fn abort() noreturn {
}
windows.ExitProcess(3);
},
+ Os.uefi => {
+ // TODO there's gotta be a better thing to do here than loop forever
+ while (true) {}
+ },
else => @compileError("Unsupported OS"),
}
}
@@ -459,6 +472,7 @@ pub const PosixOpenError = error{
NoSpaceLeft,
NotDir,
PathAlreadyExists,
+ DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,
@@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
posix.ENOTDIR => return PosixOpenError.NotDir,
posix.EPERM => return PosixOpenError.AccessDenied,
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
+ posix.EBUSY => return PosixOpenError.DeviceBusy,
else => return unexpectedErrorPosix(err),
}
}
@@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
// +1 for the null terminating byte
const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);
defer allocator.free(path_buf);
- var it = mem.split(PATH, ":");
+ var it = mem.tokenize(PATH, ":");
var seen_eacces = false;
var err: usize = undefined;
while (it.next()) |search_path| {
@@ -682,12 +697,7 @@ pub fn getBaseAddress() usize {
return base;
}
const phdr = linuxGetAuxVal(std.elf.AT_PHDR);
- const ElfHeader = switch (@sizeOf(usize)) {
- 4 => std.elf.Elf32_Ehdr,
- 8 => std.elf.Elf64_Ehdr,
- else => @compileError("Unsupported architecture"),
- };
- return phdr - @sizeOf(ElfHeader);
+ return phdr - @sizeOf(std.elf.Ehdr);
},
builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
@@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
errdefer result.deinit();
if (is_windows) {
- const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;
- defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);
+ const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
+ defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
var i: usize = 0;
while (true) {
@@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
const key_start = i;
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
- const key = ptr[key_start..i];
+ const key_w = ptr[key_start..i];
+ const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
+ errdefer allocator.free(key);
if (ptr[i] == '=') i += 1;
const value_start = i;
while (ptr[i] != 0) : (i += 1) {}
- const value = ptr[value_start..i];
+ const value_w = ptr[value_start..i];
+ const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
+ errdefer allocator.free(value);
i += 1; // skip over null byte
- try result.set(key, value);
+ try result.setMove(key, value);
}
} else {
for (posix_environ_raw) |ptr| {
@@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
}
}
+test "os.getEnvMap" {
+ var env = try getEnvMap(std.debug.global_allocator);
+ defer env.deinit();
+}
+
/// TODO make this go through libc when we have it
pub fn getEnvPosix(key: []const u8) ?[]const u8 {
for (posix_environ_raw) |ptr| {
@@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
pub const GetEnvVarOwnedError = error{
OutOfMemory,
EnvironmentVariableNotFound,
+
+ /// See https://github.com/ziglang/zig/issues/1774
+ InvalidUtf8,
};
/// Caller must free returned memory.
/// TODO make this go through libc when we have it
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
if (is_windows) {
- const key_with_null = try cstr.addNullByte(allocator, key);
+ const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
defer allocator.free(key_with_null);
- var buf = try allocator.alloc(u8, 256);
- errdefer allocator.free(buf);
+ var buf = try allocator.alloc(u16, 256);
+ defer allocator.free(buf);
while (true) {
const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
- const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);
+ const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
if (result == 0) {
const err = windows.GetLastError();
@@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
}
if (result > buf.len) {
- buf = try allocator.realloc(u8, buf, result);
+ buf = try allocator.realloc(u16, buf, result);
continue;
}
- return allocator.shrink(u8, buf, result);
+ return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
+ error.DanglingSurrogateHalf => return error.InvalidUtf8,
+ error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ error.OutOfMemory => return error.OutOfMemory,
+ };
}
} else {
const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
@@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
}
}
+test "os.getEnvVarOwned" {
+ var ga = debug.global_allocator;
+ testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));
+}
+
/// Caller must free the returned memory.
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
var buf: [MAX_PATH_BYTES]u8 = undefined;
@@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void {
/// already exists and is a directory.
/// TODO determine if we can remove the allocator requirement from this function
pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
- const resolved_path = try path.resolve(allocator, full_path);
+ const resolved_path = try path.resolve(allocator, [][]const u8{full_path});
defer allocator.free(resolved_path);
var end_index: usize = resolved_path.len;
@@ -1380,6 +1412,7 @@ const DeleteTreeError = error{
FileSystem,
FileBusy,
DirNotEmpty,
+ DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
error.Unexpected,
error.InvalidUtf8,
error.BadPathName,
+ error.DeviceBusy,
=> return err,
};
defer dir.close();
@@ -1523,6 +1557,7 @@ pub const Dir = struct {
OutOfMemory,
InvalidUtf8,
BadPathName,
+ DeviceBusy,
/// See https://github.com/ziglang/zig/issues/1396
Unexpected,
@@ -1731,8 +1766,57 @@ pub const Dir = struct {
}
fn nextFreebsd(self: *Dir) !?Entry {
- //self.handle.buf = try self.allocator.alloc(u8, page_size);
- @compileError("TODO implement dirs for FreeBSD");
+ start_over: while (true) {
+ if (self.handle.index >= self.handle.end_index) {
+ if (self.handle.buf.len == 0) {
+ self.handle.buf = try self.allocator.alloc(u8, page_size);
+ }
+
+ while (true) {
+ const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
+ const err = posix.getErrno(result);
+ if (err > 0) {
+ switch (err) {
+ posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
+ posix.EINVAL => {
+ self.handle.buf = try self.allocator.realloc(u8, self.handle.buf, self.handle.buf.len * 2);
+ continue;
+ },
+ else => return unexpectedErrorPosix(err),
+ }
+ }
+ if (result == 0) return null;
+ self.handle.index = 0;
+ self.handle.end_index = result;
+ break;
+ }
+ }
+ const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
+ const next_index = self.handle.index + freebsd_entry.d_reclen;
+ self.handle.index = next_index;
+
+ const name = @ptrCast([*]u8, &freebsd_entry.d_name)[0..freebsd_entry.d_namlen];
+
+ if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
+ continue :start_over;
+ }
+
+ const entry_kind = switch (freebsd_entry.d_type) {
+ posix.DT_BLK => Entry.Kind.BlockDevice,
+ posix.DT_CHR => Entry.Kind.CharacterDevice,
+ posix.DT_DIR => Entry.Kind.Directory,
+ posix.DT_FIFO => Entry.Kind.NamedPipe,
+ posix.DT_LNK => Entry.Kind.SymLink,
+ posix.DT_REG => Entry.Kind.File,
+ posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
+ posix.DT_WHT => Entry.Kind.Whiteout,
+ else => Entry.Kind.Unknown,
+ };
+ return Entry{
+ .name = name,
+ .kind = entry_kind,
+ };
+ }
}
};
@@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons
var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
for (expected_args) |expected_arg| {
const arg = it.next(debug.global_allocator).? catch unreachable;
- assert(mem.eql(u8, arg, expected_arg));
+ testing.expectEqualSlices(u8, expected_arg, arg);
}
- assert(it.next(debug.global_allocator) == null);
+ testing.expect(it.next(debug.global_allocator) == null);
}
// TODO make this a build variable that you can set
@@ -2220,7 +2304,19 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
switch (builtin.os) {
Os.linux => return readLink(out_buffer, "/proc/self/exe"),
- Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"),
+ Os.freebsd => {
+ var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };
+ var out_len: usize = out_buffer.len;
+ const err = posix.getErrno(posix.sysctl(&mib, 4, out_buffer, &out_len, null, 0));
+
+ if (err == 0) return mem.toSlice(u8, out_buffer);
+
+ return switch (err) {
+ posix.EFAULT => error.BadAdress,
+ posix.EPERM => error.PermissionDenied,
+ else => unexpectedErrorPosix(err),
+ };
+ },
Os.windows => {
var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
const utf16le_slice = try selfExePathW(&utf16le_buf);
@@ -2811,14 +2907,15 @@ pub const Thread = struct {
pub const Data = if (use_pthreads)
struct {
handle: Thread.Handle,
- stack_addr: usize,
- stack_len: usize,
+ mmap_addr: usize,
+ mmap_len: usize,
}
else switch (builtin.os) {
builtin.Os.linux => struct {
handle: Thread.Handle,
- stack_addr: usize,
- stack_len: usize,
+ mmap_addr: usize,
+ mmap_len: usize,
+ tls_end_addr: usize,
},
builtin.Os.windows => struct {
handle: Thread.Handle,
@@ -2858,7 +2955,7 @@ pub const Thread = struct {
posix.EDEADLK => unreachable,
else => unreachable,
}
- assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0);
+ assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
} else switch (builtin.os) {
builtin.Os.linux => {
while (true) {
@@ -2872,7 +2969,7 @@ pub const Thread = struct {
else => unreachable,
}
}
- assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0);
+ assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
},
builtin.Os.windows => {
assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
@@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{
Unexpected,
};
+pub var linux_tls_phdr: ?*std.elf.Phdr = null;
+pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is
+
/// caller must call wait on the returned thread
/// fn startFn(@typeOf(context)) T
/// where T is u8, noreturn, void, or !void
/// caller must call wait on the returned thread
pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
+ if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
// TODO compile-time call graph analysis to determine stack upper bound
// https://github.com/ziglang/zig/issues/157
const default_stack_size = 8 * 1024 * 1024;
@@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;
errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];
- const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext{
+ const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable;
+ outer_context.* = WinThread.OuterContext{
.thread = Thread{
.data = Thread.Data{
.heap_handle = heap_handle,
@@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
},
},
.inner = context,
- }) catch unreachable;
+ };
const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);
outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse {
@@ -2998,42 +3100,56 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;
- const mmap_len = default_stack_size;
- const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
- if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory;
- errdefer assert(posix.munmap(stack_addr, mmap_len) == 0);
+ var stack_end_offset: usize = undefined;
+ var thread_start_offset: usize = undefined;
+ var context_start_offset: usize = undefined;
+ var tls_start_offset: usize = undefined;
+ const mmap_len = blk: {
+ // First in memory will be the stack, which grows downwards.
+ var l: usize = mem.alignForward(default_stack_size, os.page_size);
+ stack_end_offset = l;
+ // Above the stack, so that it can be in the same mmap call, put the Thread object.
+ l = mem.alignForward(l, @alignOf(Thread));
+ thread_start_offset = l;
+ l += @sizeOf(Thread);
+ // Next, the Context object.
+ if (@sizeOf(Context) != 0) {
+ l = mem.alignForward(l, @alignOf(Context));
+ context_start_offset = l;
+ l += @sizeOf(Context);
+ }
+ // Finally, the Thread Local Storage, if any.
+ if (!Thread.use_pthreads) {
+ if (linux_tls_phdr) |tls_phdr| {
+ l = mem.alignForward(l, tls_phdr.p_align);
+ tls_start_offset = l;
+ l += tls_phdr.p_memsz;
+ }
+ }
+ break :blk l;
+ };
+ const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
+ if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory;
+ errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0);
+
+ const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
+ thread_ptr.data.mmap_addr = mmap_addr;
+ thread_ptr.data.mmap_len = mmap_len;
- var stack_end: usize = stack_addr + mmap_len;
var arg: usize = undefined;
if (@sizeOf(Context) != 0) {
- stack_end -= @sizeOf(Context);
- stack_end -= stack_end % @alignOf(Context);
- assert(stack_end >= stack_addr);
- const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, stack_end));
+ arg = mmap_addr + context_start_offset;
+ const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, arg));
context_ptr.* = context;
- arg = stack_end;
}
- stack_end -= @sizeOf(Thread);
- stack_end -= stack_end % @alignOf(Thread);
- assert(stack_end >= stack_addr);
- const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, stack_end));
-
- thread_ptr.data.stack_addr = stack_addr;
- thread_ptr.data.stack_len = mmap_len;
-
- if (builtin.os == builtin.Os.windows) {
- // use windows API directly
- @compileError("TODO support spawnThread for Windows");
- } else if (Thread.use_pthreads) {
+ if (Thread.use_pthreads) {
// use pthreads
var attr: c.pthread_attr_t = undefined;
if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources;
defer assert(c.pthread_attr_destroy(&attr) == 0);
- // align to page
- stack_end -= stack_end % os.page_size;
- assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, stack_addr), stack_end - stack_addr) == 0);
+ assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, mmap_addr), stack_end_offset) == 0);
const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
switch (err) {
@@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
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
- const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED;
- const newtls: usize = 0;
- const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
+ var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND |
+ posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
+ posix.CLONE_DETACHED;
+ var newtls: usize = undefined;
+ if (linux_tls_phdr) |tls_phdr| {
+ @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);
+ thread_ptr.data.tls_end_addr = mmap_addr + mmap_len;
+ newtls = @ptrToInt(&thread_ptr.data.tls_end_addr);
+ flags |= posix.CLONE_SETTLS;
+ }
+ const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
const err = posix.getErrno(rc);
switch (err) {
0 => return thread_ptr,
diff --git a/std/os/linux/test.zig b/std/os/linux/test.zig
index 4de26012c7..40fb7823d2 100644
--- a/std/os/linux/test.zig
+++ b/std/os/linux/test.zig
@@ -1,19 +1,19 @@
const std = @import("../../index.zig");
const builtin = @import("builtin");
const linux = std.os.linux;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
test "getpid" {
- assert(linux.getpid() != 0);
+ expect(linux.getpid() != 0);
}
test "timer" {
const epoll_fd = linux.epoll_create();
var err = linux.getErrno(epoll_fd);
- assert(err == 0);
+ expect(err == 0);
const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0);
- assert(linux.getErrno(timer_fd) == 0);
+ expect(linux.getErrno(timer_fd) == 0);
const time_interval = linux.timespec{
.tv_sec = 0,
@@ -26,7 +26,7 @@ test "timer" {
};
err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null);
- assert(err == 0);
+ expect(err == 0);
var event = linux.epoll_event{
.events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET,
@@ -34,7 +34,7 @@ test "timer" {
};
err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event);
- assert(err == 0);
+ expect(err == 0);
const events_one: linux.epoll_event = undefined;
var events = []linux.epoll_event{events_one} ** 8;
diff --git a/std/os/path.zig b/std/os/path.zig
index af767b0dca..5ba345fceb 100644
--- a/std/os/path.zig
+++ b/std/os/path.zig
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
const Os = builtin.Os;
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const mem = std.mem;
const fmt = std.fmt;
const Allocator = mem.Allocator;
@@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool {
}
}
+/// This is different from mem.join in that the separator will not be repeated if
+/// it is found at the end or beginning of a pair of consecutive paths.
+fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u8 {
+ if (paths.len == 0) return (([*]u8)(undefined))[0..0];
+
+ const total_len = blk: {
+ var sum: usize = paths[0].len;
+ var i: usize = 1;
+ while (i < paths.len) : (i += 1) {
+ const prev_path = paths[i - 1];
+ const this_path = paths[i];
+ const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
+ const this_sep = (this_path.len != 0 and this_path[0] == separator);
+ sum += @boolToInt(!prev_sep and !this_sep);
+ sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
+ }
+ break :blk sum;
+ };
+
+ const buf = try allocator.alloc(u8, total_len);
+ errdefer allocator.free(buf);
+
+ mem.copy(u8, buf, paths[0]);
+ var buf_index: usize = paths[0].len;
+ var i: usize = 1;
+ while (i < paths.len) : (i += 1) {
+ const prev_path = paths[i - 1];
+ const this_path = paths[i];
+ const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
+ const this_sep = (this_path.len != 0 and this_path[0] == separator);
+ if (!prev_sep and !this_sep) {
+ buf[buf_index] = separator;
+ buf_index += 1;
+ }
+ const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;
+ mem.copy(u8, buf[buf_index..], adjusted_path);
+ buf_index += adjusted_path.len;
+ }
+
+ // No need for shrink since buf is exactly the correct size.
+ return buf;
+}
+
+pub const join = if (is_windows) joinWindows else joinPosix;
+
/// Naively combines a series of paths with the native path seperator.
/// Allocates memory for the result, which must be freed by the caller.
-pub fn join(allocator: *Allocator, paths: ...) ![]u8 {
- if (is_windows) {
- return joinWindows(allocator, paths);
- } else {
- return joinPosix(allocator, paths);
- }
+pub fn joinWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
+ return joinSep(allocator, sep_windows, paths);
}
-pub fn joinWindows(allocator: *Allocator, paths: ...) ![]u8 {
- return mem.join(allocator, sep_windows, paths);
+/// Naively combines a series of paths with the native path seperator.
+/// Allocates memory for the result, which must be freed by the caller.
+pub fn joinPosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
+ return joinSep(allocator, sep_posix, paths);
}
-pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 {
- return mem.join(allocator, sep_posix, paths);
+fn testJoinWindows(paths: []const []const u8, expected: []const u8) void {
+ var buf: [1024]u8 = undefined;
+ const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
+ const actual = joinWindows(a, paths) catch @panic("fail");
+ testing.expectEqualSlices(u8, expected, actual);
+}
+
+fn testJoinPosix(paths: []const []const u8, expected: []const u8) void {
+ var buf: [1024]u8 = undefined;
+ const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
+ const actual = joinPosix(a, paths) catch @panic("fail");
+ testing.expectEqualSlices(u8, expected, actual);
}
test "os.path.join" {
- assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c"));
- assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c"));
+ testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
+ testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
+ testJoinWindows([][]const u8{ "c:\\a\\b\\", "c" }, "c:\\a\\b\\c");
- assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c"));
- assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c"));
+ testJoinWindows([][]const u8{ "c:\\", "a", "b\\", "c" }, "c:\\a\\b\\c");
+ testJoinWindows([][]const u8{ "c:\\a\\", "b\\", "c" }, "c:\\a\\b\\c");
- assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"), "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig"));
+ testJoinWindows(
+ [][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig" },
+ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig",
+ );
- assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c"));
- assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c"));
+ testJoinPosix([][]const u8{ "/a/b", "c" }, "/a/b/c");
+ testJoinPosix([][]const u8{ "/a/b/", "c" }, "/a/b/c");
- assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c"));
- assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c"));
+ testJoinPosix([][]const u8{ "/", "a", "b/", "c" }, "/a/b/c");
+ testJoinPosix([][]const u8{ "/a/", "b/", "c" }, "/a/b/c");
- assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), "/home/andy/dev/zig/build/lib/zig/std/io.zig"));
+ testJoinPosix(
+ [][]const u8{ "/home/andy/dev/zig/build/lib/zig/std", "io.zig" },
+ "/home/andy/dev/zig/build/lib/zig/std/io.zig",
+ );
+
+ testJoinPosix([][]const u8{ "a", "/c" }, "a/c");
+ testJoinPosix([][]const u8{ "a/", "/c" }, "a/c");
}
pub fn isAbsolute(path: []const u8) bool {
@@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" {
}
fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void {
- assert(isAbsoluteWindows(path) == expected_result);
+ testing.expectEqual(expected_result, isAbsoluteWindows(path));
}
fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void {
- assert(isAbsolutePosix(path) == expected_result);
+ testing.expectEqual(expected_result, isAbsolutePosix(path));
}
pub const WindowsPath = struct {
@@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
return relative_path;
}
- var it = mem.split(path, []u8{this_sep});
+ var it = mem.tokenize(path, []u8{this_sep});
_ = (it.next() orelse return relative_path);
_ = (it.next() orelse return relative_path);
return WindowsPath{
@@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
return relative_path;
}
- var it = mem.split(path, []u8{this_sep});
+ var it = mem.tokenize(path, []u8{this_sep});
_ = (it.next() orelse return relative_path);
_ = (it.next() orelse return relative_path);
return WindowsPath{
@@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
test "os.path.windowsParsePath" {
{
const parsed = windowsParsePath("//a/b");
- assert(parsed.is_abs);
- assert(parsed.kind == WindowsPath.Kind.NetworkShare);
- assert(mem.eql(u8, parsed.disk_designator, "//a/b"));
+ testing.expect(parsed.is_abs);
+ testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
+ testing.expect(mem.eql(u8, parsed.disk_designator, "//a/b"));
}
{
const parsed = windowsParsePath("\\\\a\\b");
- assert(parsed.is_abs);
- assert(parsed.kind == WindowsPath.Kind.NetworkShare);
- assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
+ testing.expect(parsed.is_abs);
+ testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
+ testing.expect(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
}
{
const parsed = windowsParsePath("\\\\a\\");
- assert(!parsed.is_abs);
- assert(parsed.kind == WindowsPath.Kind.None);
- assert(mem.eql(u8, parsed.disk_designator, ""));
+ testing.expect(!parsed.is_abs);
+ testing.expect(parsed.kind == WindowsPath.Kind.None);
+ testing.expect(mem.eql(u8, parsed.disk_designator, ""));
}
{
const parsed = windowsParsePath("/usr/local");
- assert(parsed.is_abs);
- assert(parsed.kind == WindowsPath.Kind.None);
- assert(mem.eql(u8, parsed.disk_designator, ""));
+ testing.expect(parsed.is_abs);
+ testing.expect(parsed.kind == WindowsPath.Kind.None);
+ testing.expect(mem.eql(u8, parsed.disk_designator, ""));
}
{
const parsed = windowsParsePath("c:../");
- assert(!parsed.is_abs);
- assert(parsed.kind == WindowsPath.Kind.Drive);
- assert(mem.eql(u8, parsed.disk_designator, "c:"));
+ testing.expect(!parsed.is_abs);
+ testing.expect(parsed.kind == WindowsPath.Kind.Drive);
+ testing.expect(mem.eql(u8, parsed.disk_designator, "c:"));
}
}
@@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
const sep1 = ns1[0];
const sep2 = ns2[0];
- var it1 = mem.split(ns1, []u8{sep1});
- var it2 = mem.split(ns2, []u8{sep2});
+ var it1 = mem.tokenize(ns1, []u8{sep1});
+ var it2 = mem.tokenize(ns2, []u8{sep2});
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
@@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
const sep1 = p1[0];
const sep2 = p2[0];
- var it1 = mem.split(p1, []u8{sep1});
- var it2 = mem.split(p2, []u8{sep2});
+ var it1 = mem.tokenize(p1, []u8{sep1});
+ var it2 = mem.tokenize(p2, []u8{sep2});
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);
@@ -312,18 +376,8 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
return true;
}
-/// Converts the command line arguments into a slice and calls `resolveSlice`.
-pub fn resolve(allocator: *Allocator, args: ...) ![]u8 {
- var paths: [args.len][]const u8 = undefined;
- comptime var arg_i = 0;
- inline while (arg_i < args.len) : (arg_i += 1) {
- paths[arg_i] = args[arg_i];
- }
- return resolveSlice(allocator, paths);
-}
-
/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
-pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {
+pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (is_windows) {
return resolveWindows(allocator, paths);
} else {
@@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {
/// If all paths are relative it uses the current working directory as a starting point.
/// Each drive has its own current working directory.
/// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.
+/// Note: all usage of this function should be audited due to the existence of symlinks.
+/// Without performing actual syscalls, resolving `..` could be incorrect.
pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (paths.len == 0) {
assert(is_windows); // resolveWindows called on non windows can't use getCwd
@@ -416,7 +472,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
},
WindowsPath.Kind.NetworkShare => {
result = try allocator.alloc(u8, max_size);
- var it = mem.split(paths[first_index], "/\\");
+ var it = mem.tokenize(paths[first_index], "/\\");
const server_name = it.next().?;
const other_name = it.next().?;
@@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (!correct_disk_designator) {
continue;
}
- var it = mem.split(p[parsed.disk_designator.len..], "/\\");
+ var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\");
while (it.next()) |component| {
if (mem.eql(u8, component, ".")) {
continue;
@@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
/// It resolves "." and "..".
/// The result does not have a trailing path separator.
/// If all paths are relative it uses the current working directory as a starting point.
+/// Note: all usage of this function should be audited due to the existence of symlinks.
+/// Without performing actual syscalls, resolving `..` could be incorrect.
pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
if (paths.len == 0) {
assert(!is_windows); // resolvePosix called on windows can't use getCwd
@@ -550,7 +608,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
errdefer allocator.free(result);
for (paths[first_index..]) |p, i| {
- var it = mem.split(p, "/");
+ var it = mem.tokenize(p, "/");
while (it.next()) |component| {
if (mem.eql(u8, component, ".")) {
continue;
@@ -585,10 +643,10 @@ test "os.path.resolve" {
if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
cwd[0] = asciiUpper(cwd[0]);
}
- assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
} else {
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
- assert(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
}
}
@@ -598,48 +656,54 @@ test "os.path.resolveWindows" {
const parsed_cwd = windowsParsePath(cwd);
{
const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
- const expected = try join(debug.global_allocator, parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig");
+ const expected = try join(debug.global_allocator, [][]const u8{
+ parsed_cwd.disk_designator,
+ "usr\\local\\lib\\zig\\std\\array_list.zig",
+ });
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
}
- assert(mem.eql(u8, result, expected));
+ testing.expect(mem.eql(u8, result, expected));
}
{
const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" });
- const expected = try join(debug.global_allocator, cwd, "usr\\local\\lib\\zig");
+ const expected = try join(debug.global_allocator, [][]const u8{
+ cwd,
+ "usr\\local\\lib\\zig",
+ });
if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
}
- assert(mem.eql(u8, result, expected));
+ testing.expect(mem.eql(u8, result, expected));
}
}
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
- assert(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
+ testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
}
test "os.path.resolvePosix" {
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
- assert(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
+ testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
}
fn testResolveWindows(paths: []const []const u8) []u8 {
@@ -770,17 +834,17 @@ test "os.path.dirnameWindows" {
fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {
if (dirnamePosix(input)) |output| {
- assert(mem.eql(u8, output, expected_output.?));
+ testing.expect(mem.eql(u8, output, expected_output.?));
} else {
- assert(expected_output == null);
+ testing.expect(expected_output == null);
}
}
fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
if (dirnameWindows(input)) |output| {
- assert(mem.eql(u8, output, expected_output.?));
+ testing.expect(mem.eql(u8, output, expected_output.?));
} else {
- assert(expected_output == null);
+ testing.expect(expected_output == null);
}
}
@@ -885,15 +949,15 @@ test "os.path.basename" {
}
fn testBasename(input: []const u8, expected_output: []const u8) void {
- assert(mem.eql(u8, basename(input), expected_output));
+ testing.expectEqualSlices(u8, expected_output, basename(input));
}
fn testBasenamePosix(input: []const u8, expected_output: []const u8) void {
- assert(mem.eql(u8, basenamePosix(input), expected_output));
+ testing.expectEqualSlices(u8, expected_output, basenamePosix(input));
}
fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
- assert(mem.eql(u8, basenameWindows(input), expected_output));
+ testing.expectEqualSlices(u8, expected_output, basenameWindows(input));
}
/// Returns the relative path from `from` to `to`. If `from` and `to` each
@@ -937,8 +1001,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
return resolved_to;
}
- var from_it = mem.split(resolved_from, "/\\");
- var to_it = mem.split(resolved_to, "/\\");
+ var from_it = mem.tokenize(resolved_from, "/\\");
+ var to_it = mem.tokenize(resolved_to, "/\\");
while (true) {
const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
const to_rest = to_it.rest();
@@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
// shave off the trailing slash
result_index -= 1;
- var rest_it = mem.split(to_rest, "/\\");
+ var rest_it = mem.tokenize(to_rest, "/\\");
while (rest_it.next()) |to_component| {
result[result_index] = '\\';
result_index += 1;
@@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
const resolved_to = try resolvePosix(allocator, [][]const u8{to});
defer allocator.free(resolved_to);
- var from_it = mem.split(resolved_from, "/");
- var to_it = mem.split(resolved_to, "/");
+ var from_it = mem.tokenize(resolved_from, "/");
+ var to_it = mem.tokenize(resolved_to, "/");
while (true) {
const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
const to_rest = to_it.rest();
@@ -1068,12 +1132,12 @@ test "os.path.relative" {
fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void {
const result = relativePosix(debug.global_allocator, from, to) catch unreachable;
- assert(mem.eql(u8, result, expected_output));
+ testing.expectEqualSlices(u8, expected_output, result);
}
fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void {
const result = relativeWindows(debug.global_allocator, from, to) catch unreachable;
- assert(mem.eql(u8, result, expected_output));
+ testing.expectEqualSlices(u8, expected_output, result);
}
pub const RealError = error{
@@ -1093,6 +1157,7 @@ pub const RealError = error{
NoSpaceLeft,
FileSystem,
BadPathName,
+ DeviceBusy,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);
return realW(out_buffer, pathname_w);
},
- Os.macosx, Os.ios => {
+ Os.freebsd, Os.macosx, Os.ios => {
// TODO instead of calling the libc function here, port the implementation to Zig
const err = posix.getErrno(posix.realpath(pathname, out_buffer));
switch (err) {
@@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
return os.readLinkC(out_buffer, proc_path.ptr);
},
- Os.freebsd => { // XXX requires fdescfs
- const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
- defer os.close(fd);
-
- var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined;
- const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable;
-
- return os.readLinkC(out_buffer, proc_path.ptr);
- },
else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
}
}
@@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
test "os.path.real" {
// at least call it so it gets compiled
var buf: [os.MAX_PATH_BYTES]u8 = undefined;
- std.debug.assertError(real(&buf, "definitely_bogus_does_not_exist1234"), error.FileNotFound);
+ testing.expectError(error.FileNotFound, real(&buf, "definitely_bogus_does_not_exist1234"));
}
diff --git a/std/os/test.zig b/std/os/test.zig
index 5142920687..b2a4d96651 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -1,6 +1,6 @@
const std = @import("../index.zig");
const os = std.os;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const io = std.io;
const mem = std.mem;
@@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" {
if (os.Dir.open(a, "os_test_tmp")) |dir| {
@panic("expected error");
} else |err| {
- assert(err == error.FileNotFound);
+ expect(err == error.FileNotFound);
}
}
@@ -27,7 +27,7 @@ test "access file" {
if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
@panic("expected error");
} else |err| {
- assert(err == error.FileNotFound);
+ expect(err == error.FileNotFound);
}
try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
@@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
}
test "std.os.Thread.getCurrentId" {
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var thread_current_id: os.Thread.Id = undefined;
const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
const thread_id = thread.handle();
thread.wait();
switch (builtin.os) {
- builtin.Os.windows => assert(os.Thread.getCurrentId() != thread_current_id),
+ builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id),
else => {
- assert(thread_current_id == thread_id);
+ expect(thread_current_id == thread_id);
},
}
}
test "spawn threads" {
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var shared_ctx: i32 = 1;
const thread1 = try std.os.spawnThread({}, start1);
@@ -65,7 +69,7 @@ test "spawn threads" {
thread3.wait();
thread4.wait();
- assert(shared_ctx == 4);
+ expect(shared_ctx == 4);
}
fn start1(ctx: void) u8 {
@@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 {
test "cpu count" {
const cpu_count = try std.os.cpuCount(a);
- assert(cpu_count >= 1);
+ expect(cpu_count >= 1);
}
test "AtomicFile" {
@@ -97,7 +101,23 @@ test "AtomicFile" {
try af.finish();
}
const content = try io.readFileAlloc(allocator, test_out_file);
- assert(mem.eql(u8, content, test_content));
+ expect(mem.eql(u8, content, test_content));
try os.deleteFile(test_out_file);
}
+
+test "thread local storage" {
+ if (builtin.single_threaded) return error.SkipZigTest;
+ const thread1 = try std.os.spawnThread({}, testTls);
+ const thread2 = try std.os.spawnThread({}, testTls);
+ testTls({});
+ thread1.wait();
+ thread2.wait();
+}
+
+threadlocal var x: i32 = 1234;
+fn testTls(context: void) void {
+ if (x != 1234) @panic("bad start value");
+ x += 1;
+ if (x != 1235) @panic("bad end value");
+}
diff --git a/std/os/time.zig b/std/os/time.zig
index d9fe046a55..638fb41ff1 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -2,6 +2,7 @@ const std = @import("../index.zig");
const builtin = @import("builtin");
const Os = builtin.Os;
const debug = std.debug;
+const testing = std.testing;
const windows = std.os.windows;
const linux = std.os.linux;
@@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig");
/// Sleep for the specified duration
pub fn sleep(nanoseconds: u64) void {
switch (builtin.os) {
- Os.linux, Os.macosx, Os.ios => {
+ Os.linux, Os.macosx, Os.ios, Os.freebsd => {
const s = nanoseconds / ns_per_s;
const ns = nanoseconds % ns_per_s;
posixSleep(@intCast(u63, s), @intCast(u63, ns));
@@ -61,7 +62,7 @@ pub fn timestamp() u64 {
/// Get the posix timestamp, UTC, in milliseconds
pub const milliTimestamp = switch (builtin.os) {
Os.windows => milliTimestampWindows,
- Os.linux => milliTimestampPosix,
+ Os.linux, Os.freebsd => milliTimestampPosix,
Os.macosx, Os.ios => milliTimestampDarwin,
else => @compileError("Unsupported OS"),
};
@@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 {
}
fn milliTimestampDarwin() u64 {
- //Sources suggest MacOS 10.12 has support for
- // posix clock_gettime.
var tv: darwin.timeval = undefined;
var err = darwin.gettimeofday(&tv, null);
debug.assert(err == 0);
- 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);
+ const sec_ms = tv.tv_sec * ms_per_s;
+ const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
+ return @intCast(u64, sec_ms + usec_ms);
}
fn milliTimestampPosix() u64 {
@@ -179,7 +178,7 @@ pub const Timer = struct {
debug.assert(err != windows.FALSE);
self.start_time = @intCast(u64, start_time);
},
- Os.linux => {
+ Os.linux, Os.freebsd => {
//On Linux, seccomp can do arbitrary things to our ability to call
// syscalls, including return any errno value it wants and
// inconsistently throwing errors. Since we can't account for
@@ -215,7 +214,7 @@ pub const Timer = struct {
var clock = clockNative() - self.start_time;
return switch (builtin.os) {
Os.windows => @divFloor(clock * ns_per_s, self.frequency),
- Os.linux => clock,
+ Os.linux, Os.freebsd => clock,
Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
else => @compileError("Unsupported OS"),
};
@@ -236,7 +235,7 @@ pub const Timer = struct {
const clockNative = switch (builtin.os) {
Os.windows => clockWindows,
- Os.linux => clockLinux,
+ Os.linux, Os.freebsd => clockLinux,
Os.macosx, Os.ios => clockDarwin,
else => @compileError("Unsupported OS"),
};
@@ -272,7 +271,7 @@ test "os.time.timestamp" {
sleep(ns_per_ms);
const time_1 = milliTimestamp();
const interval = time_1 - time_0;
- debug.assert(interval > 0 and interval < margin);
+ testing.expect(interval > 0 and interval < margin);
}
test "os.time.Timer" {
@@ -282,11 +281,11 @@ test "os.time.Timer" {
var timer = try Timer.start();
sleep(10 * ns_per_ms);
const time_0 = timer.read();
- debug.assert(time_0 > 0 and time_0 < margin);
+ testing.expect(time_0 > 0 and time_0 < margin);
const time_1 = timer.lap();
- debug.assert(time_1 >= time_0);
+ testing.expect(time_1 >= time_0);
timer.reset();
- debug.assert(timer.read() < time_1);
+ testing.expect(timer.read() < time_1);
}
diff --git a/std/os/uefi.zig b/std/os/uefi.zig
new file mode 100644
index 0000000000..8ed60d9c9b
--- /dev/null
+++ b/std/os/uefi.zig
@@ -0,0 +1,2 @@
+// TODO this is where the extern declarations go. For example, see
+// inc/efilib.h in gnu-efi-code
diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig
index 3d6ee67113..8e9ed8b8db 100644
--- a/std/os/windows/index.zig
+++ b/std/os/windows/index.zig
@@ -49,6 +49,10 @@ pub const UNICODE = false;
pub const WCHAR = u16;
pub const WORD = u16;
pub const LARGE_INTEGER = i64;
+pub const ULONG = u32;
+pub const LONG = i32;
+pub const ULONGLONG = u64;
+pub const LONGLONG = i64;
pub const TRUE = 1;
pub const FALSE = 0;
@@ -379,3 +383,17 @@ pub const COORD = extern struct {
};
pub const CREATE_UNICODE_ENVIRONMENT = 1024;
+
+pub const TLS_OUT_OF_INDEXES = 4294967295;
+pub const IMAGE_TLS_DIRECTORY = extern struct {
+ StartAddressOfRawData: usize,
+ EndAddressOfRawData: usize,
+ AddressOfIndex: usize,
+ AddressOfCallBacks: usize,
+ SizeOfZeroFill: u32,
+ Characteristics: u32,
+};
+pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY;
+pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY;
+
+pub const PIMAGE_TLS_CALLBACK = ?extern fn(PVOID, DWORD, PVOID) void;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 7eec5faba9..ce8443de02 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
-pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
+pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
-pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
+pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
-pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
+pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;
+pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD;
+
+pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL;
+
pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
pub extern "kernel32" stdcallcc fn WriteFile(
@@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1;
pub const FOREGROUND_GREEN = 2;
pub const FOREGROUND_RED = 4;
pub const FOREGROUND_INTENSITY = 8;
+
+pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
+pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
+
+pub const LIST_ENTRY = extern struct {
+ Flink: *LIST_ENTRY,
+ Blink: *LIST_ENTRY,
+};
+
+pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {
+ Type: WORD,
+ CreatorBackTraceIndex: WORD,
+ CriticalSection: *RTL_CRITICAL_SECTION,
+ ProcessLocksList: LIST_ENTRY,
+ EntryCount: DWORD,
+ ContentionCount: DWORD,
+ Flags: DWORD,
+ CreatorBackTraceIndexHigh: WORD,
+ SpareWORD: WORD,
+};
+
+pub const RTL_CRITICAL_SECTION = extern struct {
+ DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,
+ LockCount: LONG,
+ RecursionCount: LONG,
+ OwningThread: HANDLE,
+ LockSemaphore: HANDLE,
+ SpinCount: ULONG_PTR,
+};
+
+pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
+pub const INIT_ONCE = RTL_RUN_ONCE;
+pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT;
+
+pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL;
+
+pub const INIT_ONCE_FN = extern fn(InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL;
+
+pub const RTL_RUN_ONCE = extern struct {
+ Ptr: ?*c_void,
+};
+
+pub const RTL_RUN_ONCE_INIT = RTL_RUN_ONCE {
+ .Ptr = null,
+};
diff --git a/std/os/windows/tls.zig b/std/os/windows/tls.zig
new file mode 100644
index 0000000000..9e62a7c5c6
--- /dev/null
+++ b/std/os/windows/tls.zig
@@ -0,0 +1,36 @@
+const std = @import("../../index.zig");
+
+export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
+export var _tls_start: u8 linksection(".tls") = 0;
+export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
+export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
+export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
+
+// TODO this is how I would like it to be expressed
+// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
+// why they do that.
+//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY {
+// .StartAddressOfRawData = @ptrToInt(&_tls_start),
+// .EndAddressOfRawData = @ptrToInt(&_tls_end),
+// .AddressOfIndex = @ptrToInt(&_tls_index),
+// .AddressOfCallBacks = @ptrToInt(__xl_a),
+// .SizeOfZeroFill = 0,
+// .Characteristics = 0,
+//};
+// This is the workaround because we can't do @ptrToInt at comptime like that.
+pub const IMAGE_TLS_DIRECTORY = extern struct {
+ StartAddressOfRawData: *c_void,
+ EndAddressOfRawData: *c_void,
+ AddressOfIndex: *c_void,
+ AddressOfCallBacks: *c_void,
+ SizeOfZeroFill: u32,
+ Characteristics: u32,
+};
+export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY {
+ .StartAddressOfRawData = &_tls_start,
+ .EndAddressOfRawData = &_tls_end,
+ .AddressOfIndex = &_tls_index,
+ .AddressOfCallBacks = &__xl_a,
+ .SizeOfZeroFill = 0,
+ .Characteristics = 0,
+};
diff --git a/std/pdb.zig b/std/pdb.zig
index 2c5df3e597..b6e48ad2f7 100644
--- a/std/pdb.zig
+++ b/std/pdb.zig
@@ -9,6 +9,10 @@ const coff = std.coff;
const ArrayList = std.ArrayList;
+// Note: most of this is based on information gathered from LLVM source code,
+// documentation and/or contributors.
+
+
// https://llvm.org/docs/PDB/DbiStream.html#stream-header
pub const DbiStreamHeader = packed struct {
VersionSignature: i32,
@@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct {
RecordKind: SymbolKind,
};
+/// The following variable length array appears immediately after the header.
+/// The structure definition follows.
+/// LineBlockFragmentHeader Blocks[]
+/// Each `LineBlockFragmentHeader` as specified below.
pub const LineFragmentHeader = packed struct {
/// Code offset of line contribution.
RelocOffset: u32,
@@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct {
/// TODO runtime crash when I make the actual type of Flags this
const Flags = packed struct {
+ /// Start line number
Start: u24,
+
+ /// Delta of lines to the end of the expression. Still unclear.
+ // TODO figure out the point of this field.
End: u7,
IsStatement: bool,
};
@@ -508,11 +520,11 @@ const Msf = struct {
allocator,
);
- const stream_count = try self.directory.stream.readIntLe(u32);
+ const stream_count = try self.directory.stream.readIntLittle(u32);
const stream_sizes = try allocator.alloc(u32, stream_count);
for (stream_sizes) |*s| {
- const size = try self.directory.stream.readIntLe(u32);
+ const size = try self.directory.stream.readIntLittle(u32);
s.* = blockCountFromSize(size, superblock.BlockSize);
}
@@ -603,7 +615,7 @@ const MsfStream = struct {
var i: u32 = 0;
while (i < block_count) : (i += 1) {
- stream.blocks[i] = try in.readIntLe(u32);
+ stream.blocks[i] = try in.readIntLittle(u32);
}
return stream;
diff --git a/std/rand/index.zig b/std/rand/index.zig
index 97101bc3b7..12dd763aee 100644
--- a/std/rand/index.zig
+++ b/std/rand/index.zig
@@ -5,7 +5,7 @@
// ```
// var buf: [8]u8 = undefined;
// try std.os.getRandomBytes(buf[0..]);
-// const seed = mem.readIntLE(u64, buf[0..8]);
+// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
//
// var r = DefaultPrng.init(seed);
//
@@ -17,6 +17,7 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const assert = std.debug.assert;
+const expect = std.testing.expect;
const mem = std.mem;
const math = std.math;
const ziggurat = @import("ziggurat.zig");
@@ -52,7 +53,7 @@ pub const Random = struct {
// use LE instead of native endian for better portability maybe?
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
// TODO: document the endian portability of this library.
- const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);
+ const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
return @bitCast(T, unsigned_result);
}
@@ -69,6 +70,7 @@ pub const Random = struct {
return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
}
}
+
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
/// Within this assumption, the runtime of this function is exponentially distributed.
@@ -123,6 +125,7 @@ pub const Random = struct {
}
return r.uintLessThanBiased(T, at_most + 1);
}
+
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
/// See ::uintLessThan, which this function uses in most cases,
/// for commentary on the runtime of this function.
@@ -151,6 +154,7 @@ pub const Random = struct {
return at_least + r.uintLessThanBiased(T, less_than - at_least);
}
}
+
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
/// See ::uintLessThan, which this function uses in most cases,
/// for commentary on the runtime of this function.
@@ -185,6 +189,7 @@ pub const Random = struct {
return at_least + r.uintAtMostBiased(T, at_most - at_least);
}
}
+
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
/// See ::uintLessThan, which this function uses in most cases,
/// for commentary on the runtime of this function.
@@ -312,43 +317,43 @@ test "Random int" {
fn testRandomInt() void {
var r = SequentialPrng.init();
- assert(r.random.int(u0) == 0);
+ expect(r.random.int(u0) == 0);
r.next_value = 0;
- assert(r.random.int(u1) == 0);
- assert(r.random.int(u1) == 1);
- assert(r.random.int(u2) == 2);
- assert(r.random.int(u2) == 3);
- assert(r.random.int(u2) == 0);
+ expect(r.random.int(u1) == 0);
+ expect(r.random.int(u1) == 1);
+ expect(r.random.int(u2) == 2);
+ expect(r.random.int(u2) == 3);
+ expect(r.random.int(u2) == 0);
r.next_value = 0xff;
- assert(r.random.int(u8) == 0xff);
+ expect(r.random.int(u8) == 0xff);
r.next_value = 0x11;
- assert(r.random.int(u8) == 0x11);
+ expect(r.random.int(u8) == 0x11);
r.next_value = 0xff;
- assert(r.random.int(u32) == 0xffffffff);
+ expect(r.random.int(u32) == 0xffffffff);
r.next_value = 0x11;
- assert(r.random.int(u32) == 0x11111111);
+ expect(r.random.int(u32) == 0x11111111);
r.next_value = 0xff;
- assert(r.random.int(i32) == -1);
+ expect(r.random.int(i32) == -1);
r.next_value = 0x11;
- assert(r.random.int(i32) == 0x11111111);
+ expect(r.random.int(i32) == 0x11111111);
r.next_value = 0xff;
- assert(r.random.int(i8) == -1);
+ expect(r.random.int(i8) == -1);
r.next_value = 0x11;
- assert(r.random.int(i8) == 0x11);
+ expect(r.random.int(i8) == 0x11);
r.next_value = 0xff;
- assert(r.random.int(u33) == 0x1ffffffff);
+ expect(r.random.int(u33) == 0x1ffffffff);
r.next_value = 0xff;
- assert(r.random.int(i1) == -1);
+ expect(r.random.int(i1) == -1);
r.next_value = 0xff;
- assert(r.random.int(i2) == -1);
+ expect(r.random.int(i2) == -1);
r.next_value = 0xff;
- assert(r.random.int(i33) == -1);
+ expect(r.random.int(i33) == -1);
}
test "Random boolean" {
@@ -357,10 +362,10 @@ test "Random boolean" {
}
fn testRandomBoolean() void {
var r = SequentialPrng.init();
- assert(r.random.boolean() == false);
- assert(r.random.boolean() == true);
- assert(r.random.boolean() == false);
- assert(r.random.boolean() == true);
+ expect(r.random.boolean() == false);
+ expect(r.random.boolean() == true);
+ expect(r.random.boolean() == false);
+ expect(r.random.boolean() == true);
}
test "Random intLessThan" {
@@ -371,36 +376,36 @@ test "Random intLessThan" {
fn testRandomIntLessThan() void {
var r = SequentialPrng.init();
r.next_value = 0xff;
- assert(r.random.uintLessThan(u8, 4) == 3);
- assert(r.next_value == 0);
- assert(r.random.uintLessThan(u8, 4) == 0);
- assert(r.next_value == 1);
+ expect(r.random.uintLessThan(u8, 4) == 3);
+ expect(r.next_value == 0);
+ expect(r.random.uintLessThan(u8, 4) == 0);
+ expect(r.next_value == 1);
r.next_value = 0;
- assert(r.random.uintLessThan(u64, 32) == 0);
+ expect(r.random.uintLessThan(u64, 32) == 0);
// trigger the bias rejection code path
r.next_value = 0;
- assert(r.random.uintLessThan(u8, 3) == 0);
+ expect(r.random.uintLessThan(u8, 3) == 0);
// verify we incremented twice
- assert(r.next_value == 2);
+ expect(r.next_value == 2);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
+ expect(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
+ expect(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
+ expect(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
+ expect(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
+ expect(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
+ expect(r.random.intRangeLessThan(i3, -4, 0) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
+ expect(r.random.intRangeLessThan(i3, -2, 2) == 1);
}
test "Random intAtMost" {
@@ -411,34 +416,34 @@ test "Random intAtMost" {
fn testRandomIntAtMost() void {
var r = SequentialPrng.init();
r.next_value = 0xff;
- assert(r.random.uintAtMost(u8, 3) == 3);
- assert(r.next_value == 0);
- assert(r.random.uintAtMost(u8, 3) == 0);
+ expect(r.random.uintAtMost(u8, 3) == 3);
+ expect(r.next_value == 0);
+ expect(r.random.uintAtMost(u8, 3) == 0);
// trigger the bias rejection code path
r.next_value = 0;
- assert(r.random.uintAtMost(u8, 2) == 0);
+ expect(r.random.uintAtMost(u8, 2) == 0);
// verify we incremented twice
- assert(r.next_value == 2);
+ expect(r.next_value == 2);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
+ expect(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
+ expect(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
+ expect(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
+ expect(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
+ expect(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
+ expect(r.random.intRangeAtMost(i3, -4, -1) == -1);
r.next_value = 0xff;
- assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
+ expect(r.random.intRangeAtMost(i3, -2, 1) == 1);
- assert(r.random.uintAtMost(u0, 0) == 0);
+ expect(r.random.uintAtMost(u0, 0) == 0);
}
test "Random Biased" {
@@ -446,30 +451,30 @@ test "Random Biased" {
// Not thoroughly checking the logic here.
// Just want to execute all the paths with different types.
- assert(r.random.uintLessThanBiased(u1, 1) == 0);
- assert(r.random.uintLessThanBiased(u32, 10) < 10);
- assert(r.random.uintLessThanBiased(u64, 20) < 20);
+ expect(r.random.uintLessThanBiased(u1, 1) == 0);
+ expect(r.random.uintLessThanBiased(u32, 10) < 10);
+ expect(r.random.uintLessThanBiased(u64, 20) < 20);
- assert(r.random.uintAtMostBiased(u0, 0) == 0);
- assert(r.random.uintAtMostBiased(u1, 0) <= 0);
- assert(r.random.uintAtMostBiased(u32, 10) <= 10);
- assert(r.random.uintAtMostBiased(u64, 20) <= 20);
+ expect(r.random.uintAtMostBiased(u0, 0) == 0);
+ expect(r.random.uintAtMostBiased(u1, 0) <= 0);
+ expect(r.random.uintAtMostBiased(u32, 10) <= 10);
+ expect(r.random.uintAtMostBiased(u64, 20) <= 20);
- assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
- assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
- assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
- assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
- assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
- assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
+ expect(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
+ expect(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
+ expect(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
+ expect(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
+ expect(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
+ expect(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
// uncomment for broken module error:
- //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
- assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
- assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
- assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
- assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
- assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
- assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
+ //expect(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
+ expect(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
+ expect(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
+ expect(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
+ expect(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
+ expect(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
+ expect(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
}
// Generator to extend 64-bit seed values into longer sequences.
@@ -506,7 +511,7 @@ test "splitmix64 sequence" {
};
for (seq) |s| {
- std.debug.assert(s == r.next());
+ expect(s == r.next());
}
}
@@ -599,7 +604,7 @@ test "pcg sequence" {
};
for (seq) |s| {
- std.debug.assert(s == r.next());
+ expect(s == r.next());
}
}
@@ -708,7 +713,7 @@ test "xoroshiro sequence" {
};
for (seq1) |s| {
- std.debug.assert(s == r.next());
+ expect(s == r.next());
}
r.jump();
@@ -723,7 +728,7 @@ test "xoroshiro sequence" {
};
for (seq2) |s| {
- std.debug.assert(s == r.next());
+ expect(s == r.next());
}
}
@@ -926,7 +931,7 @@ test "isaac64 sequence" {
};
for (seq) |s| {
- std.debug.assert(s == r.next());
+ expect(s == r.next());
}
}
@@ -937,12 +942,12 @@ test "Random float" {
var i: usize = 0;
while (i < 1000) : (i += 1) {
const val1 = prng.random.float(f32);
- std.debug.assert(val1 >= 0.0);
- std.debug.assert(val1 < 1.0);
+ expect(val1 >= 0.0);
+ expect(val1 < 1.0);
const val2 = prng.random.float(f64);
- std.debug.assert(val2 >= 0.0);
- std.debug.assert(val2 < 1.0);
+ expect(val2 >= 0.0);
+ expect(val2 < 1.0);
}
}
@@ -956,12 +961,12 @@ test "Random shuffle" {
while (i < 1000) : (i += 1) {
prng.random.shuffle(u8, seq[0..]);
seen[seq[0]] = true;
- std.debug.assert(sumArray(seq[0..]) == 10);
+ expect(sumArray(seq[0..]) == 10);
}
// we should see every entry at the head at least once
for (seen) |e| {
- std.debug.assert(e == true);
+ expect(e == true);
}
}
diff --git a/std/rb.zig b/std/rb.zig
index beb7f3aae9..27e60dca6a 100644
--- a/std/rb.zig
+++ b/std/rb.zig
@@ -1,5 +1,6 @@
const std = @import("index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem; // For mem.Compare
const Color = enum(u1) {
@@ -533,13 +534,13 @@ test "rb" {
_ = tree.insert(&ns[8].node);
_ = tree.insert(&ns[9].node);
tree.remove(&ns[3].node);
- assert(tree.insert(&dup.node) == &ns[7].node);
+ testing.expect(tree.insert(&dup.node) == &ns[7].node);
try tree.replace(&ns[7].node, &dup.node);
var num: *testNumber = undefined;
num = testGetNumber(tree.first().?);
while (num.node.next() != null) {
- assert(testGetNumber(num.node.next().?).value > num.value);
+ testing.expect(testGetNumber(num.node.next().?).value > num.value);
num = testGetNumber(num.node.next().?);
}
}
diff --git a/std/segmented_list.zig b/std/segmented_list.zig
index d786e0becd..26b7fa48f5 100644
--- a/std/segmented_list.zig
+++ b/std/segmented_list.zig
@@ -1,5 +1,6 @@
const std = @import("index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const Allocator = std.mem.Allocator;
// Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box
@@ -352,14 +353,14 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
var i: usize = 0;
while (i < 100) : (i += 1) {
try list.push(@intCast(i32, i + 1));
- assert(list.len == i + 1);
+ testing.expect(list.len == i + 1);
}
}
{
var i: usize = 0;
while (i < 100) : (i += 1) {
- assert(list.at(i).* == @intCast(i32, i + 1));
+ testing.expect(list.at(i).* == @intCast(i32, i + 1));
}
}
@@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
var x: i32 = 0;
while (it.next()) |item| {
x += 1;
- assert(item.* == x);
+ testing.expect(item.* == x);
}
- assert(x == 100);
+ testing.expect(x == 100);
while (it.prev()) |item| : (x -= 1) {
- assert(item.* == x);
+ testing.expect(item.* == x);
}
- assert(x == 0);
+ testing.expect(x == 0);
}
- assert(list.pop().? == 100);
- assert(list.len == 99);
+ testing.expect(list.pop().? == 100);
+ testing.expect(list.len == 99);
try list.pushMany([]i32{
1,
2,
3,
});
- assert(list.len == 102);
- assert(list.pop().? == 3);
- assert(list.pop().? == 2);
- assert(list.pop().? == 1);
- assert(list.len == 99);
+ testing.expect(list.len == 102);
+ testing.expect(list.pop().? == 3);
+ testing.expect(list.pop().? == 2);
+ testing.expect(list.pop().? == 1);
+ testing.expect(list.len == 99);
try list.pushMany([]const i32{});
- assert(list.len == 99);
+ testing.expect(list.len == 99);
var i: i32 = 99;
while (list.pop()) |item| : (i -= 1) {
- assert(item == i);
+ testing.expect(item == i);
list.shrinkCapacity(list.len);
}
}
diff --git a/std/sort.zig b/std/sort.zig
index f29f51b7cf..86a6724fee 100644
--- a/std/sort.zig
+++ b/std/sort.zig
@@ -1,5 +1,6 @@
const std = @import("index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
const math = std.math;
const builtin = @import("builtin");
@@ -1031,8 +1032,8 @@ fn testStableSort() void {
for (cases) |*case| {
insertionSort(IdAndValue, (case.*)[0..], cmpByValue);
for (case.*) |item, i| {
- assert(item.id == expected[i].id);
- assert(item.value == expected[i].value);
+ testing.expect(item.id == expected[i].id);
+ testing.expect(item.value == expected[i].value);
}
}
}
@@ -1077,7 +1078,7 @@ test "std.sort" {
const slice = buf[0..case[0].len];
mem.copy(u8, slice, case[0]);
sort(u8, slice, asc(u8));
- assert(mem.eql(u8, slice, case[1]));
+ testing.expect(mem.eql(u8, slice, case[1]));
}
const i32cases = [][]const []const i32{
@@ -1112,7 +1113,7 @@ test "std.sort" {
const slice = buf[0..case[0].len];
mem.copy(i32, slice, case[0]);
sort(i32, slice, asc(i32));
- assert(mem.eql(i32, slice, case[1]));
+ testing.expect(mem.eql(i32, slice, case[1]));
}
}
@@ -1149,7 +1150,7 @@ test "std.sort descending" {
const slice = buf[0..case[0].len];
mem.copy(i32, slice, case[0]);
sort(i32, slice, desc(i32));
- assert(mem.eql(i32, slice, case[1]));
+ testing.expect(mem.eql(i32, slice, case[1]));
}
}
@@ -1157,7 +1158,7 @@ test "another sort case" {
var arr = []i32{ 5, 3, 1, 2, 4 };
sort(i32, arr[0..], asc(i32));
- assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
+ testing.expect(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
}
test "sort fuzz testing" {
@@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void {
var index: usize = 1;
while (index < array.len) : (index += 1) {
if (array[index].value == array[index - 1].value) {
- assert(array[index].id > array[index - 1].id);
+ testing.expect(array[index].id > array[index - 1].id);
} else {
- assert(array[index].value > array[index - 1].value);
+ testing.expect(array[index].value > array[index - 1].value);
}
}
}
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index a15be317ab..6dcc90b372 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -4,6 +4,7 @@
const root = @import("@root");
const std = @import("std");
const builtin = @import("builtin");
+const assert = std.debug.assert;
var argc_ptr: [*]usize = undefined;
@@ -20,17 +21,10 @@ comptime {
nakedcc fn _start() noreturn {
switch (builtin.arch) {
- builtin.Arch.x86_64 => switch (builtin.os) {
- builtin.Os.freebsd => {
- argc_ptr = asm ("lea (%%rdi), %[argc]"
- : [argc] "=r" (-> [*]usize)
- );
- },
- else => {
- argc_ptr = asm ("lea (%%rsp), %[argc]"
- : [argc] "=r" (-> [*]usize)
- );
- },
+ builtin.Arch.x86_64 => {
+ argc_ptr = asm ("lea (%%rsp), %[argc]"
+ : [argc] "=r" (-> [*]usize)
+ );
},
builtin.Arch.i386 => {
argc_ptr = asm ("lea (%%esp), %[argc]"
@@ -51,7 +45,9 @@ nakedcc fn _start() noreturn {
extern fn WinMainCRTStartup() noreturn {
@setAlignStack(16);
-
+ if (!builtin.single_threaded) {
+ _ = @import("../os/windows/tls.zig");
+ }
std.os.windows.ExitProcess(callMain());
}
@@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn {
while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
if (builtin.os == builtin.Os.linux) {
- const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1);
- std.os.linux_elf_aux_maybe = @ptrCast([*]std.elf.Auxv, auxv);
- std.debug.assert(std.os.linuxGetAuxVal(std.elf.AT_PAGESZ) == std.os.page_size);
+ // Scan auxiliary vector.
+ const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
+ std.os.linux_elf_aux_maybe = auxv;
+ var i: usize = 0;
+ var at_phdr: usize = 0;
+ var at_phnum: usize = 0;
+ var at_phent: usize = 0;
+ while (auxv[i].a_un.a_val != 0) : (i += 1) {
+ switch (auxv[i].a_type) {
+ std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size),
+ std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
+ std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
+ std.elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
+ else => {},
+ }
+ }
+ if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent);
}
std.os.posix.exit(callMainWithArgs(argc, argv, envp));
@@ -123,3 +133,41 @@ inline fn callMain() u8 {
else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
}
}
+
+var tls_end_addr: usize = undefined;
+const main_thread_tls_align = 32;
+var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;
+
+fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: usize) void {
+ var phdr_addr = at_phdr;
+ var n = at_phnum;
+ var base: usize = 0;
+ while (n != 0) : ({n -= 1; phdr_addr += at_phent;}) {
+ const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
+ // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
+ switch (phdr.p_type) {
+ std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr,
+ std.elf.PT_TLS => std.os.linux_tls_phdr = phdr,
+ else => continue,
+ }
+ }
+ const tls_phdr = std.os.linux_tls_phdr orelse return;
+ std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
+ assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage
+ assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
+ @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
+ tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
+ linuxSetThreadArea(@ptrToInt(&tls_end_addr));
+}
+
+fn linuxSetThreadArea(addr: usize) void {
+ switch (builtin.arch) {
+ builtin.Arch.x86_64 => {
+ const ARCH_SET_FS = 0x1002;
+ const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl, ARCH_SET_FS, addr);
+ // acrh_prctl is documented to never fail
+ assert(rc == 0);
+ },
+ else => @compileError("Unsupported architecture"),
+ }
+}
diff --git a/std/special/compiler_rt/addXf3.zig b/std/special/compiler_rt/addXf3.zig
new file mode 100644
index 0000000000..09413b2328
--- /dev/null
+++ b/std/special/compiler_rt/addXf3.zig
@@ -0,0 +1,191 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
+
+const std = @import("std");
+const builtin = @import("builtin");
+const compiler_rt = @import("index.zig");
+
+pub extern fn __addtf3(a: f128, b: f128) f128 {
+ return addXf3(f128, a, b);
+}
+
+pub extern fn __subtf3(a: f128, b: f128) f128 {
+ const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127));
+ return addXf3(f128, a, neg_b);
+}
+
+inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
+ const Z = @IntType(false, T.bit_count);
+ const significandBits = std.math.floatMantissaBits(T);
+ const implicitBit = Z(1) << significandBits;
+
+ const shift = @clz(significand.*) - @clz(implicitBit);
+ significand.* <<= @intCast(u7, shift);
+ return 1 - shift;
+}
+
+inline fn addXf3(comptime T: type, a: T, b: T) T {
+ const Z = @IntType(false, T.bit_count);
+
+ const typeWidth = T.bit_count;
+ const significandBits = std.math.floatMantissaBits(T);
+ const exponentBits = std.math.floatExponentBits(T);
+
+ const signBit = (Z(1) << (significandBits + exponentBits));
+ const maxExponent = ((1 << exponentBits) - 1);
+ const exponentBias = (maxExponent >> 1);
+
+ const implicitBit = (Z(1) << significandBits);
+ const quietBit = implicitBit >> 1;
+ const significandMask = implicitBit - 1;
+
+ const absMask = signBit - 1;
+ const exponentMask = absMask ^ significandMask;
+ const qnanRep = exponentMask | quietBit;
+
+ var aRep = @bitCast(Z, a);
+ var bRep = @bitCast(Z, b);
+ const aAbs = aRep & absMask;
+ const bAbs = bRep & absMask;
+
+ const negative = (aRep & signBit) != 0;
+ const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
+ const significand = (aAbs & significandMask) | implicitBit;
+
+ const infRep = @bitCast(Z, std.math.inf(T));
+
+ // Detect if a or b is zero, infinity, or NaN.
+ if (aAbs - Z(1) >= infRep - Z(1) or
+ bAbs - Z(1) >= infRep - Z(1))
+ {
+ // NaN + anything = qNaN
+ if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
+ // anything + NaN = qNaN
+ if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
+
+ if (aAbs == infRep) {
+ // +/-infinity + -/+infinity = qNaN
+ if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) {
+ return @bitCast(T, qnanRep);
+ }
+ // +/-infinity + anything remaining = +/- infinity
+ else {
+ return a;
+ }
+ }
+
+ // anything remaining + +/-infinity = +/-infinity
+ if (bAbs == infRep) return b;
+
+ // zero + anything = anything
+ if (aAbs == 0) {
+ // but we need to get the sign right for zero + zero
+ if (bAbs == 0) {
+ return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b));
+ } else {
+ return b;
+ }
+ }
+
+ // anything + zero = anything
+ if (bAbs == 0) return a;
+ }
+
+ // Swap a and b if necessary so that a has the larger absolute value.
+ if (bAbs > aAbs) {
+ const temp = aRep;
+ aRep = bRep;
+ bRep = temp;
+ }
+
+ // Extract the exponent and significand from the (possibly swapped) a and b.
+ var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent);
+ var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent);
+ var aSignificand = aRep & significandMask;
+ var bSignificand = bRep & significandMask;
+
+ // Normalize any denormals, and adjust the exponent accordingly.
+ if (aExponent == 0) aExponent = normalize(T, &aSignificand);
+ if (bExponent == 0) bExponent = normalize(T, &bSignificand);
+
+ // The sign of the result is the sign of the larger operand, a. If they
+ // have opposite signs, we are performing a subtraction; otherwise addition.
+ const resultSign = aRep & signBit;
+ const subtraction = (aRep ^ bRep) & signBit != 0;
+
+ // Shift the significands to give us round, guard and sticky, and or in the
+ // implicit significand bit. (If we fell through from the denormal path it
+ // was already set by normalize( ), but setting it twice won't hurt
+ // anything.)
+ aSignificand = (aSignificand | implicitBit) << 3;
+ bSignificand = (bSignificand | implicitBit) << 3;
+
+ // Shift the significand of b by the difference in exponents, with a sticky
+ // bottom bit to get rounding correct.
+ const @"align" = @intCast(Z, aExponent - bExponent);
+ if (@"align" != 0) {
+ if (@"align" < typeWidth) {
+ const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0;
+ bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky;
+ } else {
+ bSignificand = 1; // sticky; b is known to be non-zero.
+ }
+ }
+ if (subtraction) {
+ aSignificand -= bSignificand;
+ // If a == -b, return +zero.
+ if (aSignificand == 0) return @bitCast(T, Z(0));
+
+ // If partial cancellation occured, we need to left-shift the result
+ // and adjust the exponent:
+ if (aSignificand < implicitBit << 3) {
+ const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3));
+ aSignificand <<= @intCast(u7, shift);
+ aExponent -= shift;
+ }
+ } else { // addition
+ aSignificand += bSignificand;
+
+ // If the addition carried up, we need to right-shift the result and
+ // adjust the exponent:
+ if (aSignificand & (implicitBit << 4) != 0) {
+ const sticky = aSignificand & 1;
+ aSignificand = aSignificand >> 1 | sticky;
+ aExponent += 1;
+ }
+ }
+
+ // If we have overflowed the type, return +/- infinity:
+ if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
+
+ if (aExponent <= 0) {
+ // Result is denormal before rounding; the exponent is zero and we
+ // need to shift the significand.
+ const shift = @intCast(Z, 1 - aExponent);
+ const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0;
+ aSignificand = aSignificand >> @intCast(u7, shift | sticky);
+ aExponent = 0;
+ }
+
+ // Low three bits are round, guard, and sticky.
+ const roundGuardSticky = aSignificand & 0x7;
+
+ // Shift the significand into place, and mask off the implicit bit.
+ var result = (aSignificand >> 3) & significandMask;
+
+ // Insert the exponent and sign.
+ result |= @intCast(Z, aExponent) << significandBits;
+ result |= resultSign;
+
+ // Final rounding. The result may overflow to infinity, but that is the
+ // correct result in that case.
+ if (roundGuardSticky > 0x4) result += 1;
+ if (roundGuardSticky == 0x4) result += result & 1;
+
+ return @bitCast(T, result);
+}
+
+test "import addXf3" {
+ _ = @import("addXf3_test.zig");
+}
diff --git a/std/special/compiler_rt/addXf3_test.zig b/std/special/compiler_rt/addXf3_test.zig
new file mode 100644
index 0000000000..099b737976
--- /dev/null
+++ b/std/special/compiler_rt/addXf3_test.zig
@@ -0,0 +1,85 @@
+// Ported from:
+//
+// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c
+// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c
+
+const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64);
+const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64);
+
+const __addtf3 = @import("addXf3.zig").__addtf3;
+
+fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
+ const x = __addtf3(a, b);
+
+ const rep = @bitCast(u128, x);
+ const hi = @intCast(u64, rep >> 64);
+ const lo = @truncate(u64, rep);
+
+ if (hi == expected_hi and lo == expected_lo) {
+ return;
+ }
+ // test other possible NaN representation (signal NaN)
+ else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
+ if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
+ ((hi & 0xffffffffffff) > 0 or lo > 0))
+ {
+ return;
+ }
+ }
+
+ @panic("__addtf3 test failure");
+}
+
+test "addtf3" {
+ test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
+
+ // NaN + any = NaN
+ test__addtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
+
+ // inf + inf = inf
+ test__addtf3(inf128, inf128, 0x7fff000000000000, 0x0);
+
+ // inf + any = inf
+ test__addtf3(inf128, 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0);
+
+ // any + any
+ test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c);
+}
+
+const __subtf3 = @import("addXf3.zig").__subtf3;
+
+fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
+ const x = __subtf3(a, b);
+
+ const rep = @bitCast(u128, x);
+ const hi = @intCast(u64, rep >> 64);
+ const lo = @truncate(u64, rep);
+
+ if (hi == expected_hi and lo == expected_lo) {
+ return;
+ }
+ // test other possible NaN representation (signal NaN)
+ else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
+ if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
+ ((hi & 0xffffffffffff) > 0 or lo > 0))
+ {
+ return;
+ }
+ }
+
+ @panic("__subtf3 test failure");
+}
+
+test "subtf3" {
+ // qNaN - any = qNaN
+ test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
+
+ // NaN + any = NaN
+ test__subtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
+
+ // inf - any = inf
+ test__subtf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
+
+ // any + any
+ test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c);
+}
diff --git a/std/special/compiler_rt/divti3_test.zig b/std/special/compiler_rt/divti3_test.zig
index eef5a9b812..e1c1babae7 100644
--- a/std/special/compiler_rt/divti3_test.zig
+++ b/std/special/compiler_rt/divti3_test.zig
@@ -1,9 +1,9 @@
const __divti3 = @import("divti3.zig").__divti3;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__divti3(a: i128, b: i128, expected: i128) void {
const x = __divti3(a, b);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "divti3" {
diff --git a/std/special/compiler_rt/extendXfYf2_test.zig b/std/special/compiler_rt/extendXfYf2_test.zig
index 9969607011..050a799823 100644
--- a/std/special/compiler_rt/extendXfYf2_test.zig
+++ b/std/special/compiler_rt/extendXfYf2_test.zig
@@ -1,7 +1,6 @@
const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
-const assert = @import("std").debug.assert;
fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
const x = __extenddftf2(a);
diff --git a/std/special/compiler_rt/fixdfdi.zig b/std/special/compiler_rt/fixdfdi.zig
new file mode 100644
index 0000000000..c108fd15aa
--- /dev/null
+++ b/std/special/compiler_rt/fixdfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfdi(a: f64) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i64, a);
+}
+
+test "import fixdfdi" {
+ _ = @import("fixdfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfdi_test.zig b/std/special/compiler_rt/fixdfdi_test.zig
new file mode 100644
index 0000000000..a55245210b
--- /dev/null
+++ b/std/special/compiler_rt/fixdfdi_test.zig
@@ -0,0 +1,66 @@
+const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixdfdi(a: f64, expected: i64) void {
+ const x = __fixdfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected));
+ testing.expect(x == expected);
+}
+
+test "fixdfdi" {
+ //warn("\n");
+
+ test__fixdfdi(-math.f64_max, math.minInt(i64));
+
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixdfdi(-2.01, -2);
+ test__fixdfdi(-2.0, -2);
+ test__fixdfdi(-1.99, -1);
+ test__fixdfdi(-1.0, -1);
+ test__fixdfdi(-0.99, 0);
+ test__fixdfdi(-0.5, 0);
+ test__fixdfdi(-math.f64_min, 0);
+ test__fixdfdi(0.0, 0);
+ test__fixdfdi(math.f64_min, 0);
+ test__fixdfdi(0.5, 0);
+ test__fixdfdi(0.99, 0);
+ test__fixdfdi(1.0, 1);
+ test__fixdfdi(1.5, 1);
+ test__fixdfdi(1.99, 1);
+ test__fixdfdi(2.0, 2);
+ test__fixdfdi(2.01, 2);
+
+ test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixdfdi(math.f64_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixdfsi.zig b/std/special/compiler_rt/fixdfsi.zig
new file mode 100644
index 0000000000..83a17b2b0d
--- /dev/null
+++ b/std/special/compiler_rt/fixdfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfsi(a: f64) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i32, a);
+}
+
+test "import fixdfsi" {
+ _ = @import("fixdfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfsi_test.zig b/std/special/compiler_rt/fixdfsi_test.zig
new file mode 100644
index 0000000000..5cb9bef1d9
--- /dev/null
+++ b/std/special/compiler_rt/fixdfsi_test.zig
@@ -0,0 +1,74 @@
+const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixdfsi(a: f64, expected: i32) void {
+ const x = __fixdfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected));
+ testing.expect(x == expected);
+}
+
+test "fixdfsi" {
+ //warn("\n");
+
+ test__fixdfsi(-math.f64_max, math.minInt(i32));
+
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixdfsi(-0x1.000000p+31, -0x80000000);
+ test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+
+ test__fixdfsi(-2.01, -2);
+ test__fixdfsi(-2.0, -2);
+ test__fixdfsi(-1.99, -1);
+ test__fixdfsi(-1.0, -1);
+ test__fixdfsi(-0.99, 0);
+ test__fixdfsi(-0.5, 0);
+ test__fixdfsi(-math.f64_min, 0);
+ test__fixdfsi(0.0, 0);
+ test__fixdfsi(math.f64_min, 0);
+ test__fixdfsi(0.5, 0);
+ test__fixdfsi(0.99, 0);
+ test__fixdfsi(1.0, 1);
+ test__fixdfsi(1.5, 1);
+ test__fixdfsi(1.99, 1);
+ test__fixdfsi(2.0, 2);
+ test__fixdfsi(2.01, 2);
+
+ test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixdfsi(math.f64_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixdfti.zig b/std/special/compiler_rt/fixdfti.zig
new file mode 100644
index 0000000000..e30f885cf6
--- /dev/null
+++ b/std/special/compiler_rt/fixdfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixdfti(a: f64) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f64, i128, a);
+}
+
+test "import fixdfti" {
+ _ = @import("fixdfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixdfti_test.zig b/std/special/compiler_rt/fixdfti_test.zig
new file mode 100644
index 0000000000..5fbcd206ed
--- /dev/null
+++ b/std/special/compiler_rt/fixdfti_test.zig
@@ -0,0 +1,66 @@
+const __fixdfti = @import("fixdfti.zig").__fixdfti;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixdfti(a: f64, expected: i128) void {
+ const x = __fixdfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected));
+ testing.expect(x == expected);
+}
+
+test "fixdfti" {
+ //warn("\n");
+
+ test__fixdfti(-math.f64_max, math.minInt(i128));
+
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
+
+ test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
+ test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixdfti(-2.01, -2);
+ test__fixdfti(-2.0, -2);
+ test__fixdfti(-1.99, -1);
+ test__fixdfti(-1.0, -1);
+ test__fixdfti(-0.99, 0);
+ test__fixdfti(-0.5, 0);
+ test__fixdfti(-math.f64_min, 0);
+ test__fixdfti(0.0, 0);
+ test__fixdfti(math.f64_min, 0);
+ test__fixdfti(0.5, 0);
+ test__fixdfti(0.99, 0);
+ test__fixdfti(1.0, 1);
+ test__fixdfti(1.5, 1);
+ test__fixdfti(1.99, 1);
+ test__fixdfti(2.0, 2);
+ test__fixdfti(2.01, 2);
+
+ test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixdfti(math.f64_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixint.zig b/std/special/compiler_rt/fixint.zig
new file mode 100644
index 0000000000..fd31798cc2
--- /dev/null
+++ b/std/special/compiler_rt/fixint.zig
@@ -0,0 +1,74 @@
+const is_test = @import("builtin").is_test;
+const std = @import("std");
+const math = std.math;
+const Log2Int = std.math.Log2Int;
+const maxInt = std.math.maxInt;
+const minInt = std.math.minInt;
+
+const DBG = false;
+
+pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
+ @setRuntimeSafety(is_test);
+
+ const rep_t = switch (fp_t) {
+ f32 => u32,
+ f64 => u64,
+ f128 => u128,
+ else => unreachable,
+ };
+ const significandBits = switch (fp_t) {
+ f32 => 23,
+ f64 => 52,
+ f128 => 112,
+ else => unreachable,
+ };
+
+ const typeWidth = rep_t.bit_count;
+ const exponentBits = (typeWidth - significandBits - 1);
+ const signBit = (rep_t(1) << (significandBits + exponentBits));
+ const maxExponent = ((1 << exponentBits) - 1);
+ const exponentBias = (maxExponent >> 1);
+
+ const implicitBit = (rep_t(1) << significandBits);
+ const significandMask = (implicitBit - 1);
+
+ // Break a into sign, exponent, significand
+ const aRep: rep_t = @bitCast(rep_t, a);
+ const absMask = signBit - 1;
+ const aAbs: rep_t = aRep & absMask;
+
+ const negative = (aRep & signBit) != 0;
+ const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
+ const significand: rep_t = (aAbs & significandMask) | implicitBit;
+
+ // If exponent is negative, the uint_result is zero.
+ if (exponent < 0) return 0;
+
+ // The unsigned result needs to be large enough to handle an fixint_t or rep_t
+ const fixuint_t = @IntType(false, fixint_t.bit_count);
+ const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
+ var uint_result: UintResultType = undefined;
+
+ // If the value is too large for the integer type, saturate.
+ if (@intCast(usize, exponent) >= fixint_t.bit_count) {
+ return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t));
+ }
+
+ // If 0 <= exponent < significandBits, right shift else left shift
+ if (exponent < significandBits) {
+ uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent);
+ } else {
+ uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits);
+ }
+
+ // Cast to final signed result
+ if (negative) {
+ return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result);
+ } else {
+ return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result);
+ }
+}
+
+test "import fixint" {
+ _ = @import("fixint_test.zig");
+}
diff --git a/std/special/compiler_rt/fixint_test.zig b/std/special/compiler_rt/fixint_test.zig
new file mode 100644
index 0000000000..0b0936d1e2
--- /dev/null
+++ b/std/special/compiler_rt/fixint_test.zig
@@ -0,0 +1,152 @@
+const is_test = @import("builtin").is_test;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+const fixint = @import("fixint.zig").fixint;
+
+fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) void {
+ const x = fixint(fp_t, fixint_t, a);
+ //warn("a={} x={}:{x} expected={}:{x})\n", a, x, x, expected, expected);
+ testing.expect(x == expected);
+}
+
+test "fixint.i1" {
+ test__fixint(f32, i1, -math.inf_f32, -1);
+ test__fixint(f32, i1, -math.f32_max, -1);
+ test__fixint(f32, i1, -2.0, -1);
+ test__fixint(f32, i1, -1.1, -1);
+ test__fixint(f32, i1, -1.0, -1);
+ test__fixint(f32, i1, -0.9, 0);
+ test__fixint(f32, i1, -0.1, 0);
+ test__fixint(f32, i1, -math.f32_min, 0);
+ test__fixint(f32, i1, -0.0, 0);
+ test__fixint(f32, i1, 0.0, 0);
+ test__fixint(f32, i1, math.f32_min, 0);
+ test__fixint(f32, i1, 0.1, 0);
+ test__fixint(f32, i1, 0.9, 0);
+ test__fixint(f32, i1, 1.0, 0);
+ test__fixint(f32, i1, 2.0, 0);
+ test__fixint(f32, i1, math.f32_max, 0);
+ test__fixint(f32, i1, math.inf_f32, 0);
+}
+
+test "fixint.i2" {
+ test__fixint(f32, i2, -math.inf_f32, -2);
+ test__fixint(f32, i2, -math.f32_max, -2);
+ test__fixint(f32, i2, -2.0, -2);
+ test__fixint(f32, i2, -1.9, -1);
+ test__fixint(f32, i2, -1.1, -1);
+ test__fixint(f32, i2, -1.0, -1);
+ test__fixint(f32, i2, -0.9, 0);
+ test__fixint(f32, i2, -0.1, 0);
+ test__fixint(f32, i2, -math.f32_min, 0);
+ test__fixint(f32, i2, -0.0, 0);
+ test__fixint(f32, i2, 0.0, 0);
+ test__fixint(f32, i2, math.f32_min, 0);
+ test__fixint(f32, i2, 0.1, 0);
+ test__fixint(f32, i2, 0.9, 0);
+ test__fixint(f32, i2, 1.0, 1);
+ test__fixint(f32, i2, 2.0, 1);
+ test__fixint(f32, i2, math.f32_max, 1);
+ test__fixint(f32, i2, math.inf_f32, 1);
+}
+
+test "fixint.i3" {
+ test__fixint(f32, i3, -math.inf_f32, -4);
+ test__fixint(f32, i3, -math.f32_max, -4);
+ test__fixint(f32, i3, -4.0, -4);
+ test__fixint(f32, i3, -3.0, -3);
+ test__fixint(f32, i3, -2.0, -2);
+ test__fixint(f32, i3, -1.9, -1);
+ test__fixint(f32, i3, -1.1, -1);
+ test__fixint(f32, i3, -1.0, -1);
+ test__fixint(f32, i3, -0.9, 0);
+ test__fixint(f32, i3, -0.1, 0);
+ test__fixint(f32, i3, -math.f32_min, 0);
+ test__fixint(f32, i3, -0.0, 0);
+ test__fixint(f32, i3, 0.0, 0);
+ test__fixint(f32, i3, math.f32_min, 0);
+ test__fixint(f32, i3, 0.1, 0);
+ test__fixint(f32, i3, 0.9, 0);
+ test__fixint(f32, i3, 1.0, 1);
+ test__fixint(f32, i3, 2.0, 2);
+ test__fixint(f32, i3, 3.0, 3);
+ test__fixint(f32, i3, 4.0, 3);
+ test__fixint(f32, i3, math.f32_max, 3);
+ test__fixint(f32, i3, math.inf_f32, 3);
+}
+
+test "fixint.i32" {
+ test__fixint(f64, i32, -math.inf_f64, math.minInt(i32));
+ test__fixint(f64, i32, -math.f64_max, math.minInt(i32));
+ test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32));
+ test__fixint(f64, i32, f64(math.minInt(i32))+1, math.minInt(i32)+1);
+ test__fixint(f64, i32, -2.0, -2);
+ test__fixint(f64, i32, -1.9, -1);
+ test__fixint(f64, i32, -1.1, -1);
+ test__fixint(f64, i32, -1.0, -1);
+ test__fixint(f64, i32, -0.9, 0);
+ test__fixint(f64, i32, -0.1, 0);
+ test__fixint(f64, i32, -math.f32_min, 0);
+ test__fixint(f64, i32, -0.0, 0);
+ test__fixint(f64, i32, 0.0, 0);
+ test__fixint(f64, i32, math.f32_min, 0);
+ test__fixint(f64, i32, 0.1, 0);
+ test__fixint(f64, i32, 0.9, 0);
+ test__fixint(f64, i32, 1.0, 1);
+ test__fixint(f64, i32, f64(math.maxInt(i32))-1, math.maxInt(i32)-1);
+ test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32));
+ test__fixint(f64, i32, math.f64_max, math.maxInt(i32));
+ test__fixint(f64, i32, math.inf_f64, math.maxInt(i32));
+}
+
+test "fixint.i64" {
+ test__fixint(f64, i64, -math.inf_f64, math.minInt(i64));
+ test__fixint(f64, i64, -math.f64_max, math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64))+1, math.minInt(i64));
+ test__fixint(f64, i64, f64(math.minInt(i64)/2), math.minInt(i64)/2);
+ test__fixint(f64, i64, -2.0, -2);
+ test__fixint(f64, i64, -1.9, -1);
+ test__fixint(f64, i64, -1.1, -1);
+ test__fixint(f64, i64, -1.0, -1);
+ test__fixint(f64, i64, -0.9, 0);
+ test__fixint(f64, i64, -0.1, 0);
+ test__fixint(f64, i64, -math.f32_min, 0);
+ test__fixint(f64, i64, -0.0, 0);
+ test__fixint(f64, i64, 0.0, 0);
+ test__fixint(f64, i64, math.f32_min, 0);
+ test__fixint(f64, i64, 0.1, 0);
+ test__fixint(f64, i64, 0.9, 0);
+ test__fixint(f64, i64, 1.0, 1);
+ test__fixint(f64, i64, f64(math.maxInt(i64))-1, math.maxInt(i64));
+ test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64));
+ test__fixint(f64, i64, math.f64_max, math.maxInt(i64));
+ test__fixint(f64, i64, math.inf_f64, math.maxInt(i64));
+}
+
+test "fixint.i128" {
+ test__fixint(f64, i128, -math.inf_f64, math.minInt(i128));
+ test__fixint(f64, i128, -math.f64_max, math.minInt(i128));
+ test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128));
+ test__fixint(f64, i128, f64(math.minInt(i128))+1, math.minInt(i128));
+ test__fixint(f64, i128, -2.0, -2);
+ test__fixint(f64, i128, -1.9, -1);
+ test__fixint(f64, i128, -1.1, -1);
+ test__fixint(f64, i128, -1.0, -1);
+ test__fixint(f64, i128, -0.9, 0);
+ test__fixint(f64, i128, -0.1, 0);
+ test__fixint(f64, i128, -math.f32_min, 0);
+ test__fixint(f64, i128, -0.0, 0);
+ test__fixint(f64, i128, 0.0, 0);
+ test__fixint(f64, i128, math.f32_min, 0);
+ test__fixint(f64, i128, 0.1, 0);
+ test__fixint(f64, i128, 0.9, 0);
+ test__fixint(f64, i128, 1.0, 1);
+ test__fixint(f64, i128, f64(math.maxInt(i128))-1, math.maxInt(i128));
+ test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128));
+ test__fixint(f64, i128, math.f64_max, math.maxInt(i128));
+ test__fixint(f64, i128, math.inf_f64, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixsfdi.zig b/std/special/compiler_rt/fixsfdi.zig
new file mode 100644
index 0000000000..ffa81d13ab
--- /dev/null
+++ b/std/special/compiler_rt/fixsfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfdi(a: f32) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i64, a);
+}
+
+test "import fixsfdi" {
+ _ = @import("fixsfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfdi_test.zig b/std/special/compiler_rt/fixsfdi_test.zig
new file mode 100644
index 0000000000..276670421b
--- /dev/null
+++ b/std/special/compiler_rt/fixsfdi_test.zig
@@ -0,0 +1,68 @@
+const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixsfdi(a: f32, expected: i64) void {
+ const x = __fixsfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected));
+ testing.expect(x == expected);
+}
+
+test "fixsfdi" {
+ //warn("\n");
+
+ test__fixsfdi(-math.f32_max, math.minInt(i64));
+
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
+
+ test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);
+ test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixsfdi(-2.01, -2);
+ test__fixsfdi(-2.0, -2);
+ test__fixsfdi(-1.99, -1);
+ test__fixsfdi(-1.0, -1);
+ test__fixsfdi(-0.99, 0);
+ test__fixsfdi(-0.5, 0);
+ test__fixsfdi(-math.f32_min, 0);
+ test__fixsfdi(0.0, 0);
+ test__fixsfdi(math.f32_min, 0);
+ test__fixsfdi(0.5, 0);
+ test__fixsfdi(0.99, 0);
+ test__fixsfdi(1.0, 1);
+ test__fixsfdi(1.5, 1);
+ test__fixsfdi(1.99, 1);
+ test__fixsfdi(2.0, 2);
+ test__fixsfdi(2.01, 2);
+
+ test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+ test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixsfdi(math.f64_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixsfsi.zig b/std/special/compiler_rt/fixsfsi.zig
new file mode 100644
index 0000000000..9a94b4395b
--- /dev/null
+++ b/std/special/compiler_rt/fixsfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfsi(a: f32) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i32, a);
+}
+
+test "import fixsfsi" {
+ _ = @import("fixsfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfsi_test.zig b/std/special/compiler_rt/fixsfsi_test.zig
new file mode 100644
index 0000000000..a05c15e536
--- /dev/null
+++ b/std/special/compiler_rt/fixsfsi_test.zig
@@ -0,0 +1,76 @@
+const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixsfsi(a: f32, expected: i32) void {
+ const x = __fixsfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected));
+ testing.expect(x == expected);
+}
+
+test "fixsfsi" {
+ //warn("\n");
+
+ test__fixsfsi(-math.f32_max, math.minInt(i32));
+
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixsfsi(-0x1.000000p+31, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);
+ test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixsfsi(-2.01, -2);
+ test__fixsfsi(-2.0, -2);
+ test__fixsfsi(-1.99, -1);
+ test__fixsfsi(-1.0, -1);
+ test__fixsfsi(-0.99, 0);
+ test__fixsfsi(-0.5, 0);
+ test__fixsfsi(-math.f32_min, 0);
+ test__fixsfsi(0.0, 0);
+ test__fixsfsi(math.f32_min, 0);
+ test__fixsfsi(0.5, 0);
+ test__fixsfsi(0.99, 0);
+ test__fixsfsi(1.0, 1);
+ test__fixsfsi(1.5, 1);
+ test__fixsfsi(1.99, 1);
+ test__fixsfsi(2.0, 2);
+ test__fixsfsi(2.01, 2);
+
+ test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);
+ test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixsfsi(math.f32_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixsfti.zig b/std/special/compiler_rt/fixsfti.zig
new file mode 100644
index 0000000000..806a1678aa
--- /dev/null
+++ b/std/special/compiler_rt/fixsfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixsfti(a: f32) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f32, i128, a);
+}
+
+test "import fixsfti" {
+ _ = @import("fixsfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixsfti_test.zig b/std/special/compiler_rt/fixsfti_test.zig
new file mode 100644
index 0000000000..32410e2dee
--- /dev/null
+++ b/std/special/compiler_rt/fixsfti_test.zig
@@ -0,0 +1,84 @@
+const __fixsfti = @import("fixsfti.zig").__fixsfti;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixsfti(a: f32, expected: i128) void {
+ const x = __fixsfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected));
+ testing.expect(x == expected);
+}
+
+test "fixsfti" {
+ //warn("\n");
+
+ test__fixsfti(-math.f32_max, math.minInt(i128));
+
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
+ test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
+
+ test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
+
+ test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);
+ test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixsfti(-0x1.000000p+31, -0x80000000);
+ test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);
+ test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixsfti(-2.01, -2);
+ test__fixsfti(-2.0, -2);
+ test__fixsfti(-1.99, -1);
+ test__fixsfti(-1.0, -1);
+ test__fixsfti(-0.99, 0);
+ test__fixsfti(-0.5, 0);
+ test__fixsfti(-math.f32_min, 0);
+ test__fixsfti(0.0, 0);
+ test__fixsfti(math.f32_min, 0);
+ test__fixsfti(0.5, 0);
+ test__fixsfti(0.99, 0);
+ test__fixsfti(1.0, 1);
+ test__fixsfti(1.5, 1);
+ test__fixsfti(1.99, 1);
+ test__fixsfti(2.0, 2);
+ test__fixsfti(2.01, 2);
+
+ test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixsfti(0x1.FFFFFFp+30, 0x80000000);
+ test__fixsfti(0x1.000000p+31, 0x80000000);
+
+ test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+ test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);
+
+ test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
+ test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);
+
+ test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
+ test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
+ test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixsfti(math.f32_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixtfdi.zig b/std/special/compiler_rt/fixtfdi.zig
new file mode 100644
index 0000000000..8d99231b74
--- /dev/null
+++ b/std/special/compiler_rt/fixtfdi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfdi(a: f128) i64 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i64, a);
+}
+
+test "import fixtfdi" {
+ _ = @import("fixtfdi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfdi_test.zig b/std/special/compiler_rt/fixtfdi_test.zig
new file mode 100644
index 0000000000..a31bcb7d6f
--- /dev/null
+++ b/std/special/compiler_rt/fixtfdi_test.zig
@@ -0,0 +1,76 @@
+const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixtfdi(a: f128, expected: i64) void {
+ const x = __fixtfdi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected));
+ testing.expect(x == expected);
+}
+
+test "fixtfdi" {
+ //warn("\n");
+
+ test__fixtfdi(-math.f128_max, math.minInt(i64));
+
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
+
+ test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
+
+ test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);
+ test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
+ test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
+
+ test__fixtfdi(-0x1.000000p+31, -0x80000000);
+ test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixtfdi(-2.01, -2);
+ test__fixtfdi(-2.0, -2);
+ test__fixtfdi(-1.99, -1);
+ test__fixtfdi(-1.0, -1);
+ test__fixtfdi(-0.99, 0);
+ test__fixtfdi(-0.5, 0);
+ test__fixtfdi(-math.f64_min, 0);
+ test__fixtfdi(0.0, 0);
+ test__fixtfdi(math.f64_min, 0);
+ test__fixtfdi(0.5, 0);
+ test__fixtfdi(0.99, 0);
+ test__fixtfdi(1.0, 1);
+ test__fixtfdi(1.5, 1);
+ test__fixtfdi(1.99, 1);
+ test__fixtfdi(2.0, 2);
+ test__fixtfdi(2.01, 2);
+
+ test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixtfdi(0x1.000000p+31, 0x80000000);
+
+ test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
+
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
+ test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
+
+ test__fixtfdi(math.f128_max, math.maxInt(i64));
+}
diff --git a/std/special/compiler_rt/fixtfsi.zig b/std/special/compiler_rt/fixtfsi.zig
new file mode 100644
index 0000000000..f3f83634b2
--- /dev/null
+++ b/std/special/compiler_rt/fixtfsi.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfsi(a: f128) i32 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i32, a);
+}
+
+test "import fixtfsi" {
+ _ = @import("fixtfsi_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfsi_test.zig b/std/special/compiler_rt/fixtfsi_test.zig
new file mode 100644
index 0000000000..7b37e4e09f
--- /dev/null
+++ b/std/special/compiler_rt/fixtfsi_test.zig
@@ -0,0 +1,76 @@
+const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixtfsi(a: f128, expected: i32) void {
+ const x = __fixtfsi(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected));
+ testing.expect(x == expected);
+}
+
+test "fixtfsi" {
+ //warn("\n");
+
+ test__fixtfsi(-math.f128_max, math.minInt(i32));
+
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
+
+ test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
+
+ test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);
+ test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
+
+ test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);
+
+ test__fixtfsi(-0x1.000000p+31, -0x80000000);
+ test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
+ test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
+ test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
+
+ test__fixtfsi(-2.01, -2);
+ test__fixtfsi(-2.0, -2);
+ test__fixtfsi(-1.99, -1);
+ test__fixtfsi(-1.0, -1);
+ test__fixtfsi(-0.99, 0);
+ test__fixtfsi(-0.5, 0);
+ test__fixtfsi(-math.f32_min, 0);
+ test__fixtfsi(0.0, 0);
+ test__fixtfsi(math.f32_min, 0);
+ test__fixtfsi(0.5, 0);
+ test__fixtfsi(0.99, 0);
+ test__fixtfsi(1.0, 1);
+ test__fixtfsi(1.5, 1);
+ test__fixtfsi(1.99, 1);
+ test__fixtfsi(2.0, 2);
+ test__fixtfsi(2.01, 2);
+
+ test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
+ test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
+ test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
+ test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
+ test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
+
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
+ test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
+
+ test__fixtfsi(math.f128_max, math.maxInt(i32));
+}
diff --git a/std/special/compiler_rt/fixtfti.zig b/std/special/compiler_rt/fixtfti.zig
new file mode 100644
index 0000000000..07d38f2c3b
--- /dev/null
+++ b/std/special/compiler_rt/fixtfti.zig
@@ -0,0 +1,11 @@
+const fixint = @import("fixint.zig").fixint;
+const builtin = @import("builtin");
+
+pub extern fn __fixtfti(a: f128) i128 {
+ @setRuntimeSafety(builtin.is_test);
+ return fixint(f128, i128, a);
+}
+
+test "import fixtfti" {
+ _ = @import("fixtfti_test.zig");
+}
diff --git a/std/special/compiler_rt/fixtfti_test.zig b/std/special/compiler_rt/fixtfti_test.zig
new file mode 100644
index 0000000000..be461a1c91
--- /dev/null
+++ b/std/special/compiler_rt/fixtfti_test.zig
@@ -0,0 +1,66 @@
+const __fixtfti = @import("fixtfti.zig").__fixtfti;
+const std = @import("std");
+const math = std.math;
+const testing = std.testing;
+const warn = std.debug.warn;
+
+fn test__fixtfti(a: f128, expected: i128) void {
+ const x = __fixtfti(a);
+ //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected));
+ testing.expect(x == expected);
+}
+
+test "fixtfti" {
+ //warn("\n");
+
+ test__fixtfti(-math.f128_max, math.minInt(i128));
+
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
+
+ test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
+
+ test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
+ test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
+ test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
+ test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
+
+ test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
+ test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
+
+ test__fixtfti(-2.01, -2);
+ test__fixtfti(-2.0, -2);
+ test__fixtfti(-1.99, -1);
+ test__fixtfti(-1.0, -1);
+ test__fixtfti(-0.99, 0);
+ test__fixtfti(-0.5, 0);
+ test__fixtfti(-math.f128_min, 0);
+ test__fixtfti(0.0, 0);
+ test__fixtfti(math.f128_min, 0);
+ test__fixtfti(0.5, 0);
+ test__fixtfti(0.99, 0);
+ test__fixtfti(1.0, 1);
+ test__fixtfti(1.5, 1);
+ test__fixtfti(1.99, 1);
+ test__fixtfti(2.0, 2);
+ test__fixtfti(2.01, 2);
+
+ test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
+ test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
+ test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
+ test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
+ test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
+
+ test__fixtfti(math.f128_max, math.maxInt(i128));
+}
diff --git a/std/special/compiler_rt/fixunsdfdi_test.zig b/std/special/compiler_rt/fixunsdfdi_test.zig
index e59d09f8de..67eeb70520 100644
--- a/std/special/compiler_rt/fixunsdfdi_test.zig
+++ b/std/special/compiler_rt/fixunsdfdi_test.zig
@@ -1,9 +1,9 @@
const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunsdfdi(a: f64, expected: u64) void {
const x = __fixunsdfdi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunsdfdi" {
diff --git a/std/special/compiler_rt/fixunsdfsi_test.zig b/std/special/compiler_rt/fixunsdfsi_test.zig
index db6e32e23d..c006473fb9 100644
--- a/std/special/compiler_rt/fixunsdfsi_test.zig
+++ b/std/special/compiler_rt/fixunsdfsi_test.zig
@@ -1,9 +1,9 @@
const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunsdfsi(a: f64, expected: u32) void {
const x = __fixunsdfsi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunsdfsi" {
diff --git a/std/special/compiler_rt/fixunsdfti_test.zig b/std/special/compiler_rt/fixunsdfti_test.zig
index 7f7b083d19..8241900692 100644
--- a/std/special/compiler_rt/fixunsdfti_test.zig
+++ b/std/special/compiler_rt/fixunsdfti_test.zig
@@ -1,9 +1,9 @@
const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunsdfti(a: f64, expected: u128) void {
const x = __fixunsdfti(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunsdfti" {
diff --git a/std/special/compiler_rt/fixunssfdi_test.zig b/std/special/compiler_rt/fixunssfdi_test.zig
index e4e6c1736d..e2089822d2 100644
--- a/std/special/compiler_rt/fixunssfdi_test.zig
+++ b/std/special/compiler_rt/fixunssfdi_test.zig
@@ -1,9 +1,9 @@
const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunssfdi(a: f32, expected: u64) void {
const x = __fixunssfdi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunssfdi" {
diff --git a/std/special/compiler_rt/fixunssfsi_test.zig b/std/special/compiler_rt/fixunssfsi_test.zig
index 614c648dfe..4aee84d2d2 100644
--- a/std/special/compiler_rt/fixunssfsi_test.zig
+++ b/std/special/compiler_rt/fixunssfsi_test.zig
@@ -1,9 +1,9 @@
const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunssfsi(a: f32, expected: u32) void {
const x = __fixunssfsi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunssfsi" {
diff --git a/std/special/compiler_rt/fixunssfti_test.zig b/std/special/compiler_rt/fixunssfti_test.zig
index 43ad527f53..4cb27cbb8a 100644
--- a/std/special/compiler_rt/fixunssfti_test.zig
+++ b/std/special/compiler_rt/fixunssfti_test.zig
@@ -1,9 +1,9 @@
const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunssfti(a: f32, expected: u128) void {
const x = __fixunssfti(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunssfti" {
diff --git a/std/special/compiler_rt/fixunstfdi_test.zig b/std/special/compiler_rt/fixunstfdi_test.zig
index 6b1b9b7bd2..0d47641c09 100644
--- a/std/special/compiler_rt/fixunstfdi_test.zig
+++ b/std/special/compiler_rt/fixunstfdi_test.zig
@@ -1,9 +1,9 @@
const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunstfdi(a: f128, expected: u64) void {
const x = __fixunstfdi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "fixunstfdi" {
diff --git a/std/special/compiler_rt/fixunstfsi_test.zig b/std/special/compiler_rt/fixunstfsi_test.zig
index f47fcb3c86..e709636912 100644
--- a/std/special/compiler_rt/fixunstfsi_test.zig
+++ b/std/special/compiler_rt/fixunstfsi_test.zig
@@ -1,9 +1,9 @@
const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunstfsi(a: f128, expected: u32) void {
const x = __fixunstfsi(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
diff --git a/std/special/compiler_rt/fixunstfti_test.zig b/std/special/compiler_rt/fixunstfti_test.zig
index 9128ac6c08..833e4779dd 100644
--- a/std/special/compiler_rt/fixunstfti_test.zig
+++ b/std/special/compiler_rt/fixunstfti_test.zig
@@ -1,9 +1,9 @@
const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__fixunstfti(a: f128, expected: u128) void {
const x = __fixunstfti(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
diff --git a/std/special/compiler_rt/floattidf_test.zig b/std/special/compiler_rt/floattidf_test.zig
index 25dc595052..4914342c31 100644
--- a/std/special/compiler_rt/floattidf_test.zig
+++ b/std/special/compiler_rt/floattidf_test.zig
@@ -1,9 +1,9 @@
const __floattidf = @import("floattidf.zig").__floattidf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floattidf(a: i128, expected: f64) void {
const x = __floattidf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floattidf" {
diff --git a/std/special/compiler_rt/floattisf_test.zig b/std/special/compiler_rt/floattisf_test.zig
index ecb8eac60a..a6aa115307 100644
--- a/std/special/compiler_rt/floattisf_test.zig
+++ b/std/special/compiler_rt/floattisf_test.zig
@@ -1,9 +1,9 @@
const __floattisf = @import("floattisf.zig").__floattisf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floattisf(a: i128, expected: f32) void {
const x = __floattisf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floattisf" {
diff --git a/std/special/compiler_rt/floattitf_test.zig b/std/special/compiler_rt/floattitf_test.zig
index da2ccc8b35..53e3e48bdb 100644
--- a/std/special/compiler_rt/floattitf_test.zig
+++ b/std/special/compiler_rt/floattitf_test.zig
@@ -1,9 +1,9 @@
const __floattitf = @import("floattitf.zig").__floattitf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floattitf(a: i128, expected: f128) void {
const x = __floattitf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floattitf" {
diff --git a/std/special/compiler_rt/floatunditf_test.zig b/std/special/compiler_rt/floatunditf_test.zig
index 8533c75070..5b4e195870 100644
--- a/std/special/compiler_rt/floatunditf_test.zig
+++ b/std/special/compiler_rt/floatunditf_test.zig
@@ -1,5 +1,4 @@
const __floatunditf = @import("floatunditf.zig").__floatunditf;
-const assert = @import("std").debug.assert;
fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void {
const x = __floatunditf(a);
diff --git a/std/special/compiler_rt/floatunsitf_test.zig b/std/special/compiler_rt/floatunsitf_test.zig
index 06f54cde03..52e4786903 100644
--- a/std/special/compiler_rt/floatunsitf_test.zig
+++ b/std/special/compiler_rt/floatunsitf_test.zig
@@ -1,5 +1,4 @@
const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
-const assert = @import("std").debug.assert;
fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void {
const x = __floatunsitf(a);
diff --git a/std/special/compiler_rt/floatuntidf_test.zig b/std/special/compiler_rt/floatuntidf_test.zig
index e2c79378e2..974f3e4be3 100644
--- a/std/special/compiler_rt/floatuntidf_test.zig
+++ b/std/special/compiler_rt/floatuntidf_test.zig
@@ -1,9 +1,9 @@
const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floatuntidf(a: u128, expected: f64) void {
const x = __floatuntidf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floatuntidf" {
diff --git a/std/special/compiler_rt/floatuntisf_test.zig b/std/special/compiler_rt/floatuntisf_test.zig
index 7f84c1f963..3a97807066 100644
--- a/std/special/compiler_rt/floatuntisf_test.zig
+++ b/std/special/compiler_rt/floatuntisf_test.zig
@@ -1,9 +1,9 @@
const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floatuntisf(a: u128, expected: f32) void {
const x = __floatuntisf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floatuntisf" {
diff --git a/std/special/compiler_rt/floatuntitf_test.zig b/std/special/compiler_rt/floatuntitf_test.zig
index 8e67fee108..09f3eabb3e 100644
--- a/std/special/compiler_rt/floatuntitf_test.zig
+++ b/std/special/compiler_rt/floatuntitf_test.zig
@@ -1,9 +1,9 @@
const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__floatuntitf(a: u128, expected: f128) void {
const x = __floatuntitf(a);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "floatuntitf" {
diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig
index b2add4e3fa..6715df1805 100644
--- a/std/special/compiler_rt/index.zig
+++ b/std/special/compiler_rt/index.zig
@@ -21,6 +21,9 @@ comptime {
@export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage);
+ @export("__addtf3", @import("addXf3.zig").__addtf3, linkage);
+ @export("__subtf3", @import("addXf3.zig").__subtf3, linkage);
+
@export("__floattitf", @import("floattitf.zig").__floattitf, linkage);
@export("__floattidf", @import("floattidf.zig").__floattidf, linkage);
@export("__floattisf", @import("floattisf.zig").__floattisf, linkage);
@@ -37,6 +40,7 @@ comptime {
@export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);
@export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);
+ @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage);
@export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);
@export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);
@@ -52,6 +56,16 @@ comptime {
@export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);
@export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);
+ @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage);
+ @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage);
+ @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage);
+ @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage);
+ @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage);
+ @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage);
+ @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage);
+ @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage);
+ @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage);
+
@export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);
@export("__udivsi3", __udivsi3, linkage);
@@ -100,6 +114,7 @@ comptime {
const std = @import("std");
const assert = std.debug.assert;
+const testing = std.testing;
const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
@@ -407,7 +422,7 @@ test "test_umoddi3" {
fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void {
const r = __umoddi3(a, b);
- assert(r == expected_r);
+ testing.expect(r == expected_r);
}
test "test_udivsi3" {
@@ -1081,5 +1096,5 @@ test "test_udivsi3" {
fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
const q: u32 = __udivsi3(a, b);
- assert(q == expected_q);
+ testing.expect(q == expected_q);
}
diff --git a/std/special/compiler_rt/muloti4_test.zig b/std/special/compiler_rt/muloti4_test.zig
index 6b3671323f..00144a8839 100644
--- a/std/special/compiler_rt/muloti4_test.zig
+++ b/std/special/compiler_rt/muloti4_test.zig
@@ -1,10 +1,10 @@
const __muloti4 = @import("muloti4.zig").__muloti4;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void {
var overflow: c_int = undefined;
const x = __muloti4(a, b, &overflow);
- assert(overflow == expected_overflow and (expected_overflow != 0 or x == expected));
+ testing.expect(overflow == expected_overflow and (expected_overflow != 0 or x == expected));
}
test "muloti4" {
diff --git a/std/special/compiler_rt/multi3_test.zig b/std/special/compiler_rt/multi3_test.zig
index 413ff20a79..92c580e20f 100644
--- a/std/special/compiler_rt/multi3_test.zig
+++ b/std/special/compiler_rt/multi3_test.zig
@@ -1,9 +1,9 @@
const __multi3 = @import("multi3.zig").__multi3;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__multi3(a: i128, b: i128, expected: i128) void {
const x = __multi3(a, b);
- assert(x == expected);
+ testing.expect(x == expected);
}
test "multi3" {
diff --git a/std/special/compiler_rt/truncXfYf2.zig b/std/special/compiler_rt/truncXfYf2.zig
index 5cb2f61568..b385090a93 100644
--- a/std/special/compiler_rt/truncXfYf2.zig
+++ b/std/special/compiler_rt/truncXfYf2.zig
@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {
return @bitCast(u16, truncXfYf2(f16, f32, a));
}
+pub extern fn __truncdfhf2(a: f64) u16 {
+ return @bitCast(u16, truncXfYf2(f16, f64, a));
+}
+
pub extern fn __trunctfsf2(a: f128) f32 {
return truncXfYf2(f32, f128, a);
}
diff --git a/std/special/compiler_rt/truncXfYf2_test.zig b/std/special/compiler_rt/truncXfYf2_test.zig
index c4bf2db733..429372c3f1 100644
--- a/std/special/compiler_rt/truncXfYf2_test.zig
+++ b/std/special/compiler_rt/truncXfYf2_test.zig
@@ -63,6 +63,74 @@ test "truncsfhf2" {
test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
}
+const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2;
+
+fn test__truncdfhf2(a: f64, expected: u16) void {
+ const rep = @bitCast(u16, __truncdfhf2(a));
+
+ if (rep == expected) {
+ return;
+ }
+ // test other possible NaN representation(signal NaN)
+ else if (expected == 0x7e00) {
+ if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) {
+ return;
+ }
+ }
+
+ @panic("__truncdfhf2 test failure");
+}
+
+fn test__truncdfhf2_raw(a: u64, expected: u16) void {
+ const actual = __truncdfhf2(@bitCast(f64, a));
+
+ if (actual == expected) {
+ return;
+ }
+
+ @panic("__truncdfhf2 test failure");
+}
+
+test "truncdfhf2" {
+ test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN
+ test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN
+
+ test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf
+ test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf
+
+ test__truncdfhf2(0.0, 0x0); // zero
+ test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero
+
+ test__truncdfhf2(3.1415926535, 0x4248);
+ test__truncdfhf2(-3.1415926535, 0xc248);
+
+ test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);
+ test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);
+ test__truncdfhf2(0x1.0p+0, 0x3c00);
+ test__truncdfhf2(0x1.0p-14, 0x0400);
+
+ // denormal
+ test__truncdfhf2(0x1.0p-20, 0x0010);
+ test__truncdfhf2(0x1.0p-24, 0x0001);
+ test__truncdfhf2(-0x1.0p-24, 0x8001);
+ test__truncdfhf2(0x1.5p-25, 0x0001);
+
+ // and back to zero
+ test__truncdfhf2(0x1.0p-25, 0x0000);
+ test__truncdfhf2(-0x1.0p-25, 0x8000);
+
+ // max (precise)
+ test__truncdfhf2(65504.0, 0x7bff);
+
+ // max (rounded)
+ test__truncdfhf2(65519.0, 0x7bff);
+
+ // max (to +inf)
+ test__truncdfhf2(65520.0, 0x7c00);
+ test__truncdfhf2(-65520.0, 0xfc00);
+ test__truncdfhf2(65536.0, 0x7c00);
+}
+
const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
fn test__trunctfsf2(a: f128, expected: u32) void {
diff --git a/std/special/compiler_rt/udivmoddi4_test.zig b/std/special/compiler_rt/udivmoddi4_test.zig
index 34b9dda1ea..5e6924f290 100644
--- a/std/special/compiler_rt/udivmoddi4_test.zig
+++ b/std/special/compiler_rt/udivmoddi4_test.zig
@@ -1,13 +1,13 @@
// Disable formatting to avoid unnecessary source repository bloat.
// zig fmt: off
const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void {
var r: u64 = undefined;
const q = __udivmoddi4(a, b, &r);
- assert(q == expected_q);
- assert(r == expected_r);
+ testing.expect(q == expected_q);
+ testing.expect(r == expected_r);
}
test "udivmoddi4" {
diff --git a/std/special/compiler_rt/udivmodti4_test.zig b/std/special/compiler_rt/udivmodti4_test.zig
index f6b370c26e..0c7880f346 100644
--- a/std/special/compiler_rt/udivmodti4_test.zig
+++ b/std/special/compiler_rt/udivmodti4_test.zig
@@ -1,13 +1,13 @@
// Disable formatting to avoid unnecessary source repository bloat.
// zig fmt: off
const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;
-const assert = @import("std").debug.assert;
+const testing = @import("std").testing;
fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void {
var r: u128 = undefined;
const q = __udivmodti4(a, b, &r);
- assert(q == expected_q);
- assert(r == expected_r);
+ testing.expect(q == expected_q);
+ testing.expect(r == expected_r);
}
test "udivmodti4" {
diff --git a/std/special/fmt_runner.zig b/std/special/fmt_runner.zig
new file mode 100644
index 0000000000..46ced0e136
--- /dev/null
+++ b/std/special/fmt_runner.zig
@@ -0,0 +1,260 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+const os = std.os;
+const io = std.io;
+const mem = std.mem;
+const Allocator = mem.Allocator;
+const ArrayList = std.ArrayList;
+const Buffer = std.Buffer;
+const ast = std.zig.ast;
+
+const arg = @import("fmt/arg.zig");
+const self_hosted_main = @import("fmt/main.zig");
+const Args = arg.Args;
+const Flag = arg.Flag;
+const errmsg = @import("fmt/errmsg.zig");
+
+var stderr_file: os.File = undefined;
+var stderr: *io.OutStream(os.File.WriteError) = undefined;
+var stdout: *io.OutStream(os.File.WriteError) = undefined;
+
+// This brings `zig fmt` to stage 1.
+pub fn main() !void {
+ // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
+ // one shot program. We don't need to waste time freeing memory and finding places to squish
+ // bytes into. So we free everything all at once at the very end.
+ var direct_allocator = std.heap.DirectAllocator.init();
+ var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
+ const allocator = &arena.allocator;
+
+ var stdout_file = try std.io.getStdOut();
+ var stdout_out_stream = stdout_file.outStream();
+ stdout = &stdout_out_stream.stream;
+
+ stderr_file = try std.io.getStdErr();
+ var stderr_out_stream = stderr_file.outStream();
+ stderr = &stderr_out_stream.stream;
+ const args = try std.os.argsAlloc(allocator);
+
+ var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args);
+ defer flags.deinit();
+
+ if (flags.present("help")) {
+ try stdout.write(self_hosted_main.usage_fmt);
+ os.exit(0);
+ }
+
+ const color = blk: {
+ if (flags.single("color")) |color_flag| {
+ if (mem.eql(u8, color_flag, "auto")) {
+ break :blk errmsg.Color.Auto;
+ } else if (mem.eql(u8, color_flag, "on")) {
+ break :blk errmsg.Color.On;
+ } else if (mem.eql(u8, color_flag, "off")) {
+ break :blk errmsg.Color.Off;
+ } else unreachable;
+ } else {
+ break :blk errmsg.Color.Auto;
+ }
+ };
+
+ if (flags.present("stdin")) {
+ if (flags.positionals.len != 0) {
+ try stderr.write("cannot use --stdin with positional arguments\n");
+ os.exit(1);
+ }
+
+ var stdin_file = try io.getStdIn();
+ var stdin = stdin_file.inStream();
+
+ const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
+ defer allocator.free(source_code);
+
+ var tree = std.zig.parse(allocator, source_code) catch |err| {
+ try stderr.print("error parsing stdin: {}\n", err);
+ os.exit(1);
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(allocator, parse_error, &tree, "", stderr_file, color);
+ }
+ if (tree.errors.len != 0) {
+ os.exit(1);
+ }
+ if (flags.present("check")) {
+ const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
+ const code = if (anything_changed) u8(1) else u8(0);
+ os.exit(code);
+ }
+
+ _ = try std.zig.render(allocator, stdout, &tree);
+ return;
+ }
+
+ if (flags.positionals.len == 0) {
+ try stderr.write("expected at least one source file argument\n");
+ os.exit(1);
+ }
+
+ var fmt = Fmt{
+ .seen = Fmt.SeenMap.init(allocator),
+ .any_error = false,
+ .color = color,
+ .allocator = allocator,
+ };
+
+ const check_mode = flags.present("check");
+
+ for (flags.positionals.toSliceConst()) |file_path| {
+ try fmtPath(&fmt, file_path, check_mode);
+ }
+ if (fmt.any_error) {
+ os.exit(1);
+ }
+}
+
+const FmtError = error{
+ SystemResources,
+ OperationAborted,
+ IoPending,
+ BrokenPipe,
+ Unexpected,
+ WouldBlock,
+ FileClosed,
+ DestinationAddressRequired,
+ DiskQuota,
+ FileTooBig,
+ InputOutput,
+ NoSpaceLeft,
+ AccessDenied,
+ OutOfMemory,
+ RenameAcrossMountPoints,
+ ReadOnlyFileSystem,
+ LinkQuotaExceeded,
+ FileBusy,
+} || os.File.OpenError;
+
+fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
+ const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
+ defer fmt.allocator.free(file_path);
+
+ if (try fmt.seen.put(file_path, {})) |_| return;
+
+ const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
+ error.IsDir, error.AccessDenied => {
+ // TODO make event based (and dir.next())
+ var dir = try std.os.Dir.open(fmt.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(fmt.allocator, [][]const u8{ file_path, entry.name });
+ try fmtPath(fmt, full_path, check_mode);
+ }
+ }
+ return;
+ },
+ else => {
+ // TODO lock stderr printing
+ try stderr.print("unable to open '{}': {}\n", file_path, err);
+ fmt.any_error = true;
+ return;
+ },
+ };
+ defer fmt.allocator.free(source_code);
+
+ var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
+ try stderr.print("error parsing file '{}': {}\n", file_path, err);
+ fmt.any_error = true;
+ return;
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
+ }
+ if (tree.errors.len != 0) {
+ fmt.any_error = true;
+ return;
+ }
+
+ if (check_mode) {
+ const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", file_path);
+ fmt.any_error = true;
+ }
+ } else {
+ // TODO make this evented
+ const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
+ defer baf.destroy();
+
+ const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", file_path);
+ try baf.finish();
+ }
+ }
+}
+
+const Fmt = struct {
+ seen: SeenMap,
+ any_error: bool,
+ color: errmsg.Color,
+ allocator: *mem.Allocator,
+
+ const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
+};
+
+fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
+ path: []const u8, file: os.File, color: errmsg.Color,) !void
+{
+ const color_on = switch (color) {
+ errmsg.Color.Auto => file.isTty(),
+ errmsg.Color.On => true,
+ errmsg.Color.Off => false,
+ };
+ const lok_token = parse_error.loc();
+ const span = errmsg.Span{
+ .first = lok_token,
+ .last = lok_token,
+ };
+
+ const first_token = tree.tokens.at(span.first);
+ const last_token = tree.tokens.at(span.last);
+ const start_loc = tree.tokenLocationPtr(0, first_token);
+ const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
+
+ var text_buf = try std.Buffer.initSize(allocator, 0);
+ var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
+ try parse_error.render(&tree.tokens, out_stream);
+ const text = text_buf.toOwnedSlice();
+
+ const stream = &file.outStream().stream;
+ if (!color_on) {
+ try stream.print(
+ "{}:{}:{}: error: {}\n",
+ path,
+ start_loc.line + 1,
+ start_loc.column + 1,
+ text,
+ );
+ return;
+ }
+
+ try stream.print(
+ "{}:{}:{}: error: {}\n{}\n",
+ path,
+ start_loc.line + 1,
+ start_loc.column + 1,
+ text,
+ tree.source[start_loc.line_start..start_loc.line_end],
+ );
+ try stream.writeByteNTimes(' ', start_loc.column);
+ try stream.writeByteNTimes('~', last_token.end - first_token.start);
+ try stream.write("\n");
+}
diff --git a/std/special/init-lib/src/main.zig b/std/special/init-lib/src/main.zig
index 27fdeb2030..747bb08573 100644
--- a/std/special/init-lib/src/main.zig
+++ b/std/special/init-lib/src/main.zig
@@ -1,10 +1,10 @@
const std = @import("std");
-const assertOrPanic = std.debug.assertOrPanic;
+const testing = std.testing;
export fn add(a: i32, b: i32) i32 {
return a + b;
}
test "basic add functionality" {
- assertOrPanic(add(3, 7) == 10);
+ testing.expect(add(3, 7) == 10);
}
diff --git a/std/special/panic.zig b/std/special/panic.zig
index ca1caea73c..bd3ad971e0 100644
--- a/std/special/panic.zig
+++ b/std/special/panic.zig
@@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
builtin.Os.freestanding, builtin.Os.zen => {
while (true) {}
},
+ builtin.Os.uefi => {
+ // TODO look into using the debug info and logging helpful messages
+ std.os.abort();
+ },
else => {
const first_trace_addr = @ptrToInt(@returnAddress());
std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
diff --git a/std/statically_initialized_mutex.zig b/std/statically_initialized_mutex.zig
new file mode 100644
index 0000000000..16bcd7adaf
--- /dev/null
+++ b/std/statically_initialized_mutex.zig
@@ -0,0 +1,111 @@
+const std = @import("index.zig");
+const builtin = @import("builtin");
+const AtomicOrder = builtin.AtomicOrder;
+const AtomicRmwOp = builtin.AtomicRmwOp;
+const assert = std.debug.assert;
+const expect = std.testing.expect;
+const windows = std.os.windows;
+
+/// Lock may be held only once. If the same thread
+/// tries to acquire the same mutex twice, it deadlocks.
+/// This type is intended to be initialized statically. If you don't
+/// require static initialization, use std.Mutex.
+/// On Windows, this mutex allocates resources when it is
+/// first used, and the resources cannot be freed.
+/// On Linux, this is an alias of std.Mutex.
+pub const StaticallyInitializedMutex = switch(builtin.os) {
+ builtin.Os.linux => std.Mutex,
+ builtin.Os.windows => struct {
+ lock: windows.CRITICAL_SECTION,
+ init_once: windows.RTL_RUN_ONCE,
+
+ pub const Held = struct {
+ mutex: *StaticallyInitializedMutex,
+
+ pub fn release(self: Held) void {
+ windows.LeaveCriticalSection(&self.mutex.lock);
+ }
+ };
+
+ pub fn init() StaticallyInitializedMutex {
+ return StaticallyInitializedMutex {
+ .lock = undefined,
+ .init_once = windows.INIT_ONCE_STATIC_INIT,
+ };
+ }
+
+ extern fn initCriticalSection(
+ InitOnce: *windows.RTL_RUN_ONCE,
+ Parameter: ?*c_void,
+ Context: ?*c_void,
+ ) windows.BOOL {
+ const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter));
+ windows.InitializeCriticalSection(lock);
+ return windows.TRUE;
+ }
+
+ /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better
+ /// implementation of a runtime initialized mutex, remove this function.
+ pub fn deinit(self: *StaticallyInitializedMutex) void {
+ assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
+ windows.DeleteCriticalSection(&self.lock);
+ }
+
+ pub fn acquire(self: *StaticallyInitializedMutex) Held {
+ assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
+ windows.EnterCriticalSection(&self.lock);
+ return Held { .mutex = self };
+ }
+ },
+ else => std.Mutex,
+};
+
+test "std.StaticallyInitializedMutex" {
+ const TestContext = struct {
+ data: i128,
+
+ const TestContext = @This();
+ const incr_count = 10000;
+
+ var mutex = StaticallyInitializedMutex.init();
+
+ fn worker(ctx: *TestContext) void {
+ var i: usize = 0;
+ while (i != TestContext.incr_count) : (i += 1) {
+ const held = mutex.acquire();
+ defer held.release();
+
+ ctx.data += 1;
+ }
+ }
+ };
+
+ var direct_allocator = std.heap.DirectAllocator.init();
+ defer direct_allocator.deinit();
+
+ var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
+ defer direct_allocator.allocator.free(plenty_of_memory);
+
+ var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
+ var a = &fixed_buffer_allocator.allocator;
+
+
+ var context = TestContext{
+ .data = 0,
+ };
+
+ if (builtin.single_threaded) {
+ TestContext.worker(&context);
+ expect(context.data == TestContext.incr_count);
+ } else {
+ const thread_count = 10;
+ var threads: [thread_count]*std.os.Thread = undefined;
+ for (threads) |*t| {
+ t.* = try std.os.spawnThread(&context, TestContext.worker);
+ }
+ for (threads) |t|
+ t.wait();
+
+ expect(context.data == thread_count * TestContext.incr_count);
+ }
+}
diff --git a/std/testing.zig b/std/testing.zig
new file mode 100644
index 0000000000..a47c5984a0
--- /dev/null
+++ b/std/testing.zig
@@ -0,0 +1,147 @@
+const builtin = @import("builtin");
+const TypeId = builtin.TypeId;
+const std = @import("index.zig");
+
+/// This function is intended to be used only in tests. It prints diagnostics to stderr
+/// and then aborts when actual_error_union is not expected_error.
+pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
+ // TODO remove the workaround here for https://github.com/ziglang/zig/issues/1936
+ if (actual_error_union) |actual_payload| {
+ // TODO remove workaround here for https://github.com/ziglang/zig/issues/557
+ if (@sizeOf(@typeOf(actual_payload)) == 0) {
+ std.debug.panic("expected error.{}, found {} value", @errorName(expected_error), @typeName(@typeOf(actual_payload)));
+ } else {
+ std.debug.panic("expected error.{}, found {}", @errorName(expected_error), actual_payload);
+ }
+ } else |actual_error| {
+ if (expected_error != actual_error) {
+ std.debug.panic("expected error.{}, found error.{}", @errorName(expected_error), @errorName(actual_error));
+ }
+ }
+}
+
+/// This function is intended to be used only in tests. When the two values are not
+/// equal, prints diagnostics to stderr to show exactly how they are not equal,
+/// then aborts.
+/// The types must match exactly.
+pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
+ switch (@typeInfo(@typeOf(actual))) {
+ TypeId.NoReturn,
+ TypeId.BoundFn,
+ TypeId.ArgTuple,
+ TypeId.Opaque,
+ => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),
+
+ TypeId.Undefined,
+ TypeId.Null,
+ TypeId.Void,
+ => return,
+
+ TypeId.Type,
+ TypeId.Bool,
+ TypeId.Int,
+ TypeId.Float,
+ TypeId.ComptimeFloat,
+ TypeId.ComptimeInt,
+ TypeId.Enum,
+ TypeId.Namespace,
+ TypeId.Fn,
+ TypeId.Promise,
+ TypeId.Vector,
+ TypeId.ErrorSet,
+ => {
+ if (actual != expected) {
+ std.debug.panic("expected {}, found {}", expected, actual);
+ }
+ },
+
+ TypeId.Pointer => |pointer| {
+ switch (pointer.size) {
+ builtin.TypeInfo.Pointer.Size.One,
+ builtin.TypeInfo.Pointer.Size.Many,
+ => {
+ if (actual != expected) {
+ std.debug.panic("expected {}, found {}", expected, actual);
+ }
+ },
+
+ builtin.TypeInfo.Pointer.Size.Slice => {
+ if (actual.ptr != expected.ptr) {
+ std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
+ }
+ if (actual.len != expected.len) {
+ std.debug.panic("expected slice len {}, found {}", expected.len, actual.len);
+ }
+ },
+ }
+ },
+
+ TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual),
+
+ TypeId.Struct => {
+ @compileError("TODO implement testing.expectEqual for structs");
+ },
+
+ TypeId.Union => |union_info| {
+ if (union_info.tag_type == null) {
+ @compileError("Unable to compare untagged union values");
+ }
+ @compileError("TODO implement testing.expectEqual for tagged unions");
+ },
+
+ TypeId.Optional => {
+ if (expected) |expected_payload| {
+ if (actual) |actual_payload| {
+ expectEqual(expected_payload, actual_payload);
+ } else {
+ std.debug.panic("expected {}, found null", expected_payload);
+ }
+ } else {
+ if (actual) |actual_payload| {
+ std.debug.panic("expected null, found {}", actual_payload);
+ }
+ }
+ },
+
+ TypeId.ErrorUnion => {
+ if (expected) |expected_payload| {
+ if (actual) |actual_payload| {
+ expectEqual(expected_payload, actual_payload);
+ } else |actual_err| {
+ std.debug.panic("expected {}, found {}", expected_payload, actual_err);
+ }
+ } else |expected_err| {
+ if (actual) |actual_payload| {
+ std.debug.panic("expected {}, found {}", expected_err, actual_payload);
+ } else |actual_err| {
+ expectEqual(expected_err, actual_err);
+ }
+ }
+ },
+ }
+}
+
+/// This function is intended to be used only in tests. When the two slices are not
+/// equal, prints diagnostics to stderr to show exactly how they are not equal,
+/// then aborts.
+pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) void {
+ // TODO better printing of the difference
+ // If the arrays are small enough we could print the whole thing
+ // If the child type is u8 and no weird bytes, we could print it as strings
+ // Even for the length difference, it would be useful to see the values of the slices probably.
+ if (expected.len != actual.len) {
+ std.debug.panic("slice lengths differ. expected {}, found {}", expected.len, actual.len);
+ }
+ var i: usize = 0;
+ while (i < expected.len) : (i += 1) {
+ if (expected[i] != actual[i]) {
+ std.debug.panic("index {} incorrect. expected {}, found {}", i, expected[i], actual[i]);
+ }
+ }
+}
+
+/// This function is intended to be used only in tests. When `ok` is false, the test fails.
+/// A message is printed to stderr and then abort is called.
+pub fn expect(ok: bool) void {
+ if (!ok) @panic("test failure");
+}
diff --git a/std/unicode.zig b/std/unicode.zig
index fcb748401f..fccdf513b9 100644
--- a/std/unicode.zig
+++ b/std/unicode.zig
@@ -1,7 +1,7 @@
const std = @import("./index.zig");
const builtin = @import("builtin");
-const debug = std.debug;
const assert = std.debug.assert;
+const testing = std.testing;
const mem = std.mem;
/// Returns how many bytes the UTF-8 representation would require
@@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 {
/// Returns: the number of bytes written to out.
pub fn utf8Encode(c: u32, out: []u8) !u3 {
const length = try utf8CodepointSequenceLength(c);
- debug.assert(out.len >= length);
+ assert(out.len >= length);
switch (length) {
// The pattern for each is the same
// - Increasing the initial shift by 6 each time
@@ -81,8 +81,8 @@ const Utf8Decode2Error = error{
Utf8OverlongEncoding,
};
pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 {
- debug.assert(bytes.len == 2);
- debug.assert(bytes[0] & 0b11100000 == 0b11000000);
+ assert(bytes.len == 2);
+ assert(bytes[0] & 0b11100000 == 0b11000000);
var value: u32 = bytes[0] & 0b00011111;
if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
@@ -100,8 +100,8 @@ const Utf8Decode3Error = error{
Utf8EncodesSurrogateHalf,
};
pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 {
- debug.assert(bytes.len == 3);
- debug.assert(bytes[0] & 0b11110000 == 0b11100000);
+ assert(bytes.len == 3);
+ assert(bytes[0] & 0b11110000 == 0b11100000);
var value: u32 = bytes[0] & 0b00001111;
if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
@@ -124,8 +124,8 @@ const Utf8Decode4Error = error{
Utf8CodepointTooLarge,
};
pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 {
- debug.assert(bytes.len == 4);
- debug.assert(bytes[0] & 0b11111000 == 0b11110000);
+ assert(bytes.len == 4);
+ assert(bytes[0] & 0b11111000 == 0b11110000);
var value: u32 = bytes[0] & 0b00000111;
if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
assert(it.i <= it.bytes.len);
if (it.i == it.bytes.len) return null;
- const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
+ const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
if (c0 & ~u32(0x03ff) == 0xd800) {
// surrogate pair
it.i += 2;
if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
- const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);
+ const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
it.i += 2;
return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
@@ -274,23 +274,23 @@ test "utf8 encode" {
fn testUtf8Encode() !void {
// A few taken from wikipedia a few taken elsewhere
var array: [4]u8 = undefined;
- debug.assert((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);
- debug.assert(array[0] == 0b11100010);
- debug.assert(array[1] == 0b10000010);
- debug.assert(array[2] == 0b10101100);
+ testing.expect((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);
+ testing.expect(array[0] == 0b11100010);
+ testing.expect(array[1] == 0b10000010);
+ testing.expect(array[2] == 0b10101100);
- debug.assert((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);
- debug.assert(array[0] == 0b00100100);
+ testing.expect((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);
+ testing.expect(array[0] == 0b00100100);
- debug.assert((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);
- debug.assert(array[0] == 0b11000010);
- debug.assert(array[1] == 0b10100010);
+ testing.expect((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);
+ testing.expect(array[0] == 0b11000010);
+ testing.expect(array[1] == 0b10100010);
- debug.assert((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);
- debug.assert(array[0] == 0b11110000);
- debug.assert(array[1] == 0b10010000);
- debug.assert(array[2] == 0b10001101);
- debug.assert(array[3] == 0b10001000);
+ testing.expect((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);
+ testing.expect(array[0] == 0b11110000);
+ testing.expect(array[1] == 0b10010000);
+ testing.expect(array[2] == 0b10001101);
+ testing.expect(array[3] == 0b10001000);
}
test "utf8 encode error" {
@@ -306,11 +306,7 @@ fn testUtf8EncodeError() void {
}
fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void {
- if (utf8Encode(codePoint, array)) |_| {
- unreachable;
- } else |err| {
- debug.assert(err == expectedErr);
- }
+ testing.expectError(expectedErr, utf8Encode(codePoint, array));
}
test "utf8 iterator on ascii" {
@@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void {
const s = Utf8View.initComptime("abc");
var it1 = s.iterator();
- debug.assert(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
- debug.assert(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
- debug.assert(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
- debug.assert(it1.nextCodepointSlice() == null);
+ testing.expect(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
+ testing.expect(it1.nextCodepointSlice() == null);
var it2 = s.iterator();
- debug.assert(it2.nextCodepoint().? == 'a');
- debug.assert(it2.nextCodepoint().? == 'b');
- debug.assert(it2.nextCodepoint().? == 'c');
- debug.assert(it2.nextCodepoint() == null);
+ testing.expect(it2.nextCodepoint().? == 'a');
+ testing.expect(it2.nextCodepoint().? == 'b');
+ testing.expect(it2.nextCodepoint().? == 'c');
+ testing.expect(it2.nextCodepoint() == null);
}
test "utf8 view bad" {
@@ -340,12 +336,7 @@ test "utf8 view bad" {
fn testUtf8ViewBad() void {
// Compile-time error.
// const s3 = Utf8View.initComptime("\xfe\xf2");
- const s = Utf8View.init("hel\xadlo");
- if (s) |_| {
- unreachable;
- } else |err| {
- debug.assert(err == error.InvalidUtf8);
- }
+ testing.expectError(error.InvalidUtf8, Utf8View.init("hel\xadlo"));
}
test "utf8 view ok" {
@@ -356,16 +347,16 @@ fn testUtf8ViewOk() void {
const s = Utf8View.initComptime("東京市");
var it1 = s.iterator();
- debug.assert(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
- debug.assert(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
- debug.assert(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
- debug.assert(it1.nextCodepointSlice() == null);
+ testing.expect(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
+ testing.expect(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
+ testing.expect(it1.nextCodepointSlice() == null);
var it2 = s.iterator();
- debug.assert(it2.nextCodepoint().? == 0x6771);
- debug.assert(it2.nextCodepoint().? == 0x4eac);
- debug.assert(it2.nextCodepoint().? == 0x5e02);
- debug.assert(it2.nextCodepoint() == null);
+ testing.expect(it2.nextCodepoint().? == 0x6771);
+ testing.expect(it2.nextCodepoint().? == 0x4eac);
+ testing.expect(it2.nextCodepoint().? == 0x5e02);
+ testing.expect(it2.nextCodepoint() == null);
}
test "bad utf8 slice" {
@@ -373,10 +364,10 @@ test "bad utf8 slice" {
testBadUtf8Slice();
}
fn testBadUtf8Slice() void {
- debug.assert(utf8ValidateSlice("abc"));
- debug.assert(!utf8ValidateSlice("abc\xc0"));
- debug.assert(!utf8ValidateSlice("abc\xc0abc"));
- debug.assert(utf8ValidateSlice("abc\xdf\xbf"));
+ testing.expect(utf8ValidateSlice("abc"));
+ testing.expect(!utf8ValidateSlice("abc\xc0"));
+ testing.expect(!utf8ValidateSlice("abc\xc0abc"));
+ testing.expect(utf8ValidateSlice("abc\xdf\xbf"));
}
test "valid utf8" {
@@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void {
}
fn testError(bytes: []const u8, expected_err: anyerror) void {
- if (testDecode(bytes)) |_| {
- unreachable;
- } else |err| {
- debug.assert(err == expected_err);
- }
+ testing.expectError(expected_err, testDecode(bytes));
}
fn testValid(bytes: []const u8, expected_codepoint: u32) void {
- debug.assert((testDecode(bytes) catch unreachable) == expected_codepoint);
+ testing.expect((testDecode(bytes) catch unreachable) == expected_codepoint);
}
fn testDecode(bytes: []const u8) !u32 {
const length = try utf8ByteSequenceLength(bytes[0]);
if (bytes.len < length) return error.UnexpectedEof;
- debug.assert(bytes.len == length);
+ testing.expect(bytes.len == length);
return utf8Decode(bytes);
}
@@ -510,48 +497,48 @@ test "utf16leToUtf8" {
const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
{
- mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "Aa"));
+ testing.expect(mem.eql(u8, utf8, "Aa"));
}
{
- mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
+ testing.expect(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
}
{
// the values just outside the surrogate half range
- mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
+ testing.expect(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
}
{
// smallest surrogate pair
- mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
+ testing.expect(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
}
{
// largest surrogate pair
- mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
+ testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
}
{
- mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
- mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
- assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
+ testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
}
}
@@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
while (it.nextCodepoint()) |codepoint| {
if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
// TODO surrogate pairs
- mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little);
+ mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint));
end_index += 2;
}
return end_index / 2;
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index bb2099fb75..ea32634566 100644
--- a/std/zig/ast.zig
+++ b/std/zig/ast.zig
@@ -1,5 +1,6 @@
const std = @import("../index.zig");
const assert = std.debug.assert;
+const testing = std.testing;
const SegmentedList = std.SegmentedList;
const mem = std.mem;
const Token = std.zig.Token;
@@ -109,6 +110,7 @@ pub const Tree = struct {
pub const Error = union(enum) {
InvalidToken: InvalidToken,
ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,
+ ExpectedVarDecl: ExpectedVarDecl,
ExpectedAggregateKw: ExpectedAggregateKw,
UnattachedDocComment: UnattachedDocComment,
ExpectedEqOrSemi: ExpectedEqOrSemi,
@@ -132,6 +134,7 @@ pub const Error = union(enum) {
// TODO https://github.com/ziglang/zig/issues/683
@TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
+ @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
@TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
@TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
@@ -157,6 +160,7 @@ pub const Error = union(enum) {
// TODO https://github.com/ziglang/zig/issues/683
@TagType(Error).InvalidToken => |x| return x.token,
@TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
+ @TagType(Error).ExpectedVarDecl => |x| return x.token,
@TagType(Error).ExpectedAggregateKw => |x| return x.token,
@TagType(Error).UnattachedDocComment => |x| return x.token,
@TagType(Error).ExpectedEqOrSemi => |x| return x.token,
@@ -179,6 +183,7 @@ pub const Error = union(enum) {
pub const InvalidToken = SingleTokenError("Invalid token {}");
pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
+ pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");
pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
@@ -495,6 +500,7 @@ pub const Node = struct {
base: Node,
doc_comments: ?*DocComment,
visib_token: ?TokenIndex,
+ thread_local_token: ?TokenIndex,
name_token: TokenIndex,
eq_token: TokenIndex,
mut_token: TokenIndex,
@@ -535,6 +541,7 @@ pub const Node = struct {
pub fn firstToken(self: *const VarDecl) TokenIndex {
if (self.visib_token) |visib_token| return visib_token;
+ if (self.thread_local_token) |thread_local_token| return thread_local_token;
if (self.comptime_token) |comptime_token| return comptime_token;
if (self.extern_export_token) |extern_export_token| return extern_export_token;
assert(self.lib_name == null);
@@ -2224,5 +2231,5 @@ test "iterate" {
.shebang = null,
};
var base = &root.base;
- assert(base.iterate(0) == null);
+ testing.expect(base.iterate(0) == null);
}
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index a216484d7d..867dd11592 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
defer stack.deinit();
const arena = &tree_arena.allocator;
- const root_node = try arena.create(ast.Node.Root{
+ const root_node = try arena.create(ast.Node.Root);
+ root_node.* = ast.Node.Root{
.base = ast.Node{ .id = ast.Node.Id.Root },
.decls = ast.Node.Root.DeclList.init(arena),
.doc_comments = null,
.shebang = null,
// initialized when we get the eof token
.eof_token = undefined,
- });
+ };
var tree = ast.Tree{
.source = source,
@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
Token.Id.Keyword_test => {
stack.append(State.TopLevel) catch unreachable;
- const block = try arena.create(ast.Node.Block{
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = null,
.lbrace = undefined,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
- const test_node = try arena.create(ast.Node.TestDecl{
+ };
+ const test_node = try arena.create(ast.Node.TestDecl);
+ test_node.* = ast.Node.TestDecl{
.base = ast.Node{ .id = ast.Node.Id.TestDecl },
.doc_comments = comments,
.test_token = token_index,
.name = undefined,
.body_node = &block.base,
- });
+ };
try root_node.decls.push(&test_node.base);
try stack.append(State{ .Block = block });
try stack.append(State{
@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_comptime => {
- const block = try arena.create(ast.Node.Block{
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = null,
.lbrace = undefined,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
- const node = try arena.create(ast.Node.Comptime{
+ };
+ const node = try arena.create(ast.Node.Comptime);
+ node.* = ast.Node.Comptime{
.base = ast.Node{ .id = ast.Node.Id.Comptime },
.comptime_token = token_index,
.expr = &block.base,
.doc_comments = comments,
- });
+ };
try root_node.decls.push(&node.base);
stack.append(State.TopLevel) catch unreachable;
@@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}) catch unreachable;
continue;
},
+ State.ThreadLocal => |ctx| {
+ const token = nextToken(&tok_it, &tree);
+ const token_index = token.index;
+ const token_ptr = token.ptr;
+ switch (token_ptr.id) {
+ Token.Id.Keyword_var, Token.Id.Keyword_const => {
+ try stack.append(State{
+ .VarDecl = VarDeclCtx{
+ .comments = ctx.comments,
+ .visib_token = ctx.visib_token,
+ .thread_local_token = ctx.thread_local_token,
+ .lib_name = ctx.lib_name,
+ .comptime_token = ctx.comptime_token,
+ .extern_export_token = ctx.extern_export_token,
+ .mut_token = token_index,
+ .list = ctx.list,
+ },
+ });
+ continue;
+ },
+ else => {
+ ((try tree.errors.addOne())).* = Error{ .ExpectedVarDecl = Error.ExpectedVarDecl{ .token = token_index } };
+ return tree;
+ },
+ }
+ },
State.TopLevelDecl => |ctx| {
const token = nextToken(&tok_it, &tree);
const token_index = token.index;
@@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- const node = try arena.create(ast.Node.Use{
+ const node = try arena.create(ast.Node.Use);
+ node.* = ast.Node.Use{
.base = ast.Node{ .id = ast.Node.Id.Use },
.use_token = token_index,
.visib_token = ctx.visib_token,
.expr = undefined,
.semicolon_token = undefined,
.doc_comments = ctx.comments,
- });
+ };
try ctx.decls.push(&node.base);
stack.append(State{
@@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
continue;
},
+ Token.Id.Keyword_threadlocal => {
+ if (ctx.extern_export_inline_token) |annotated_token| {
+ if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
+ ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } };
+ return tree;
+ }
+ }
+
+ try stack.append(State{
+ .ThreadLocal = VarDeclCtx{
+ .comments = ctx.comments,
+ .visib_token = ctx.visib_token,
+ .thread_local_token = token_index,
+ .lib_name = ctx.lib_name,
+ .comptime_token = null,
+ .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
+ .mut_token = undefined,
+ .list = ctx.decls,
+ },
+ });
+ continue;
+ },
Token.Id.Keyword_var, Token.Id.Keyword_const => {
if (ctx.extern_export_inline_token) |annotated_token| {
if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
@@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.VarDecl = VarDeclCtx{
.comments = ctx.comments,
.visib_token = ctx.visib_token,
+ .thread_local_token = null,
.lib_name = ctx.lib_name,
.comptime_token = null,
.extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
@@ -276,7 +331,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {
- const fn_proto = try arena.create(ast.Node.FnProto{
+ const fn_proto = try arena.create(ast.Node.FnProto);
+ fn_proto.* = ast.Node.FnProto{
.base = ast.Node{ .id = ast.Node.Id.FnProto },
.doc_comments = ctx.comments,
.visib_token = ctx.visib_token,
@@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.lib_name = ctx.lib_name,
.align_expr = null,
.section_expr = null,
- });
+ };
try ctx.decls.push(&fn_proto.base);
stack.append(State{ .FnDef = fn_proto }) catch unreachable;
try stack.append(State{ .FnProto = fn_proto });
@@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_async => {
- const async_node = try arena.create(ast.Node.AsyncAttribute{
+ const async_node = try arena.create(ast.Node.AsyncAttribute);
+ async_node.* = ast.Node.AsyncAttribute{
.base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
.async_token = token_index,
.allocator_type = null,
.rangle_bracket = null,
- });
+ };
fn_proto.async_attr = async_node;
try stack.append(State{
@@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.TopLevelExternOrField => |ctx| {
if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {
- const node = try arena.create(ast.Node.StructField{
+ const node = try arena.create(ast.Node.StructField);
+ node.* = ast.Node.StructField{
.base = ast.Node{ .id = ast.Node.Id.StructField },
.doc_comments = ctx.comments,
.visib_token = ctx.visib_token,
.name_token = identifier,
.type_expr = undefined,
- });
+ };
const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
node_ptr.* = &node.base;
@@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token = nextToken(&tok_it, &tree);
const token_index = token.index;
const token_ptr = token.ptr;
- const node = try arena.create(ast.Node.ContainerDecl{
+ const node = try arena.create(ast.Node.ContainerDecl);
+ node.* = ast.Node.ContainerDecl{
.base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
.layout_token = ctx.layout_token,
.kind_token = switch (token_ptr.id) {
@@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
.lbrace_token = undefined,
.rbrace_token = undefined,
- });
+ };
ctx.opt_ctx.store(&node.base);
stack.append(State{ .ContainerDecl = node }) catch unreachable;
@@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
Token.Id.Identifier => {
switch (tree.tokens.at(container_decl.kind_token).id) {
Token.Id.Keyword_struct => {
- const node = try arena.create(ast.Node.StructField{
+ const node = try arena.create(ast.Node.StructField);
+ node.* = ast.Node.StructField{
.base = ast.Node{ .id = ast.Node.Id.StructField },
.doc_comments = comments,
.visib_token = null,
.name_token = token_index,
.type_expr = undefined,
- });
+ };
const node_ptr = try container_decl.fields_and_decls.addOne();
node_ptr.* = &node.base;
@@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_union => {
- const node = try arena.create(ast.Node.UnionTag{
+ const node = try arena.create(ast.Node.UnionTag);
+ node.* = ast.Node.UnionTag{
.base = ast.Node{ .id = ast.Node.Id.UnionTag },
.name_token = token_index,
.type_expr = null,
.value_expr = null,
.doc_comments = comments,
- });
+ };
try container_decl.fields_and_decls.push(&node.base);
try stack.append(State{
@@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_enum => {
- const node = try arena.create(ast.Node.EnumTag{
+ const node = try arena.create(ast.Node.EnumTag);
+ node.* = ast.Node.EnumTag{
.base = ast.Node{ .id = ast.Node.Id.EnumTag },
.name_token = token_index,
.value = null,
.doc_comments = comments,
- });
+ };
try container_decl.fields_and_decls.push(&node.base);
try stack.append(State{
@@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.VarDecl => |ctx| {
- const var_decl = try arena.create(ast.Node.VarDecl{
+ const var_decl = try arena.create(ast.Node.VarDecl);
+ var_decl.* = ast.Node.VarDecl{
.base = ast.Node{ .id = ast.Node.Id.VarDecl },
.doc_comments = ctx.comments,
.visib_token = ctx.visib_token,
+ .thread_local_token = ctx.thread_local_token,
.mut_token = ctx.mut_token,
.comptime_token = ctx.comptime_token,
.extern_export_token = ctx.extern_export_token,
@@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.name_token = undefined,
.eq_token = undefined,
.semicolon_token = undefined,
- });
+ };
try ctx.list.push(&var_decl.base);
try stack.append(State{ .VarDeclAlign = var_decl });
@@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_ptr = token.ptr;
switch (token_ptr.id) {
Token.Id.LBrace => {
- const block = try arena.create(ast.Node.Block{
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = null,
.lbrace = token_index,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
+ };
fn_proto.body_node = &block.base;
stack.append(State{ .Block = block }) catch unreachable;
continue;
@@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
// TODO: this is a special case. Remove this when #760 is fixed
if (token_ptr.id == Token.Id.Keyword_anyerror) {
if (tok_it.peek().?.id == Token.Id.LBrace) {
- const error_type_node = try arena.create(ast.Node.ErrorType{
+ const error_type_node = try arena.create(ast.Node.ErrorType);
+ error_type_node.* = ast.Node.ErrorType{
.base = ast.Node{ .id = ast.Node.Id.ErrorType },
.token = token_index,
- });
+ };
fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
continue;
}
@@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
continue;
}
- const param_decl = try arena.create(ast.Node.ParamDecl{
+ const param_decl = try arena.create(ast.Node.ParamDecl);
+ param_decl.* = ast.Node.ParamDecl{
.base = ast.Node{ .id = ast.Node.Id.ParamDecl },
.comptime_token = null,
.noalias_token = null,
.name_token = null,
.type_node = undefined,
.var_args_token = null,
- });
+ };
try fn_proto.params.push(¶m_decl.base);
stack.append(State{
@@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_ptr = token.ptr;
switch (token_ptr.id) {
Token.Id.LBrace => {
- const block = try arena.create(ast.Node.Block{
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = ctx.label,
.lbrace = token_index,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
+ };
ctx.opt_ctx.store(&block.base);
stack.append(State{ .Block = block }) catch unreachable;
continue;
@@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
},
State.While => |ctx| {
- const node = try arena.create(ast.Node.While{
+ const node = try arena.create(ast.Node.While);
+ node.* = ast.Node.While{
.base = ast.Node{ .id = ast.Node.Id.While },
.label = ctx.label,
.inline_token = ctx.inline_token,
@@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.continue_expr = null,
.body = undefined,
.@"else" = null,
- });
+ };
ctx.opt_ctx.store(&node.base);
stack.append(State{ .Else = &node.@"else" }) catch unreachable;
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
@@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
State.For => |ctx| {
- const node = try arena.create(ast.Node.For{
+ const node = try arena.create(ast.Node.For);
+ node.* = ast.Node.For{
.base = ast.Node{ .id = ast.Node.Id.For },
.label = ctx.label,
.inline_token = ctx.inline_token,
@@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.payload = null,
.body = undefined,
.@"else" = null,
- });
+ };
ctx.opt_ctx.store(&node.base);
stack.append(State{ .Else = &node.@"else" }) catch unreachable;
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
@@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.Else => |dest| {
if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
- const node = try arena.create(ast.Node.Else{
+ const node = try arena.create(ast.Node.Else);
+ node.* = ast.Node.Else{
.base = ast.Node{ .id = ast.Node.Id.Else },
.else_token = else_token,
.payload = null,
.body = undefined,
- });
+ };
dest.* = node;
stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;
@@ -1073,6 +1144,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.VarDecl = VarDeclCtx{
.comments = null,
.visib_token = null,
+ .thread_local_token = null,
.comptime_token = null,
.extern_export_token = null,
.lib_name = null,
@@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
- const node = try arena.create(ast.Node.Defer{
+ const node = try arena.create(ast.Node.Defer);
+ node.* = ast.Node.Defer{
.base = ast.Node{ .id = ast.Node.Id.Defer },
.defer_token = token_index,
.expr = undefined,
- });
+ };
const node_ptr = try block.statements.addOne();
node_ptr.* = &node.base;
@@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.LBrace => {
- const inner_block = try arena.create(ast.Node.Block{
+ const inner_block = try arena.create(ast.Node.Block);
+ inner_block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = null,
.lbrace = token_index,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
+ };
try block.statements.push(&inner_block.base);
stack.append(State{ .Block = inner_block }) catch unreachable;
@@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.VarDecl = VarDeclCtx{
.comments = null,
.visib_token = null,
+ .thread_local_token = null,
.comptime_token = ctx.comptime_token,
.extern_export_token = null,
.lib_name = null,
@@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.AsmOutput{
+ const node = try arena.create(ast.Node.AsmOutput);
+ node.* = ast.Node.AsmOutput{
.base = ast.Node{ .id = ast.Node.Id.AsmOutput },
.lbracket = lbracket_index,
.symbolic_name = undefined,
.constraint = undefined,
.kind = undefined,
.rparen = undefined,
- });
+ };
try items.push(node);
stack.append(State{ .AsmOutputItems = items }) catch unreachable;
@@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.AsmInput{
+ const node = try arena.create(ast.Node.AsmInput);
+ node.* = ast.Node.AsmInput{
.base = ast.Node{ .id = ast.Node.Id.AsmInput },
.lbracket = lbracket_index,
.symbolic_name = undefined,
.constraint = undefined,
.expr = undefined,
.rparen = undefined,
- });
+ };
try items.push(node);
stack.append(State{ .AsmInputItems = items }) catch unreachable;
@@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.FieldInitializer{
+ const node = try arena.create(ast.Node.FieldInitializer);
+ node.* = ast.Node.FieldInitializer{
.base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
.period_token = undefined,
.name_token = undefined,
.expr = undefined,
- });
+ };
try list_state.list.push(&node.base);
stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
@@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}
const comments = try eatDocComments(arena, &tok_it, &tree);
- const node = try arena.create(ast.Node.SwitchCase{
+ const node = try arena.create(ast.Node.SwitchCase);
+ node.* = ast.Node.SwitchCase{
.base = ast.Node{ .id = ast.Node.Id.SwitchCase },
.items = ast.Node.SwitchCase.ItemList.init(arena),
.payload = null,
.expr = undefined,
.arrow_token = undefined,
- });
+ };
try list_state.list.push(&node.base);
try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
@@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (token_ptr.id == Token.Id.Keyword_else) {
- const else_node = try arena.create(ast.Node.SwitchElse{
+ const else_node = try arena.create(ast.Node.SwitchElse);
+ else_node.* = ast.Node.SwitchElse{
.base = ast.Node{ .id = ast.Node.Id.SwitchElse },
.token = token_index,
- });
+ };
try switch_case.items.push(&else_node.base);
try stack.append(State{
@@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.ExternType => |ctx| {
if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {
- const fn_proto = try arena.create(ast.Node.FnProto{
+ const fn_proto = try arena.create(ast.Node.FnProto);
+ fn_proto.* = ast.Node.FnProto{
.base = ast.Node{ .id = ast.Node.Id.FnProto },
.doc_comments = ctx.comments,
.visib_token = null,
@@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.lib_name = null,
.align_expr = null,
.section_expr = null,
- });
+ };
ctx.opt_ctx.store(&fn_proto.base);
stack.append(State{ .FnProto = fn_proto }) catch unreachable;
continue;
@@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.Payload{
+ const node = try arena.create(ast.Node.Payload);
+ node.* = ast.Node.Payload{
.base = ast.Node{ .id = ast.Node.Id.Payload },
.lpipe = token_index,
.error_symbol = undefined,
.rpipe = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{
@@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.PointerPayload{
+ const node = try arena.create(ast.Node.PointerPayload);
+ node.* = ast.Node.PointerPayload{
.base = ast.Node{ .id = ast.Node.Id.PointerPayload },
.lpipe = token_index,
.ptr_token = null,
.value_symbol = undefined,
.rpipe = undefined,
- });
+ };
opt_ctx.store(&node.base);
try stack.append(State{
@@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.PointerIndexPayload{
+ const node = try arena.create(ast.Node.PointerIndexPayload);
+ node.* = ast.Node.PointerIndexPayload{
.base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
.lpipe = token_index,
.ptr_token = null,
.value_symbol = undefined,
.index_symbol = null,
.rpipe = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{
@@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_ptr = token.ptr;
switch (token_ptr.id) {
Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
- const node = try arena.create(ast.Node.ControlFlowExpression{
+ const node = try arena.create(ast.Node.ControlFlowExpression);
+ node.* = ast.Node.ControlFlowExpression{
.base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
.ltoken = token_index,
.kind = undefined,
.rhs = null,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;
@@ -1853,7 +1938,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
- const node = try arena.create(ast.Node.PrefixOp{
+ const node = try arena.create(ast.Node.PrefixOp);
+ node.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = ast.Node.Id.PrefixOp },
.op_token = token_index,
.op = switch (token_ptr.id) {
@@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
else => unreachable,
},
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
@@ -1887,13 +1973,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = ellipsis3,
.op = ast.Node.InfixOp.Op.Range,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
continue;
@@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = ass_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
@@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = unwrap_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
@@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = or_token,
.op = ast.Node.InfixOp.Op.BoolOr,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = and_token,
.op = ast.Node.InfixOp.Op.BoolAnd,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToComparison(token_ptr.id)) |comp_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = comp_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = pipe,
.op = ast.Node.InfixOp.Op.BitOr,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = caret,
.op = ast.Node.InfixOp.Op.BitXor,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = ampersand,
.op = ast.Node.InfixOp.Op.BitAnd,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = bitshift_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToAddition(token_ptr.id)) |add_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = add_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = mult_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
@@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (tok_it.peek().?.id == Token.Id.Period) {
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
.rtoken = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
@@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
.rtoken = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .IfToken = Token.Id.LBrace });
@@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const lhs = opt_ctx.get() orelse continue;
if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = bang,
.op = ast.Node.InfixOp.Op.ErrorUnion,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
@@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_index = token.index;
const token_ptr = token.ptr;
if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
- var node = try arena.create(ast.Node.PrefixOp{
+ var node = try arena.create(ast.Node.PrefixOp);
+ node.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = ast.Node.Id.PrefixOp },
.op_token = token_index,
.op = prefix_id,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
// Treat '**' token as two pointer types
if (token_ptr.id == Token.Id.AsteriskAsterisk) {
- const child = try arena.create(ast.Node.PrefixOp{
+ const child = try arena.create(ast.Node.PrefixOp);
+ child.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = ast.Node.Id.PrefixOp },
.op_token = token_index,
.op = prefix_id,
.rhs = undefined,
- });
+ };
node.rhs = &child.base;
node = child;
}
@@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.SuffixOpExpressionBegin => |opt_ctx| {
if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
- const async_node = try arena.create(ast.Node.AsyncAttribute{
+ const async_node = try arena.create(ast.Node.AsyncAttribute);
+ async_node.* = ast.Node.AsyncAttribute{
.base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
.async_token = async_token,
.allocator_type = null,
.rangle_bracket = null,
- });
+ };
stack.append(State{
.AsyncEnd = AsyncEndCtx{
.ctx = opt_ctx,
@@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
const token_ptr = token.ptr;
switch (token_ptr.id) {
Token.Id.LParen => {
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op{
@@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
},
.rtoken = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
@@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.LBracket => {
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
.rtoken = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
@@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
Token.Id.Period => {
if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op.Deref,
.rtoken = asterisk_token,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
continue;
}
if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {
- const node = try arena.create(ast.Node.SuffixOp{
+ const node = try arena.create(ast.Node.SuffixOp);
+ node.* = ast.Node.SuffixOp{
.base = ast.Node{ .id = ast.Node.Id.SuffixOp },
.lhs = lhs,
.op = ast.Node.SuffixOp.Op.UnwrapOptional,
.rtoken = question_token,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
continue;
}
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = lhs,
.op_token = token_index,
.op = ast.Node.InfixOp.Op.Period,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
@@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_promise => {
- const node = try arena.create(ast.Node.PromiseType{
+ const node = try arena.create(ast.Node.PromiseType);
+ node.* = ast.Node.PromiseType{
.base = ast.Node{ .id = ast.Node.Id.PromiseType },
.promise_token = token.index,
.result = null,
- });
+ };
opt_ctx.store(&node.base);
const next_token = nextToken(&tok_it, &tree);
const next_token_index = next_token.index;
@@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.LParen => {
- const node = try arena.create(ast.Node.GroupedExpression{
+ const node = try arena.create(ast.Node.GroupedExpression);
+ node.* = ast.Node.GroupedExpression{
.base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
.lparen = token.index,
.expr = undefined,
.rparen = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{
@@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Builtin => {
- const node = try arena.create(ast.Node.BuiltinCall{
+ const node = try arena.create(ast.Node.BuiltinCall);
+ node.* = ast.Node.BuiltinCall{
.base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
.builtin_token = token.index,
.params = ast.Node.BuiltinCall.ParamList.init(arena),
.rparen_token = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{
@@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.LBracket => {
- const node = try arena.create(ast.Node.PrefixOp{
+ const node = try arena.create(ast.Node.PrefixOp);
+ node.* = ast.Node.PrefixOp{
.base = ast.Node{ .id = ast.Node.Id.PrefixOp },
.op_token = token.index,
.op = undefined,
.rhs = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
@@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_fn => {
- const fn_proto = try arena.create(ast.Node.FnProto{
+ const fn_proto = try arena.create(ast.Node.FnProto);
+ fn_proto.* = ast.Node.FnProto{
.base = ast.Node{ .id = ast.Node.Id.FnProto },
.doc_comments = null,
.visib_token = null,
@@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.lib_name = null,
.align_expr = null,
.section_expr = null,
- });
+ };
opt_ctx.store(&fn_proto.base);
stack.append(State{ .FnProto = fn_proto }) catch unreachable;
continue;
},
Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
- const fn_proto = try arena.create(ast.Node.FnProto{
+ const fn_proto = try arena.create(ast.Node.FnProto);
+ fn_proto.* = ast.Node.FnProto{
.base = ast.Node{ .id = ast.Node.Id.FnProto },
.doc_comments = null,
.visib_token = null,
@@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.lib_name = null,
.align_expr = null,
.section_expr = null,
- });
+ };
opt_ctx.store(&fn_proto.base);
stack.append(State{ .FnProto = fn_proto }) catch unreachable;
try stack.append(State{
@@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
},
Token.Id.Keyword_asm => {
- const node = try arena.create(ast.Node.Asm{
+ const node = try arena.create(ast.Node.Asm);
+ node.* = ast.Node.Asm{
.base = ast.Node{ .id = ast.Node.Id.Asm },
.asm_token = token.index,
.volatile_token = null,
@@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
.inputs = ast.Node.Asm.InputList.init(arena),
.clobbers = ast.Node.Asm.ClobberList.init(arena),
.rparen = undefined,
- });
+ };
opt_ctx.store(&node.base);
stack.append(State{
@@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
State.ErrorTypeOrSetDecl => |ctx| {
if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {
- const node = try arena.create(ast.Node.InfixOp{
+ const node = try arena.create(ast.Node.InfixOp);
+ node.* = ast.Node.InfixOp{
.base = ast.Node{ .id = ast.Node.Id.InfixOp },
.lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,
.op_token = undefined,
.op = ast.Node.InfixOp.Op.Period,
.rhs = undefined,
- });
+ };
ctx.opt_ctx.store(&node.base);
stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
try stack.append(State{
@@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
continue;
}
- const node = try arena.create(ast.Node.ErrorSetDecl{
+ const node = try arena.create(ast.Node.ErrorSetDecl);
+ node.* = ast.Node.ErrorSetDecl{
.base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
.error_token = ctx.error_token,
.decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
.rbrace_token = undefined,
- });
+ };
ctx.opt_ctx.store(&node.base);
stack.append(State{
@@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
return tree;
}
- const node = try arena.create(ast.Node.ErrorTag{
+ const node = try arena.create(ast.Node.ErrorTag);
+ node.* = ast.Node.ErrorTag{
.base = ast.Node{ .id = ast.Node.Id.ErrorTag },
.doc_comments = comments,
.name_token = ident_token_index,
- });
+ };
node_ptr.* = &node.base;
continue;
},
@@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct {
const VarDeclCtx = struct {
mut_token: TokenIndex,
visib_token: ?TokenIndex,
+ thread_local_token: ?TokenIndex,
comptime_token: ?TokenIndex,
extern_export_token: ?TokenIndex,
lib_name: ?*ast.Node,
@@ -3014,6 +3134,7 @@ const State = union(enum) {
ContainerInitArg: *ast.Node.ContainerDecl,
ContainerDecl: *ast.Node.ContainerDecl,
+ ThreadLocal: VarDeclCtx,
VarDecl: VarDeclCtx,
VarDeclAlign: *ast.Node.VarDecl,
VarDeclSection: *ast.Node.VarDecl,
@@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as
if (result.*) |comment_node| {
break :blk comment_node;
} else {
- const comment_node = try arena.create(ast.Node.DocComment{
+ const comment_node = try arena.create(ast.Node.DocComment);
+ comment_node.* = ast.Node.DocComment{
.base = ast.Node{ .id = ast.Node.Id.DocComment },
.lines = ast.Node.DocComment.LineList.init(arena),
- });
+ };
result.* = comment_node;
break :blk comment_node;
}
@@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
},
Token.Id.MultilineStringLiteralLine => {
- const node = try arena.create(ast.Node.MultilineStringLiteral{
+ const node = try arena.create(ast.Node.MultilineStringLiteral);
+ node.* = ast.Node.MultilineStringLiteral{
.base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
.lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
- });
+ };
try node.lines.push(token_index);
while (true) {
const multiline_str = nextToken(tok_it, tree);
@@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {
switch (token_ptr.id) {
Token.Id.Keyword_suspend => {
- const node = try arena.create(ast.Node.Suspend{
+ const node = try arena.create(ast.Node.Suspend);
+ node.* = ast.Node.Suspend{
.base = ast.Node{ .id = ast.Node.Id.Suspend },
.suspend_token = token_index,
.body = null,
- });
+ };
ctx.store(&node.base);
stack.append(State{ .SuspendBody = node }) catch unreachable;
return true;
},
Token.Id.Keyword_if => {
- const node = try arena.create(ast.Node.If{
+ const node = try arena.create(ast.Node.If);
+ node.* = ast.Node.If{
.base = ast.Node{ .id = ast.Node.Id.If },
.if_token = token_index,
.condition = undefined,
.payload = null,
.body = undefined,
.@"else" = null,
- });
+ };
ctx.store(&node.base);
stack.append(State{ .Else = &node.@"else" }) catch unreachable;
@@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
return true;
},
Token.Id.Keyword_switch => {
- const node = try arena.create(ast.Node.Switch{
+ const node = try arena.create(ast.Node.Switch);
+ node.* = ast.Node.Switch{
.base = ast.Node{ .id = ast.Node.Id.Switch },
.switch_token = token_index,
.expr = undefined,
.cases = ast.Node.Switch.CaseList.init(arena),
.rbrace = undefined,
- });
+ };
ctx.store(&node.base);
stack.append(State{
@@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
return true;
},
Token.Id.Keyword_comptime => {
- const node = try arena.create(ast.Node.Comptime{
+ const node = try arena.create(ast.Node.Comptime);
+ node.* = ast.Node.Comptime{
.base = ast.Node{ .id = ast.Node.Id.Comptime },
.comptime_token = token_index,
.expr = undefined,
.doc_comments = null,
- });
+ };
ctx.store(&node.base);
try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
return true;
},
Token.Id.LBrace => {
- const block = try arena.create(ast.Node.Block{
+ const block = try arena.create(ast.Node.Block);
+ block.* = ast.Node.Block{
.base = ast.Node{ .id = ast.Node.Id.Block },
.label = null,
.lbrace = token_index,
.statements = ast.Node.Block.StatementList.init(arena),
.rbrace = undefined,
- });
+ };
ctx.store(&block.base);
stack.append(State{ .Block = block }) catch unreachable;
return true;
@@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },
- Token.Id.Asterisk, Token.Id.AsteriskAsterisk, Token.Id.BracketStarBracket => ast.Node.PrefixOp.Op{
+
+ Token.Id.Asterisk,
+ Token.Id.AsteriskAsterisk,
+ Token.Id.BracketStarBracket,
+ Token.Id.BracketStarCBracket,
+ => ast.Node.PrefixOp.Op{
.PtrType = ast.Node.PrefixOp.PtrInfo{
.align_info = null,
.const_token = null,
@@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
}
fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T {
- return arena.create(T{
+ const result = try arena.create(T);
+ result.* = T{
.base = ast.Node{ .id = ast.Node.typeToId(T) },
.token = token_index,
- });
+ };
+ return result;
}
fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T {
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 2b60fb9b00..5b7b7aa2a9 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,17 @@
+test "zig fmt: C pointers" {
+ try testCanonical(
+ \\const Ptr = [*c]i32;
+ \\
+ );
+}
+
+test "zig fmt: threadlocal" {
+ try testCanonical(
+ \\threadlocal var x: i32 = 1234;
+ \\
+ );
+}
+
test "zig fmt: linksection" {
try testCanonical(
\\export var aoeu: u64 linksection(".text.derp") = 1234;
@@ -5,6 +19,7 @@ test "zig fmt: linksection" {
\\
);
}
+
test "zig fmt: shebang line" {
try testCanonical(
\\#!/usr/bin/env zig
@@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected);
return error.TestFailed;
}
- std.debug.assert(anything_changed == changes_expected);
+ std.testing.expect(anything_changed == changes_expected);
failing_allocator.allocator.free(result_source);
break :x failing_allocator.index;
};
diff --git a/std/zig/render.zig b/std/zig/render.zig
index e55a0beb93..66aba75e1b 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -1706,6 +1706,9 @@ fn renderVarDecl(
try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
}
+ if (var_decl.thread_local_token) |thread_local_token| {
+ try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal
+ }
try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig
index 4941fe2cc2..877e4e8db3 100644
--- a/std/zig/tokenizer.zig
+++ b/std/zig/tokenizer.zig
@@ -53,6 +53,7 @@ pub const Token = struct {
Keyword{ .bytes = "switch", .id = Id.Keyword_switch },
Keyword{ .bytes = "test", .id = Id.Keyword_test },
Keyword{ .bytes = "this", .id = Id.Keyword_this },
+ Keyword{ .bytes = "threadlocal", .id = Id.Keyword_threadlocal },
Keyword{ .bytes = "true", .id = Id.Keyword_true },
Keyword{ .bytes = "try", .id = Id.Keyword_try },
Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined },
@@ -140,6 +141,7 @@ pub const Token = struct {
LineComment,
DocComment,
BracketStarBracket,
+ BracketStarCBracket,
ShebangLine,
Keyword_align,
Keyword_and,
@@ -182,6 +184,7 @@ pub const Token = struct {
Keyword_switch,
Keyword_test,
Keyword_this,
+ Keyword_threadlocal,
Keyword_true,
Keyword_try,
Keyword_undefined,
@@ -277,6 +280,7 @@ pub const Tokenizer = struct {
SawAtSign,
LBracket,
LBracketStar,
+ LBracketStarC,
};
pub fn next(self: *Tokenizer) Token {
@@ -454,6 +458,9 @@ pub const Tokenizer = struct {
},
State.LBracketStar => switch (c) {
+ 'c' => {
+ state = State.LBracketStarC;
+ },
']' => {
result.id = Token.Id.BracketStarBracket;
self.index += 1;
@@ -465,6 +472,18 @@ pub const Tokenizer = struct {
},
},
+ State.LBracketStarC => switch (c) {
+ ']' => {
+ result.id = Token.Id.BracketStarCBracket;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = Token.Id.Invalid;
+ break;
+ },
+ },
+
State.Ampersand => switch (c) {
'=' => {
result.id = Token.Id.AmpersandEqual;
@@ -1033,6 +1052,7 @@ pub const Tokenizer = struct {
State.CharLiteralEnd,
State.StringLiteralBackslash,
State.LBracketStar,
+ State.LBracketStarC,
=> {
result.id = Token.Id.Invalid;
},
@@ -1167,12 +1187,15 @@ test "tokenizer" {
testTokenize("test", []Token.Id{Token.Id.Keyword_test});
}
-test "tokenizer - unknown length pointer" {
+test "tokenizer - unknown length pointer and then c pointer" {
testTokenize(
\\[*]u8
+ \\[*c]u8
, []Token.Id{
Token.Id.BracketStarBracket,
Token.Id.Identifier,
+ Token.Id.BracketStarCBracket,
+ Token.Id.Identifier,
});
}
@@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
}
}
const last_token = tokenizer.next();
- std.debug.assert(last_token.id == Token.Id.Eof);
+ std.testing.expect(last_token.id == Token.Id.Eof);
}
diff --git a/test/behavior.zig b/test/behavior.zig
deleted file mode 100644
index 1d031343d6..0000000000
--- a/test/behavior.zig
+++ /dev/null
@@ -1,77 +0,0 @@
-const builtin = @import("builtin");
-
-comptime {
- _ = @import("cases/align.zig");
- _ = @import("cases/alignof.zig");
- _ = @import("cases/array.zig");
- _ = @import("cases/asm.zig");
- _ = @import("cases/atomics.zig");
- _ = @import("cases/bitcast.zig");
- _ = @import("cases/bool.zig");
- _ = @import("cases/bugs/1076.zig");
- _ = @import("cases/bugs/1111.zig");
- _ = @import("cases/bugs/1277.zig");
- _ = @import("cases/bugs/1322.zig");
- _ = @import("cases/bugs/1381.zig");
- _ = @import("cases/bugs/1421.zig");
- _ = @import("cases/bugs/1442.zig");
- _ = @import("cases/bugs/1486.zig");
- _ = @import("cases/bugs/394.zig");
- _ = @import("cases/bugs/655.zig");
- _ = @import("cases/bugs/656.zig");
- _ = @import("cases/bugs/726.zig");
- _ = @import("cases/bugs/828.zig");
- _ = @import("cases/bugs/920.zig");
- _ = @import("cases/byval_arg_var.zig");
- _ = @import("cases/cancel.zig");
- _ = @import("cases/cast.zig");
- _ = @import("cases/const_slice_child.zig");
- _ = @import("cases/coroutine_await_struct.zig");
- _ = @import("cases/coroutines.zig");
- _ = @import("cases/defer.zig");
- _ = @import("cases/enum.zig");
- _ = @import("cases/enum_with_members.zig");
- _ = @import("cases/error.zig");
- _ = @import("cases/eval.zig");
- _ = @import("cases/field_parent_ptr.zig");
- _ = @import("cases/fn.zig");
- _ = @import("cases/fn_in_struct_in_comptime.zig");
- _ = @import("cases/for.zig");
- _ = @import("cases/generics.zig");
- _ = @import("cases/if.zig");
- _ = @import("cases/import.zig");
- _ = @import("cases/incomplete_struct_param_tld.zig");
- _ = @import("cases/ir_block_deps.zig");
- _ = @import("cases/math.zig");
- _ = @import("cases/merge_error_sets.zig");
- _ = @import("cases/misc.zig");
- _ = @import("cases/namespace_depends_on_compile_var/index.zig");
- _ = @import("cases/new_stack_call.zig");
- _ = @import("cases/null.zig");
- _ = @import("cases/optional.zig");
- _ = @import("cases/pointers.zig");
- _ = @import("cases/popcount.zig");
- _ = @import("cases/pub_enum/index.zig");
- _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
- _ = @import("cases/reflection.zig");
- _ = @import("cases/sizeof_and_typeof.zig");
- _ = @import("cases/slice.zig");
- _ = @import("cases/struct.zig");
- _ = @import("cases/struct_contains_null_ptr_itself.zig");
- _ = @import("cases/struct_contains_slice_of_itself.zig");
- _ = @import("cases/switch.zig");
- _ = @import("cases/switch_prong_err_enum.zig");
- _ = @import("cases/switch_prong_implicit_cast.zig");
- _ = @import("cases/syntax.zig");
- _ = @import("cases/this.zig");
- _ = @import("cases/try.zig");
- _ = @import("cases/type_info.zig");
- _ = @import("cases/undefined.zig");
- _ = @import("cases/underscore.zig");
- _ = @import("cases/union.zig");
- _ = @import("cases/var_args.zig");
- _ = @import("cases/void.zig");
- _ = @import("cases/while.zig");
- _ = @import("cases/widening.zig");
- _ = @import("cases/bit_shifting.zig");
-}
diff --git a/test/cases/array.zig b/test/cases/array.zig
deleted file mode 100644
index 7c63a649a8..0000000000
--- a/test/cases/array.zig
+++ /dev/null
@@ -1,173 +0,0 @@
-const assert = @import("std").debug.assert;
-const mem = @import("std").mem;
-
-test "arrays" {
- var array: [5]u32 = undefined;
-
- var i: u32 = 0;
- while (i < 5) {
- array[i] = i + 1;
- i = array[i];
- }
-
- i = 0;
- var accumulator = u32(0);
- while (i < 5) {
- accumulator += array[i];
-
- i += 1;
- }
-
- assert(accumulator == 15);
- assert(getArrayLen(array) == 5);
-}
-fn getArrayLen(a: []const u32) usize {
- return a.len;
-}
-
-test "void arrays" {
- var array: [4]void = undefined;
- array[0] = void{};
- array[1] = array[2];
- assert(@sizeOf(@typeOf(array)) == 0);
- assert(array.len == 4);
-}
-
-test "array literal" {
- const hex_mult = []u16{
- 4096,
- 256,
- 16,
- 1,
- };
-
- assert(hex_mult.len == 4);
- assert(hex_mult[1] == 256);
-}
-
-test "array dot len const expr" {
- assert(comptime x: {
- break :x some_array.len == 4;
- });
-}
-
-const ArrayDotLenConstExpr = struct {
- y: [some_array.len]u8,
-};
-const some_array = []u8{
- 0,
- 1,
- 2,
- 3,
-};
-
-test "nested arrays" {
- const array_of_strings = [][]const u8{
- "hello",
- "this",
- "is",
- "my",
- "thing",
- };
- for (array_of_strings) |s, i| {
- if (i == 0) assert(mem.eql(u8, s, "hello"));
- if (i == 1) assert(mem.eql(u8, s, "this"));
- if (i == 2) assert(mem.eql(u8, s, "is"));
- if (i == 3) assert(mem.eql(u8, s, "my"));
- if (i == 4) assert(mem.eql(u8, s, "thing"));
- }
-}
-
-var s_array: [8]Sub = undefined;
-const Sub = struct {
- b: u8,
-};
-const Str = struct {
- a: []Sub,
-};
-test "set global var array via slice embedded in struct" {
- var s = Str{ .a = s_array[0..] };
-
- s.a[0].b = 1;
- s.a[1].b = 2;
- s.a[2].b = 3;
-
- assert(s_array[0].b == 1);
- assert(s_array[1].b == 2);
- assert(s_array[2].b == 3);
-}
-
-test "array literal with specified size" {
- var array = [2]u8{
- 1,
- 2,
- };
- assert(array[0] == 1);
- assert(array[1] == 2);
-}
-
-test "array child property" {
- var x: [5]i32 = undefined;
- assert(@typeOf(x).Child == i32);
-}
-
-test "array len property" {
- var x: [5]i32 = undefined;
- assert(@typeOf(x).len == 5);
-}
-
-test "array len field" {
- var arr = [4]u8{ 0, 0, 0, 0 };
- var ptr = &arr;
- assert(arr.len == 4);
- comptime assert(arr.len == 4);
- assert(ptr.len == 4);
- comptime assert(ptr.len == 4);
-}
-
-test "single-item pointer to array indexing and slicing" {
- testSingleItemPtrArrayIndexSlice();
- comptime testSingleItemPtrArrayIndexSlice();
-}
-
-fn testSingleItemPtrArrayIndexSlice() void {
- var array = "aaaa";
- doSomeMangling(&array);
- assert(mem.eql(u8, "azya", array));
-}
-
-fn doSomeMangling(array: *[4]u8) void {
- array[1] = 'z';
- array[2..3][0] = 'y';
-}
-
-test "implicit cast single-item pointer" {
- testImplicitCastSingleItemPtr();
- comptime testImplicitCastSingleItemPtr();
-}
-
-fn testImplicitCastSingleItemPtr() void {
- var byte: u8 = 100;
- const slice = (*[1]u8)(&byte)[0..];
- slice[0] += 1;
- assert(byte == 101);
-}
-
-fn testArrayByValAtComptime(b: [2]u8) u8 {
- return b[0];
-}
-
-test "comptime evalutating function that takes array by value" {
- const arr = []u8{ 0, 1 };
- _ = comptime testArrayByValAtComptime(arr);
- _ = comptime testArrayByValAtComptime(arr);
-}
-
-test "implicit comptime in array type size" {
- var arr: [plusOne(10)]bool = undefined;
- assert(arr.len == 11);
-}
-
-fn plusOne(x: u32) u32 {
- return x + 1;
-}
diff --git a/test/cases/asm.zig b/test/cases/asm.zig
deleted file mode 100644
index 63e37c857c..0000000000
--- a/test/cases/asm.zig
+++ /dev/null
@@ -1,48 +0,0 @@
-const config = @import("builtin");
-const assert = @import("std").debug.assert;
-
-comptime {
- if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
- asm volatile (
- \\.globl aoeu;
- \\.type aoeu, @function;
- \\.set aoeu, derp;
- );
- }
-}
-
-test "module level assembly" {
- if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
- assert(aoeu() == 1234);
- }
-}
-
-test "output constraint modifiers" {
- // This is only testing compilation.
- var a: u32 = 3;
- asm volatile ("" : [_]"=m,r"(a) : : "");
- asm volatile ("" : [_]"=r,m"(a) : : "");
-}
-
-test "alternative constraints" {
- // Make sure we allow commas as a separator for alternative constraints.
- var a: u32 = 3;
- asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : "");
-}
-
-test "sized integer/float in asm input" {
- asm volatile ("" : : [_]"m"(usize(3)) : "");
- asm volatile ("" : : [_]"m"(i15(-3)) : "");
- asm volatile ("" : : [_]"m"(u3(3)) : "");
- asm volatile ("" : : [_]"m"(i3(3)) : "");
- asm volatile ("" : : [_]"m"(u121(3)) : "");
- asm volatile ("" : : [_]"m"(i121(3)) : "");
- asm volatile ("" : : [_]"m"(f32(3.17)) : "");
- asm volatile ("" : : [_]"m"(f64(3.17)) : "");
-}
-
-extern fn aoeu() i32;
-
-export fn derp() i32 {
- return 1234;
-}
diff --git a/test/cases/optional.zig b/test/cases/optional.zig
deleted file mode 100644
index d43682bbec..0000000000
--- a/test/cases/optional.zig
+++ /dev/null
@@ -1,30 +0,0 @@
-const assert = @import("std").debug.assert;
-
-pub const EmptyStruct = struct {};
-
-test "optional pointer to size zero struct" {
- var e = EmptyStruct{};
- var o: ?*EmptyStruct = &e;
- assert(o != null);
-}
-
-test "equality compare nullable pointers" {
- testNullPtrsEql();
- comptime testNullPtrsEql();
-}
-
-fn testNullPtrsEql() void {
- var number: i32 = 1234;
-
- var x: ?*i32 = null;
- var y: ?*i32 = null;
- assert(x == y);
- y = &number;
- assert(x != y);
- assert(x != &number);
- assert(&number != x);
- x = &number;
- assert(x == y);
- assert(x == &number);
- assert(&number == x);
-}
diff --git a/test/cases/pointers.zig b/test/cases/pointers.zig
deleted file mode 100644
index 47afb60a2e..0000000000
--- a/test/cases/pointers.zig
+++ /dev/null
@@ -1,44 +0,0 @@
-const std = @import("std");
-const assert = std.debug.assert;
-
-test "dereference pointer" {
- comptime testDerefPtr();
- testDerefPtr();
-}
-
-fn testDerefPtr() void {
- var x: i32 = 1234;
- var y = &x;
- y.* += 1;
- assert(x == 1235);
-}
-
-test "pointer arithmetic" {
- var ptr = c"abcd";
-
- assert(ptr[0] == 'a');
- ptr += 1;
- assert(ptr[0] == 'b');
- ptr += 1;
- assert(ptr[0] == 'c');
- ptr += 1;
- assert(ptr[0] == 'd');
- ptr += 1;
- assert(ptr[0] == 0);
- ptr -= 1;
- assert(ptr[0] == 'd');
- ptr -= 1;
- assert(ptr[0] == 'c');
- ptr -= 1;
- assert(ptr[0] == 'b');
- ptr -= 1;
- assert(ptr[0] == 'a');
-}
-
-test "double pointer parsing" {
- comptime assert(PtrOf(PtrOf(i32)) == **i32);
-}
-
-fn PtrOf(comptime T: type) type {
- return *T;
-}
diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig
deleted file mode 100644
index b9b8aff4e1..0000000000
--- a/test/cases/reflection.zig
+++ /dev/null
@@ -1,95 +0,0 @@
-const assert = @import("std").debug.assert;
-const mem = @import("std").mem;
-const reflection = @This();
-
-test "reflection: array, pointer, optional, error union type child" {
- comptime {
- assert(([10]u8).Child == u8);
- assert((*u8).Child == u8);
- assert((anyerror!u8).Payload == u8);
- assert((?u8).Child == u8);
- }
-}
-
-test "reflection: function return type, var args, and param types" {
- comptime {
- assert(@typeOf(dummy).ReturnType == i32);
- assert(!@typeOf(dummy).is_var_args);
- assert(@typeOf(dummy_varargs).is_var_args);
- assert(@typeOf(dummy).arg_count == 3);
- assert(@ArgType(@typeOf(dummy), 0) == bool);
- assert(@ArgType(@typeOf(dummy), 1) == i32);
- assert(@ArgType(@typeOf(dummy), 2) == f32);
- }
-}
-
-fn dummy(a: bool, b: i32, c: f32) i32 {
- return 1234;
-}
-fn dummy_varargs(args: ...) void {}
-
-test "reflection: struct member types and names" {
- comptime {
- assert(@memberCount(Foo) == 3);
-
- assert(@memberType(Foo, 0) == i32);
- assert(@memberType(Foo, 1) == bool);
- assert(@memberType(Foo, 2) == void);
-
- assert(mem.eql(u8, @memberName(Foo, 0), "one"));
- assert(mem.eql(u8, @memberName(Foo, 1), "two"));
- assert(mem.eql(u8, @memberName(Foo, 2), "three"));
- }
-}
-
-test "reflection: enum member types and names" {
- comptime {
- assert(@memberCount(Bar) == 4);
-
- assert(@memberType(Bar, 0) == void);
- assert(@memberType(Bar, 1) == i32);
- assert(@memberType(Bar, 2) == bool);
- assert(@memberType(Bar, 3) == f64);
-
- assert(mem.eql(u8, @memberName(Bar, 0), "One"));
- assert(mem.eql(u8, @memberName(Bar, 1), "Two"));
- assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
- assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
- }
-}
-
-test "reflection: @field" {
- var f = Foo{
- .one = 42,
- .two = true,
- .three = void{},
- };
-
- assert(f.one == f.one);
- assert(@field(f, "o" ++ "ne") == f.one);
- assert(@field(f, "t" ++ "wo") == f.two);
- assert(@field(f, "th" ++ "ree") == f.three);
- assert(@field(Foo, "const" ++ "ant") == Foo.constant);
- assert(@field(Bar, "O" ++ "ne") == Bar.One);
- assert(@field(Bar, "T" ++ "wo") == Bar.Two);
- assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
- assert(@field(Bar, "F" ++ "our") == Bar.Four);
- assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
- @field(f, "o" ++ "ne") = 4;
- assert(f.one == 4);
-}
-
-const Foo = struct {
- const constant = 52;
-
- one: i32,
- two: bool,
- three: void,
-};
-
-const Bar = union(enum) {
- One: void,
- Two: i32,
- Three: bool,
- Four: f64,
-};
diff --git a/test/cases/sizeof_and_typeof.zig b/test/cases/sizeof_and_typeof.zig
deleted file mode 100644
index 11c6b2f6ba..0000000000
--- a/test/cases/sizeof_and_typeof.zig
+++ /dev/null
@@ -1,69 +0,0 @@
-const builtin = @import("builtin");
-const assert = @import("std").debug.assert;
-
-test "@sizeOf and @typeOf" {
- const y: @typeOf(x) = 120;
- assert(@sizeOf(@typeOf(y)) == 2);
-}
-const x: u16 = 13;
-const z: @typeOf(x) = 19;
-
-const A = struct {
- a: u8,
- b: u32,
- c: u8,
- d: u3,
- e: u5,
- f: u16,
- g: u16,
-};
-
-const P = packed struct {
- a: u8,
- b: u32,
- c: u8,
- d: u3,
- e: u5,
- f: u16,
- g: u16,
-};
-
-test "@byteOffsetOf" {
- // Packed structs have fixed memory layout
- assert(@byteOffsetOf(P, "a") == 0);
- assert(@byteOffsetOf(P, "b") == 1);
- assert(@byteOffsetOf(P, "c") == 5);
- assert(@byteOffsetOf(P, "d") == 6);
- assert(@byteOffsetOf(P, "e") == 6);
- assert(@byteOffsetOf(P, "f") == 7);
- assert(@byteOffsetOf(P, "g") == 9);
-
- // Normal struct fields can be moved/padded
- var a: A = undefined;
- assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
- assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
- assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
- assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
- assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
- assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
- assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
-}
-
-test "@bitOffsetOf" {
- // Packed structs have fixed memory layout
- assert(@bitOffsetOf(P, "a") == 0);
- assert(@bitOffsetOf(P, "b") == 8);
- assert(@bitOffsetOf(P, "c") == 40);
- assert(@bitOffsetOf(P, "d") == 48);
- assert(@bitOffsetOf(P, "e") == 51);
- assert(@bitOffsetOf(P, "f") == 56);
- assert(@bitOffsetOf(P, "g") == 72);
-
- assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
- assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
- assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
- assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
- assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
- assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
- assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
-}
diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/cases/struct_contains_slice_of_itself.zig
deleted file mode 100644
index 07987ae32b..0000000000
--- a/test/cases/struct_contains_slice_of_itself.zig
+++ /dev/null
@@ -1,43 +0,0 @@
-const assert = @import("std").debug.assert;
-
-const Node = struct {
- payload: i32,
- children: []Node,
-};
-
-test "struct contains slice of itself" {
- var other_nodes = []Node{
- Node{
- .payload = 31,
- .children = []Node{},
- },
- Node{
- .payload = 32,
- .children = []Node{},
- },
- };
- var nodes = []Node{
- Node{
- .payload = 1,
- .children = []Node{},
- },
- Node{
- .payload = 2,
- .children = []Node{},
- },
- Node{
- .payload = 3,
- .children = other_nodes[0..],
- },
- };
- const root = Node{
- .payload = 1234,
- .children = nodes[0..],
- };
- assert(root.payload == 1234);
- assert(root.children[0].payload == 1);
- assert(root.children[1].payload == 2);
- assert(root.children[2].payload == 3);
- assert(root.children[2].children[0].payload == 31);
- assert(root.children[2].children[1].payload == 32);
-}
diff --git a/test/cases/type_info.zig b/test/cases/type_info.zig
deleted file mode 100644
index 6f99268c08..0000000000
--- a/test/cases/type_info.zig
+++ /dev/null
@@ -1,259 +0,0 @@
-const assert = @import("std").debug.assert;
-const mem = @import("std").mem;
-const TypeInfo = @import("builtin").TypeInfo;
-const TypeId = @import("builtin").TypeId;
-
-test "type info: tag type, void info" {
- testBasic();
- comptime testBasic();
-}
-
-fn testBasic() void {
- assert(@TagType(TypeInfo) == TypeId);
- const void_info = @typeInfo(void);
- assert(TypeId(void_info) == TypeId.Void);
- assert(void_info.Void == {});
-}
-
-test "type info: integer, floating point type info" {
- testIntFloat();
- comptime testIntFloat();
-}
-
-fn testIntFloat() void {
- const u8_info = @typeInfo(u8);
- assert(TypeId(u8_info) == TypeId.Int);
- assert(!u8_info.Int.is_signed);
- assert(u8_info.Int.bits == 8);
-
- const f64_info = @typeInfo(f64);
- assert(TypeId(f64_info) == TypeId.Float);
- assert(f64_info.Float.bits == 64);
-}
-
-test "type info: pointer type info" {
- testPointer();
- comptime testPointer();
-}
-
-fn testPointer() void {
- const u32_ptr_info = @typeInfo(*u32);
- assert(TypeId(u32_ptr_info) == TypeId.Pointer);
- assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
- assert(u32_ptr_info.Pointer.is_const == false);
- assert(u32_ptr_info.Pointer.is_volatile == false);
- assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
- assert(u32_ptr_info.Pointer.child == u32);
-}
-
-test "type info: unknown length pointer type info" {
- testUnknownLenPtr();
- comptime testUnknownLenPtr();
-}
-
-fn testUnknownLenPtr() void {
- const u32_ptr_info = @typeInfo([*]const volatile f64);
- assert(TypeId(u32_ptr_info) == TypeId.Pointer);
- assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
- assert(u32_ptr_info.Pointer.is_const == true);
- assert(u32_ptr_info.Pointer.is_volatile == true);
- assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
- assert(u32_ptr_info.Pointer.child == f64);
-}
-
-test "type info: slice type info" {
- testSlice();
- comptime testSlice();
-}
-
-fn testSlice() void {
- const u32_slice_info = @typeInfo([]u32);
- assert(TypeId(u32_slice_info) == TypeId.Pointer);
- assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
- assert(u32_slice_info.Pointer.is_const == false);
- assert(u32_slice_info.Pointer.is_volatile == false);
- assert(u32_slice_info.Pointer.alignment == 4);
- assert(u32_slice_info.Pointer.child == u32);
-}
-
-test "type info: array type info" {
- testArray();
- comptime testArray();
-}
-
-fn testArray() void {
- const arr_info = @typeInfo([42]bool);
- assert(TypeId(arr_info) == TypeId.Array);
- assert(arr_info.Array.len == 42);
- assert(arr_info.Array.child == bool);
-}
-
-test "type info: optional type info" {
- testOptional();
- comptime testOptional();
-}
-
-fn testOptional() void {
- const null_info = @typeInfo(?void);
- assert(TypeId(null_info) == TypeId.Optional);
- assert(null_info.Optional.child == void);
-}
-
-test "type info: promise info" {
- testPromise();
- comptime testPromise();
-}
-
-fn testPromise() void {
- const null_promise_info = @typeInfo(promise);
- assert(TypeId(null_promise_info) == TypeId.Promise);
- assert(null_promise_info.Promise.child == null);
-
- const promise_info = @typeInfo(promise->usize);
- assert(TypeId(promise_info) == TypeId.Promise);
- assert(promise_info.Promise.child.? == usize);
-}
-
-test "type info: error set, error union info" {
- testErrorSet();
- comptime testErrorSet();
-}
-
-fn testErrorSet() void {
- const TestErrorSet = error{
- First,
- Second,
- Third,
- };
-
- const error_set_info = @typeInfo(TestErrorSet);
- assert(TypeId(error_set_info) == TypeId.ErrorSet);
- assert(error_set_info.ErrorSet.errors.len == 3);
- assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
- assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
-
- const error_union_info = @typeInfo(TestErrorSet!usize);
- assert(TypeId(error_union_info) == TypeId.ErrorUnion);
- assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
- assert(error_union_info.ErrorUnion.payload == usize);
-}
-
-test "type info: enum info" {
- testEnum();
- comptime testEnum();
-}
-
-fn testEnum() void {
- const Os = @import("builtin").Os;
-
- const os_info = @typeInfo(Os);
- assert(TypeId(os_info) == TypeId.Enum);
- assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
- assert(os_info.Enum.fields.len == 32);
- assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
- assert(os_info.Enum.fields[10].value == 10);
- assert(os_info.Enum.tag_type == u5);
- assert(os_info.Enum.defs.len == 0);
-}
-
-test "type info: union info" {
- testUnion();
- comptime testUnion();
-}
-
-fn testUnion() void {
- const typeinfo_info = @typeInfo(TypeInfo);
- assert(TypeId(typeinfo_info) == TypeId.Union);
- assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
- assert(typeinfo_info.Union.tag_type.? == TypeId);
- assert(typeinfo_info.Union.fields.len == 24);
- assert(typeinfo_info.Union.fields[4].enum_field != null);
- assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
- assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
- assert(typeinfo_info.Union.defs.len == 20);
-
- const TestNoTagUnion = union {
- Foo: void,
- Bar: u32,
- };
-
- const notag_union_info = @typeInfo(TestNoTagUnion);
- assert(TypeId(notag_union_info) == TypeId.Union);
- assert(notag_union_info.Union.tag_type == null);
- assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
- assert(notag_union_info.Union.fields.len == 2);
- assert(notag_union_info.Union.fields[0].enum_field == null);
- assert(notag_union_info.Union.fields[1].field_type == u32);
-
- const TestExternUnion = extern union {
- foo: *c_void,
- };
-
- const extern_union_info = @typeInfo(TestExternUnion);
- assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
- assert(extern_union_info.Union.tag_type == null);
- assert(extern_union_info.Union.fields[0].enum_field == null);
- assert(extern_union_info.Union.fields[0].field_type == *c_void);
-}
-
-test "type info: struct info" {
- testStruct();
- comptime testStruct();
-}
-
-fn testStruct() void {
- const struct_info = @typeInfo(TestStruct);
- assert(TypeId(struct_info) == TypeId.Struct);
- assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
- assert(struct_info.Struct.fields.len == 3);
- assert(struct_info.Struct.fields[1].offset == null);
- assert(struct_info.Struct.fields[2].field_type == *TestStruct);
- assert(struct_info.Struct.defs.len == 2);
- assert(struct_info.Struct.defs[0].is_pub);
- assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
- assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
- assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
- assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
-}
-
-const TestStruct = packed struct {
- const Self = @This();
-
- fieldA: usize,
- fieldB: void,
- fieldC: *Self,
-
- pub fn foo(self: *const Self) void {}
-};
-
-test "type info: function type info" {
- testFunction();
- comptime testFunction();
-}
-
-fn testFunction() void {
- const fn_info = @typeInfo(@typeOf(foo));
- assert(TypeId(fn_info) == TypeId.Fn);
- assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
- assert(fn_info.Fn.is_generic);
- assert(fn_info.Fn.args.len == 2);
- assert(fn_info.Fn.is_var_args);
- assert(fn_info.Fn.return_type == null);
- assert(fn_info.Fn.async_allocator_type == null);
-
- const test_instance: TestStruct = undefined;
- const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
- assert(TypeId(bound_fn_info) == TypeId.BoundFn);
- assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
-}
-
-fn foo(comptime a: usize, b: bool, args: ...) usize {
- return 0;
-}
-
-test "typeInfo with comptime parameter in struct fn def" {
- const S = struct {
- pub fn func(comptime x: f32) void {}
- };
- comptime var info = @typeInfo(S);
-}
diff --git a/test/cli.zig b/test/cli.zig
index a07c447d2d..1520b3bde0 100644
--- a/test/cli.zig
+++ b/test/cli.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const builtin = @import("builtin");
const os = std.os;
-const assertOrPanic = std.debug.assertOrPanic;
+const testing = std.testing;
var a: *std.mem.Allocator = undefined;
@@ -27,9 +27,9 @@ pub fn main() !void {
std.debug.warn("Expected second argument to be cache root directory path\n");
return error.InvalidArgs;
});
- const zig_exe = try os.path.resolve(a, zig_exe_rel);
+ const zig_exe = try os.path.resolve(a, [][]const u8{zig_exe_rel});
- const dir_path = try os.path.join(a, cache_root, "clitest");
+ const dir_path = try os.path.join(a, [][]const u8{ cache_root, "clitest" });
const TestFn = fn ([]const u8, []const u8) anyerror!void;
const test_fns = []TestFn{
testZigInitLib,
@@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {
fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });
const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" });
- assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
+ testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
}
fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
_ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });
const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" });
- assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
+ testing.expect(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
}
fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;
- const example_zig_path = try os.path.join(a, dir_path, "example.zig");
- const example_s_path = try os.path.join(a, dir_path, "example.s");
+ const example_zig_path = try os.path.join(a, [][]const u8{ dir_path, "example.zig" });
+ const example_s_path = try os.path.join(a, [][]const u8{ dir_path, "example.s" });
try std.io.writeFile(example_zig_path,
\\// Type your code here, or load an example.
@@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
_ = try exec(dir_path, args);
const out_asm = try std.io.readFileAlloc(a, example_s_path);
- assertOrPanic(std.mem.indexOf(u8, out_asm, "square:") != null);
- assertOrPanic(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
+ testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null);
+ testing.expect(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index be839f0550..9ef4af4162 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -1,6 +1,270 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest(
+ "C pointer to c_void",
+ \\export fn a() void {
+ \\ var x: *c_void = undefined;
+ \\ var y: [*c]c_void = x;
+ \\}
+ ,
+ ".tmp_source.zig:3:12: error: C pointers cannot point opaque types",
+ );
+
+ cases.addTest(
+ "directly embedding opaque type in struct and union",
+ \\const O = @OpaqueType();
+ \\const Foo = struct {
+ \\ o: O,
+ \\};
+ \\const Bar = union {
+ \\ One: i32,
+ \\ Two: O,
+ \\};
+ \\export fn a() void {
+ \\ var foo: Foo = undefined;
+ \\}
+ \\export fn b() void {
+ \\ var bar: Bar = undefined;
+ \\}
+ ,
+ ".tmp_source.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
+ ".tmp_source.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
+ );
+
+ cases.addTest(
+ "implicit cast between C pointer and Zig pointer - bad const/align/child",
+ \\export fn a() void {
+ \\ var x: [*c]u8 = undefined;
+ \\ var y: *align(4) u8 = x;
+ \\}
+ \\export fn b() void {
+ \\ var x: [*c]const u8 = undefined;
+ \\ var y: *u8 = x;
+ \\}
+ \\export fn c() void {
+ \\ var x: [*c]u8 = undefined;
+ \\ var y: *u32 = x;
+ \\}
+ \\export fn d() void {
+ \\ var y: *align(1) u32 = undefined;
+ \\ var x: [*c]u32 = y;
+ \\}
+ \\export fn e() void {
+ \\ var y: *const u8 = undefined;
+ \\ var x: [*c]u8 = y;
+ \\}
+ \\export fn f() void {
+ \\ var y: *u8 = undefined;
+ \\ var x: [*c]u32 = y;
+ \\}
+ ,
+ ".tmp_source.zig:3:27: error: cast increases pointer alignment",
+ ".tmp_source.zig:7:18: error: cast discards const qualifier",
+ ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'",
+ ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'",
+ ".tmp_source.zig:15:22: error: cast increases pointer alignment",
+ ".tmp_source.zig:19:21: error: cast discards const qualifier",
+ ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'",
+ );
+
+ cases.addTest(
+ "implicit casting null c pointer to zig pointer",
+ \\comptime {
+ \\ var c_ptr: [*c]u8 = 0;
+ \\ var zig_ptr: *u8 = c_ptr;
+ \\}
+ ,
+ ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'",
+ );
+
+ cases.addTest(
+ "implicit casting undefined c pointer to zig pointer",
+ \\comptime {
+ \\ var c_ptr: [*c]u8 = undefined;
+ \\ var zig_ptr: *u8 = c_ptr;
+ \\}
+ ,
+ ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior",
+ );
+
+ cases.addTest(
+ "implicit casting C pointers which would mess up null semantics",
+ \\export fn entry() void {
+ \\ var slice: []const u8 = "aoeu";
+ \\ const opt_many_ptr: [*]const u8 = slice.ptr;
+ \\ var ptr_opt_many_ptr = &opt_many_ptr;
+ \\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
+ \\ ptr_opt_many_ptr = c_ptr;
+ \\}
+ \\export fn entry2() void {
+ \\ var buf: [4]u8 = "aoeu";
+ \\ var slice: []u8 = &buf;
+ \\ var opt_many_ptr: [*]u8 = slice.ptr;
+ \\ var ptr_opt_many_ptr = &opt_many_ptr;
+ \\ var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr;
+ \\}
+ ,
+ ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'",
+ ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'",
+ ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'",
+ ".tmp_source.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'",
+ ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'",
+ ".tmp_source.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",
+ );
+
+ cases.addTest(
+ "implicit casting too big integers to C pointers",
+ \\export fn a() void {
+ \\ var ptr: [*c]u8 = (1 << 64) + 1;
+ \\}
+ \\export fn b() void {
+ \\ var x: @IntType(false, 65) = 0x1234;
+ \\ var ptr: [*c]u8 = x;
+ \\}
+ ,
+ ".tmp_source.zig:2:33: error: integer value 71615590737044764481 cannot be implicitly casted to type 'usize'",
+ ".tmp_source.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",
+ );
+
+ cases.addTest(
+ "C pointer pointing to non C ABI compatible type or has align attr",
+ \\const Foo = struct {};
+ \\export fn a() void {
+ \\ const T = [*c]Foo;
+ \\}
+ ,
+ ".tmp_source.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
+ );
+
+ cases.addTest(
+ "@truncate undefined value",
+ \\export fn entry() void {
+ \\ var z = @truncate(u8, u16(undefined));
+ \\}
+ ,
+ ".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior",
+ );
+
+ cases.addTest(
+ "return invalid type from test",
+ \\test "example" { return 1; }
+ ,
+ ".tmp_source.zig:1:25: error: integer value 1 cannot be implicitly casted to type 'void'",
+ );
+
+ cases.add(
+ "threadlocal qualifier on const",
+ \\threadlocal const x: i32 = 1234;
+ \\export fn entry() i32 {
+ \\ return x;
+ \\}
+ ,
+ ".tmp_source.zig:1:13: error: threadlocal variable cannot be constant",
+ );
+
+ cases.add(
+ "threadlocal qualifier on local variable",
+ \\export fn entry() void {
+ \\ threadlocal var x: i32 = 1234;
+ \\}
+ ,
+ ".tmp_source.zig:2:5: error: function-local variable 'x' cannot be threadlocal",
+ );
+
+ cases.add(
+ "@bitCast same size but bit count mismatch",
+ \\export fn entry(byte: u8) void {
+ \\ var oops = @bitCast(u7, byte);
+ \\}
+ ,
+ ".tmp_source.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
+ );
+
+ cases.add(
+ "attempted `&&`",
+ \\export fn entry(a: bool, b: bool) i32 {
+ \\ if (a && b) {
+ \\ return 1234;
+ \\ }
+ \\ return 5678;
+ \\}
+ ,
+ ".tmp_source.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND.",
+ );
+
+ cases.add(
+ "attempted `||` on boolean values",
+ \\export fn entry(a: bool, b: bool) i32 {
+ \\ if (a || b) {
+ \\ return 1234;
+ \\ }
+ \\ return 5678;
+ \\}
+ ,
+ ".tmp_source.zig:2:9: error: expected error set type, found 'bool'",
+ ".tmp_source.zig:2:11: note: `||` merges error sets; `or` performs boolean OR",
+ );
+
+ cases.add(
+ "compile log a pointer to an opaque value",
+ \\export fn entry() void {
+ \\ @compileLog(@ptrCast(*const c_void, &entry));
+ \\}
+ ,
+ ".tmp_source.zig:2:5: error: found compile log statement",
+ );
+
+ cases.add(
+ "duplicate boolean switch value",
+ \\comptime {
+ \\ const x = switch (true) {
+ \\ true => false,
+ \\ false => true,
+ \\ true => false,
+ \\ };
+ \\}
+ \\comptime {
+ \\ const x = switch (true) {
+ \\ false => true,
+ \\ true => false,
+ \\ false => true,
+ \\ };
+ \\}
+ ,
+ ".tmp_source.zig:5:9: error: duplicate switch value",
+ ".tmp_source.zig:12:9: error: duplicate switch value",
+ );
+
+ cases.add(
+ "missing boolean switch value",
+ \\comptime {
+ \\ const x = switch (true) {
+ \\ true => false,
+ \\ };
+ \\}
+ \\comptime {
+ \\ const x = switch (true) {
+ \\ false => true,
+ \\ };
+ \\}
+ ,
+ ".tmp_source.zig:2:15: error: switch must handle all possibilities",
+ ".tmp_source.zig:7:15: error: switch must handle all possibilities",
+ );
+
+ cases.add(
+ "reading past end of pointer casted array",
+ \\comptime {
+ \\ const array = "aoeu";
+ \\ const slice = array[2..];
+ \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
+ \\ const deref = int_ptr.*;
+ \\}
+ ,
+ ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes",
+ );
+
cases.add(
"error note for function parameter incompatibility",
\\fn do_the_thing(func: fn (arg: i32) void) void {}
@@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
);
cases.add(
- "Panic declared with wrong type signature in tests",
+ "wrong panic signature, runtime function",
\\test "" {}
\\
\\pub fn panic() void {}
\\
,
- ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",
+ ".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'",
+ );
+
+ cases.add(
+ "wrong panic signature, generic function",
+ \\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
+ \\ while (true) {}
+ \\}
+ ,
+ ".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'",
+ ".tmp_source.zig:1:5: note: only one of the functions is generic",
);
cases.add(
@@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ const Errors = error{} || u16;
\\}
,
- ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",
- ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",
+ ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'",
+ ".tmp_source.zig:2:23: note: `||` merges error sets; `or` performs boolean OR",
+ ".tmp_source.zig:5:31: error: expected error set type, found type 'u16'",
+ ".tmp_source.zig:5:28: note: `||` merges error sets; `or` performs boolean OR",
);
cases.add(
@@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ f(i32);
\\}
,
- ".tmp_source.zig:4:5: error: use of undefined value",
+ ".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ command.exec();
\\}
,
- ".tmp_source.zig:6:12: error: use of undefined value",
+ ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ command.exec();
\\}
,
- ".tmp_source.zig:6:12: error: use of undefined value",
+ ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
,
- ".tmp_source.zig:1:13: error: newline not allowed in string literal",
+ ".tmp_source.zig:1:15: error: newline not allowed in string literal",
);
cases.add(
@@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(x)); }
,
- ".tmp_source.zig:1:15: error: use of undefined value",
+ ".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a / a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a /= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a % a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a %= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a + a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a += a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a +% a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a +%= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a - a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a -= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a -% a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a -%= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a * a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a *= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a *% a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a *%= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a << 2;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a <<= 2;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a >> 2;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a >>= 2;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a & a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a &= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a | a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a |= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a ^ a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ a ^= a;
\\}
,
- ".tmp_source.zig:3:5: error: use of undefined value",
+ ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a == a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a != a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a > a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a >= a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a < a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a <= a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a and a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a or a;
\\}
,
- ".tmp_source.zig:3:9: error: use of undefined value",
+ ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = -a;
\\}
,
- ".tmp_source.zig:3:10: error: use of undefined value",
+ ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = -%a;
\\}
,
- ".tmp_source.zig:3:11: error: use of undefined value",
+ ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = ~a;
\\}
,
- ".tmp_source.zig:3:10: error: use of undefined value",
+ ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = !a;
\\}
,
- ".tmp_source.zig:3:10: error: use of undefined value",
+ ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a orelse false;
\\}
,
- ".tmp_source.zig:3:11: error: use of undefined value",
+ ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ _ = a catch |err| false;
\\}
,
- ".tmp_source.zig:3:11: error: use of undefined value",
+ ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
);
cases.add(
@@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return 2;
\\}
,
- ".tmp_source.zig:2:15: error: unable to infer expression type",
+ ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
);
cases.add(
@@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"truncate sign mismatch",
\\fn f() i8 {
- \\ const x: u32 = 10;
+ \\ var x: u32 = 10;
\\ return @truncate(i8, x);
\\}
\\
@@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\
\\export fn entry() usize { return @sizeOf(@typeOf(a)); }
,
- ".tmp_source.zig:2:11: error: expected type, found 'i32'",
+ ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
);
cases.add(
@@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
);
- cases.add(
- "@setEvalBranchQuota in non-root comptime execution context",
- \\comptime {
- \\ foo();
- \\}
- \\fn foo() void {
- \\ @setEvalBranchQuota(1001);
- \\}
- ,
- ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",
- ".tmp_source.zig:2:8: note: called from here",
- ".tmp_source.zig:1:10: note: called from here",
- );
-
cases.add(
"wrong pointer implicitly casted to pointer to @OpaqueType()",
\\const Derp = @OpaqueType();
@@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
);
+
+ cases.add(
+ "runtime assignment to comptime struct type",
+ \\const Foo = struct {
+ \\ Bar: u8,
+ \\ Baz: type,
+ \\};
+ \\export fn f() void {
+ \\ var x: u8 = 0;
+ \\ const foo = Foo { .Bar = x, .Baz = u8 };
+ \\}
+ ,
+ ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
+ );
+
+ cases.add(
+ "runtime assignment to comptime union type",
+ \\const Foo = union {
+ \\ Bar: u8,
+ \\ Baz: type,
+ \\};
+ \\export fn f() void {
+ \\ var x: u8 = 0;
+ \\ const foo = Foo { .Bar = x };
+ \\}
+ ,
+ ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
+ );
+
+ cases.addTest(
+ "nested vectors",
+ \\export fn entry() void {
+ \\ const V = @Vector(4, @Vector(4, u8));
+ \\ var v: V = undefined;
+ \\}
+ ,
+ ".tmp_source.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid",
+ );
}
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
index 7c13f5b6fa..12cac64b3a 100644
--- a/test/runtime_safety.zig
+++ b/test/runtime_safety.zig
@@ -1,6 +1,16 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompareOutputContext) void {
+ cases.addRuntimeSafety("pointer casting null to non-optional pointer",
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ @import("std").os.exit(126);
+ \\}
+ \\pub fn main() void {
+ \\ var c_ptr: [*c]u8 = 0;
+ \\ var zig_ptr: *u8 = c_ptr;
+ \\}
+ );
+
cases.addRuntimeSafety("@intToEnum - no matching tag value",
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
\\ @import("std").os.exit(126);
@@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\}
);
+ cases.addRuntimeSafety("vector integer addition overflow",
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ @import("std").os.exit(126);
+ \\}
+ \\pub fn main() void {
+ \\ var a: @Vector(4, i32) = []i32{ 1, 2, 2147483643, 4 };
+ \\ var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 };
+ \\ const x = add(a, b);
+ \\}
+ \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+ \\ return a + b;
+ \\}
+ );
+
cases.addRuntimeSafety("integer subtraction overflow",
\\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
\\ @import("std").os.exit(126);
@@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\}
);
+ // @intCast a runtime integer to u0 actually results in a comptime-known value,
+ // but we still emit a safety check to ensure the integer was 0 and thus
+ // did not truncate information.
+ cases.addRuntimeSafety("@intCast to u0",
+ \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+ \\ @import("std").os.exit(126);
+ \\}
+ \\
+ \\pub fn main() void {
+ \\ bar(1, 1);
+ \\}
+ \\
+ \\fn bar(one: u1, not_zero: i32) void {
+ \\ var x = one << @intCast(u0, not_zero);
+ \\}
+ );
+
// This case makes sure that the code compiles and runs. There is not actually a special
// runtime safety check having to do specifically with error return traces across suspend points.
cases.addRuntimeSafety("error return trace across suspend points",
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
new file mode 100644
index 0000000000..df311637fa
--- /dev/null
+++ b/test/stage1/behavior.zig
@@ -0,0 +1,82 @@
+comptime {
+ _ = @import("behavior/align.zig");
+ _ = @import("behavior/alignof.zig");
+ _ = @import("behavior/array.zig");
+ _ = @import("behavior/asm.zig");
+ _ = @import("behavior/atomics.zig");
+ _ = @import("behavior/bit_shifting.zig");
+ _ = @import("behavior/bitcast.zig");
+ _ = @import("behavior/bitreverse.zig");
+ _ = @import("behavior/bool.zig");
+ _ = @import("behavior/bswap.zig");
+ _ = @import("behavior/bugs/1076.zig");
+ _ = @import("behavior/bugs/1111.zig");
+ _ = @import("behavior/bugs/1277.zig");
+ _ = @import("behavior/bugs/1322.zig");
+ _ = @import("behavior/bugs/1381.zig");
+ _ = @import("behavior/bugs/1421.zig");
+ _ = @import("behavior/bugs/1442.zig");
+ _ = @import("behavior/bugs/1486.zig");
+ _ = @import("behavior/bugs/1851.zig");
+ _ = @import("behavior/bugs/394.zig");
+ _ = @import("behavior/bugs/655.zig");
+ _ = @import("behavior/bugs/656.zig");
+ _ = @import("behavior/bugs/726.zig");
+ _ = @import("behavior/bugs/828.zig");
+ _ = @import("behavior/bugs/920.zig");
+ _ = @import("behavior/byval_arg_var.zig");
+ _ = @import("behavior/cancel.zig");
+ _ = @import("behavior/cast.zig");
+ _ = @import("behavior/const_slice_child.zig");
+ _ = @import("behavior/coroutine_await_struct.zig");
+ _ = @import("behavior/coroutines.zig");
+ _ = @import("behavior/defer.zig");
+ _ = @import("behavior/enum.zig");
+ _ = @import("behavior/enum_with_members.zig");
+ _ = @import("behavior/error.zig");
+ _ = @import("behavior/eval.zig");
+ _ = @import("behavior/field_parent_ptr.zig");
+ _ = @import("behavior/fn.zig");
+ _ = @import("behavior/fn_in_struct_in_comptime.zig");
+ _ = @import("behavior/for.zig");
+ _ = @import("behavior/generics.zig");
+ _ = @import("behavior/if.zig");
+ _ = @import("behavior/import.zig");
+ _ = @import("behavior/incomplete_struct_param_tld.zig");
+ _ = @import("behavior/inttoptr.zig");
+ _ = @import("behavior/ir_block_deps.zig");
+ _ = @import("behavior/math.zig");
+ _ = @import("behavior/merge_error_sets.zig");
+ _ = @import("behavior/misc.zig");
+ _ = @import("behavior/namespace_depends_on_compile_var/index.zig");
+ _ = @import("behavior/new_stack_call.zig");
+ _ = @import("behavior/null.zig");
+ _ = @import("behavior/optional.zig");
+ _ = @import("behavior/pointers.zig");
+ _ = @import("behavior/popcount.zig");
+ _ = @import("behavior/ptrcast.zig");
+ _ = @import("behavior/pub_enum/index.zig");
+ _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
+ _ = @import("behavior/reflection.zig");
+ _ = @import("behavior/sizeof_and_typeof.zig");
+ _ = @import("behavior/slice.zig");
+ _ = @import("behavior/struct.zig");
+ _ = @import("behavior/struct_contains_null_ptr_itself.zig");
+ _ = @import("behavior/struct_contains_slice_of_itself.zig");
+ _ = @import("behavior/switch.zig");
+ _ = @import("behavior/switch_prong_err_enum.zig");
+ _ = @import("behavior/switch_prong_implicit_cast.zig");
+ _ = @import("behavior/syntax.zig");
+ _ = @import("behavior/this.zig");
+ _ = @import("behavior/truncate.zig");
+ _ = @import("behavior/try.zig");
+ _ = @import("behavior/type_info.zig");
+ _ = @import("behavior/undefined.zig");
+ _ = @import("behavior/underscore.zig");
+ _ = @import("behavior/union.zig");
+ _ = @import("behavior/var_args.zig");
+ _ = @import("behavior/vector.zig");
+ _ = @import("behavior/void.zig");
+ _ = @import("behavior/while.zig");
+ _ = @import("behavior/widening.zig");
+}
diff --git a/test/cases/align.zig b/test/stage1/behavior/align.zig
similarity index 72%
rename from test/cases/align.zig
rename to test/stage1/behavior/align.zig
index 3dff57feb8..dbd705ddc4 100644
--- a/test/cases/align.zig
+++ b/test/stage1/behavior/align.zig
@@ -1,13 +1,13 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const builtin = @import("builtin");
var foo: u8 align(4) = 100;
test "global variable alignment" {
- assert(@typeOf(&foo).alignment == 4);
- assert(@typeOf(&foo) == *align(4) u8);
+ expect(@typeOf(&foo).alignment == 4);
+ expect(@typeOf(&foo) == *align(4) u8);
const slice = (*[1]u8)(&foo)[0..];
- assert(@typeOf(slice) == []align(4) u8);
+ expect(@typeOf(slice) == []align(4) u8);
}
fn derp() align(@sizeOf(usize) * 2) i32 {
@@ -17,9 +17,9 @@ fn noop1() align(1) void {}
fn noop4() align(4) void {}
test "function alignment" {
- assert(derp() == 1234);
- assert(@typeOf(noop1) == fn () align(1) void);
- assert(@typeOf(noop4) == fn () align(4) void);
+ expect(derp() == 1234);
+ expect(@typeOf(noop1) == fn () align(1) void);
+ expect(@typeOf(noop4) == fn () align(4) void);
noop1();
noop4();
}
@@ -30,7 +30,7 @@ var baz: packed struct {
} = undefined;
test "packed struct alignment" {
- assert(@typeOf(&baz.b) == *align(1) u32);
+ expect(@typeOf(&baz.b) == *align(1) u32);
}
const blah: packed struct {
@@ -40,17 +40,17 @@ const blah: packed struct {
} = undefined;
test "bit field alignment" {
- assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
+ expect(@typeOf(&blah.b) == *align(1:3:1) const u3);
}
test "default alignment allows unspecified in type syntax" {
- assert(*u32 == *align(@alignOf(u32)) u32);
+ expect(*u32 == *align(@alignOf(u32)) u32);
}
test "implicitly decreasing pointer alignment" {
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
- assert(addUnaligned(&a, &b) == 7);
+ expect(addUnaligned(&a, &b) == 7);
}
fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
@@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
test "implicitly decreasing slice alignment" {
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
- assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
+ expect(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
}
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
return a[0] + b[0];
@@ -77,7 +77,7 @@ fn testBytesAlign(b: u8) void {
b,
};
const ptr = @ptrCast(*u32, &bytes[0]);
- assert(ptr.* == 0x33333333);
+ expect(ptr.* == 0x33333333);
}
test "specifying alignment allows slice cast" {
@@ -91,13 +91,13 @@ fn testBytesAlignSlice(b: u8) void {
b,
};
const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
- assert(slice[0] == 0x33333333);
+ expect(slice[0] == 0x33333333);
}
test "@alignCast pointers" {
var x: u32 align(4) = 1;
expectsOnly1(&x);
- assert(x == 2);
+ expect(x == 2);
}
fn expectsOnly1(x: *align(1) u32) void {
expects4(@alignCast(4, x));
@@ -113,7 +113,7 @@ test "@alignCast slices" {
};
const slice = array[0..];
sliceExpectsOnly1(slice);
- assert(slice[0] == 2);
+ expect(slice[0] == 2);
}
fn sliceExpectsOnly1(slice: []align(1) u32) void {
sliceExpects4(@alignCast(4, slice));
@@ -128,7 +128,7 @@ test "implicitly decreasing fn alignment" {
}
fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
- assert(ptr() == answer);
+ expect(ptr() == answer);
}
fn alignedSmall() align(8) i32 {
@@ -139,7 +139,7 @@ fn alignedBig() align(16) i32 {
}
test "@alignCast functions" {
- assert(fnExpectsOnly1(simple4) == 0x19);
+ expect(fnExpectsOnly1(simple4) == 0x19);
}
fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
return fnExpects4(@alignCast(4, ptr));
@@ -152,9 +152,9 @@ fn simple4() align(4) i32 {
}
test "generic function with align param" {
- assert(whyWouldYouEverDoThis(1) == 0x1);
- assert(whyWouldYouEverDoThis(4) == 0x1);
- assert(whyWouldYouEverDoThis(8) == 0x1);
+ expect(whyWouldYouEverDoThis(1) == 0x1);
+ expect(whyWouldYouEverDoThis(4) == 0x1);
+ expect(whyWouldYouEverDoThis(8) == 0x1);
}
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
@@ -164,28 +164,28 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
test "@ptrCast preserves alignment of bigger source" {
var x: u32 align(16) = 1234;
const ptr = @ptrCast(*u8, &x);
- assert(@typeOf(ptr) == *align(16) u8);
+ expect(@typeOf(ptr) == *align(16) u8);
}
test "runtime known array index has best alignment possible" {
// take full advantage of over-alignment
var array align(4) = []u8{ 1, 2, 3, 4 };
- assert(@typeOf(&array[0]) == *align(4) u8);
- assert(@typeOf(&array[1]) == *u8);
- assert(@typeOf(&array[2]) == *align(2) u8);
- assert(@typeOf(&array[3]) == *u8);
+ expect(@typeOf(&array[0]) == *align(4) u8);
+ expect(@typeOf(&array[1]) == *u8);
+ expect(@typeOf(&array[2]) == *align(2) u8);
+ expect(@typeOf(&array[3]) == *u8);
// because align is too small but we still figure out to use 2
var bigger align(2) = []u64{ 1, 2, 3, 4 };
- assert(@typeOf(&bigger[0]) == *align(2) u64);
- assert(@typeOf(&bigger[1]) == *align(2) u64);
- assert(@typeOf(&bigger[2]) == *align(2) u64);
- assert(@typeOf(&bigger[3]) == *align(2) u64);
+ expect(@typeOf(&bigger[0]) == *align(2) u64);
+ expect(@typeOf(&bigger[1]) == *align(2) u64);
+ expect(@typeOf(&bigger[2]) == *align(2) u64);
+ expect(@typeOf(&bigger[3]) == *align(2) u64);
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
var smaller align(2) = []u32{ 1, 2, 3, 4 };
- comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
- comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
+ comptime expect(@typeOf(smaller[0..]) == []align(2) u32);
+ comptime expect(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
testIndex(smaller[0..].ptr, 0, *align(2) u32);
testIndex(smaller[0..].ptr, 1, *align(2) u32);
testIndex(smaller[0..].ptr, 2, *align(2) u32);
@@ -198,14 +198,14 @@ test "runtime known array index has best alignment possible" {
testIndex2(array[0..].ptr, 3, *u8);
}
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
- comptime assert(@typeOf(&smaller[index]) == T);
+ comptime expect(@typeOf(&smaller[index]) == T);
}
fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
- comptime assert(@typeOf(&ptr[index]) == T);
+ comptime expect(@typeOf(&ptr[index]) == T);
}
test "alignstack" {
- assert(fnWithAlignedStack() == 1234);
+ expect(fnWithAlignedStack() == 1234);
}
fn fnWithAlignedStack() i32 {
@@ -214,7 +214,7 @@ fn fnWithAlignedStack() i32 {
}
test "alignment of structs" {
- assert(@alignOf(struct {
+ expect(@alignOf(struct {
a: i32,
b: *i32,
}) == @alignOf(usize));
diff --git a/test/cases/alignof.zig b/test/stage1/behavior/alignof.zig
similarity index 65%
rename from test/cases/alignof.zig
rename to test/stage1/behavior/alignof.zig
index 433e86e45e..d4d9661ead 100644
--- a/test/cases/alignof.zig
+++ b/test/stage1/behavior/alignof.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
@@ -10,8 +10,9 @@ const Foo = struct {
};
test "@alignOf(T) before referencing T" {
- comptime assert(@alignOf(Foo) != maxInt(usize));
+ comptime expect(@alignOf(Foo) != maxInt(usize));
if (builtin.arch == builtin.Arch.x86_64) {
- comptime assert(@alignOf(Foo) == 4);
+ comptime expect(@alignOf(Foo) == 4);
}
}
+
diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig
new file mode 100644
index 0000000000..99b828e53c
--- /dev/null
+++ b/test/stage1/behavior/array.zig
@@ -0,0 +1,270 @@
+const expect = @import("std").testing.expect;
+const mem = @import("std").mem;
+
+test "arrays" {
+ var array: [5]u32 = undefined;
+
+ var i: u32 = 0;
+ while (i < 5) {
+ array[i] = i + 1;
+ i = array[i];
+ }
+
+ i = 0;
+ var accumulator = u32(0);
+ while (i < 5) {
+ accumulator += array[i];
+
+ i += 1;
+ }
+
+ expect(accumulator == 15);
+ expect(getArrayLen(array) == 5);
+}
+fn getArrayLen(a: []const u32) usize {
+ return a.len;
+}
+
+test "void arrays" {
+ var array: [4]void = undefined;
+ array[0] = void{};
+ array[1] = array[2];
+ expect(@sizeOf(@typeOf(array)) == 0);
+ expect(array.len == 4);
+}
+
+test "array literal" {
+ const hex_mult = []u16{
+ 4096,
+ 256,
+ 16,
+ 1,
+ };
+
+ expect(hex_mult.len == 4);
+ expect(hex_mult[1] == 256);
+}
+
+test "array dot len const expr" {
+ expect(comptime x: {
+ break :x some_array.len == 4;
+ });
+}
+
+const ArrayDotLenConstExpr = struct {
+ y: [some_array.len]u8,
+};
+const some_array = []u8{
+ 0,
+ 1,
+ 2,
+ 3,
+};
+
+test "nested arrays" {
+ const array_of_strings = [][]const u8{
+ "hello",
+ "this",
+ "is",
+ "my",
+ "thing",
+ };
+ for (array_of_strings) |s, i| {
+ if (i == 0) expect(mem.eql(u8, s, "hello"));
+ if (i == 1) expect(mem.eql(u8, s, "this"));
+ if (i == 2) expect(mem.eql(u8, s, "is"));
+ if (i == 3) expect(mem.eql(u8, s, "my"));
+ if (i == 4) expect(mem.eql(u8, s, "thing"));
+ }
+}
+
+var s_array: [8]Sub = undefined;
+const Sub = struct {
+ b: u8,
+};
+const Str = struct {
+ a: []Sub,
+};
+test "set global var array via slice embedded in struct" {
+ var s = Str{ .a = s_array[0..] };
+
+ s.a[0].b = 1;
+ s.a[1].b = 2;
+ s.a[2].b = 3;
+
+ expect(s_array[0].b == 1);
+ expect(s_array[1].b == 2);
+ expect(s_array[2].b == 3);
+}
+
+test "array literal with specified size" {
+ var array = [2]u8{
+ 1,
+ 2,
+ };
+ expect(array[0] == 1);
+ expect(array[1] == 2);
+}
+
+test "array child property" {
+ var x: [5]i32 = undefined;
+ expect(@typeOf(x).Child == i32);
+}
+
+test "array len property" {
+ var x: [5]i32 = undefined;
+ expect(@typeOf(x).len == 5);
+}
+
+test "array len field" {
+ var arr = [4]u8{ 0, 0, 0, 0 };
+ var ptr = &arr;
+ expect(arr.len == 4);
+ comptime expect(arr.len == 4);
+ expect(ptr.len == 4);
+ comptime expect(ptr.len == 4);
+}
+
+test "single-item pointer to array indexing and slicing" {
+ testSingleItemPtrArrayIndexSlice();
+ comptime testSingleItemPtrArrayIndexSlice();
+}
+
+fn testSingleItemPtrArrayIndexSlice() void {
+ var array = "aaaa";
+ doSomeMangling(&array);
+ expect(mem.eql(u8, "azya", array));
+}
+
+fn doSomeMangling(array: *[4]u8) void {
+ array[1] = 'z';
+ array[2..3][0] = 'y';
+}
+
+test "implicit cast single-item pointer" {
+ testImplicitCastSingleItemPtr();
+ comptime testImplicitCastSingleItemPtr();
+}
+
+fn testImplicitCastSingleItemPtr() void {
+ var byte: u8 = 100;
+ const slice = (*[1]u8)(&byte)[0..];
+ slice[0] += 1;
+ expect(byte == 101);
+}
+
+fn testArrayByValAtComptime(b: [2]u8) u8 {
+ return b[0];
+}
+
+test "comptime evalutating function that takes array by value" {
+ const arr = []u8{ 0, 1 };
+ _ = comptime testArrayByValAtComptime(arr);
+ _ = comptime testArrayByValAtComptime(arr);
+}
+
+test "implicit comptime in array type size" {
+ var arr: [plusOne(10)]bool = undefined;
+ expect(arr.len == 11);
+}
+
+fn plusOne(x: u32) u32 {
+ return x + 1;
+}
+
+test "array literal as argument to function" {
+ const S = struct {
+ fn entry(two: i32) void {
+ foo([]i32{
+ 1,
+ 2,
+ 3,
+ });
+ foo([]i32{
+ 1,
+ two,
+ 3,
+ });
+ foo2(true, []i32{
+ 1,
+ 2,
+ 3,
+ });
+ foo2(true, []i32{
+ 1,
+ two,
+ 3,
+ });
+ }
+ fn foo(x: []const i32) void {
+ expect(x[0] == 1);
+ expect(x[1] == 2);
+ expect(x[2] == 3);
+ }
+ fn foo2(trash: bool, x: []const i32) void {
+ expect(trash);
+ expect(x[0] == 1);
+ expect(x[1] == 2);
+ expect(x[2] == 3);
+ }
+ };
+ S.entry(2);
+ comptime S.entry(2);
+}
+
+test "double nested array to const slice cast in array literal" {
+ const S = struct {
+ fn entry(two: i32) void {
+ const cases = [][]const []const i32{
+ [][]const i32{[]i32{1}},
+ [][]const i32{[]i32{ 2, 3 }},
+ [][]const i32{
+ []i32{4},
+ []i32{ 5, 6, 7 },
+ },
+ };
+ check(cases);
+
+ const cases2 = [][]const i32{
+ []i32{1},
+ []i32{ two, 3 },
+ };
+ expect(cases2.len == 2);
+ expect(cases2[0].len == 1);
+ expect(cases2[0][0] == 1);
+ expect(cases2[1].len == 2);
+ expect(cases2[1][0] == 2);
+ expect(cases2[1][1] == 3);
+
+ const cases3 = [][]const []const i32{
+ [][]const i32{[]i32{1}},
+ [][]const i32{[]i32{ two, 3 }},
+ [][]const i32{
+ []i32{4},
+ []i32{ 5, 6, 7 },
+ },
+ };
+ check(cases3);
+ }
+
+ fn check(cases: []const []const []const i32) void {
+ expect(cases.len == 3);
+ expect(cases[0].len == 1);
+ expect(cases[0][0].len == 1);
+ expect(cases[0][0][0] == 1);
+ expect(cases[1].len == 1);
+ expect(cases[1][0].len == 2);
+ expect(cases[1][0][0] == 2);
+ expect(cases[1][0][1] == 3);
+ expect(cases[2].len == 2);
+ expect(cases[2][0].len == 1);
+ expect(cases[2][0][0] == 4);
+ expect(cases[2][1].len == 3);
+ expect(cases[2][1][0] == 5);
+ expect(cases[2][1][1] == 6);
+ expect(cases[2][1][2] == 7);
+ }
+ };
+ S.entry(2);
+ comptime S.entry(2);
+}
diff --git a/test/stage1/behavior/asm.zig b/test/stage1/behavior/asm.zig
new file mode 100644
index 0000000000..845d80777a
--- /dev/null
+++ b/test/stage1/behavior/asm.zig
@@ -0,0 +1,92 @@
+const config = @import("builtin");
+const expect = @import("std").testing.expect;
+
+comptime {
+ if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
+ asm volatile (
+ \\.globl aoeu;
+ \\.type aoeu, @function;
+ \\.set aoeu, derp;
+ );
+ }
+}
+
+test "module level assembly" {
+ if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
+ expect(aoeu() == 1234);
+ }
+}
+
+test "output constraint modifiers" {
+ // This is only testing compilation.
+ var a: u32 = 3;
+ asm volatile (""
+ : [_] "=m,r" (a)
+ :
+ : ""
+ );
+ asm volatile (""
+ : [_] "=r,m" (a)
+ :
+ : ""
+ );
+}
+
+test "alternative constraints" {
+ // Make sure we allow commas as a separator for alternative constraints.
+ var a: u32 = 3;
+ asm volatile (""
+ : [_] "=r,m" (a)
+ : [_] "r,m" (a)
+ : ""
+ );
+}
+
+test "sized integer/float in asm input" {
+ asm volatile (""
+ :
+ : [_] "m" (usize(3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (i15(-3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (u3(3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (i3(3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (u121(3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (i121(3))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (f32(3.17))
+ : ""
+ );
+ asm volatile (""
+ :
+ : [_] "m" (f64(3.17))
+ : ""
+ );
+}
+
+extern fn aoeu() i32;
+
+export fn derp() i32 {
+ return 1234;
+}
diff --git a/test/cases/atomics.zig b/test/stage1/behavior/atomics.zig
similarity index 71%
rename from test/cases/atomics.zig
rename to test/stage1/behavior/atomics.zig
index 67c9ab3dd1..daa463fd45 100644
--- a/test/cases/atomics.zig
+++ b/test/stage1/behavior/atomics.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
@@ -7,18 +7,18 @@ const AtomicOrder = builtin.AtomicOrder;
test "cmpxchg" {
var x: i32 = 1234;
if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
- assert(x1 == 1234);
+ expect(x1 == 1234);
} else {
@panic("cmpxchg should have failed");
}
while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
- assert(x1 == 1234);
+ expect(x1 == 1234);
}
- assert(x == 5678);
+ expect(x == 5678);
- assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
- assert(x == 42);
+ expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ expect(x == 42);
}
test "fence" {
@@ -30,24 +30,24 @@ test "fence" {
test "atomicrmw and atomicload" {
var data: u8 = 200;
testAtomicRmw(&data);
- assert(data == 42);
+ expect(data == 42);
testAtomicLoad(&data);
}
fn testAtomicRmw(ptr: *u8) void {
const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
- assert(prev_value == 200);
+ expect(prev_value == 200);
comptime {
var x: i32 = 1234;
const y: i32 = 12345;
- assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
- assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
+ expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
+ expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
}
}
fn testAtomicLoad(ptr: *u8) void {
const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
- assert(x == 42);
+ expect(x == 42);
}
test "cmpxchg with ptr" {
@@ -56,16 +56,16 @@ test "cmpxchg with ptr" {
var data3: i32 = 9101;
var x: *i32 = &data1;
if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
- assert(x1 == &data1);
+ expect(x1 == &data1);
} else {
@panic("cmpxchg should have failed");
}
while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
- assert(x1 == &data1);
+ expect(x1 == &data1);
}
- assert(x == &data3);
+ expect(x == &data3);
- assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
- assert(x == &data2);
+ expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
+ expect(x == &data2);
}
diff --git a/test/cases/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig
similarity index 92%
rename from test/cases/bit_shifting.zig
rename to test/stage1/behavior/bit_shifting.zig
index 325e765bb0..610acc06c2 100644
--- a/test/cases/bit_shifting.zig
+++ b/test/stage1/behavior/bit_shifting.zig
@@ -1,9 +1,9 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
- assert(Key == @IntType(false, Key.bit_count));
- assert(Key.bit_count >= mask_bit_count);
+ expect(Key == @IntType(false, Key.bit_count));
+ expect(Key.bit_count >= mask_bit_count);
const ShardKey = @IntType(false, mask_bit_count);
const shift_amount = Key.bit_count - ShardKey.bit_count;
return struct {
@@ -77,12 +77,12 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c
var node_buffer: [node_count]Table.Node = undefined;
for (node_buffer) |*node, i| {
const key = @intCast(Key, i);
- assert(table.get(key) == null);
+ expect(table.get(key) == null);
node.init(key, {});
table.put(node);
}
for (node_buffer) |*node, i| {
- assert(table.get(@intCast(Key, i)) == node);
+ expect(table.get(@intCast(Key, i)) == node);
}
}
diff --git a/test/cases/bitcast.zig b/test/stage1/behavior/bitcast.zig
similarity index 81%
rename from test/cases/bitcast.zig
rename to test/stage1/behavior/bitcast.zig
index d85a84ed22..9607d2e3ef 100644
--- a/test/cases/bitcast.zig
+++ b/test/stage1/behavior/bitcast.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const maxInt = std.math.maxInt;
test "@bitCast i32 -> u32" {
@@ -8,8 +8,8 @@ test "@bitCast i32 -> u32" {
}
fn testBitCast_i32_u32() void {
- assert(conv(-1) == maxInt(u32));
- assert(conv2(maxInt(u32)) == -1);
+ expect(conv(-1) == maxInt(u32));
+ expect(conv2(maxInt(u32)) == -1);
}
fn conv(x: i32) u32 {
@@ -27,11 +27,10 @@ test "@bitCast extern enum to its integer type" {
fn testBitCastExternEnum() void {
var SOCK_DGRAM = @This().B;
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
- assert(sock_dgram == 1);
+ expect(sock_dgram == 1);
}
};
SOCK.testBitCastExternEnum();
comptime SOCK.testBitCastExternEnum();
}
-
diff --git a/test/stage1/behavior/bitreverse.zig b/test/stage1/behavior/bitreverse.zig
new file mode 100644
index 0000000000..3897a3eab7
--- /dev/null
+++ b/test/stage1/behavior/bitreverse.zig
@@ -0,0 +1,81 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const minInt = std.math.minInt;
+
+test "@bitreverse" {
+ comptime testBitReverse();
+ testBitReverse();
+}
+
+fn testBitReverse() void {
+ // using comptime_ints, unsigned
+ expect(@bitreverse(u0, 0) == 0);
+ expect(@bitreverse(u5, 0x12) == 0x9);
+ expect(@bitreverse(u8, 0x12) == 0x48);
+ expect(@bitreverse(u16, 0x1234) == 0x2c48);
+ expect(@bitreverse(u24, 0x123456) == 0x6a2c48);
+ expect(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
+ expect(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
+ expect(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
+ expect(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
+ expect(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
+ expect(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
+
+ // using runtime uints, unsigned
+ var num0: u0 = 0;
+ expect(@bitreverse(u0, num0) == 0);
+ var num5: u5 = 0x12;
+ expect(@bitreverse(u5, num5) == 0x9);
+ var num8: u8 = 0x12;
+ expect(@bitreverse(u8, num8) == 0x48);
+ var num16: u16 = 0x1234;
+ expect(@bitreverse(u16, num16) == 0x2c48);
+ var num24: u24 = 0x123456;
+ expect(@bitreverse(u24, num24) == 0x6a2c48);
+ var num32: u32 = 0x12345678;
+ expect(@bitreverse(u32, num32) == 0x1e6a2c48);
+ var num40: u40 = 0x123456789a;
+ expect(@bitreverse(u40, num40) == 0x591e6a2c48);
+ var num48: u48 = 0x123456789abc;
+ expect(@bitreverse(u48, num48) == 0x3d591e6a2c48);
+ var num56: u56 = 0x123456789abcde;
+ expect(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
+ var num64: u64 = 0x123456789abcdef1;
+ expect(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
+ var num128: u128 = 0x123456789abcdef11121314151617181;
+ expect(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
+
+ // using comptime_ints, signed, positive
+ expect(@bitreverse(i0, 0) == 0);
+ expect(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
+ expect(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
+ expect(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
+ expect(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
+ expect(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
+ expect(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
+ expect(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
+ expect(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
+ expect(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
+
+ // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
+ var neg5: i5 = minInt(i5) + 1;
+ expect(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
+ var neg8: i8 = -18;
+ expect(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
+ var neg16: i16 = -32694;
+ expect(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
+ var neg24: i24 = -6773785;
+ expect(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
+ var neg32: i32 = -16773785;
+ expect(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
+ var neg40: i40 = minInt(i40) + 12345;
+ expect(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
+ var neg48: i48 = minInt(i48) + 12345;
+ expect(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
+ var neg56: i56 = minInt(i56) + 12345;
+ expect(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
+ var neg64: i64 = minInt(i64) + 12345;
+ expect(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
+ var neg128: i128 = minInt(i128) + 12345;
+ expect(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
+}
diff --git a/test/cases/bool.zig b/test/stage1/behavior/bool.zig
similarity index 55%
rename from test/cases/bool.zig
rename to test/stage1/behavior/bool.zig
index 3e4ac9c1cf..dfc2279005 100644
--- a/test/cases/bool.zig
+++ b/test/stage1/behavior/bool.zig
@@ -1,25 +1,25 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "bool literals" {
- assert(true);
- assert(!false);
+ expect(true);
+ expect(!false);
}
test "cast bool to int" {
const t = true;
const f = false;
- assert(@boolToInt(t) == u32(1));
- assert(@boolToInt(f) == u32(0));
+ expect(@boolToInt(t) == u32(1));
+ expect(@boolToInt(f) == u32(0));
nonConstCastBoolToInt(t, f);
}
fn nonConstCastBoolToInt(t: bool, f: bool) void {
- assert(@boolToInt(t) == u32(1));
- assert(@boolToInt(f) == u32(0));
+ expect(@boolToInt(t) == u32(1));
+ expect(@boolToInt(f) == u32(0));
}
test "bool cmp" {
- assert(testBoolCmp(true, false) == false);
+ expect(testBoolCmp(true, false) == false);
}
fn testBoolCmp(a: bool, b: bool) bool {
return a == b;
@@ -30,6 +30,6 @@ const global_t = true;
const not_global_f = !global_f;
const not_global_t = !global_t;
test "compile time bool not" {
- assert(not_global_f);
- assert(!not_global_t);
+ expect(not_global_f);
+ expect(!not_global_t);
}
diff --git a/test/stage1/behavior/bswap.zig b/test/stage1/behavior/bswap.zig
new file mode 100644
index 0000000000..beffa0f73a
--- /dev/null
+++ b/test/stage1/behavior/bswap.zig
@@ -0,0 +1,32 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "@bswap" {
+ comptime testByteSwap();
+ testByteSwap();
+}
+
+fn testByteSwap() void {
+ expect(@bswap(u0, 0) == 0);
+ expect(@bswap(u8, 0x12) == 0x12);
+ expect(@bswap(u16, 0x1234) == 0x3412);
+ expect(@bswap(u24, 0x123456) == 0x563412);
+ expect(@bswap(u32, 0x12345678) == 0x78563412);
+ expect(@bswap(u40, 0x123456789a) == 0x9a78563412);
+ expect(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
+ expect(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
+ expect(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
+ expect(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
+
+ expect(@bswap(i0, 0) == 0);
+ expect(@bswap(i8, -50) == -50);
+ expect(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
+ expect(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
+ expect(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
+ expect(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
+ expect(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
+ expect(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
+ expect(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
+ expect(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
+ @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
+}
diff --git a/test/cases/bugs/1076.zig b/test/stage1/behavior/bugs/1076.zig
similarity index 79%
rename from test/cases/bugs/1076.zig
rename to test/stage1/behavior/bugs/1076.zig
index 7b84312310..9dc1d111ea 100644
--- a/test/cases/bugs/1076.zig
+++ b/test/stage1/behavior/bugs/1076.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const mem = std.mem;
-const assert = std.debug.assert;
+const expect = std.testing.expect;
test "comptime code should not modify constant data" {
testCastPtrOfArrayToSliceAndPtr();
@@ -11,6 +11,6 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu";
const x: [*]u8 = &array;
x[0] += 1;
- assert(mem.eql(u8, array[0..], "boeu"));
+ expect(mem.eql(u8, array[0..], "boeu"));
}
diff --git a/test/cases/bugs/1111.zig b/test/stage1/behavior/bugs/1111.zig
similarity index 100%
rename from test/cases/bugs/1111.zig
rename to test/stage1/behavior/bugs/1111.zig
diff --git a/test/cases/bugs/1277.zig b/test/stage1/behavior/bugs/1277.zig
similarity index 82%
rename from test/cases/bugs/1277.zig
rename to test/stage1/behavior/bugs/1277.zig
index a83e7653e2..3aa1db2ea0 100644
--- a/test/cases/bugs/1277.zig
+++ b/test/stage1/behavior/bugs/1277.zig
@@ -11,5 +11,5 @@ fn f() i32 {
}
test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
- std.debug.assertOrPanic(s.f.?() == 1234);
+ std.testing.expect(s.f.?() == 1234);
}
diff --git a/test/cases/bugs/1322.zig b/test/stage1/behavior/bugs/1322.zig
similarity index 68%
rename from test/cases/bugs/1322.zig
rename to test/stage1/behavior/bugs/1322.zig
index 2de92191ec..f1d61baa3a 100644
--- a/test/cases/bugs/1322.zig
+++ b/test/stage1/behavior/bugs/1322.zig
@@ -13,7 +13,7 @@ const C = struct {};
test "tagged union with all void fields but a meaningful tag" {
var a: A = A{ .b = B{ .c = C{} } };
- std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
+ std.testing.expect(@TagType(B)(a.b) == @TagType(B).c);
a = A{ .b = B.None };
- std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
+ std.testing.expect(@TagType(B)(a.b) == @TagType(B).None);
}
diff --git a/test/cases/bugs/1381.zig b/test/stage1/behavior/bugs/1381.zig
similarity index 88%
rename from test/cases/bugs/1381.zig
rename to test/stage1/behavior/bugs/1381.zig
index 2d452da156..91c994d7c0 100644
--- a/test/cases/bugs/1381.zig
+++ b/test/stage1/behavior/bugs/1381.zig
@@ -17,5 +17,5 @@ test "union that needs padding bytes inside an array" {
};
const a = as[0].B;
- std.debug.assertOrPanic(a.D == 1);
+ std.testing.expect(a.D == 1);
}
diff --git a/test/cases/bugs/1421.zig b/test/stage1/behavior/bugs/1421.zig
similarity index 73%
rename from test/cases/bugs/1421.zig
rename to test/stage1/behavior/bugs/1421.zig
index fcbb8b70e4..48cf1ae2a6 100644
--- a/test/cases/bugs/1421.zig
+++ b/test/stage1/behavior/bugs/1421.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const S = struct {
fn method() builtin.TypeInfo {
@@ -10,5 +10,5 @@ const S = struct {
test "functions with return type required to be comptime are generic" {
const ti = S.method();
- assert(builtin.TypeId(ti) == builtin.TypeId.Struct);
+ expect(builtin.TypeId(ti) == builtin.TypeId.Struct);
}
diff --git a/test/cases/bugs/1442.zig b/test/stage1/behavior/bugs/1442.zig
similarity index 72%
rename from test/cases/bugs/1442.zig
rename to test/stage1/behavior/bugs/1442.zig
index e9dfd5d2ce..d5ea3f66fe 100644
--- a/test/cases/bugs/1442.zig
+++ b/test/stage1/behavior/bugs/1442.zig
@@ -7,5 +7,5 @@ const Union = union(enum) {
test "const error union field alignment" {
var union_or_err: anyerror!Union = Union{ .Color = 1234 };
- std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
+ std.testing.expect((union_or_err catch unreachable).Color == 1234);
}
diff --git a/test/cases/bugs/1486.zig b/test/stage1/behavior/bugs/1486.zig
similarity index 56%
rename from test/cases/bugs/1486.zig
rename to test/stage1/behavior/bugs/1486.zig
index 98fae36d3a..d1bb8d7053 100644
--- a/test/cases/bugs/1486.zig
+++ b/test/stage1/behavior/bugs/1486.zig
@@ -1,11 +1,11 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const ptr = &global;
var global: u64 = 123;
test "constant pointer to global variable causes runtime load" {
global = 1234;
- assert(&global == ptr);
- assert(ptr.* == 1234);
+ expect(&global == ptr);
+ expect(ptr.* == 1234);
}
diff --git a/test/stage1/behavior/bugs/1851.zig b/test/stage1/behavior/bugs/1851.zig
new file mode 100644
index 0000000000..ff9ab419f8
--- /dev/null
+++ b/test/stage1/behavior/bugs/1851.zig
@@ -0,0 +1,27 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "allocation and looping over 3-byte integer" {
+ expect(@sizeOf(u24) == 4);
+ expect(@sizeOf([1]u24) == 4);
+ expect(@alignOf(u24) == 4);
+ expect(@alignOf([1]u24) == 4);
+ var buffer: [100]u8 = undefined;
+ const a = &std.heap.FixedBufferAllocator.init(&buffer).allocator;
+
+ var x = a.alloc(u24, 2) catch unreachable;
+ expect(x.len == 2);
+ x[0] = 0xFFFFFF;
+ x[1] = 0xFFFFFF;
+
+ const bytes = @sliceToBytes(x);
+ expect(@typeOf(bytes) == []align(4) u8);
+ expect(bytes.len == 8);
+
+ for (bytes) |*b| {
+ b.* = 0x00;
+ }
+
+ expect(x[0] == 0x00);
+ expect(x[1] == 0x00);
+}
diff --git a/test/cases/bugs/394.zig b/test/stage1/behavior/bugs/394.zig
similarity index 73%
rename from test/cases/bugs/394.zig
rename to test/stage1/behavior/bugs/394.zig
index b0afec2357..b1f0b6b605 100644
--- a/test/cases/bugs/394.zig
+++ b/test/stage1/behavior/bugs/394.zig
@@ -7,12 +7,12 @@ const S = struct {
y: E,
};
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "bug 394 fixed" {
const x = S{
.x = 3,
.y = E{ .B = 1 },
};
- assert(x.x == 3);
+ expect(x.x == 3);
}
diff --git a/test/cases/bugs/655.zig b/test/stage1/behavior/bugs/655.zig
similarity index 69%
rename from test/cases/bugs/655.zig
rename to test/stage1/behavior/bugs/655.zig
index ebb8da0658..d4491bfc27 100644
--- a/test/cases/bugs/655.zig
+++ b/test/stage1/behavior/bugs/655.zig
@@ -3,10 +3,10 @@ const other_file = @import("655_other_file.zig");
test "function with *const parameter with type dereferenced by namespace" {
const x: other_file.Integer = 1234;
- comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer);
+ comptime std.testing.expect(@typeOf(&x) == *const other_file.Integer);
foo(&x);
}
fn foo(x: *const other_file.Integer) void {
- std.debug.assert(x.* == 1234);
+ std.testing.expect(x.* == 1234);
}
diff --git a/test/cases/bugs/655_other_file.zig b/test/stage1/behavior/bugs/655_other_file.zig
similarity index 100%
rename from test/cases/bugs/655_other_file.zig
rename to test/stage1/behavior/bugs/655_other_file.zig
diff --git a/test/cases/bugs/656.zig b/test/stage1/behavior/bugs/656.zig
similarity index 86%
rename from test/cases/bugs/656.zig
rename to test/stage1/behavior/bugs/656.zig
index f93f0ac4d5..159ec52d43 100644
--- a/test/cases/bugs/656.zig
+++ b/test/stage1/behavior/bugs/656.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const PrefixOp = union(enum) {
Return,
@@ -22,7 +22,7 @@ fn foo(a: bool, b: bool) void {
PrefixOp.AddrOf => |addr_of_info| {
if (b) {}
if (addr_of_info.align_expr) |align_expr| {
- assert(align_expr == 1234);
+ expect(align_expr == 1234);
}
},
PrefixOp.Return => {},
diff --git a/test/cases/bugs/726.zig b/test/stage1/behavior/bugs/726.zig
similarity index 75%
rename from test/cases/bugs/726.zig
rename to test/stage1/behavior/bugs/726.zig
index 2acc91eb26..dd2a135b56 100644
--- a/test/cases/bugs/726.zig
+++ b/test/stage1/behavior/bugs/726.zig
@@ -1,9 +1,9 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "@ptrCast from const to nullable" {
const c: u8 = 4;
var x: ?*const u8 = @ptrCast(?*const u8, &c);
- assert(x.?.* == 4);
+ expect(x.?.* == 4);
}
test "@ptrCast from var in empty struct to nullable" {
@@ -11,6 +11,6 @@ test "@ptrCast from var in empty struct to nullable" {
var c: u8 = 4;
};
var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
- assert(x.?.* == 4);
+ expect(x.?.* == 4);
}
diff --git a/test/cases/bugs/828.zig b/test/stage1/behavior/bugs/828.zig
similarity index 100%
rename from test/cases/bugs/828.zig
rename to test/stage1/behavior/bugs/828.zig
diff --git a/test/cases/bugs/920.zig b/test/stage1/behavior/bugs/920.zig
similarity index 95%
rename from test/cases/bugs/920.zig
rename to test/stage1/behavior/bugs/920.zig
index 2903f05a29..10c002f6ba 100644
--- a/test/cases/bugs/920.zig
+++ b/test/stage1/behavior/bugs/920.zig
@@ -60,6 +60,6 @@ test "bug 920 fixed" {
};
for (NormalDist1.f) |_, i| {
- std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
+ std.testing.expect(NormalDist1.f[i] == NormalDist.f[i]);
}
}
diff --git a/test/cases/byval_arg_var.zig b/test/stage1/behavior/byval_arg_var.zig
similarity index 70%
rename from test/cases/byval_arg_var.zig
rename to test/stage1/behavior/byval_arg_var.zig
index 826b9cc9e5..3794a965c6 100644
--- a/test/cases/byval_arg_var.zig
+++ b/test/stage1/behavior/byval_arg_var.zig
@@ -2,11 +2,11 @@ const std = @import("std");
var result: []const u8 = "wrong";
-test "aoeu" {
+test "pass string literal byvalue to a generic var param" {
start();
blowUpStack(10);
- std.debug.assert(std.mem.eql(u8, result, "string literal"));
+ std.testing.expect(std.mem.eql(u8, result, "string literal"));
}
fn start() void {
diff --git a/test/cases/cancel.zig b/test/stage1/behavior/cancel.zig
similarity index 86%
rename from test/cases/cancel.zig
rename to test/stage1/behavior/cancel.zig
index c0f74fd34f..7fadf7f230 100644
--- a/test/cases/cancel.zig
+++ b/test/stage1/behavior/cancel.zig
@@ -10,9 +10,9 @@ test "cancel forwards" {
const p = async<&da.allocator> f1() catch unreachable;
cancel p;
- std.debug.assert(defer_f1);
- std.debug.assert(defer_f2);
- std.debug.assert(defer_f3);
+ std.testing.expect(defer_f1);
+ std.testing.expect(defer_f2);
+ std.testing.expect(defer_f3);
}
async fn f1() void {
@@ -47,10 +47,10 @@ test "cancel backwards" {
const p = async<&da.allocator> b1() catch unreachable;
cancel p;
- std.debug.assert(defer_b1);
- std.debug.assert(defer_b2);
- std.debug.assert(defer_b3);
- std.debug.assert(defer_b4);
+ std.testing.expect(defer_b1);
+ std.testing.expect(defer_b2);
+ std.testing.expect(defer_b3);
+ std.testing.expect(defer_b4);
}
async fn b1() void {
diff --git a/test/cases/cast.zig b/test/stage1/behavior/cast.zig
similarity index 70%
rename from test/cases/cast.zig
rename to test/stage1/behavior/cast.zig
index bd45bbc00f..8ed03f4936 100644
--- a/test/cases/cast.zig
+++ b/test/stage1/behavior/cast.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const mem = std.mem;
const maxInt = std.math.maxInt;
@@ -7,12 +7,12 @@ test "int to ptr cast" {
const x = usize(13);
const y = @intToPtr(*u8, x);
const z = @ptrToInt(y);
- assert(z == 13);
+ expect(z == 13);
}
test "integer literal to pointer cast" {
const vga_mem = @intToPtr(*u16, 0xB8000);
- assert(@ptrToInt(vga_mem) == 0xB8000);
+ expect(@ptrToInt(vga_mem) == 0xB8000);
}
test "pointer reinterpret const float to int" {
@@ -20,7 +20,7 @@ test "pointer reinterpret const float to int" {
const float_ptr = &float;
const int_ptr = @ptrCast(*const i32, float_ptr);
const int_val = int_ptr.*;
- assert(int_val == 858993411);
+ expect(int_val == 858993411);
}
test "implicitly cast indirect pointer to maybe-indirect pointer" {
@@ -44,10 +44,10 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
const p = &s;
const q = &p;
const r = &q;
- assert(42 == S.constConst(q));
- assert(42 == S.maybeConstConst(q));
- assert(42 == S.constConstConst(r));
- assert(42 == S.maybeConstConstConst(r));
+ expect(42 == S.constConst(q));
+ expect(42 == S.maybeConstConst(q));
+ expect(42 == S.constConstConst(r));
+ expect(42 == S.maybeConstConstConst(r));
}
test "explicit cast from integer to error type" {
@@ -57,14 +57,14 @@ test "explicit cast from integer to error type" {
fn testCastIntToErr(err: anyerror) void {
const x = @errorToInt(err);
const y = @intToError(x);
- assert(error.ItBroke == y);
+ expect(error.ItBroke == y);
}
test "peer resolve arrays of different size to const slice" {
- assert(mem.eql(u8, boolToStr(true), "true"));
- assert(mem.eql(u8, boolToStr(false), "false"));
- comptime assert(mem.eql(u8, boolToStr(true), "true"));
- comptime assert(mem.eql(u8, boolToStr(false), "false"));
+ expect(mem.eql(u8, boolToStr(true), "true"));
+ expect(mem.eql(u8, boolToStr(false), "false"));
+ comptime expect(mem.eql(u8, boolToStr(true), "true"));
+ comptime expect(mem.eql(u8, boolToStr(false), "false"));
}
fn boolToStr(b: bool) []const u8 {
return if (b) "true" else "false";
@@ -77,28 +77,29 @@ test "peer resolve array and const slice" {
fn testPeerResolveArrayConstSlice(b: bool) void {
const value1 = if (b) "aoeu" else ([]const u8)("zz");
const value2 = if (b) ([]const u8)("zz") else "aoeu";
- assert(mem.eql(u8, value1, "aoeu"));
- assert(mem.eql(u8, value2, "zz"));
+ expect(mem.eql(u8, value1, "aoeu"));
+ expect(mem.eql(u8, value2, "zz"));
}
test "implicitly cast from T to anyerror!?T" {
castToOptionalTypeError(1);
comptime castToOptionalTypeError(1);
}
+
const A = struct {
a: i32,
};
fn castToOptionalTypeError(z: i32) void {
const x = i32(1);
const y: anyerror!?i32 = x;
- assert((try y).? == 1);
+ expect((try y).? == 1);
const f = z;
const g: anyerror!?i32 = f;
const a = A{ .a = z };
const b: anyerror!?A = a;
- assert((b catch unreachable).?.a == 1);
+ expect((b catch unreachable).?.a == 1);
}
test "implicitly cast from int to anyerror!?T" {
@@ -113,7 +114,7 @@ fn implicitIntLitToOptional() void {
test "return null from fn() anyerror!?&T" {
const a = returnNullFromOptionalTypeErrorRef();
const b = returnNullLitFromOptionalTypeErrorRef();
- assert((try a) == null and (try b) == null);
+ expect((try a) == null and (try b) == null);
}
fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
const a: ?*A = null;
@@ -124,11 +125,11 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
}
test "peer type resolution: ?T and T" {
- assert(peerTypeTAndOptionalT(true, false).? == 0);
- assert(peerTypeTAndOptionalT(false, false).? == 3);
+ expect(peerTypeTAndOptionalT(true, false).? == 0);
+ expect(peerTypeTAndOptionalT(false, false).? == 3);
comptime {
- assert(peerTypeTAndOptionalT(true, false).? == 0);
- assert(peerTypeTAndOptionalT(false, false).? == 3);
+ expect(peerTypeTAndOptionalT(true, false).? == 0);
+ expect(peerTypeTAndOptionalT(false, false).? == 3);
}
}
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
@@ -140,11 +141,11 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
}
test "peer type resolution: [0]u8 and []const u8" {
- assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
- assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
+ expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
+ expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
comptime {
- assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
- assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
+ expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
+ expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
}
}
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
@@ -156,8 +157,8 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
}
test "implicitly cast from [N]T to ?[]const T" {
- assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
- comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
+ expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
+ comptime expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
}
fn castToOptionalSlice() ?[]const u8 {
@@ -170,7 +171,7 @@ test "implicitly cast from [0]T to anyerror![]T" {
}
fn testCastZeroArrayToErrSliceMut() void {
- assert((gimmeErrOrSlice() catch unreachable).len == 0);
+ expect((gimmeErrOrSlice() catch unreachable).len == 0);
}
fn gimmeErrOrSlice() anyerror![]u8 {
@@ -181,14 +182,14 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
{
var data = "hi";
const slice = data[0..];
- assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+ expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+ expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
comptime {
var data = "hi";
const slice = data[0..];
- assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
- assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+ expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+ expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
@@ -206,7 +207,7 @@ test "resolve undefined with integer" {
fn testResolveUndefWithInt(b: bool, x: i32) void {
const value = if (b) x else undefined;
if (b) {
- assert(value == x);
+ expect(value == x);
}
}
@@ -218,17 +219,17 @@ test "implicit cast from &const [N]T to []const T" {
fn testCastConstArrayRefToConstSlice() void {
const blah = "aoeu";
const const_array_ref = &blah;
- assert(@typeOf(const_array_ref) == *const [4]u8);
+ expect(@typeOf(const_array_ref) == *const [4]u8);
const slice: []const u8 = const_array_ref;
- assert(mem.eql(u8, slice, "aoeu"));
+ expect(mem.eql(u8, slice, "aoeu"));
}
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"));
- //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
- assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
- comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
+ //expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
+ //comptime expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
+ expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
+ comptime expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
}
//fn testPeerErrorAndArray(x: u8) error![]const u8 {
@@ -252,9 +253,9 @@ test "@floatToInt" {
fn testFloatToInts() void {
const x = i32(1e4);
- assert(x == 10000);
+ expect(x == 10000);
const y = @floatToInt(i32, f32(1e4));
- assert(y == 10000);
+ expect(y == 10000);
expectFloatToInt(f16, 255.1, u8, 255);
expectFloatToInt(f16, 127.2, i8, 127);
expectFloatToInt(f16, -128.2, i8, -128);
@@ -265,7 +266,7 @@ fn testFloatToInts() void {
}
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
- assert(@floatToInt(I, f) == i);
+ expect(@floatToInt(I, f) == i);
}
test "cast u128 to f128 and back" {
@@ -274,7 +275,7 @@ test "cast u128 to f128 and back" {
}
fn testCast128() void {
- assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
+ expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
}
fn cast128Int(x: f128) u128 {
@@ -294,9 +295,9 @@ test "const slice widen cast" {
};
const u32_value = @bytesToSlice(u32, bytes[0..])[0];
- assert(u32_value == 0x12121212);
+ expect(u32_value == 0x12121212);
- assert(@bitCast(u32, bytes) == 0x12121212);
+ expect(@bitCast(u32, bytes) == 0x12121212);
}
test "single-item pointer of array to slice and to unknown length pointer" {
@@ -308,76 +309,76 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu";
const x: [*]u8 = &array;
x[0] += 1;
- assert(mem.eql(u8, array[0..], "boeu"));
+ expect(mem.eql(u8, array[0..], "boeu"));
const y: []u8 = &array;
y[0] += 1;
- assert(mem.eql(u8, array[0..], "coeu"));
+ expect(mem.eql(u8, array[0..], "coeu"));
}
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
const window_name = [1][*]const u8{c"window name"};
const x: [*]const ?[*]const u8 = &window_name;
- assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
+ expect(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);
+ expect(@typeOf(result) == i32);
+ expect(result == 1234);
}
test "@floatCast comptime_int and comptime_float" {
{
const result = @floatCast(f16, 1234);
- assert(@typeOf(result) == f16);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f16);
+ expect(result == 1234.0);
}
{
const result = @floatCast(f16, 1234.0);
- assert(@typeOf(result) == f16);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f16);
+ expect(result == 1234.0);
}
{
const result = @floatCast(f32, 1234);
- assert(@typeOf(result) == f32);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f32);
+ expect(result == 1234.0);
}
{
const result = @floatCast(f32, 1234.0);
- assert(@typeOf(result) == f32);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f32);
+ expect(result == 1234.0);
}
}
test "comptime_int @intToFloat" {
{
const result = @intToFloat(f16, 1234);
- assert(@typeOf(result) == f16);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f16);
+ expect(result == 1234.0);
}
{
const result = @intToFloat(f32, 1234);
- assert(@typeOf(result) == f32);
- assert(result == 1234.0);
+ expect(@typeOf(result) == f32);
+ expect(result == 1234.0);
}
}
test "@bytesToSlice keeps pointer alignment" {
var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
const numbers = @bytesToSlice(u32, bytes[0..]);
- comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
+ comptime expect(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
}
test "@intCast i32 to u7" {
var x: u128 = maxInt(u128);
var y: i32 = 120;
var z = x >> @intCast(u7, y);
- assert(z == 0xff);
+ expect(z == 0xff);
}
test "implicit cast undefined to optional" {
- assert(MakeType(void).getNull() == null);
- assert(MakeType(void).getNonNull() != null);
+ expect(MakeType(void).getNull() == null);
+ expect(MakeType(void).getNonNull() != null);
}
fn MakeType(comptime T: type) type {
@@ -397,16 +398,16 @@ test "implicit cast from *[N]T to ?[*]T" {
var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
x = &y;
- assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
+ expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
x.?[0] = 8;
y[3] = 6;
- assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
+ expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
}
test "implicit cast from *T to ?*c_void" {
var a: u8 = 1;
incrementVoidPtrValue(&a);
- std.debug.assert(a == 2);
+ std.testing.expect(a == 2);
}
fn incrementVoidPtrValue(value: ?*c_void) void {
@@ -416,7 +417,7 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
test "implicit cast from [*]T to ?*c_void" {
var a = []u8{ 3, 2, 1 };
incrementVoidPtrArray(a[0..].ptr, 3);
- assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
+ expect(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
}
fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
@@ -440,27 +441,27 @@ pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
pub const PFN_void = extern fn (*c_void) void;
fn foobar(func: PFN_void) void {
- std.debug.assert(@ptrToInt(func) == maxInt(usize));
+ std.testing.expect(@ptrToInt(func) == maxInt(usize));
}
test "implicit ptr to *c_void" {
var a: u32 = 1;
var ptr: *c_void = &a;
var b: *u32 = @ptrCast(*u32, ptr);
- assert(b.* == 1);
+ expect(b.* == 1);
var ptr2: ?*c_void = &a;
var c: *u32 = @ptrCast(*u32, ptr2.?);
- assert(c.* == 1);
+ expect(c.* == 1);
}
test "@intCast to comptime_int" {
- assert(@intCast(comptime_int, 0) == 0);
+ expect(@intCast(comptime_int, 0) == 0);
}
test "implicit cast comptime numbers to any type when the value fits" {
const a: u64 = 255;
var b: u8 = a;
- assert(b == 255);
+ expect(b == 255);
}
test "@intToEnum passed a comptime_int to an enum with one item" {
@@ -468,5 +469,16 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
A,
};
const x = @intToEnum(E, 0);
- assert(x == E.A);
+ expect(x == E.A);
+}
+
+test "@intCast to u0 and use the result" {
+ const S = struct {
+ fn doTheTest(zero: u1, one: u1, bigzero: i32) void {
+ expect((one << @intCast(u0, bigzero)) == 1);
+ expect((zero << @intCast(u0, bigzero)) == 0);
+ }
+ };
+ S.doTheTest(0, 1, 0);
+ comptime S.doTheTest(0, 1, 0);
}
diff --git a/test/cases/const_slice_child.zig b/test/stage1/behavior/const_slice_child.zig
similarity index 79%
rename from test/cases/const_slice_child.zig
rename to test/stage1/behavior/const_slice_child.zig
index 07d02d5df0..57044d8aae 100644
--- a/test/cases/const_slice_child.zig
+++ b/test/stage1/behavior/const_slice_child.zig
@@ -1,5 +1,6 @@
-const debug = @import("std").debug;
-const assert = debug.assert;
+const std = @import("std");
+const debug = std.debug;
+const expect = std.testing.expect;
var argv: [*]const [*]const u8 = undefined;
@@ -15,10 +16,10 @@ test "const slice child" {
}
fn foo(args: [][]const u8) void {
- assert(args.len == 3);
- assert(streql(args[0], "one"));
- assert(streql(args[1], "two"));
- assert(streql(args[2], "three"));
+ expect(args.len == 3);
+ expect(streql(args[0], "one"));
+ expect(streql(args[1], "two"));
+ expect(streql(args[2], "three"));
}
fn bar(argc: usize) void {
diff --git a/test/cases/coroutine_await_struct.zig b/test/stage1/behavior/coroutine_await_struct.zig
similarity index 88%
rename from test/cases/coroutine_await_struct.zig
rename to test/stage1/behavior/coroutine_await_struct.zig
index 79168715d8..29f77bf67c 100644
--- a/test/cases/coroutine_await_struct.zig
+++ b/test/stage1/behavior/coroutine_await_struct.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const Foo = struct {
x: i32,
@@ -18,8 +18,8 @@ test "coroutine await struct" {
await_seq('f');
resume await_a_promise;
await_seq('i');
- assert(await_final_result.x == 1234);
- assert(std.mem.eql(u8, await_points, "abcdefghi"));
+ expect(await_final_result.x == 1234);
+ expect(std.mem.eql(u8, await_points, "abcdefghi"));
}
async fn await_amain() void {
await_seq('b');
diff --git a/test/cases/coroutines.zig b/test/stage1/behavior/coroutines.zig
similarity index 87%
rename from test/cases/coroutines.zig
rename to test/stage1/behavior/coroutines.zig
index 89490ebc2c..be977bbfce 100644
--- a/test/cases/coroutines.zig
+++ b/test/stage1/behavior/coroutines.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
var x: i32 = 1;
@@ -9,9 +9,9 @@ test "create a coroutine and cancel it" {
defer da.deinit();
const p = try async<&da.allocator> simpleAsyncFn();
- comptime assert(@typeOf(p) == promise->void);
+ comptime expect(@typeOf(p) == promise->void);
cancel p;
- assert(x == 2);
+ expect(x == 2);
}
async fn simpleAsyncFn() void {
x += 1;
@@ -31,7 +31,7 @@ test "coroutine suspend, resume, cancel" {
cancel p;
seq('g');
- assert(std.mem.eql(u8, points, "abcdefg"));
+ expect(std.mem.eql(u8, points, "abcdefg"));
}
async fn testAsyncSeq() void {
defer seq('e');
@@ -53,9 +53,9 @@ test "coroutine suspend with block" {
defer da.deinit();
const p = try async<&da.allocator> testSuspendBlock();
- std.debug.assert(!result);
+ std.testing.expect(!result);
resume a_promise;
- std.debug.assert(result);
+ std.testing.expect(result);
cancel p;
}
@@ -63,13 +63,13 @@ var a_promise: promise = undefined;
var result = false;
async fn testSuspendBlock() void {
suspend {
- comptime assert(@typeOf(@handle()) == promise->void);
+ comptime expect(@typeOf(@handle()) == promise->void);
a_promise = @handle();
}
//Test to make sure that @handle() works as advertised (issue #1296)
//var our_handle: promise = @handle();
- assert( a_promise == @handle() );
+ expect(a_promise == @handle());
result = true;
}
@@ -86,8 +86,8 @@ test "coroutine await" {
await_seq('f');
resume await_a_promise;
await_seq('i');
- assert(await_final_result == 1234);
- assert(std.mem.eql(u8, await_points, "abcdefghi"));
+ expect(await_final_result == 1234);
+ expect(std.mem.eql(u8, await_points, "abcdefghi"));
}
async fn await_amain() void {
await_seq('b');
@@ -123,8 +123,8 @@ test "coroutine await early return" {
early_seq('a');
const p = async<&da.allocator> early_amain() catch @panic("out of memory");
early_seq('f');
- assert(early_final_result == 1234);
- assert(std.mem.eql(u8, early_points, "abcdef"));
+ expect(early_final_result == 1234);
+ expect(std.mem.eql(u8, early_points, "abcdef"));
}
async fn early_amain() void {
early_seq('b');
@@ -170,7 +170,7 @@ test "async function with dot syntax" {
defer da.deinit();
const p = try async<&da.allocator> S.foo();
cancel p;
- assert(S.y == 2);
+ expect(S.y == 2);
}
test "async fn pointer in a struct field" {
@@ -182,9 +182,9 @@ test "async fn pointer in a struct field" {
var da = std.heap.DirectAllocator.init();
defer da.deinit();
const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
- assert(data == 2);
+ expect(data == 2);
cancel p;
- assert(data == 4);
+ expect(data == 4);
}
async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
defer y.* += 2;
@@ -199,6 +199,7 @@ test "async fn with inferred error set" {
resume p;
cancel p;
}
+
async fn failing() !void {
suspend;
return error.Fail;
@@ -220,8 +221,7 @@ test "error return trace across suspend points - async return" {
cancel p2;
}
-// TODO https://github.com/ziglang/zig/issues/760
-fn nonFailing() promise->(anyerror!void) {
+fn nonFailing() (promise->anyerror!void) {
return async suspendThenFail() catch unreachable;
}
async fn suspendThenFail() anyerror!void {
@@ -230,9 +230,9 @@ async fn suspendThenFail() anyerror!void {
}
async fn printTrace(p: promise->(anyerror!void)) void {
(await p) catch |e| {
- std.debug.assert(e == error.Fail);
+ std.testing.expect(e == error.Fail);
if (@errorReturnTrace()) |trace| {
- assert(trace.index == 1);
+ expect(trace.index == 1);
} else switch (builtin.mode) {
builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
@@ -246,7 +246,7 @@ test "break from suspend" {
var my_result: i32 = 1;
const p = try async testBreakFromSuspend(&my_result);
cancel p;
- std.debug.assert(my_result == 2);
+ std.testing.expect(my_result == 2);
}
async fn testBreakFromSuspend(my_result: *i32) void {
suspend {
diff --git a/test/cases/defer.zig b/test/stage1/behavior/defer.zig
similarity index 76%
rename from test/cases/defer.zig
rename to test/stage1/behavior/defer.zig
index f9a2b69cd9..0bb9125e7c 100644
--- a/test/cases/defer.zig
+++ b/test/stage1/behavior/defer.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
var result: [3]u8 = undefined;
var index: usize = undefined;
@@ -21,18 +21,18 @@ fn runSomeErrorDefers(x: bool) !bool {
}
test "mixing normal and error defers" {
- assert(runSomeErrorDefers(true) catch unreachable);
- assert(result[0] == 'c');
- assert(result[1] == 'a');
+ expect(runSomeErrorDefers(true) catch unreachable);
+ expect(result[0] == 'c');
+ expect(result[1] == 'a');
const ok = runSomeErrorDefers(false) catch |err| x: {
- assert(err == error.FalseNotAllowed);
+ expect(err == error.FalseNotAllowed);
break :x true;
};
- assert(ok);
- assert(result[0] == 'c');
- assert(result[1] == 'b');
- assert(result[2] == 'a');
+ expect(ok);
+ expect(result[0] == 'c');
+ expect(result[1] == 'b');
+ expect(result[2] == 'a');
}
test "break and continue inside loop inside defer expression" {
@@ -47,7 +47,7 @@ fn testBreakContInDefer(x: usize) void {
if (i < 5) continue;
if (i == 5) break;
}
- assert(i == 5);
+ expect(i == 5);
}
}
@@ -59,11 +59,11 @@ test "defer and labeled break" {
break :blk;
}
- assert(i == 1);
+ expect(i == 1);
}
test "errdefer does not apply to fn inside fn" {
- if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
+ if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| expect(e == error.Bad);
}
fn testNestedFnErrDefer() anyerror!void {
diff --git a/test/cases/enum.zig b/test/stage1/behavior/enum.zig
similarity index 86%
rename from test/cases/enum.zig
rename to test/stage1/behavior/enum.zig
index 2dd552488c..899aeea67d 100644
--- a/test/cases/enum.zig
+++ b/test/stage1/behavior/enum.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const mem = @import("std").mem;
test "enum type" {
@@ -11,16 +11,16 @@ test "enum type" {
};
const bar = Bar.B;
- assert(bar == Bar.B);
- assert(@memberCount(Foo) == 3);
- assert(@memberCount(Bar) == 4);
- assert(@sizeOf(Foo) == @sizeOf(FooNoVoid));
- assert(@sizeOf(Bar) == 1);
+ expect(bar == Bar.B);
+ expect(@memberCount(Foo) == 3);
+ expect(@memberCount(Bar) == 4);
+ expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
+ expect(@sizeOf(Bar) == 1);
}
test "enum as return value" {
switch (returnAnInt(13)) {
- Foo.One => |value| assert(value == 13),
+ Foo.One => |value| expect(value == 13),
else => unreachable,
}
}
@@ -92,14 +92,14 @@ test "enum to int" {
}
fn shouldEqual(n: Number, expected: u3) void {
- assert(@enumToInt(n) == expected);
+ expect(@enumToInt(n) == expected);
}
test "int to enum" {
testIntToEnumEval(3);
}
fn testIntToEnumEval(x: i32) void {
- assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
+ expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
}
const IntToEnumNumber = enum {
Zero,
@@ -110,8 +110,8 @@ const IntToEnumNumber = enum {
};
test "@tagName" {
- assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
- comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
+ expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
+ comptime expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
}
fn testEnumTagNameBare(n: BareNumber) []const u8 {
@@ -126,8 +126,8 @@ const BareNumber = enum {
test "enum alignment" {
comptime {
- assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
- assert(@alignOf(AlignTestEnum) >= @alignOf(u64));
+ expect(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
+ expect(@alignOf(AlignTestEnum) >= @alignOf(u64));
}
}
@@ -663,10 +663,10 @@ const ValueCount257 = enum {
test "enum sizes" {
comptime {
- assert(@sizeOf(ValueCount1) == 0);
- assert(@sizeOf(ValueCount2) == 1);
- assert(@sizeOf(ValueCount256) == 1);
- assert(@sizeOf(ValueCount257) == 2);
+ expect(@sizeOf(ValueCount1) == 0);
+ expect(@sizeOf(ValueCount2) == 1);
+ expect(@sizeOf(ValueCount256) == 1);
+ expect(@sizeOf(ValueCount257) == 2);
}
}
@@ -685,12 +685,12 @@ test "set enum tag type" {
{
var x = Small.One;
x = Small.Two;
- comptime assert(@TagType(Small) == u2);
+ comptime expect(@TagType(Small) == u2);
}
{
var x = Small2.One;
x = Small2.Two;
- comptime assert(@TagType(Small2) == u2);
+ comptime expect(@TagType(Small2) == u2);
}
}
@@ -737,17 +737,17 @@ const bit_field_1 = BitFieldOfEnums{
test "bit field access with enum fields" {
var data = bit_field_1;
- assert(getA(&data) == A.Two);
- assert(getB(&data) == B.Three3);
- assert(getC(&data) == C.Four4);
- comptime assert(@sizeOf(BitFieldOfEnums) == 1);
+ expect(getA(&data) == A.Two);
+ expect(getB(&data) == B.Three3);
+ expect(getC(&data) == C.Four4);
+ comptime expect(@sizeOf(BitFieldOfEnums) == 1);
data.b = B.Four3;
- assert(data.b == B.Four3);
+ expect(data.b == B.Four3);
data.a = A.Three;
- assert(data.a == A.Three);
- assert(data.b == B.Four3);
+ expect(data.a == A.Three);
+ expect(data.b == B.Four3);
}
fn getA(data: *const BitFieldOfEnums) A {
@@ -768,7 +768,7 @@ test "casting enum to its tag type" {
}
fn testCastEnumToTagType(value: Small2) void {
- assert(@enumToInt(value) == 1);
+ expect(@enumToInt(value) == 1);
}
const MultipleChoice = enum(u32) {
@@ -784,8 +784,8 @@ test "enum with specified tag values" {
}
fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
- assert(@enumToInt(x) == 60);
- assert(1234 == switch (x) {
+ expect(@enumToInt(x) == 60);
+ expect(1234 == switch (x) {
MultipleChoice.A => 1,
MultipleChoice.B => 2,
MultipleChoice.C => u32(1234),
@@ -811,8 +811,8 @@ test "enum with specified and unspecified tag values" {
}
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
- assert(@enumToInt(x) == 1000);
- assert(1234 == switch (x) {
+ expect(@enumToInt(x) == 1000);
+ expect(1234 == switch (x) {
MultipleChoice2.A => 1,
MultipleChoice2.B => 2,
MultipleChoice2.C => 3,
@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
}
test "cast integer literal to enum" {
- assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
- assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
+ expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
+ expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
}
const EnumWithOneMember = enum {
@@ -865,14 +865,14 @@ const EnumWithTagValues = enum(u4) {
D = 1 << 3,
};
test "enum with tag values don't require parens" {
- assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
+ expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
}
test "enum with 1 field but explicit tag type should still have the tag type" {
const Enum = enum(u8) {
B = 2,
};
- comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
+ comptime @import("std").testing.expect(@sizeOf(Enum) == @sizeOf(u8));
}
test "empty extern enum with members" {
@@ -881,14 +881,14 @@ test "empty extern enum with members" {
B,
C,
};
- assert(@sizeOf(E) == @sizeOf(c_int));
+ expect(@sizeOf(E) == @sizeOf(c_int));
}
-test "aoeu" {
+test "tag name with assigned enum values" {
const LocalFoo = enum {
A = 1,
B = 0,
};
var b = LocalFoo.B;
- assert(mem.eql(u8, @tagName(b), "B"));
+ expect(mem.eql(u8, @tagName(b), "B"));
}
diff --git a/test/cases/enum_with_members.zig b/test/stage1/behavior/enum_with_members.zig
similarity index 67%
rename from test/cases/enum_with_members.zig
rename to test/stage1/behavior/enum_with_members.zig
index 088496bd2f..2e022a3427 100644
--- a/test/cases/enum_with_members.zig
+++ b/test/stage1/behavior/enum_with_members.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const mem = @import("std").mem;
const fmt = @import("std").fmt;
@@ -19,9 +19,9 @@ test "enum with members" {
const b = ET{ .UINT = 42 };
var buf: [20]u8 = undefined;
- assert((a.print(buf[0..]) catch unreachable) == 3);
- assert(mem.eql(u8, buf[0..3], "-42"));
+ expect((a.print(buf[0..]) catch unreachable) == 3);
+ expect(mem.eql(u8, buf[0..3], "-42"));
- assert((b.print(buf[0..]) catch unreachable) == 2);
- assert(mem.eql(u8, buf[0..2], "42"));
+ expect((b.print(buf[0..]) catch unreachable) == 2);
+ expect(mem.eql(u8, buf[0..2], "42"));
}
diff --git a/test/cases/error.zig b/test/stage1/behavior/error.zig
similarity index 58%
rename from test/cases/error.zig
rename to test/stage1/behavior/error.zig
index a731f39021..7d9dae7bdd 100644
--- a/test/cases/error.zig
+++ b/test/stage1/behavior/error.zig
@@ -1,5 +1,6 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
+const expectError = std.testing.expectError;
const mem = std.mem;
const builtin = @import("builtin");
@@ -18,7 +19,7 @@ pub fn baz() anyerror!i32 {
}
test "error wrapping" {
- assert((baz() catch unreachable) == 15);
+ expect((baz() catch unreachable) == 15);
}
fn gimmeItBroke() []const u8 {
@@ -26,14 +27,14 @@ fn gimmeItBroke() []const u8 {
}
test "@errorName" {
- assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
- assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
+ expect(mem.eql(u8, @errorName(error.AnError), "AnError"));
+ expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
}
test "error values" {
const a = @errorToInt(error.err1);
const b = @errorToInt(error.err2);
- assert(a != b);
+ expect(a != b);
}
test "redefinition of error values allowed" {
@@ -46,8 +47,8 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
test "error binary operator" {
const a = errBinaryOperatorG(true) catch 3;
const b = errBinaryOperatorG(false) catch 3;
- assert(a == 3);
- assert(b == 10);
+ expect(a == 3);
+ expect(b == 10);
}
fn errBinaryOperatorG(x: bool) anyerror!isize {
return if (x) error.ItBroke else isize(10);
@@ -55,7 +56,7 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {
test "unwrap simple value from error" {
const i = unwrapSimpleValueFromErrorDo() catch unreachable;
- assert(i == 13);
+ expect(i == 13);
}
fn unwrapSimpleValueFromErrorDo() anyerror!isize {
return 13;
@@ -81,13 +82,13 @@ test "error union type " {
fn testErrorUnionType() void {
const x: anyerror!i32 = 1234;
- if (x) |value| assert(value == 1234) else |_| unreachable;
- assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
- assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
- assert(@typeOf(x).ErrorSet == anyerror);
+ if (x) |value| expect(value == 1234) else |_| unreachable;
+ expect(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
+ expect(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
+ expect(@typeOf(x).ErrorSet == anyerror);
}
-test "error set type " {
+test "error set type" {
testErrorSetType();
comptime testErrorSetType();
}
@@ -98,12 +99,12 @@ const MyErrSet = error{
};
fn testErrorSetType() void {
- assert(@memberCount(MyErrSet) == 2);
+ expect(@memberCount(MyErrSet) == 2);
const a: MyErrSet!i32 = 5678;
const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
- if (a) |value| assert(value == 5678) else |err| switch (err) {
+ if (a) |value| expect(value == 5678) else |err| switch (err) {
error.OutOfMemory => unreachable,
error.FileNotFound => unreachable,
}
@@ -126,7 +127,7 @@ const Set2 = error{
fn testExplicitErrorSetCast(set1: Set1) void {
var x = @errSetCast(Set2, set1);
var y = @errSetCast(Set1, x);
- assert(y == error.A);
+ expect(y == error.A);
}
test "comptime test error for empty error set" {
@@ -137,12 +138,12 @@ test "comptime test error for empty error set" {
const EmptyErrorSet = error{};
fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
- if (x) |v| assert(v == 1234) else |err| @compileError("bad");
+ if (x) |v| expect(v == 1234) else |err| @compileError("bad");
}
test "syntax: optional operator in front of error union operator" {
comptime {
- assert(?(anyerror!i32) == ?(anyerror!i32));
+ expect(?(anyerror!i32) == ?(anyerror!i32));
}
}
@@ -161,7 +162,6 @@ fn testErrToIntWithOnePossibleValue(
test "error union peer type resolution" {
testErrorUnionPeerTypeResolution(1);
- comptime testErrorUnionPeerTypeResolution(1);
}
fn testErrorUnionPeerTypeResolution(x: i32) void {
@@ -170,6 +170,11 @@ fn testErrorUnionPeerTypeResolution(x: i32) void {
2 => baz_1(),
else => quux_1(),
};
+ if (y) |_| {
+ @panic("expected error");
+ } else |e| {
+ expect(e == error.A);
+ }
}
fn bar_1() anyerror {
@@ -243,3 +248,90 @@ fn intLiteral(str: []const u8) !?i64 {
return error.T;
}
+
+test "nested error union function call in optional unwrap" {
+ const S = struct {
+ const Foo = struct {
+ a: i32,
+ };
+
+ fn errorable() !i32 {
+ var x: Foo = (try getFoo()) orelse return error.Other;
+ return x.a;
+ }
+
+ fn errorable2() !i32 {
+ var x: Foo = (try getFoo2()) orelse return error.Other;
+ return x.a;
+ }
+
+ fn errorable3() !i32 {
+ var x: Foo = (try getFoo3()) orelse return error.Other;
+ return x.a;
+ }
+
+ fn getFoo() anyerror!?Foo {
+ return Foo{ .a = 1234 };
+ }
+
+ fn getFoo2() anyerror!?Foo {
+ return error.Failure;
+ }
+
+ fn getFoo3() anyerror!?Foo {
+ return null;
+ }
+ };
+ expect((try S.errorable()) == 1234);
+ expectError(error.Failure, S.errorable2());
+ expectError(error.Other, S.errorable3());
+ comptime {
+ expect((try S.errorable()) == 1234);
+ expectError(error.Failure, S.errorable2());
+ expectError(error.Other, S.errorable3());
+ }
+}
+
+test "widen cast integer payload of error union function call" {
+ const S = struct {
+ fn errorable() !u64 {
+ var x = u64(try number());
+ return x;
+ }
+
+ fn number() anyerror!u32 {
+ return 1234;
+ }
+ };
+ expect((try S.errorable()) == 1234);
+}
+
+test "return function call to error set from error union function" {
+ const S = struct {
+ fn errorable() anyerror!i32 {
+ return fail();
+ }
+
+ fn fail() anyerror {
+ return error.Failure;
+ }
+ };
+ expectError(error.Failure, S.errorable());
+ comptime expectError(error.Failure, S.errorable());
+}
+
+test "optional error set is the same size as error set" {
+ comptime expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
+ const S = struct {
+ fn returnsOptErrSet() ?anyerror {
+ return null;
+ }
+ };
+ expect(S.returnsOptErrSet() == null);
+ comptime expect(S.returnsOptErrSet() == null);
+}
+
+test "debug info for optional error set" {
+ const SomeError = error{Hello};
+ var a_local_variable: ?SomeError = null;
+}
diff --git a/test/cases/eval.zig b/test/stage1/behavior/eval.zig
similarity index 73%
rename from test/cases/eval.zig
rename to test/stage1/behavior/eval.zig
index a9eded151e..5976761f77 100644
--- a/test/cases/eval.zig
+++ b/test/stage1/behavior/eval.zig
@@ -1,9 +1,9 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
test "compile time recursion" {
- assert(some_data.len == 21);
+ expect(some_data.len == 21);
}
var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
fn fibonacci(x: i32) i32 {
@@ -16,7 +16,7 @@ fn unwrapAndAddOne(blah: ?i32) i32 {
}
const should_be_1235 = unwrapAndAddOne(1234);
test "static add one" {
- assert(should_be_1235 == 1235);
+ expect(should_be_1235 == 1235);
}
test "inlined loop" {
@@ -24,7 +24,7 @@ test "inlined loop" {
comptime var sum = 0;
inline while (i <= 5) : (i += 1)
sum += i;
- assert(sum == 15);
+ expect(sum == 15);
}
fn gimme1or2(comptime a: bool) i32 {
@@ -34,12 +34,12 @@ fn gimme1or2(comptime a: bool) i32 {
return z;
}
test "inline variable gets result of const if" {
- assert(gimme1or2(true) == 1);
- assert(gimme1or2(false) == 2);
+ expect(gimme1or2(true) == 1);
+ expect(gimme1or2(false) == 2);
}
test "static function evaluation" {
- assert(statically_added_number == 3);
+ expect(statically_added_number == 3);
}
const statically_added_number = staticAdd(1, 2);
fn staticAdd(a: i32, b: i32) i32 {
@@ -47,7 +47,8 @@ fn staticAdd(a: i32, b: i32) i32 {
}
test "const expr eval on single expr blocks" {
- assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
+ expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
+ comptime expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
}
fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
@@ -63,10 +64,10 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
}
test "statically initialized list" {
- assert(static_point_list[0].x == 1);
- assert(static_point_list[0].y == 2);
- assert(static_point_list[1].x == 3);
- assert(static_point_list[1].y == 4);
+ expect(static_point_list[0].x == 1);
+ expect(static_point_list[0].y == 2);
+ expect(static_point_list[1].x == 3);
+ expect(static_point_list[1].y == 4);
}
const Point = struct {
x: i32,
@@ -84,8 +85,8 @@ fn makePoint(x: i32, y: i32) Point {
}
test "static eval list init" {
- assert(static_vec3.data[2] == 1.0);
- assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
+ expect(static_vec3.data[2] == 1.0);
+ expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
}
const static_vec3 = vec3(0.0, 0.0, 1.0);
pub const Vec3 = struct {
@@ -101,12 +102,12 @@ pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
test "constant expressions" {
var array: [array_size]u8 = undefined;
- assert(@sizeOf(@typeOf(array)) == 20);
+ expect(@sizeOf(@typeOf(array)) == 20);
}
const array_size: u8 = 20;
test "constant struct with negation" {
- assert(vertices[0].x == -0.6);
+ expect(vertices[0].x == -0.6);
}
const Vertex = struct {
x: f32,
@@ -141,7 +142,7 @@ const vertices = []Vertex{
test "statically initialized struct" {
st_init_str_foo.x += 1;
- assert(st_init_str_foo.x == 14);
+ expect(st_init_str_foo.x == 14);
}
const StInitStrFoo = struct {
x: i32,
@@ -154,7 +155,7 @@ var st_init_str_foo = StInitStrFoo{
test "statically initalized array literal" {
const y: [4]u8 = st_init_arr_lit_x;
- assert(y[3] == 4);
+ expect(y[3] == 4);
}
const st_init_arr_lit_x = []u8{
1,
@@ -166,15 +167,15 @@ const st_init_arr_lit_x = []u8{
test "const slice" {
comptime {
const a = "1234567890";
- assert(a.len == 10);
+ expect(a.len == 10);
const b = a[1..2];
- assert(b.len == 1);
- assert(b[0] == '2');
+ expect(b.len == 1);
+ expect(b[0] == '2');
}
}
test "try to trick eval with runtime if" {
- assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
+ expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
}
fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
@@ -200,16 +201,16 @@ fn letsTryToCompareBools(a: bool, b: bool) bool {
return max(bool, a, b);
}
test "inlined block and runtime block phi" {
- assert(letsTryToCompareBools(true, true));
- assert(letsTryToCompareBools(true, false));
- assert(letsTryToCompareBools(false, true));
- assert(!letsTryToCompareBools(false, false));
+ expect(letsTryToCompareBools(true, true));
+ expect(letsTryToCompareBools(true, false));
+ expect(letsTryToCompareBools(false, true));
+ expect(!letsTryToCompareBools(false, false));
comptime {
- assert(letsTryToCompareBools(true, true));
- assert(letsTryToCompareBools(true, false));
- assert(letsTryToCompareBools(false, true));
- assert(!letsTryToCompareBools(false, false));
+ expect(letsTryToCompareBools(true, true));
+ expect(letsTryToCompareBools(true, false));
+ expect(letsTryToCompareBools(false, true));
+ expect(!letsTryToCompareBools(false, false));
}
}
@@ -254,14 +255,14 @@ fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
}
test "comptime iterate over fn ptr list" {
- assert(performFn('t', 1) == 6);
- assert(performFn('o', 0) == 1);
- assert(performFn('w', 99) == 99);
+ expect(performFn('t', 1) == 6);
+ expect(performFn('o', 0) == 1);
+ expect(performFn('w', 99) == 99);
}
test "eval @setRuntimeSafety at compile-time" {
const result = comptime fnWithSetRuntimeSafety();
- assert(result == 1234);
+ expect(result == 1234);
}
fn fnWithSetRuntimeSafety() i32 {
@@ -271,7 +272,7 @@ fn fnWithSetRuntimeSafety() i32 {
test "eval @setFloatMode at compile-time" {
const result = comptime fnWithFloatMode();
- assert(result == 1234.0);
+ expect(result == 1234.0);
}
fn fnWithFloatMode() f32 {
@@ -292,15 +293,15 @@ var simple_struct = SimpleStruct{ .field = 1234 };
const bound_fn = simple_struct.method;
test "call method on bound fn referring to var instance" {
- assert(bound_fn() == 1237);
+ expect(bound_fn() == 1237);
}
test "ptr to local array argument at comptime" {
comptime {
var bytes: [10]u8 = undefined;
modifySomeBytes(bytes[0..]);
- assert(bytes[0] == 'a');
- assert(bytes[9] == 'b');
+ expect(bytes[0] == 'a');
+ expect(bytes[9] == 'b');
}
}
@@ -328,9 +329,9 @@ fn testCompTimeUIntComparisons(x: u32) void {
}
test "const ptr to variable data changes at runtime" {
- assert(foo_ref.name[0] == 'a');
+ expect(foo_ref.name[0] == 'a');
foo_ref.name = "b";
- assert(foo_ref.name[0] == 'b');
+ expect(foo_ref.name[0] == 'b');
}
const Foo = struct {
@@ -341,8 +342,8 @@ var foo_contents = Foo{ .name = "a" };
const foo_ref = &foo_contents;
test "create global array with for loop" {
- assert(global_array[5] == 5 * 5);
- assert(global_array[9] == 9 * 9);
+ expect(global_array[5] == 5 * 5);
+ expect(global_array[9] == 9 * 9);
}
const global_array = x: {
@@ -357,7 +358,7 @@ test "compile-time downcast when the bits fit" {
comptime {
const spartan_count: u16 = 255;
const byte = @intCast(u8, spartan_count);
- assert(byte == 255);
+ expect(byte == 255);
}
}
@@ -365,44 +366,45 @@ const hi1 = "hi";
const hi2 = hi1;
test "const global shares pointer with other same one" {
assertEqualPtrs(&hi1[0], &hi2[0]);
- comptime assert(&hi1[0] == &hi2[0]);
+ comptime expect(&hi1[0] == &hi2[0]);
}
fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
- assert(ptr1 == ptr2);
+ expect(ptr1 == ptr2);
}
test "@setEvalBranchQuota" {
comptime {
- // 1001 for the loop and then 1 more for the assert fn call
+ // 1001 for the loop and then 1 more for the expect fn call
@setEvalBranchQuota(1002);
var i = 0;
var sum = 0;
while (i < 1001) : (i += 1) {
sum += i;
}
- assert(sum == 500500);
+ expect(sum == 500500);
}
}
// TODO test "float literal at compile time not lossy" {
-// TODO assert(16777216.0 + 1.0 == 16777217.0);
-// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0);
+// TODO expect(16777216.0 + 1.0 == 16777217.0);
+// TODO expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
// TODO }
test "f32 at compile time is lossy" {
- assert(f32(1 << 24) + 1 == 1 << 24);
+ expect(f32(1 << 24) + 1 == 1 << 24);
}
test "f64 at compile time is lossy" {
- assert(f64(1 << 53) + 1 == 1 << 53);
+ expect(f64(1 << 53) + 1 == 1 << 53);
}
test "f128 at compile time is lossy" {
- assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
+ expect(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
}
-// TODO need a better implementation of bigfloat_init_bigint
-// assert(f128(1 << 113) == 10384593717069655257060992658440192);
+comptime {
+ expect(f128(1 << 113) == 10384593717069655257060992658440192);
+}
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
return struct {
@@ -413,15 +415,15 @@ pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
test "string literal used as comptime slice is memoized" {
const a = "link";
const b = "link";
- comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
- comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
+ comptime expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
+ comptime expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
}
test "comptime slice of undefined pointer of length 0" {
const slice1 = ([*]i32)(undefined)[0..0];
- assert(slice1.len == 0);
+ expect(slice1.len == 0);
const slice2 = ([*]i32)(undefined)[100..100];
- assert(slice2.len == 0);
+ expect(slice2.len == 0);
}
fn copyWithPartialInline(s: []u32, b: []u8) void {
@@ -443,16 +445,16 @@ test "binary math operator in partially inlined function" {
r.* = @intCast(u8, i + 1);
copyWithPartialInline(s[0..], b[0..]);
- assert(s[0] == 0x1020304);
- assert(s[1] == 0x5060708);
- assert(s[2] == 0x90a0b0c);
- assert(s[3] == 0xd0e0f10);
+ expect(s[0] == 0x1020304);
+ expect(s[1] == 0x5060708);
+ expect(s[2] == 0x90a0b0c);
+ expect(s[3] == 0xd0e0f10);
}
test "comptime function with the same args is memoized" {
comptime {
- assert(MakeType(i32) == MakeType(i32));
- assert(MakeType(i32) != MakeType(f64));
+ expect(MakeType(i32) == MakeType(i32));
+ expect(MakeType(i32) != MakeType(f64));
}
}
@@ -468,7 +470,7 @@ test "comptime function with mutable pointer is not memoized" {
const ptr = &x;
increment(ptr);
increment(ptr);
- assert(x == 3);
+ expect(x == 3);
}
}
@@ -494,14 +496,14 @@ fn doesAlotT(comptime T: type, value: usize) T {
}
test "@setEvalBranchQuota at same scope as generic function call" {
- assert(doesAlotT(u32, 2) == 2);
+ expect(doesAlotT(u32, 2) == 2);
}
test "comptime slice of slice preserves comptime var" {
comptime {
var buff: [10]u8 = undefined;
buff[0..][0..][0] = 1;
- assert(buff[0..][0..][0] == 1);
+ expect(buff[0..][0..][0] == 1);
}
}
@@ -510,7 +512,7 @@ test "comptime slice of pointer preserves comptime var" {
var buff: [10]u8 = undefined;
var a = buff[0..].ptr;
a[0..1][0] = 1;
- assert(buff[0..][0..][0] == 1);
+ expect(buff[0..][0..][0] == 1);
}
}
@@ -524,9 +526,9 @@ const SingleFieldStruct = struct {
test "const ptr to comptime mutable data is not memoized" {
comptime {
var foo = SingleFieldStruct{ .x = 1 };
- assert(foo.read_x() == 1);
+ expect(foo.read_x() == 1);
foo.x = 2;
- assert(foo.read_x() == 2);
+ expect(foo.read_x() == 2);
}
}
@@ -535,7 +537,7 @@ test "array concat of slices gives slice" {
var a: []const u8 = "aoeu";
var b: []const u8 = "asdf";
const c = a ++ b;
- assert(std.mem.eql(u8, c, "aoeuasdf"));
+ expect(std.mem.eql(u8, c, "aoeuasdf"));
}
}
@@ -552,14 +554,14 @@ test "comptime shlWithOverflow" {
break :amt amt;
};
- assert(ct_shifted == rt_shifted);
+ expect(ct_shifted == rt_shifted);
}
test "runtime 128 bit integer division" {
var a: u128 = 152313999999999991610955792383;
var b: u128 = 10000000000000000000;
var c = a / b;
- assert(c == 15231399999);
+ expect(c == 15231399999);
}
pub const Info = struct {
@@ -572,20 +574,20 @@ test "comptime modification of const struct field" {
comptime {
var res = diamond_info;
res.version = 1;
- assert(diamond_info.version == 0);
- assert(res.version == 1);
+ expect(diamond_info.version == 0);
+ expect(res.version == 1);
}
}
test "pointer to type" {
comptime {
var T: type = i32;
- assert(T == i32);
+ expect(T == i32);
var ptr = &T;
- assert(@typeOf(ptr) == *type);
+ expect(@typeOf(ptr) == *type);
ptr.* = f32;
- assert(T == f32);
- assert(*T == *f32);
+ expect(T == f32);
+ expect(*T == *f32);
}
}
@@ -594,17 +596,17 @@ test "slice of type" {
var types_array = []type{ i32, f64, type };
for (types_array) |T, i| {
switch (i) {
- 0 => assert(T == i32),
- 1 => assert(T == f64),
- 2 => assert(T == type),
+ 0 => expect(T == i32),
+ 1 => expect(T == f64),
+ 2 => expect(T == type),
else => unreachable,
}
}
for (types_array[0..]) |T, i| {
switch (i) {
- 0 => assert(T == i32),
- 1 => assert(T == f64),
- 2 => assert(T == type),
+ 0 => expect(T == i32),
+ 1 => expect(T == f64),
+ 2 => expect(T == type),
else => unreachable,
}
}
@@ -621,7 +623,7 @@ fn wrap(comptime T: type) Wrapper {
test "function which returns struct with type field causes implicit comptime" {
const ty = wrap(i32).T;
- assert(ty == i32);
+ expect(ty == i32);
}
test "call method with comptime pass-by-non-copying-value self parameter" {
@@ -635,12 +637,12 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
const s = S{ .a = 2 };
var b = s.b();
- assert(b == 2);
+ expect(b == 2);
}
test "@tagName of @typeId" {
const str = @tagName(@typeId(u8));
- assert(std.mem.eql(u8, str, "Int"));
+ expect(std.mem.eql(u8, str, "Int"));
}
test "setting backward branch quota just before a generic fn call" {
@@ -661,8 +663,8 @@ fn testVarInsideInlineLoop(args: ...) void {
comptime var i = 0;
inline while (i < args.len) : (i += 1) {
const x = args[i];
- if (i == 0) assert(x);
- if (i == 1) assert(x == 42);
+ if (i == 0) expect(x);
+ if (i == 1) expect(x == 42);
}
}
@@ -672,7 +674,7 @@ test "inline for with same type but different values" {
var a: T = undefined;
res += a.len;
}
- assert(res == 5);
+ expect(res == 5);
}
test "refer to the type of a generic function" {
@@ -686,19 +688,13 @@ fn doNothingWithType(comptime T: type) void {}
test "zero extend from u0 to u1" {
var zero_u0: u0 = 0;
var zero_u1: u1 = zero_u0;
- assert(zero_u1 == 0);
+ expect(zero_u1 == 0);
}
test "bit shift a u1" {
var x: u1 = 1;
var y = x << 0;
- assert(y == 1);
-}
-
-test "@intCast to a u0" {
- var x: u8 = 0;
- var y: u0 = @intCast(u0, x);
- assert(y == 0);
+ expect(y == 1);
}
test "@bytesToslice on a packed struct" {
@@ -708,7 +704,7 @@ test "@bytesToslice on a packed struct" {
var b = [1]u8{9};
var f = @bytesToSlice(F, b);
- assert(f[0].a == 9);
+ expect(f[0].a == 9);
}
test "comptime pointer cast array and then slice" {
@@ -720,57 +716,57 @@ test "comptime pointer cast array and then slice" {
const ptrB: [*]const u8 = &array;
const sliceB: []const u8 = ptrB[0..2];
- assert(sliceA[1] == 2);
- assert(sliceB[1] == 2);
+ expect(sliceA[1] == 2);
+ expect(sliceB[1] == 2);
}
test "slice bounds in comptime concatenation" {
const bs = comptime blk: {
- const b = c"11";
- break :blk b[0..1];
+ const b = c"........1........";
+ break :blk b[8..9];
};
const str = "" ++ bs;
- assert(str.len == 1);
- assert(std.mem.eql(u8, str, "1"));
+ expect(str.len == 1);
+ expect(std.mem.eql(u8, str, "1"));
const str2 = bs ++ "";
- assert(str2.len == 1);
- assert(std.mem.eql(u8, str2, "1"));
+ expect(str2.len == 1);
+ expect(std.mem.eql(u8, str2, "1"));
}
test "comptime bitwise operators" {
comptime {
- assert(3 & 1 == 1);
- assert(3 & -1 == 3);
- assert(-3 & -1 == -3);
- assert(3 | -1 == -1);
- assert(-3 | -1 == -1);
- assert(3 ^ -1 == -4);
- assert(-3 ^ -1 == 2);
- assert(~i8(-1) == 0);
- assert(~i128(-1) == 0);
- assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
- assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
- assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
+ expect(3 & 1 == 1);
+ expect(3 & -1 == 3);
+ expect(-3 & -1 == -3);
+ expect(3 | -1 == -1);
+ expect(-3 | -1 == -1);
+ expect(3 ^ -1 == -4);
+ expect(-3 ^ -1 == 2);
+ expect(~i8(-1) == 0);
+ expect(~i128(-1) == 0);
+ expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
+ expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
+ expect(~u128(0) == 0xffffffffffffffffffffffffffffffff);
}
}
test "*align(1) u16 is the same as *align(1:0:2) u16" {
comptime {
- assert(*align(1:0:2) u16 == *align(1) u16);
+ expect(*align(1:0:2) u16 == *align(1) u16);
// TODO add parsing support for this syntax
- //assert(*align(:0:2) u16 == *u16);
+ //expect(*align(:0:2) u16 == *u16);
}
}
test "array concatenation forces comptime" {
var a = oneItem(3) ++ oneItem(4);
- assert(std.mem.eql(i32, a, []i32{3, 4}));
+ expect(std.mem.eql(i32, a, []i32{ 3, 4 }));
}
test "array multiplication forces comptime" {
var a = oneItem(3) ** scalar(2);
- assert(std.mem.eql(i32, a, []i32{3, 3}));
+ expect(std.mem.eql(i32, a, []i32{ 3, 3 }));
}
fn oneItem(x: i32) [1]i32 {
diff --git a/test/cases/field_parent_ptr.zig b/test/stage1/behavior/field_parent_ptr.zig
similarity index 74%
rename from test/cases/field_parent_ptr.zig
rename to test/stage1/behavior/field_parent_ptr.zig
index 00d4e0f367..6026a49d12 100644
--- a/test/cases/field_parent_ptr.zig
+++ b/test/stage1/behavior/field_parent_ptr.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "@fieldParentPtr non-first field" {
testParentFieldPtr(&foo.c);
@@ -25,17 +25,17 @@ const foo = Foo{
};
fn testParentFieldPtr(c: *const i32) void {
- assert(c == &foo.c);
+ expect(c == &foo.c);
const base = @fieldParentPtr(Foo, "c", c);
- assert(base == &foo);
- assert(&base.c == c);
+ expect(base == &foo);
+ expect(&base.c == c);
}
fn testParentFieldPtrFirst(a: *const bool) void {
- assert(a == &foo.a);
+ expect(a == &foo.a);
const base = @fieldParentPtr(Foo, "a", a);
- assert(base == &foo);
- assert(&base.a == a);
+ expect(base == &foo);
+ expect(&base.a == a);
}
diff --git a/test/cases/fn.zig b/test/stage1/behavior/fn.zig
similarity index 81%
rename from test/cases/fn.zig
rename to test/stage1/behavior/fn.zig
index 8908bd7854..3f78c80290 100644
--- a/test/cases/fn.zig
+++ b/test/stage1/behavior/fn.zig
@@ -1,7 +1,7 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "params" {
- assert(testParamsAdd(22, 11) == 33);
+ expect(testParamsAdd(22, 11) == 33);
}
fn testParamsAdd(a: i32, b: i32) i32 {
return a + b;
@@ -21,32 +21,32 @@ test "void parameters" {
fn voidFun(a: i32, b: void, c: i32, d: void) void {
const v = b;
const vv: void = if (a == 1) v else {};
- assert(a + c == 3);
+ expect(a + c == 3);
return vv;
}
test "mutable local variables" {
var zero: i32 = 0;
- assert(zero == 0);
+ expect(zero == 0);
var i = i32(0);
while (i != 3) {
i += 1;
}
- assert(i == 3);
+ expect(i == 3);
}
test "separate block scopes" {
{
const no_conflict: i32 = 5;
- assert(no_conflict == 5);
+ expect(no_conflict == 5);
}
const c = x: {
const no_conflict = i32(10);
break :x no_conflict;
};
- assert(c == 10);
+ expect(c == 10);
}
test "call function with empty string" {
@@ -59,7 +59,7 @@ fn @"weird function name"() i32 {
return 1234;
}
test "weird function name" {
- assert(@"weird function name"() == 1234);
+ expect(@"weird function name"() == 1234);
}
test "implicit cast function unreachable return" {
@@ -80,7 +80,7 @@ test "function pointers" {
fn4,
};
for (fns) |f, i| {
- assert(f() == @intCast(u32, i) + 5);
+ expect(f() == @intCast(u32, i) + 5);
}
}
fn fn1() u32 {
@@ -97,7 +97,7 @@ fn fn4() u32 {
}
test "inline function call" {
- assert(@inlineCall(add, 3, 9) == 12);
+ expect(@inlineCall(add, 3, 9) == 12);
}
fn add(a: i32, b: i32) i32 {
@@ -110,7 +110,7 @@ test "number literal as an argument" {
}
fn numberLiteralArg(a: var) void {
- assert(a == 3);
+ expect(a == 3);
}
test "assign inline fn to const variable" {
@@ -121,7 +121,7 @@ test "assign inline fn to const variable" {
inline fn inlineFn() void {}
test "pass by non-copying value" {
- assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
+ expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
}
const Point = struct {
@@ -134,17 +134,17 @@ fn addPointCoords(pt: Point) i32 {
}
test "pass by non-copying value through var arg" {
- assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
+ expect(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
}
fn addPointCoordsVar(pt: var) i32 {
- comptime assert(@typeOf(pt) == Point);
+ comptime expect(@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);
+ expect(pt.addPointCoords() == 3);
}
const Point2 = struct {
@@ -158,7 +158,7 @@ const Point2 = struct {
test "pass by non-copying value as method, which is generic" {
var pt = Point3{ .x = 1, .y = 2 };
- assert(pt.addPointCoords(i32) == 3);
+ expect(pt.addPointCoords(i32) == 3);
}
const Point3 = struct {
@@ -173,7 +173,7 @@ const Point3 = struct {
test "pass by non-copying value as method, at comptime" {
comptime {
var pt = Point2{ .x = 1, .y = 2 };
- assert(pt.addPointCoords() == 3);
+ expect(pt.addPointCoords() == 3);
}
}
@@ -189,7 +189,7 @@ fn outer(y: u32) fn (u32) u32 {
test "return inner function which references comptime variable of outer function" {
var func = outer(10);
- assert(func(3) == 7);
+ expect(func(3) == 7);
}
test "extern struct with stdcallcc fn pointer" {
@@ -203,5 +203,6 @@ test "extern struct with stdcallcc fn pointer" {
var s: S = undefined;
s.ptr = S.foo;
- assert(s.ptr() == 1234);
+ expect(s.ptr() == 1234);
}
+
diff --git a/test/cases/fn_in_struct_in_comptime.zig b/test/stage1/behavior/fn_in_struct_in_comptime.zig
similarity index 76%
rename from test/cases/fn_in_struct_in_comptime.zig
rename to test/stage1/behavior/fn_in_struct_in_comptime.zig
index fabb57e9cb..030693ac59 100644
--- a/test/cases/fn_in_struct_in_comptime.zig
+++ b/test/stage1/behavior/fn_in_struct_in_comptime.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
fn get_foo() fn (*u8) usize {
comptime {
@@ -13,5 +13,5 @@ fn get_foo() fn (*u8) usize {
test "define a function in an anonymous struct in comptime" {
const foo = get_foo();
- assert(foo(@intToPtr(*u8, 12345)) == 12345);
+ expect(foo(@intToPtr(*u8, 12345)) == 12345);
}
diff --git a/test/cases/for.zig b/test/stage1/behavior/for.zig
similarity index 91%
rename from test/cases/for.zig
rename to test/stage1/behavior/for.zig
index aecd8b9a07..b10dd14fa4 100644
--- a/test/cases/for.zig
+++ b/test/stage1/behavior/for.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const mem = std.mem;
test "continue in for loop" {
@@ -26,7 +26,7 @@ test "for loop with pointer elem var" {
var target: [source.len]u8 = undefined;
mem.copy(u8, target[0..], source);
mangleString(target[0..]);
- assert(mem.eql(u8, target, "bcdefgh"));
+ expect(mem.eql(u8, target, "bcdefgh"));
}
fn mangleString(s: []u8) void {
for (s) |*c| {
@@ -68,7 +68,7 @@ test "basic for loop" {
buf_index += 1;
}
- assert(mem.eql(u8, buffer[0..buf_index], expected_result));
+ expect(mem.eql(u8, buffer[0..buf_index], expected_result));
}
test "break from outer for loop" {
@@ -85,7 +85,7 @@ fn testBreakOuter() void {
break :outer;
}
}
- assert(count == 1);
+ expect(count == 1);
}
test "continue outer for loop" {
@@ -102,5 +102,5 @@ fn testContinueOuter() void {
continue :outer;
}
}
- assert(counter == array.len);
+ expect(counter == array.len);
}
diff --git a/test/cases/generics.zig b/test/stage1/behavior/generics.zig
similarity index 71%
rename from test/cases/generics.zig
rename to test/stage1/behavior/generics.zig
index 52aa013989..637f9b88ae 100644
--- a/test/cases/generics.zig
+++ b/test/stage1/behavior/generics.zig
@@ -1,9 +1,9 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "simple generic fn" {
- assert(max(i32, 3, -1) == 3);
- assert(max(f32, 0.123, 0.456) == 0.456);
- assert(add(2, 3) == 5);
+ expect(max(i32, 3, -1) == 3);
+ expect(max(f32, 0.123, 0.456) == 0.456);
+ expect(add(2, 3) == 5);
}
fn max(comptime T: type, a: T, b: T) T {
@@ -16,7 +16,7 @@ fn add(comptime a: i32, b: i32) i32 {
const the_max = max(u32, 1234, 5678);
test "compile time generic eval" {
- assert(the_max == 5678);
+ expect(the_max == 5678);
}
fn gimmeTheBigOne(a: u32, b: u32) u32 {
@@ -32,19 +32,19 @@ fn sameButWithFloats(a: f64, b: f64) f64 {
}
test "fn with comptime args" {
- assert(gimmeTheBigOne(1234, 5678) == 5678);
- assert(shouldCallSameInstance(34, 12) == 34);
- assert(sameButWithFloats(0.43, 0.49) == 0.49);
+ expect(gimmeTheBigOne(1234, 5678) == 5678);
+ expect(shouldCallSameInstance(34, 12) == 34);
+ expect(sameButWithFloats(0.43, 0.49) == 0.49);
}
test "var params" {
- assert(max_i32(12, 34) == 34);
- assert(max_f64(1.2, 3.4) == 3.4);
+ expect(max_i32(12, 34) == 34);
+ expect(max_f64(1.2, 3.4) == 3.4);
}
comptime {
- assert(max_i32(12, 34) == 34);
- assert(max_f64(1.2, 3.4) == 3.4);
+ expect(max_i32(12, 34) == 34);
+ expect(max_f64(1.2, 3.4) == 3.4);
}
fn max_var(a: var, b: var) @typeOf(a + b) {
@@ -76,8 +76,8 @@ test "function with return type type" {
var list2: List(i32) = undefined;
list.length = 10;
list2.length = 10;
- assert(list.prealloc_items.len == 8);
- assert(list2.prealloc_items.len == 8);
+ expect(list.prealloc_items.len == 8);
+ expect(list2.prealloc_items.len == 8);
}
test "generic struct" {
@@ -89,9 +89,9 @@ test "generic struct" {
.value = true,
.next = null,
};
- assert(a1.value == 13);
- assert(a1.value == a1.getVal());
- assert(b1.getVal());
+ expect(a1.value == 13);
+ expect(a1.value == a1.getVal());
+ expect(b1.getVal());
}
fn GenNode(comptime T: type) type {
return struct {
@@ -104,7 +104,7 @@ fn GenNode(comptime T: type) type {
}
test "const decls in struct" {
- assert(GenericDataThing(3).count_plus_one == 4);
+ expect(GenericDataThing(3).count_plus_one == 4);
}
fn GenericDataThing(comptime count: isize) type {
return struct {
@@ -113,15 +113,15 @@ fn GenericDataThing(comptime count: isize) type {
}
test "use generic param in generic param" {
- assert(aGenericFn(i32, 3, 4) == 7);
+ expect(aGenericFn(i32, 3, 4) == 7);
}
fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
return a + b;
}
test "generic fn with implicit cast" {
- assert(getFirstByte(u8, []u8{13}) == 13);
- assert(getFirstByte(u16, []u16{
+ expect(getFirstByte(u8, []u8{13}) == 13);
+ expect(getFirstByte(u16, []u16{
0,
13,
}) == 0);
@@ -146,6 +146,6 @@ fn foo2(arg: var) bool {
}
test "array of generic fns" {
- assert(foos[0](true));
- assert(!foos[1](true));
+ expect(foos[0](true));
+ expect(!foos[1](true));
}
diff --git a/test/cases/if.zig b/test/stage1/behavior/if.zig
similarity index 87%
rename from test/cases/if.zig
rename to test/stage1/behavior/if.zig
index 808936bfa5..a61b9dcfb4 100644
--- a/test/cases/if.zig
+++ b/test/stage1/behavior/if.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "if statements" {
shouldBeEqual(1, 1);
@@ -24,7 +24,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
}
test "else if expression" {
- assert(elseIfExpressionF(1) == 1);
+ expect(elseIfExpressionF(1) == 1);
}
fn elseIfExpressionF(c: u8) u8 {
if (c == 0) {
diff --git a/test/cases/import.zig b/test/stage1/behavior/import.zig
similarity index 54%
rename from test/cases/import.zig
rename to test/stage1/behavior/import.zig
index 6d6d4b0208..9a8c6848e2 100644
--- a/test/cases/import.zig
+++ b/test/stage1/behavior/import.zig
@@ -1,10 +1,10 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const a_namespace = @import("import/a_namespace.zig");
test "call fn via namespace lookup" {
- assert(a_namespace.foo() == 1234);
+ expect(a_namespace.foo() == 1234);
}
test "importing the same thing gives the same import" {
- assert(@import("std") == @import("std"));
+ expect(@import("std") == @import("std"));
}
diff --git a/test/cases/import/a_namespace.zig b/test/stage1/behavior/import/a_namespace.zig
similarity index 100%
rename from test/cases/import/a_namespace.zig
rename to test/stage1/behavior/import/a_namespace.zig
diff --git a/test/cases/incomplete_struct_param_tld.zig b/test/stage1/behavior/incomplete_struct_param_tld.zig
similarity index 82%
rename from test/cases/incomplete_struct_param_tld.zig
rename to test/stage1/behavior/incomplete_struct_param_tld.zig
index f1ac03a292..77a3dfd221 100644
--- a/test/cases/incomplete_struct_param_tld.zig
+++ b/test/stage1/behavior/incomplete_struct_param_tld.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const A = struct {
b: B,
@@ -26,5 +26,5 @@ test "incomplete struct param top level declaration" {
.c = C{ .x = 13 },
},
};
- assert(foo(a) == 13);
+ expect(foo(a) == 13);
}
diff --git a/test/stage1/behavior/inttoptr.zig b/test/stage1/behavior/inttoptr.zig
new file mode 100644
index 0000000000..b1780f93d6
--- /dev/null
+++ b/test/stage1/behavior/inttoptr.zig
@@ -0,0 +1,26 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "casting random address to function pointer" {
+ randomAddressToFunction();
+ comptime randomAddressToFunction();
+}
+
+fn randomAddressToFunction() void {
+ var addr: usize = 0xdeadbeef;
+ var ptr = @intToPtr(fn () void, addr);
+}
+
+test "mutate through ptr initialized with constant intToPtr value" {
+ forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
+}
+
+fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
+ const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
+ if (x) {
+ hardCodedP.* = hardCodedP.* | 10;
+ } else {
+ return;
+ }
+}
diff --git a/test/cases/ir_block_deps.zig b/test/stage1/behavior/ir_block_deps.zig
similarity index 68%
rename from test/cases/ir_block_deps.zig
rename to test/stage1/behavior/ir_block_deps.zig
index 5c1b18c00e..821079df79 100644
--- a/test/cases/ir_block_deps.zig
+++ b/test/stage1/behavior/ir_block_deps.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
fn foo(id: u64) !i32 {
return switch (id) {
@@ -16,6 +16,6 @@ fn getErrInt() anyerror!i32 {
}
test "ir block deps" {
- assert((foo(1) catch unreachable) == 0);
- assert((foo(2) catch unreachable) == 0);
+ expect((foo(1) catch unreachable) == 0);
+ expect((foo(2) catch unreachable) == 0);
}
diff --git a/test/cases/math.zig b/test/stage1/behavior/math.zig
similarity index 62%
rename from test/cases/math.zig
rename to test/stage1/behavior/math.zig
index 7d6b1bd9ac..36e81e11ed 100644
--- a/test/cases/math.zig
+++ b/test/stage1/behavior/math.zig
@@ -1,5 +1,7 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
+const expectEqualSlices = std.testing.expectEqualSlices;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
@@ -8,57 +10,57 @@ test "division" {
comptime testDivision();
}
fn testDivision() void {
- assert(div(u32, 13, 3) == 4);
- assert(div(f16, 1.0, 2.0) == 0.5);
- assert(div(f32, 1.0, 2.0) == 0.5);
+ expect(div(u32, 13, 3) == 4);
+ expect(div(f16, 1.0, 2.0) == 0.5);
+ expect(div(f32, 1.0, 2.0) == 0.5);
- assert(divExact(u32, 55, 11) == 5);
- assert(divExact(i32, -55, 11) == -5);
- assert(divExact(f16, 55.0, 11.0) == 5.0);
- assert(divExact(f16, -55.0, 11.0) == -5.0);
- assert(divExact(f32, 55.0, 11.0) == 5.0);
- assert(divExact(f32, -55.0, 11.0) == -5.0);
+ expect(divExact(u32, 55, 11) == 5);
+ expect(divExact(i32, -55, 11) == -5);
+ expect(divExact(f16, 55.0, 11.0) == 5.0);
+ expect(divExact(f16, -55.0, 11.0) == -5.0);
+ expect(divExact(f32, 55.0, 11.0) == 5.0);
+ expect(divExact(f32, -55.0, 11.0) == -5.0);
- assert(divFloor(i32, 5, 3) == 1);
- assert(divFloor(i32, -5, 3) == -2);
- assert(divFloor(f16, 5.0, 3.0) == 1.0);
- assert(divFloor(f16, -5.0, 3.0) == -2.0);
- assert(divFloor(f32, 5.0, 3.0) == 1.0);
- assert(divFloor(f32, -5.0, 3.0) == -2.0);
- assert(divFloor(i32, -0x80000000, -2) == 0x40000000);
- assert(divFloor(i32, 0, -0x80000000) == 0);
- assert(divFloor(i32, -0x40000001, 0x40000000) == -2);
- assert(divFloor(i32, -0x80000000, 1) == -0x80000000);
+ expect(divFloor(i32, 5, 3) == 1);
+ expect(divFloor(i32, -5, 3) == -2);
+ expect(divFloor(f16, 5.0, 3.0) == 1.0);
+ expect(divFloor(f16, -5.0, 3.0) == -2.0);
+ expect(divFloor(f32, 5.0, 3.0) == 1.0);
+ expect(divFloor(f32, -5.0, 3.0) == -2.0);
+ expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
+ expect(divFloor(i32, 0, -0x80000000) == 0);
+ expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
+ expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
- assert(divTrunc(i32, 5, 3) == 1);
- assert(divTrunc(i32, -5, 3) == -1);
- assert(divTrunc(f16, 5.0, 3.0) == 1.0);
- assert(divTrunc(f16, -5.0, 3.0) == -1.0);
- assert(divTrunc(f32, 5.0, 3.0) == 1.0);
- assert(divTrunc(f32, -5.0, 3.0) == -1.0);
- assert(divTrunc(f64, 5.0, 3.0) == 1.0);
- assert(divTrunc(f64, -5.0, 3.0) == -1.0);
+ expect(divTrunc(i32, 5, 3) == 1);
+ expect(divTrunc(i32, -5, 3) == -1);
+ expect(divTrunc(f16, 5.0, 3.0) == 1.0);
+ expect(divTrunc(f16, -5.0, 3.0) == -1.0);
+ expect(divTrunc(f32, 5.0, 3.0) == 1.0);
+ expect(divTrunc(f32, -5.0, 3.0) == -1.0);
+ expect(divTrunc(f64, 5.0, 3.0) == 1.0);
+ expect(divTrunc(f64, -5.0, 3.0) == -1.0);
comptime {
- assert(
+ expect(
1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
);
- assert(
+ expect(
@rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
);
- assert(
+ expect(
1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
);
- assert(
+ expect(
@divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
);
- assert(
+ expect(
@divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
);
- assert(
+ expect(
@divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
);
- assert(
+ expect(
4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
);
}
@@ -78,9 +80,9 @@ fn divTrunc(comptime T: type, a: T, b: T) T {
test "@addWithOverflow" {
var result: u8 = undefined;
- assert(@addWithOverflow(u8, 250, 100, &result));
- assert(!@addWithOverflow(u8, 100, 150, &result));
- assert(result == 250);
+ expect(@addWithOverflow(u8, 250, 100, &result));
+ expect(!@addWithOverflow(u8, 100, 150, &result));
+ expect(result == 250);
}
// TODO test mulWithOverflow
@@ -88,9 +90,9 @@ test "@addWithOverflow" {
test "@shlWithOverflow" {
var result: u16 = undefined;
- assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
- assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
- assert(result == 0b1011111111111100);
+ expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
+ expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
+ expect(result == 0b1011111111111100);
}
test "@clz" {
@@ -99,11 +101,11 @@ test "@clz" {
}
fn testClz() void {
- assert(clz(u8(0b00001010)) == 4);
- assert(clz(u8(0b10001010)) == 0);
- assert(clz(u8(0b00000000)) == 8);
- assert(clz(u128(0xffffffffffffffff)) == 64);
- assert(clz(u128(0x10000000000000000)) == 63);
+ expect(clz(u8(0b00001010)) == 4);
+ expect(clz(u8(0b10001010)) == 0);
+ expect(clz(u8(0b00000000)) == 8);
+ expect(clz(u128(0xffffffffffffffff)) == 64);
+ expect(clz(u128(0x10000000000000000)) == 63);
}
fn clz(x: var) usize {
@@ -116,9 +118,9 @@ test "@ctz" {
}
fn testCtz() void {
- assert(ctz(u8(0b10100000)) == 5);
- assert(ctz(u8(0b10001010)) == 1);
- assert(ctz(u8(0b00000000)) == 8);
+ expect(ctz(u8(0b10100000)) == 5);
+ expect(ctz(u8(0b10001010)) == 1);
+ expect(ctz(u8(0b00000000)) == 8);
}
fn ctz(x: var) usize {
@@ -128,27 +130,27 @@ fn ctz(x: var) usize {
test "assignment operators" {
var i: u32 = 0;
i += 5;
- assert(i == 5);
+ expect(i == 5);
i -= 2;
- assert(i == 3);
+ expect(i == 3);
i *= 20;
- assert(i == 60);
+ expect(i == 60);
i /= 3;
- assert(i == 20);
+ expect(i == 20);
i %= 11;
- assert(i == 9);
+ expect(i == 9);
i <<= 1;
- assert(i == 18);
+ expect(i == 18);
i >>= 2;
- assert(i == 4);
+ expect(i == 4);
i = 6;
i &= 5;
- assert(i == 4);
+ expect(i == 4);
i ^= 6;
- assert(i == 2);
+ expect(i == 2);
i = 6;
i |= 3;
- assert(i == 7);
+ expect(i == 7);
}
test "three expr in a row" {
@@ -170,14 +172,14 @@ fn testThreeExprInARow(f: bool, t: bool) void {
assertFalse(i32(7) != --(i32(7)));
}
fn assertFalse(b: bool) void {
- assert(!b);
+ expect(!b);
}
test "const number literal" {
const one = 1;
const eleven = ten + one;
- assert(eleven == 11);
+ expect(eleven == 11);
}
const ten = 10;
@@ -187,9 +189,9 @@ test "unsigned wrapping" {
}
fn testUnsignedWrappingEval(x: u32) void {
const zero = x +% 1;
- assert(zero == 0);
+ expect(zero == 0);
const orig = zero -% 1;
- assert(orig == maxInt(u32));
+ expect(orig == maxInt(u32));
}
test "signed wrapping" {
@@ -198,9 +200,9 @@ test "signed wrapping" {
}
fn testSignedWrappingEval(x: i32) void {
const min_val = x +% 1;
- assert(min_val == minInt(i32));
+ expect(min_val == minInt(i32));
const max_val = min_val -% 1;
- assert(max_val == maxInt(i32));
+ expect(max_val == maxInt(i32));
}
test "negation wrapping" {
@@ -208,9 +210,9 @@ test "negation wrapping" {
comptime testNegationWrappingEval(minInt(i16));
}
fn testNegationWrappingEval(x: i16) void {
- assert(x == -32768);
+ expect(x == -32768);
const neg = -%x;
- assert(neg == -32768);
+ expect(neg == -32768);
}
test "unsigned 64-bit division" {
@@ -219,8 +221,8 @@ test "unsigned 64-bit division" {
}
fn test_u64_div() void {
const result = divWithResult(1152921504606846976, 34359738365);
- assert(result.quotient == 33554432);
- assert(result.remainder == 100663296);
+ expect(result.quotient == 33554432);
+ expect(result.remainder == 100663296);
}
fn divWithResult(a: u64, b: u64) DivResult {
return DivResult{
@@ -234,36 +236,36 @@ const DivResult = struct {
};
test "binary not" {
- assert(comptime x: {
+ expect(comptime x: {
break :x ~u16(0b1010101010101010) == 0b0101010101010101;
});
- assert(comptime x: {
+ expect(comptime x: {
break :x ~u64(2147483647) == 18446744071562067968;
});
testBinaryNot(0b1010101010101010);
}
fn testBinaryNot(x: u16) void {
- assert(~x == 0b0101010101010101);
+ expect(~x == 0b0101010101010101);
}
test "small int addition" {
var x: @IntType(false, 2) = 0;
- assert(x == 0);
+ expect(x == 0);
x += 1;
- assert(x == 1);
+ expect(x == 1);
x += 1;
- assert(x == 2);
+ expect(x == 2);
x += 1;
- assert(x == 3);
+ expect(x == 3);
var result: @typeOf(x) = 3;
- assert(@addWithOverflow(@typeOf(x), x, 1, &result));
+ expect(@addWithOverflow(@typeOf(x), x, 1, &result));
- assert(result == 0);
+ expect(result == 0);
}
test "float equality" {
@@ -276,20 +278,20 @@ test "float equality" {
fn testFloatEqualityImpl(x: f64, y: f64) void {
const y2 = x + 1.0;
- assert(y == y2);
+ expect(y == y2);
}
test "allow signed integer division/remainder when values are comptime known and positive or exact" {
- assert(5 / 3 == 1);
- assert(-5 / -3 == 1);
- assert(-6 / 3 == -2);
+ expect(5 / 3 == 1);
+ expect(-5 / -3 == 1);
+ expect(-6 / 3 == -2);
- assert(5 % 3 == 2);
- assert(-6 % 3 == 0);
+ expect(5 % 3 == 2);
+ expect(-6 % 3 == 0);
}
test "hex float literal parsing" {
- comptime assert(0x1.0 == 1.0);
+ comptime expect(0x1.0 == 1.0);
}
test "quad hex float literal parsing in range" {
@@ -304,7 +306,7 @@ test "quad hex float literal parsing accurate" {
// implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
const expected: u128 = 0x3fff1111222233334444555566667777;
- assert(@bitCast(u128, a) == expected);
+ expect(@bitCast(u128, a) == expected);
}
test "hex float literal within range" {
@@ -319,7 +321,7 @@ test "truncating shift left" {
}
fn testShlTrunc(x: u16) void {
const shifted = x << 1;
- assert(shifted == 65534);
+ expect(shifted == 65534);
}
test "truncating shift right" {
@@ -328,7 +330,7 @@ test "truncating shift right" {
}
fn testShrTrunc(x: u16) void {
const shifted = x >> 1;
- assert(shifted == 32767);
+ expect(shifted == 32767);
}
test "exact shift left" {
@@ -337,7 +339,7 @@ test "exact shift left" {
}
fn testShlExact(x: u8) void {
const shifted = @shlExact(x, 2);
- assert(shifted == 0b11010100);
+ expect(shifted == 0b11010100);
}
test "exact shift right" {
@@ -346,22 +348,22 @@ test "exact shift right" {
}
fn testShrExact(x: u8) void {
const shifted = @shrExact(x, 2);
- assert(shifted == 0b00101101);
+ expect(shifted == 0b00101101);
}
test "comptime_int addition" {
comptime {
- assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
- assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
+ expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
+ expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
}
}
test "comptime_int multiplication" {
comptime {
- assert(
+ expect(
45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
);
- assert(
+ expect(
594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
);
}
@@ -369,7 +371,7 @@ test "comptime_int multiplication" {
test "comptime_int shifting" {
comptime {
- assert((u128(1) << 127) == 0x80000000000000000000000000000000);
+ expect((u128(1) << 127) == 0x80000000000000000000000000000000);
}
}
@@ -377,16 +379,16 @@ test "comptime_int multi-limb shift and mask" {
comptime {
var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
- assert(u32(a & 0xffffffff) == 0xaaaaaaab);
+ expect(u32(a & 0xffffffff) == 0xaaaaaaab);
a >>= 32;
- assert(u32(a & 0xffffffff) == 0xeeeeeeef);
+ expect(u32(a & 0xffffffff) == 0xeeeeeeef);
a >>= 32;
- assert(u32(a & 0xffffffff) == 0xa0000001);
+ expect(u32(a & 0xffffffff) == 0xa0000001);
a >>= 32;
- assert(u32(a & 0xffffffff) == 0xefffffff);
+ expect(u32(a & 0xffffffff) == 0xefffffff);
a >>= 32;
- assert(a == 0);
+ expect(a == 0);
}
}
@@ -394,7 +396,7 @@ test "comptime_int multi-limb partial shift right" {
comptime {
var a = 0x1ffffffffeeeeeeee;
a >>= 16;
- assert(a == 0x1ffffffffeeee);
+ expect(a == 0x1ffffffffeeee);
}
}
@@ -404,23 +406,23 @@ test "xor" {
}
fn test_xor() void {
- assert(0xFF ^ 0x00 == 0xFF);
- assert(0xF0 ^ 0x0F == 0xFF);
- assert(0xFF ^ 0xF0 == 0x0F);
- assert(0xFF ^ 0x0F == 0xF0);
- assert(0xFF ^ 0xFF == 0x00);
+ expect(0xFF ^ 0x00 == 0xFF);
+ expect(0xF0 ^ 0x0F == 0xFF);
+ expect(0xFF ^ 0xF0 == 0x0F);
+ expect(0xFF ^ 0x0F == 0xF0);
+ expect(0xFF ^ 0xFF == 0x00);
}
test "comptime_int xor" {
comptime {
- assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
- assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
- assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
- assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
- assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
- assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
- assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
- assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
+ expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
+ expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
+ expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
+ expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
+ expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
+ expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
}
}
@@ -434,23 +436,23 @@ fn make_f128(x: f128) f128 {
}
fn test_f128() void {
- assert(@sizeOf(f128) == 16);
- assert(make_f128(1.0) == 1.0);
- assert(make_f128(1.0) != 1.1);
- assert(make_f128(1.0) > 0.9);
- assert(make_f128(1.0) >= 0.9);
- assert(make_f128(1.0) >= 1.0);
+ expect(@sizeOf(f128) == 16);
+ expect(make_f128(1.0) == 1.0);
+ expect(make_f128(1.0) != 1.1);
+ expect(make_f128(1.0) > 0.9);
+ expect(make_f128(1.0) >= 0.9);
+ expect(make_f128(1.0) >= 1.0);
should_not_be_zero(1.0);
}
fn should_not_be_zero(x: f128) void {
- assert(x != 0.0);
+ expect(x != 0.0);
}
test "comptime float rem int" {
comptime {
var x = f32(1) % 2;
- assert(x == 1.0);
+ expect(x == 1.0);
}
}
@@ -465,8 +467,8 @@ test "remainder division" {
}
fn remdiv(comptime T: type) void {
- assert(T(1) == T(1) % T(2));
- assert(T(1) == T(7) % T(3));
+ expect(T(1) == T(1) % T(2));
+ expect(T(1) == T(7) % T(3));
}
test "@sqrt" {
@@ -480,21 +482,36 @@ test "@sqrt" {
const x = 14.0;
const y = x * x;
const z = @sqrt(@typeOf(y), y);
- comptime assert(z == x);
+ comptime expect(z == x);
}
fn testSqrt(comptime T: type, x: T) void {
- assert(@sqrt(T, x * x) == x);
+ expect(@sqrt(T, x * x) == x);
}
test "comptime_int param and return" {
const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
- assert(a == 137114567242441932203689521744947848950);
+ expect(a == 137114567242441932203689521744947848950);
const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
- assert(b == 985095453608931032642182098849559179469148836107390954364380);
+ expect(b == 985095453608931032642182098849559179469148836107390954364380);
}
fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
return a + b;
}
+
+test "vector integer addition" {
+ const S = struct {
+ fn doTheTest() void {
+ var a: @Vector(4, i32) = []i32{ 1, 2, 3, 4 };
+ var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 };
+ var result = a + b;
+ var result_array: [4]i32 = result;
+ const expected = []i32{ 6, 8, 10, 12 };
+ expectEqualSlices(i32, &expected, &result_array);
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/cases/merge_error_sets.zig b/test/stage1/behavior/merge_error_sets.zig
similarity index 100%
rename from test/cases/merge_error_sets.zig
rename to test/stage1/behavior/merge_error_sets.zig
diff --git a/test/cases/misc.zig b/test/stage1/behavior/misc.zig
similarity index 64%
rename from test/cases/misc.zig
rename to test/stage1/behavior/misc.zig
index 1a34d54e9e..91cab78bc7 100644
--- a/test/cases/misc.zig
+++ b/test/stage1/behavior/misc.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const mem = std.mem;
const cstr = std.cstr;
const builtin = @import("builtin");
@@ -26,38 +26,38 @@ test "call disabled extern fn" {
}
test "@IntType builtin" {
- assert(@IntType(true, 8) == i8);
- assert(@IntType(true, 16) == i16);
- assert(@IntType(true, 32) == i32);
- assert(@IntType(true, 64) == i64);
+ expect(@IntType(true, 8) == i8);
+ expect(@IntType(true, 16) == i16);
+ expect(@IntType(true, 32) == i32);
+ expect(@IntType(true, 64) == i64);
- assert(@IntType(false, 8) == u8);
- assert(@IntType(false, 16) == u16);
- assert(@IntType(false, 32) == u32);
- assert(@IntType(false, 64) == u64);
+ expect(@IntType(false, 8) == u8);
+ expect(@IntType(false, 16) == u16);
+ expect(@IntType(false, 32) == u32);
+ expect(@IntType(false, 64) == u64);
- assert(i8.bit_count == 8);
- assert(i16.bit_count == 16);
- assert(i32.bit_count == 32);
- assert(i64.bit_count == 64);
+ expect(i8.bit_count == 8);
+ expect(i16.bit_count == 16);
+ expect(i32.bit_count == 32);
+ expect(i64.bit_count == 64);
- assert(i8.is_signed);
- assert(i16.is_signed);
- assert(i32.is_signed);
- assert(i64.is_signed);
- assert(isize.is_signed);
+ expect(i8.is_signed);
+ expect(i16.is_signed);
+ expect(i32.is_signed);
+ expect(i64.is_signed);
+ expect(isize.is_signed);
- assert(!u8.is_signed);
- assert(!u16.is_signed);
- assert(!u32.is_signed);
- assert(!u64.is_signed);
- assert(!usize.is_signed);
+ expect(!u8.is_signed);
+ expect(!u16.is_signed);
+ expect(!u32.is_signed);
+ expect(!u64.is_signed);
+ expect(!usize.is_signed);
}
test "floating point primitive bit counts" {
- assert(f16.bit_count == 16);
- assert(f32.bit_count == 32);
- assert(f64.bit_count == 64);
+ expect(f16.bit_count == 16);
+ expect(f32.bit_count == 32);
+ expect(f64.bit_count == 64);
}
test "short circuit" {
@@ -72,7 +72,7 @@ fn testShortCircuit(f: bool, t: bool) void {
var hit_4 = f;
if (t or x: {
- assert(f);
+ expect(f);
break :x f;
}) {
hit_1 = t;
@@ -81,31 +81,31 @@ fn testShortCircuit(f: bool, t: bool) void {
hit_2 = t;
break :x f;
}) {
- assert(f);
+ expect(f);
}
if (t and x: {
hit_3 = t;
break :x f;
}) {
- assert(f);
+ expect(f);
}
if (f and x: {
- assert(f);
+ expect(f);
break :x f;
}) {
- assert(f);
+ expect(f);
} else {
hit_4 = t;
}
- assert(hit_1);
- assert(hit_2);
- assert(hit_3);
- assert(hit_4);
+ expect(hit_1);
+ expect(hit_2);
+ expect(hit_3);
+ expect(hit_4);
}
test "truncate" {
- assert(testTruncate(0x10fd) == 0xfd);
+ expect(testTruncate(0x10fd) == 0xfd);
}
fn testTruncate(x: u32) u8 {
return @truncate(u8, x);
@@ -116,16 +116,16 @@ fn first4KeysOfHomeRow() []const u8 {
}
test "return string from function" {
- assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
+ expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
}
const g1: i32 = 1233 + 1;
var g2: i32 = 0;
test "global variables" {
- assert(g2 == 0);
+ expect(g2 == 0);
g2 = g1;
- assert(g2 == 1234);
+ expect(g2 == 1234);
}
test "memcpy and memset intrinsics" {
@@ -142,7 +142,7 @@ test "builtin static eval" {
const x: i32 = comptime x: {
break :x 1 + 2 + 3;
};
- assert(x == comptime 6);
+ expect(x == comptime 6);
}
test "slicing" {
@@ -163,7 +163,7 @@ test "slicing" {
test "constant equal function pointers" {
const alias = emptyFn;
- assert(comptime x: {
+ expect(comptime x: {
break :x emptyFn == alias;
});
}
@@ -171,25 +171,25 @@ test "constant equal function pointers" {
fn emptyFn() void {}
test "hex escape" {
- assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
+ expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
}
test "string concatenation" {
- assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
+ expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
}
test "array mult operator" {
- assert(mem.eql(u8, "ab" ** 5, "ababababab"));
+ expect(mem.eql(u8, "ab" ** 5, "ababababab"));
}
test "string escapes" {
- assert(mem.eql(u8, "\"", "\x22"));
- assert(mem.eql(u8, "\'", "\x27"));
- assert(mem.eql(u8, "\n", "\x0a"));
- assert(mem.eql(u8, "\r", "\x0d"));
- assert(mem.eql(u8, "\t", "\x09"));
- assert(mem.eql(u8, "\\", "\x5c"));
- assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
+ expect(mem.eql(u8, "\"", "\x22"));
+ expect(mem.eql(u8, "\'", "\x27"));
+ expect(mem.eql(u8, "\n", "\x0a"));
+ expect(mem.eql(u8, "\r", "\x0d"));
+ expect(mem.eql(u8, "\t", "\x09"));
+ expect(mem.eql(u8, "\\", "\x5c"));
+ expect(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
}
test "multiline string" {
@@ -199,7 +199,7 @@ test "multiline string" {
\\three
;
const s2 = "one\ntwo)\nthree";
- assert(mem.eql(u8, s1, s2));
+ expect(mem.eql(u8, s1, s2));
}
test "multiline C string" {
@@ -209,11 +209,11 @@ test "multiline C string" {
c\\three
;
const s2 = c"one\ntwo)\nthree";
- assert(cstr.cmp(s1, s2) == 0);
+ expect(cstr.cmp(s1, s2) == 0);
}
test "type equality" {
- assert(*const u8 != *u8);
+ expect(*const u8 != *u8);
}
const global_a: i32 = 1234;
@@ -221,7 +221,7 @@ const global_b: *const i32 = &global_a;
const global_c: *const f32 = @ptrCast(*const f32, global_b);
test "compile time global reinterpret" {
const d = @ptrCast(*const i32, global_c);
- assert(d.* == 1234);
+ expect(d.* == 1234);
}
test "explicit cast maybe pointers" {
@@ -247,8 +247,8 @@ test "cast undefined" {
fn testCastUndefined(x: []const u8) void {}
test "cast small unsigned to larger signed" {
- assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
- assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
+ expect(castSmallUnsignedToLargerSigned1(200) == i16(200));
+ expect(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
}
fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
return x;
@@ -258,7 +258,7 @@ fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
}
test "implicit cast after unreachable" {
- assert(outer() == 1234);
+ expect(outer() == 1234);
}
fn inner() i32 {
return 1234;
@@ -273,13 +273,13 @@ test "pointer dereferencing" {
y.* += 1;
- assert(x == 4);
- assert(y.* == 4);
+ expect(x == 4);
+ expect(y.* == 4);
}
test "call result of if else expression" {
- assert(mem.eql(u8, f2(true), "a"));
- assert(mem.eql(u8, f2(false), "b"));
+ expect(mem.eql(u8, f2(true), "a"));
+ expect(mem.eql(u8, f2(false), "b"));
}
fn f2(x: bool) []const u8 {
return (if (x) fA else fB)();
@@ -321,8 +321,8 @@ const test3_bar = Test3Foo{ .Two = 13 };
fn test3_1(f: Test3Foo) void {
switch (f) {
Test3Foo.Three => |pt| {
- assert(pt.x == 3);
- assert(pt.y == 4);
+ expect(pt.x == 3);
+ expect(pt.y == 4);
},
else => unreachable,
}
@@ -330,14 +330,14 @@ fn test3_1(f: Test3Foo) void {
fn test3_2(f: Test3Foo) void {
switch (f) {
Test3Foo.Two => |x| {
- assert(x == 13);
+ expect(x == 13);
},
else => unreachable,
}
}
test "character literals" {
- assert('\'' == single_quote);
+ expect('\'' == single_quote);
}
const single_quote = '\'';
@@ -346,13 +346,13 @@ test "take address of parameter" {
}
fn testTakeAddressOfParameter(f: f32) void {
const f_ptr = &f;
- assert(f_ptr.* == 12.34);
+ expect(f_ptr.* == 12.34);
}
test "pointer comparison" {
const a = ([]const u8)("a");
const b = &a;
- assert(ptrEql(b, b));
+ expect(ptrEql(b, b));
}
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
return a == b;
@@ -367,36 +367,31 @@ test "C string concatenation" {
{
var i: u32 = 0;
while (i < len_with_null) : (i += 1) {
- assert(a[i] == b[i]);
+ expect(a[i] == b[i]);
}
}
- assert(a[len] == 0);
- assert(b[len] == 0);
+ expect(a[len] == 0);
+ expect(b[len] == 0);
}
test "cast slice to u8 slice" {
- assert(@sizeOf(i32) == 4);
- var big_thing_array = []i32{
- 1,
- 2,
- 3,
- 4,
- };
+ expect(@sizeOf(i32) == 4);
+ var big_thing_array = []i32{ 1, 2, 3, 4 };
const big_thing_slice: []i32 = big_thing_array[0..];
const bytes = @sliceToBytes(big_thing_slice);
- assert(bytes.len == 4 * 4);
+ expect(bytes.len == 4 * 4);
bytes[4] = 0;
bytes[5] = 0;
bytes[6] = 0;
bytes[7] = 0;
- assert(big_thing_slice[1] == 0);
+ expect(big_thing_slice[1] == 0);
const big_thing_again = @bytesToSlice(i32, bytes);
- assert(big_thing_again[2] == 3);
+ expect(big_thing_again[2] == 3);
big_thing_again[2] = -1;
- assert(bytes[8] == maxInt(u8));
- assert(bytes[9] == maxInt(u8));
- assert(bytes[10] == maxInt(u8));
- assert(bytes[11] == maxInt(u8));
+ expect(bytes[8] == maxInt(u8));
+ expect(bytes[9] == maxInt(u8));
+ expect(bytes[10] == maxInt(u8));
+ expect(bytes[11] == maxInt(u8));
}
test "pointer to void return type" {
@@ -413,7 +408,7 @@ fn testPointerToVoidReturnType2() *const void {
test "non const ptr to aliased type" {
const int = i32;
- assert(?*int == ?*i32);
+ expect(?*int == ?*i32);
}
test "array 2D const double ptr" {
@@ -426,8 +421,8 @@ test "array 2D const double ptr" {
fn testArray2DConstDoublePtr(ptr: *const f32) void {
const ptr2 = @ptrCast([*]const f32, ptr);
- assert(ptr2[0] == 1.0);
- assert(ptr2[1] == 2.0);
+ expect(ptr2[0] == 1.0);
+ expect(ptr2[1] == 2.0);
}
const Tid = builtin.TypeId;
@@ -449,32 +444,32 @@ const AUnion = union {
test "@typeId" {
comptime {
- assert(@typeId(type) == Tid.Type);
- assert(@typeId(void) == Tid.Void);
- assert(@typeId(bool) == Tid.Bool);
- assert(@typeId(noreturn) == Tid.NoReturn);
- assert(@typeId(i8) == Tid.Int);
- assert(@typeId(u8) == Tid.Int);
- assert(@typeId(i64) == Tid.Int);
- assert(@typeId(u64) == Tid.Int);
- assert(@typeId(f32) == Tid.Float);
- assert(@typeId(f64) == Tid.Float);
- assert(@typeId(*f32) == Tid.Pointer);
- assert(@typeId([2]u8) == Tid.Array);
- assert(@typeId(AStruct) == Tid.Struct);
- assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
- assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
- assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
- assert(@typeId(@typeOf(null)) == Tid.Null);
- assert(@typeId(?i32) == Tid.Optional);
- assert(@typeId(anyerror!i32) == Tid.ErrorUnion);
- assert(@typeId(anyerror) == Tid.ErrorSet);
- assert(@typeId(AnEnum) == Tid.Enum);
- assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
- assert(@typeId(AUnionEnum) == Tid.Union);
- assert(@typeId(AUnion) == Tid.Union);
- assert(@typeId(fn () void) == Tid.Fn);
- assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
+ expect(@typeId(type) == Tid.Type);
+ expect(@typeId(void) == Tid.Void);
+ expect(@typeId(bool) == Tid.Bool);
+ expect(@typeId(noreturn) == Tid.NoReturn);
+ expect(@typeId(i8) == Tid.Int);
+ expect(@typeId(u8) == Tid.Int);
+ expect(@typeId(i64) == Tid.Int);
+ expect(@typeId(u64) == Tid.Int);
+ expect(@typeId(f32) == Tid.Float);
+ expect(@typeId(f64) == Tid.Float);
+ expect(@typeId(*f32) == Tid.Pointer);
+ expect(@typeId([2]u8) == Tid.Array);
+ expect(@typeId(AStruct) == Tid.Struct);
+ expect(@typeId(@typeOf(1)) == Tid.ComptimeInt);
+ expect(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
+ expect(@typeId(@typeOf(undefined)) == Tid.Undefined);
+ expect(@typeId(@typeOf(null)) == Tid.Null);
+ expect(@typeId(?i32) == Tid.Optional);
+ expect(@typeId(anyerror!i32) == Tid.ErrorUnion);
+ expect(@typeId(anyerror) == Tid.ErrorSet);
+ expect(@typeId(AnEnum) == Tid.Enum);
+ expect(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
+ expect(@typeId(AUnionEnum) == Tid.Union);
+ expect(@typeId(AUnion) == Tid.Union);
+ expect(@typeId(fn () void) == Tid.Fn);
+ expect(@typeId(@typeOf(builtin)) == Tid.Namespace);
// TODO bound fn
// TODO arg tuple
// TODO opaque
@@ -490,13 +485,13 @@ test "@typeName" {
Unused,
};
comptime {
- assert(mem.eql(u8, @typeName(i64), "i64"));
- assert(mem.eql(u8, @typeName(*usize), "*usize"));
+ expect(mem.eql(u8, @typeName(i64), "i64"));
+ expect(mem.eql(u8, @typeName(*usize), "*usize"));
// https://github.com/ziglang/zig/issues/675
- assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
- assert(mem.eql(u8, @typeName(Struct), "Struct"));
- assert(mem.eql(u8, @typeName(Union), "Union"));
- assert(mem.eql(u8, @typeName(Enum), "Enum"));
+ expect(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
+ expect(mem.eql(u8, @typeName(Struct), "Struct"));
+ expect(mem.eql(u8, @typeName(Union), "Union"));
+ expect(mem.eql(u8, @typeName(Enum), "Enum"));
}
}
@@ -504,28 +499,16 @@ fn TypeFromFn(comptime T: type) type {
return struct {};
}
-test "volatile load and store" {
- var number: i32 = 1234;
- const ptr = (*volatile i32)(&number);
- ptr.* += 1;
- assert(ptr.* == 1235);
+test "double implicit cast in same expression" {
+ var x = i32(u16(nine()));
+ expect(x == 9);
}
-
-test "slice string literal has type []const u8" {
- comptime {
- assert(@typeOf("aoeu"[0..]) == []const u8);
- const array = []i32{
- 1,
- 2,
- 3,
- 4,
- };
- assert(@typeOf(array[0..]) == []const i32);
- }
+fn nine() u8 {
+ return 9;
}
test "global variable initialized to global variable array element" {
- assert(global_ptr == &gdt[0]);
+ expect(global_ptr == &gdt[0]);
}
const GDTEntry = struct {
field: i32,
@@ -543,16 +526,12 @@ export fn writeToVRam() void {
vram[0] = 'X';
}
-test "pointer child field" {
- assert((*u32).Child == u32);
-}
-
const OpaqueA = @OpaqueType();
const OpaqueB = @OpaqueType();
test "@OpaqueType" {
- assert(*OpaqueA != *OpaqueB);
- assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
- assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
+ expect(*OpaqueA != *OpaqueB);
+ expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
+ expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
}
test "variable is allowed to be a pointer to an opaque type" {
@@ -581,25 +560,6 @@ test "implicit comptime while" {
}
}
-test "struct inside function" {
- testStructInFn();
- comptime testStructInFn();
-}
-
-fn testStructInFn() void {
- const BlockKind = u32;
-
- const Block = struct {
- kind: BlockKind,
- };
-
- var block = Block{ .kind = 1234 };
-
- block.kind += 1;
-
- assert(block.kind == 1235);
-}
-
fn fnThatClosesOverLocalConst() type {
const c = 1;
return struct {
@@ -611,7 +571,7 @@ fn fnThatClosesOverLocalConst() type {
test "function closes over local const" {
const x = fnThatClosesOverLocalConst().g();
- assert(x == 1);
+ expect(x == 1);
}
test "cold function" {
@@ -648,21 +608,21 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: Pack
test "slicing zero length array" {
const s1 = ""[0..];
const s2 = ([]u32{})[0..];
- assert(s1.len == 0);
- assert(s2.len == 0);
- assert(mem.eql(u8, s1, ""));
- assert(mem.eql(u32, s2, []u32{}));
+ expect(s1.len == 0);
+ expect(s2.len == 0);
+ expect(mem.eql(u8, s1, ""));
+ expect(mem.eql(u32, s2, []u32{}));
}
const addr1 = @ptrCast(*const u8, emptyFn);
test "comptime cast fn to ptr" {
const addr2 = @ptrCast(*const u8, emptyFn);
- comptime assert(addr1 == addr2);
+ comptime expect(addr1 == addr2);
}
test "equality compare fn ptrs" {
var a = emptyFn;
- assert(a == a);
+ expect(a == a);
}
test "self reference through fn ptr field" {
@@ -677,5 +637,59 @@ test "self reference through fn ptr field" {
};
var a: S.A = undefined;
a.f = S.foo;
- assert(a.f(a) == 12);
+ expect(a.f(a) == 12);
+}
+
+test "volatile load and store" {
+ var number: i32 = 1234;
+ const ptr = (*volatile i32)(&number);
+ ptr.* += 1;
+ expect(ptr.* == 1235);
+}
+
+test "slice string literal has type []const u8" {
+ comptime {
+ expect(@typeOf("aoeu"[0..]) == []const u8);
+ const array = []i32{ 1, 2, 3, 4 };
+ expect(@typeOf(array[0..]) == []const i32);
+ }
+}
+
+test "pointer child field" {
+ expect((*u32).Child == u32);
+}
+
+test "struct inside function" {
+ testStructInFn();
+ comptime testStructInFn();
+}
+
+fn testStructInFn() void {
+ const BlockKind = u32;
+
+ const Block = struct {
+ kind: BlockKind,
+ };
+
+ var block = Block{ .kind = 1234 };
+
+ block.kind += 1;
+
+ expect(block.kind == 1235);
+}
+
+test "fn call returning scalar optional in equality expression" {
+ expect(getNull() == null);
+}
+
+fn getNull() ?*i32 {
+ return null;
+}
+
+test "thread local variable" {
+ const S = struct {
+ threadlocal var t: i32 = 1234;
+ };
+ S.t += 1;
+ expect(S.t == 1235);
}
diff --git a/test/cases/namespace_depends_on_compile_var/a.zig b/test/stage1/behavior/namespace_depends_on_compile_var/a.zig
similarity index 100%
rename from test/cases/namespace_depends_on_compile_var/a.zig
rename to test/stage1/behavior/namespace_depends_on_compile_var/a.zig
diff --git a/test/cases/namespace_depends_on_compile_var/b.zig b/test/stage1/behavior/namespace_depends_on_compile_var/b.zig
similarity index 100%
rename from test/cases/namespace_depends_on_compile_var/b.zig
rename to test/stage1/behavior/namespace_depends_on_compile_var/b.zig
diff --git a/test/cases/namespace_depends_on_compile_var/index.zig b/test/stage1/behavior/namespace_depends_on_compile_var/index.zig
similarity index 66%
rename from test/cases/namespace_depends_on_compile_var/index.zig
rename to test/stage1/behavior/namespace_depends_on_compile_var/index.zig
index ccc49d9367..32feaced10 100644
--- a/test/cases/namespace_depends_on_compile_var/index.zig
+++ b/test/stage1/behavior/namespace_depends_on_compile_var/index.zig
@@ -1,11 +1,11 @@
const builtin = @import("builtin");
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "namespace depends on compile var" {
if (some_namespace.a_bool) {
- assert(some_namespace.a_bool);
+ expect(some_namespace.a_bool);
} else {
- assert(!some_namespace.a_bool);
+ expect(!some_namespace.a_bool);
}
}
const some_namespace = switch (builtin.os) {
diff --git a/test/cases/new_stack_call.zig b/test/stage1/behavior/new_stack_call.zig
similarity index 77%
rename from test/cases/new_stack_call.zig
rename to test/stage1/behavior/new_stack_call.zig
index 5912550d54..1e01a5a8a2 100644
--- a/test/cases/new_stack_call.zig
+++ b/test/stage1/behavior/new_stack_call.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
var new_stack_bytes: [1024]u8 = undefined;
@@ -10,17 +10,17 @@ test "calling a function with a new stack" {
const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
_ = targetFunction(arg);
- assert(arg == 1234);
- assert(a < b);
+ expect(arg == 1234);
+ expect(a < b);
}
fn targetFunction(x: i32) usize {
- assert(x == 1234);
+ expect(x == 1234);
var local_variable: i32 = 42;
const ptr = &local_variable;
ptr.* += 1;
- assert(local_variable == 43);
+ expect(local_variable == 43);
return @ptrToInt(ptr);
}
diff --git a/test/cases/null.zig b/test/stage1/behavior/null.zig
similarity index 83%
rename from test/cases/null.zig
rename to test/stage1/behavior/null.zig
index 825db88b1e..8c9b86b260 100644
--- a/test/cases/null.zig
+++ b/test/stage1/behavior/null.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "optional type" {
const x: ?bool = true;
@@ -17,13 +17,13 @@ test "optional type" {
const z = next_x orelse 1234;
- assert(z == 1234);
+ expect(z == 1234);
const final_x: ?i32 = 13;
const num = final_x orelse unreachable;
- assert(num == 13);
+ expect(num == 13);
}
test "test maybe object and get a pointer to the inner value" {
@@ -33,7 +33,7 @@ test "test maybe object and get a pointer to the inner value" {
b.* = false;
}
- assert(maybe_bool.? == false);
+ expect(maybe_bool.? == false);
}
test "rhs maybe unwrap return" {
@@ -47,9 +47,9 @@ test "maybe return" {
}
fn maybeReturnImpl() void {
- assert(foo(1235).?);
+ expect(foo(1235).?);
if (foo(null) != null) unreachable;
- assert(!foo(1234).?);
+ expect(!foo(1234).?);
}
fn foo(x: ?i32) ?bool {
@@ -58,7 +58,7 @@ fn foo(x: ?i32) ?bool {
}
test "if var maybe pointer" {
- assert(shouldBeAPlus1(Particle{
+ expect(shouldBeAPlus1(Particle{
.a = 14,
.b = 1,
.c = 1,
@@ -84,10 +84,10 @@ const Particle = struct {
test "null literal outside function" {
const is_null = here_is_a_null_literal.context == null;
- assert(is_null);
+ expect(is_null);
const is_non_null = here_is_a_null_literal.context != null;
- assert(!is_non_null);
+ expect(!is_non_null);
}
const SillyStruct = struct {
context: ?i32,
@@ -98,8 +98,8 @@ test "test null runtime" {
testTestNullRuntime(null);
}
fn testTestNullRuntime(x: ?i32) void {
- assert(x == null);
- assert(!(x != null));
+ expect(x == null);
+ expect(!(x != null));
}
test "optional void" {
@@ -108,8 +108,8 @@ test "optional void" {
}
fn optionalVoidImpl() void {
- assert(bar(null) == null);
- assert(bar({}) != null);
+ expect(bar(null) == null);
+ expect(bar({}) != null);
}
fn bar(x: ?void) ?void {
@@ -133,7 +133,7 @@ test "unwrap optional which is field of global var" {
}
struct_with_optional.field = 1234;
if (struct_with_optional.field) |payload| {
- assert(payload == 1234);
+ expect(payload == 1234);
} else {
unreachable;
}
@@ -141,13 +141,13 @@ test "unwrap optional which is field of global var" {
test "null with default unwrap" {
const x: i32 = null orelse 1;
- assert(x == 1);
+ expect(x == 1);
}
test "optional types" {
comptime {
const opt_type_struct = StructWithOptionalType{ .t = u8 };
- assert(opt_type_struct.t != null and opt_type_struct.t.? == u8);
+ expect(opt_type_struct.t != null and opt_type_struct.t.? == u8);
}
}
@@ -158,5 +158,5 @@ const StructWithOptionalType = struct {
test "optional pointer to 0 bit type null value at runtime" {
const EmptyStruct = struct {};
var x: ?*EmptyStruct = null;
- assert(x == null);
+ expect(x == null);
}
diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig
new file mode 100644
index 0000000000..a65bed020c
--- /dev/null
+++ b/test/stage1/behavior/optional.zig
@@ -0,0 +1,81 @@
+const expect = @import("std").testing.expect;
+
+pub const EmptyStruct = struct {};
+
+test "optional pointer to size zero struct" {
+ var e = EmptyStruct{};
+ var o: ?*EmptyStruct = &e;
+ expect(o != null);
+}
+
+test "equality compare nullable pointers" {
+ testNullPtrsEql();
+ comptime testNullPtrsEql();
+}
+
+fn testNullPtrsEql() void {
+ var number: i32 = 1234;
+
+ var x: ?*i32 = null;
+ var y: ?*i32 = null;
+ expect(x == y);
+ y = &number;
+ expect(x != y);
+ expect(x != &number);
+ expect(&number != x);
+ x = &number;
+ expect(x == y);
+ expect(x == &number);
+ expect(&number == x);
+}
+
+test "address of unwrap optional" {
+ const S = struct {
+ const Foo = struct {
+ a: i32,
+ };
+
+ var global: ?Foo = null;
+
+ pub fn getFoo() anyerror!*Foo {
+ return &global.?;
+ }
+ };
+ S.global = S.Foo{ .a = 1234 };
+ const foo = S.getFoo() catch unreachable;
+ expect(foo.a == 1234);
+}
+
+test "passing an optional integer as a parameter" {
+ const S = struct {
+ fn entry() bool {
+ var x: i32 = 1234;
+ return foo(x);
+ }
+
+ fn foo(x: ?i32) bool {
+ return x.? == 1234;
+ }
+ };
+ expect(S.entry());
+ comptime expect(S.entry());
+}
+
+test "unwrap function call with optional pointer return value" {
+ const S = struct {
+ fn entry() void {
+ expect(foo().?.* == 1234);
+ expect(bar() == null);
+ }
+ const global: i32 = 1234;
+ fn foo() ?*const i32 {
+ return &global;
+ }
+ fn bar() ?*i32 {
+ return null;
+ }
+ };
+ S.entry();
+ // TODO https://github.com/ziglang/zig/issues/1901
+ //comptime S.entry();
+}
diff --git a/test/stage1/behavior/pointers.zig b/test/stage1/behavior/pointers.zig
new file mode 100644
index 0000000000..eed7a765d7
--- /dev/null
+++ b/test/stage1/behavior/pointers.zig
@@ -0,0 +1,126 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const expectError = std.testing.expectError;
+
+test "dereference pointer" {
+ comptime testDerefPtr();
+ testDerefPtr();
+}
+
+fn testDerefPtr() void {
+ var x: i32 = 1234;
+ var y = &x;
+ y.* += 1;
+ expect(x == 1235);
+}
+
+test "pointer arithmetic" {
+ var ptr = c"abcd";
+
+ expect(ptr[0] == 'a');
+ ptr += 1;
+ expect(ptr[0] == 'b');
+ ptr += 1;
+ expect(ptr[0] == 'c');
+ ptr += 1;
+ expect(ptr[0] == 'd');
+ ptr += 1;
+ expect(ptr[0] == 0);
+ ptr -= 1;
+ expect(ptr[0] == 'd');
+ ptr -= 1;
+ expect(ptr[0] == 'c');
+ ptr -= 1;
+ expect(ptr[0] == 'b');
+ ptr -= 1;
+ expect(ptr[0] == 'a');
+}
+
+test "double pointer parsing" {
+ comptime expect(PtrOf(PtrOf(i32)) == **i32);
+}
+
+fn PtrOf(comptime T: type) type {
+ return *T;
+}
+
+test "assigning integer to C pointer" {
+ var x: i32 = 0;
+ var ptr: [*c]u8 = 0;
+ var ptr2: [*c]u8 = x;
+}
+
+test "implicit cast single item pointer to C pointer and back" {
+ var y: u8 = 11;
+ var x: [*c]u8 = &y;
+ var z: *u8 = x;
+ z.* += 1;
+ expect(y == 12);
+}
+
+test "C pointer comparison and arithmetic" {
+ const S = struct {
+ fn doTheTest() void {
+ var one: usize = 1;
+ var ptr1: [*c]u32 = 0;
+ var ptr2 = ptr1 + 10;
+ expect(ptr1 == 0);
+ expect(ptr1 >= 0);
+ expect(ptr1 <= 0);
+ expect(ptr1 < 1);
+ expect(ptr1 < one);
+ expect(1 > ptr1);
+ expect(one > ptr1);
+ expect(ptr1 < ptr2);
+ expect(ptr2 > ptr1);
+ expect(ptr2 >= 40);
+ expect(ptr2 == 40);
+ expect(ptr2 <= 40);
+ ptr2 -= 10;
+ expect(ptr1 == ptr2);
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
+test "peer type resolution with C pointers" {
+ var ptr_one: *u8 = undefined;
+ var ptr_many: [*]u8 = undefined;
+ var ptr_c: [*c]u8 = undefined;
+ var t = true;
+ var x1 = if (t) ptr_one else ptr_c;
+ var x2 = if (t) ptr_many else ptr_c;
+ var x3 = if (t) ptr_c else ptr_one;
+ var x4 = if (t) ptr_c else ptr_many;
+ expect(@typeOf(x1) == [*c]u8);
+ expect(@typeOf(x2) == [*c]u8);
+ expect(@typeOf(x3) == [*c]u8);
+ expect(@typeOf(x4) == [*c]u8);
+}
+
+test "implicit casting between C pointer and optional non-C pointer" {
+ var slice: []const u8 = "aoeu";
+ const opt_many_ptr: ?[*]const u8 = slice.ptr;
+ var ptr_opt_many_ptr = &opt_many_ptr;
+ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
+ expect(c_ptr.*.* == 'a');
+ ptr_opt_many_ptr = c_ptr;
+ expect(ptr_opt_many_ptr.*.?[1] == 'o');
+}
+
+test "implicit cast error unions with non-optional to optional pointer" {
+ const S = struct {
+ fn doTheTest() void {
+ expectError(error.Fail, foo());
+ }
+ fn foo() anyerror!?*u8 {
+ return bar() orelse error.Fail;
+ }
+ fn bar() ?*u8 {
+ return null;
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/cases/popcount.zig b/test/stage1/behavior/popcount.zig
similarity index 55%
rename from test/cases/popcount.zig
rename to test/stage1/behavior/popcount.zig
index 7dc7f28c0e..2b63284720 100644
--- a/test/cases/popcount.zig
+++ b/test/stage1/behavior/popcount.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "@popCount" {
comptime testPopCount();
@@ -8,17 +8,18 @@ test "@popCount" {
fn testPopCount() void {
{
var x: u32 = 0xaa;
- assert(@popCount(x) == 4);
+ expect(@popCount(x) == 4);
}
{
var x: u32 = 0xaaaaaaaa;
- assert(@popCount(x) == 16);
+ expect(@popCount(x) == 16);
}
{
var x: i16 = -1;
- assert(@popCount(x) == 16);
+ expect(@popCount(x) == 16);
}
comptime {
- assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
+ expect(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
}
}
+
diff --git a/test/stage1/behavior/ptrcast.zig b/test/stage1/behavior/ptrcast.zig
new file mode 100644
index 0000000000..3787382aea
--- /dev/null
+++ b/test/stage1/behavior/ptrcast.zig
@@ -0,0 +1,52 @@
+const builtin = @import("builtin");
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "reinterpret bytes as integer with nonzero offset" {
+ testReinterpretBytesAsInteger();
+ comptime testReinterpretBytesAsInteger();
+}
+
+fn testReinterpretBytesAsInteger() void {
+ const bytes = "\x12\x34\x56\x78\xab";
+ const expected = switch (builtin.endian) {
+ builtin.Endian.Little => 0xab785634,
+ builtin.Endian.Big => 0x345678ab,
+ };
+ expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
+}
+
+test "reinterpret bytes of an array into an extern struct" {
+ testReinterpretBytesAsExternStruct();
+ comptime testReinterpretBytesAsExternStruct();
+}
+
+fn testReinterpretBytesAsExternStruct() void {
+ var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
+
+ const S = extern struct {
+ a: u8,
+ b: u16,
+ c: u8,
+ };
+
+ var ptr = @ptrCast(*const S, &bytes);
+ var val = ptr.c;
+ expect(val == 5);
+}
+
+test "reinterpret struct field at comptime" {
+ const numLittle = comptime Bytes.init(0x12345678);
+ expect(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
+}
+
+const Bytes = struct {
+ bytes: [4]u8,
+
+ pub fn init(v: u32) Bytes {
+ var res: Bytes = undefined;
+ @ptrCast(*align(1) u32, &res.bytes).* = v;
+
+ return res;
+ }
+};
diff --git a/test/cases/pub_enum/index.zig b/test/stage1/behavior/pub_enum/index.zig
similarity index 59%
rename from test/cases/pub_enum/index.zig
rename to test/stage1/behavior/pub_enum/index.zig
index 7fdd07b8a3..15e4114c2d 100644
--- a/test/cases/pub_enum/index.zig
+++ b/test/stage1/behavior/pub_enum/index.zig
@@ -1,13 +1,13 @@
const other = @import("other.zig");
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "pub enum" {
pubEnumTest(other.APubEnum.Two);
}
fn pubEnumTest(foo: other.APubEnum) void {
- assert(foo == other.APubEnum.Two);
+ expect(foo == other.APubEnum.Two);
}
test "cast with imported symbol" {
- assert(other.size_t(42) == 42);
+ expect(other.size_t(42) == 42);
}
diff --git a/test/cases/pub_enum/other.zig b/test/stage1/behavior/pub_enum/other.zig
similarity index 100%
rename from test/cases/pub_enum/other.zig
rename to test/stage1/behavior/pub_enum/other.zig
diff --git a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig b/test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig
similarity index 82%
rename from test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig
rename to test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig
index 3c94bb0d49..2c1cf06268 100644
--- a/test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig
+++ b/test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig
@@ -1,14 +1,14 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const mem = @import("std").mem;
var ok: bool = false;
test "reference a variable in an if after an if in the 2nd switch prong" {
foo(true, Num.Two, false, "aoeu");
- assert(!ok);
+ expect(!ok);
foo(false, Num.One, false, "aoeu");
- assert(!ok);
+ expect(!ok);
foo(true, Num.One, false, "aoeu");
- assert(ok);
+ expect(ok);
}
const Num = enum {
@@ -32,6 +32,6 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
}
fn a(x: []const u8) void {
- assert(mem.eql(u8, x, "aoeu"));
+ expect(mem.eql(u8, x, "aoeu"));
ok = true;
}
diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig
new file mode 100644
index 0000000000..55efc85b97
--- /dev/null
+++ b/test/stage1/behavior/reflection.zig
@@ -0,0 +1,96 @@
+const expect = @import("std").testing.expect;
+const mem = @import("std").mem;
+const reflection = @This();
+
+test "reflection: array, pointer, optional, error union type child" {
+ comptime {
+ expect(([10]u8).Child == u8);
+ expect((*u8).Child == u8);
+ expect((anyerror!u8).Payload == u8);
+ expect((?u8).Child == u8);
+ }
+}
+
+test "reflection: function return type, var args, and param types" {
+ comptime {
+ expect(@typeOf(dummy).ReturnType == i32);
+ expect(!@typeOf(dummy).is_var_args);
+ expect(@typeOf(dummy_varargs).is_var_args);
+ expect(@typeOf(dummy).arg_count == 3);
+ expect(@ArgType(@typeOf(dummy), 0) == bool);
+ expect(@ArgType(@typeOf(dummy), 1) == i32);
+ expect(@ArgType(@typeOf(dummy), 2) == f32);
+ }
+}
+
+fn dummy(a: bool, b: i32, c: f32) i32 {
+ return 1234;
+}
+fn dummy_varargs(args: ...) void {}
+
+test "reflection: struct member types and names" {
+ comptime {
+ expect(@memberCount(Foo) == 3);
+
+ expect(@memberType(Foo, 0) == i32);
+ expect(@memberType(Foo, 1) == bool);
+ expect(@memberType(Foo, 2) == void);
+
+ expect(mem.eql(u8, @memberName(Foo, 0), "one"));
+ expect(mem.eql(u8, @memberName(Foo, 1), "two"));
+ expect(mem.eql(u8, @memberName(Foo, 2), "three"));
+ }
+}
+
+test "reflection: enum member types and names" {
+ comptime {
+ expect(@memberCount(Bar) == 4);
+
+ expect(@memberType(Bar, 0) == void);
+ expect(@memberType(Bar, 1) == i32);
+ expect(@memberType(Bar, 2) == bool);
+ expect(@memberType(Bar, 3) == f64);
+
+ expect(mem.eql(u8, @memberName(Bar, 0), "One"));
+ expect(mem.eql(u8, @memberName(Bar, 1), "Two"));
+ expect(mem.eql(u8, @memberName(Bar, 2), "Three"));
+ expect(mem.eql(u8, @memberName(Bar, 3), "Four"));
+ }
+}
+
+test "reflection: @field" {
+ var f = Foo{
+ .one = 42,
+ .two = true,
+ .three = void{},
+ };
+
+ expect(f.one == f.one);
+ expect(@field(f, "o" ++ "ne") == f.one);
+ expect(@field(f, "t" ++ "wo") == f.two);
+ expect(@field(f, "th" ++ "ree") == f.three);
+ expect(@field(Foo, "const" ++ "ant") == Foo.constant);
+ expect(@field(Bar, "O" ++ "ne") == Bar.One);
+ expect(@field(Bar, "T" ++ "wo") == Bar.Two);
+ expect(@field(Bar, "Th" ++ "ree") == Bar.Three);
+ expect(@field(Bar, "F" ++ "our") == Bar.Four);
+ expect(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
+ @field(f, "o" ++ "ne") = 4;
+ expect(f.one == 4);
+}
+
+const Foo = struct {
+ const constant = 52;
+
+ one: i32,
+ two: bool,
+ three: void,
+};
+
+const Bar = union(enum) {
+ One: void,
+ Two: i32,
+ Three: bool,
+ Four: f64,
+};
+
diff --git a/test/stage1/behavior/sizeof_and_typeof.zig b/test/stage1/behavior/sizeof_and_typeof.zig
new file mode 100644
index 0000000000..58a6c81759
--- /dev/null
+++ b/test/stage1/behavior/sizeof_and_typeof.zig
@@ -0,0 +1,69 @@
+const builtin = @import("builtin");
+const expect = @import("std").testing.expect;
+
+test "@sizeOf and @typeOf" {
+ const y: @typeOf(x) = 120;
+ expect(@sizeOf(@typeOf(y)) == 2);
+}
+const x: u16 = 13;
+const z: @typeOf(x) = 19;
+
+const A = struct {
+ a: u8,
+ b: u32,
+ c: u8,
+ d: u3,
+ e: u5,
+ f: u16,
+ g: u16,
+};
+
+const P = packed struct {
+ a: u8,
+ b: u32,
+ c: u8,
+ d: u3,
+ e: u5,
+ f: u16,
+ g: u16,
+};
+
+test "@byteOffsetOf" {
+ // Packed structs have fixed memory layout
+ expect(@byteOffsetOf(P, "a") == 0);
+ expect(@byteOffsetOf(P, "b") == 1);
+ expect(@byteOffsetOf(P, "c") == 5);
+ expect(@byteOffsetOf(P, "d") == 6);
+ expect(@byteOffsetOf(P, "e") == 6);
+ expect(@byteOffsetOf(P, "f") == 7);
+ expect(@byteOffsetOf(P, "g") == 9);
+
+ // Normal struct fields can be moved/padded
+ var a: A = undefined;
+ expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
+ expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
+ expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
+ expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
+ expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
+ expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
+ expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
+}
+
+test "@bitOffsetOf" {
+ // Packed structs have fixed memory layout
+ expect(@bitOffsetOf(P, "a") == 0);
+ expect(@bitOffsetOf(P, "b") == 8);
+ expect(@bitOffsetOf(P, "c") == 40);
+ expect(@bitOffsetOf(P, "d") == 48);
+ expect(@bitOffsetOf(P, "e") == 51);
+ expect(@bitOffsetOf(P, "f") == 56);
+ expect(@bitOffsetOf(P, "g") == 72);
+
+ expect(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
+ expect(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
+ expect(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
+ expect(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
+ expect(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
+ expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
+ expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
+}
diff --git a/test/cases/slice.zig b/test/stage1/behavior/slice.zig
similarity index 67%
rename from test/cases/slice.zig
rename to test/stage1/behavior/slice.zig
index b4b43bdd19..13fa84d0fa 100644
--- a/test/cases/slice.zig
+++ b/test/stage1/behavior/slice.zig
@@ -1,20 +1,20 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const mem = @import("std").mem;
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
- assert(@ptrToInt(x.ptr) == 0x1000);
- assert(x.len == 0x500);
+ expect(@ptrToInt(x.ptr) == 0x1000);
+ expect(x.len == 0x500);
- assert(@ptrToInt(y.ptr) == 0x1100);
- assert(y.len == 0x400);
+ expect(@ptrToInt(y.ptr) == 0x1100);
+ expect(y.len == 0x400);
}
test "slice child property" {
var array: [5]i32 = undefined;
var slice = array[0..];
- assert(@typeOf(slice).Child == i32);
+ expect(@typeOf(slice).Child == i32);
}
test "runtime safety lets us slice from len..len" {
@@ -23,7 +23,7 @@ test "runtime safety lets us slice from len..len" {
2,
3,
};
- assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
+ expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
}
fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
@@ -36,5 +36,5 @@ test "implicitly cast array of size 0 to slice" {
}
fn assertLenIsZero(msg: []const u8) void {
- assert(msg.len == 0);
+ expect(msg.len == 0);
}
diff --git a/test/cases/struct.zig b/test/stage1/behavior/struct.zig
similarity index 69%
rename from test/cases/struct.zig
rename to test/stage1/behavior/struct.zig
index bbbd21912c..a045f482a2 100644
--- a/test/cases/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
@@ -12,7 +12,7 @@ const empty_global_instance = StructWithNoFields{};
test "call struct static method" {
const result = StructWithNoFields.add(3, 4);
- assert(result == 7);
+ expect(result == 7);
}
test "return empty struct instance" {
@@ -24,8 +24,8 @@ fn returnEmptyStructInstance() StructWithNoFields {
const should_be_11 = StructWithNoFields.add(5, 6);
-test "invake static method in global scope" {
- assert(should_be_11 == 11);
+test "invoke static method in global scope" {
+ expect(should_be_11 == 11);
}
test "void struct fields" {
@@ -34,8 +34,8 @@ test "void struct fields" {
.b = 1,
.c = void{},
};
- assert(foo.b == 1);
- assert(@sizeOf(VoidStructFieldsFoo) == 4);
+ expect(foo.b == 1);
+ expect(@sizeOf(VoidStructFieldsFoo) == 4);
}
const VoidStructFieldsFoo = struct {
a: void,
@@ -50,7 +50,7 @@ test "structs" {
foo.b = foo.a == 1;
testFoo(foo);
testMutation(&foo);
- assert(foo.c == 100);
+ expect(foo.c == 100);
}
const StructFoo = struct {
a: i32,
@@ -58,7 +58,7 @@ const StructFoo = struct {
c: f32,
};
fn testFoo(foo: StructFoo) void {
- assert(foo.b);
+ expect(foo.b);
}
fn testMutation(foo: *StructFoo) void {
foo.c = 100;
@@ -83,7 +83,7 @@ test "struct point to self" {
root.next = &node;
- assert(node.next.next.next.val.x == 1);
+ expect(node.next.next.next.val.x == 1);
}
test "struct byval assign" {
@@ -92,18 +92,18 @@ test "struct byval assign" {
foo1.a = 1234;
foo2.a = 0;
- assert(foo2.a == 0);
+ expect(foo2.a == 0);
foo2 = foo1;
- assert(foo2.a == 1234);
+ expect(foo2.a == 1234);
}
fn structInitializer() void {
const val = Val{ .x = 42 };
- assert(val.x == 42);
+ expect(val.x == 42);
}
test "fn call of struct field" {
- assert(callStructField(Foo{ .ptr = aFunc }) == 13);
+ expect(callStructField(Foo{ .ptr = aFunc }) == 13);
}
const Foo = struct {
@@ -122,7 +122,7 @@ test "store member function in variable" {
const instance = MemberFnTestFoo{ .x = 1234 };
const memberFn = MemberFnTestFoo.member;
const result = memberFn(instance);
- assert(result == 1234);
+ expect(result == 1234);
}
const MemberFnTestFoo = struct {
x: i32,
@@ -134,12 +134,12 @@ const MemberFnTestFoo = struct {
test "call member function directly" {
const instance = MemberFnTestFoo{ .x = 1234 };
const result = MemberFnTestFoo.member(instance);
- assert(result == 1234);
+ expect(result == 1234);
}
test "member functions" {
const r = MemberFnRand{ .seed = 1234 };
- assert(r.getSeed() == 1234);
+ expect(r.getSeed() == 1234);
}
const MemberFnRand = struct {
seed: u32,
@@ -150,7 +150,7 @@ const MemberFnRand = struct {
test "return struct byval from function" {
const bar = makeBar(1234, 5678);
- assert(bar.y == 5678);
+ expect(bar.y == 5678);
}
const Bar = struct {
x: i32,
@@ -165,7 +165,7 @@ fn makeBar(x: i32, y: i32) Bar {
test "empty struct method call" {
const es = EmptyStruct{};
- assert(es.method() == 1234);
+ expect(es.method() == 1234);
}
const EmptyStruct = struct {
fn method(es: *const EmptyStruct) i32 {
@@ -182,7 +182,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {
}
test "pass slice of empty struct to fn" {
- assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
+ expect(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
}
fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
return slice.len;
@@ -200,7 +200,7 @@ test "packed struct" {
};
foo.y += 1;
const four = foo.x + foo.y;
- assert(four == 4);
+ expect(four == 4);
}
const BitField1 = packed struct {
@@ -217,17 +217,17 @@ const bit_field_1 = BitField1{
test "bit field access" {
var data = bit_field_1;
- assert(getA(&data) == 1);
- assert(getB(&data) == 2);
- assert(getC(&data) == 3);
- comptime assert(@sizeOf(BitField1) == 1);
+ expect(getA(&data) == 1);
+ expect(getB(&data) == 2);
+ expect(getC(&data) == 3);
+ comptime expect(@sizeOf(BitField1) == 1);
data.b += 1;
- assert(data.b == 3);
+ expect(data.b == 3);
data.a += 1;
- assert(data.a == 2);
- assert(data.b == 3);
+ expect(data.a == 2);
+ expect(data.b == 3);
}
fn getA(data: *const BitField1) u3 {
@@ -254,8 +254,8 @@ const Foo96Bits = packed struct {
test "packed struct 24bits" {
comptime {
- assert(@sizeOf(Foo24Bits) == 3);
- assert(@sizeOf(Foo96Bits) == 12);
+ expect(@sizeOf(Foo24Bits) == 3);
+ expect(@sizeOf(Foo96Bits) == 12);
}
var value = Foo96Bits{
@@ -265,28 +265,28 @@ test "packed struct 24bits" {
.d = 0,
};
value.a += 1;
- assert(value.a == 1);
- assert(value.b == 0);
- assert(value.c == 0);
- assert(value.d == 0);
+ expect(value.a == 1);
+ expect(value.b == 0);
+ expect(value.c == 0);
+ expect(value.d == 0);
value.b += 1;
- assert(value.a == 1);
- assert(value.b == 1);
- assert(value.c == 0);
- assert(value.d == 0);
+ expect(value.a == 1);
+ expect(value.b == 1);
+ expect(value.c == 0);
+ expect(value.d == 0);
value.c += 1;
- assert(value.a == 1);
- assert(value.b == 1);
- assert(value.c == 1);
- assert(value.d == 0);
+ expect(value.a == 1);
+ expect(value.b == 1);
+ expect(value.c == 1);
+ expect(value.d == 0);
value.d += 1;
- assert(value.a == 1);
- assert(value.b == 1);
- assert(value.c == 1);
- assert(value.d == 1);
+ expect(value.a == 1);
+ expect(value.b == 1);
+ expect(value.c == 1);
+ expect(value.d == 1);
}
const FooArray24Bits = packed struct {
@@ -297,43 +297,43 @@ const FooArray24Bits = packed struct {
test "packed array 24bits" {
comptime {
- assert(@sizeOf([9]Foo24Bits) == 9 * 3);
- assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
+ expect(@sizeOf([9]Foo24Bits) == 9 * 3);
+ expect(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
}
var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
bytes[bytes.len - 1] = 0xaa;
const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
- assert(ptr.a == 0);
- assert(ptr.b[0].field == 0);
- assert(ptr.b[1].field == 0);
- assert(ptr.c == 0);
+ expect(ptr.a == 0);
+ expect(ptr.b[0].field == 0);
+ expect(ptr.b[1].field == 0);
+ expect(ptr.c == 0);
ptr.a = maxInt(u16);
- assert(ptr.a == maxInt(u16));
- assert(ptr.b[0].field == 0);
- assert(ptr.b[1].field == 0);
- assert(ptr.c == 0);
+ expect(ptr.a == maxInt(u16));
+ expect(ptr.b[0].field == 0);
+ expect(ptr.b[1].field == 0);
+ expect(ptr.c == 0);
ptr.b[0].field = maxInt(u24);
- assert(ptr.a == maxInt(u16));
- assert(ptr.b[0].field == maxInt(u24));
- assert(ptr.b[1].field == 0);
- assert(ptr.c == 0);
+ expect(ptr.a == maxInt(u16));
+ expect(ptr.b[0].field == maxInt(u24));
+ expect(ptr.b[1].field == 0);
+ expect(ptr.c == 0);
ptr.b[1].field = maxInt(u24);
- assert(ptr.a == maxInt(u16));
- assert(ptr.b[0].field == maxInt(u24));
- assert(ptr.b[1].field == maxInt(u24));
- assert(ptr.c == 0);
+ expect(ptr.a == maxInt(u16));
+ expect(ptr.b[0].field == maxInt(u24));
+ expect(ptr.b[1].field == maxInt(u24));
+ expect(ptr.c == 0);
ptr.c = maxInt(u16);
- assert(ptr.a == maxInt(u16));
- assert(ptr.b[0].field == maxInt(u24));
- assert(ptr.b[1].field == maxInt(u24));
- assert(ptr.c == maxInt(u16));
+ expect(ptr.a == maxInt(u16));
+ expect(ptr.b[0].field == maxInt(u24));
+ expect(ptr.b[1].field == maxInt(u24));
+ expect(ptr.c == maxInt(u16));
- assert(bytes[bytes.len - 1] == 0xaa);
+ expect(bytes[bytes.len - 1] == 0xaa);
}
const FooStructAligned = packed struct {
@@ -347,17 +347,17 @@ const FooArrayOfAligned = packed struct {
test "aligned array of packed struct" {
comptime {
- assert(@sizeOf(FooStructAligned) == 2);
- assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
+ expect(@sizeOf(FooStructAligned) == 2);
+ expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
}
var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
- assert(ptr.a[0].a == 0xbb);
- assert(ptr.a[0].b == 0xbb);
- assert(ptr.a[1].a == 0xbb);
- assert(ptr.a[1].b == 0xbb);
+ expect(ptr.a[0].a == 0xbb);
+ expect(ptr.a[0].b == 0xbb);
+ expect(ptr.a[1].a == 0xbb);
+ expect(ptr.a[1].b == 0xbb);
}
test "runtime struct initialization of bitfield" {
@@ -370,10 +370,10 @@ test "runtime struct initialization of bitfield" {
.y = @intCast(u4, x2),
};
- assert(s1.x == x1);
- assert(s1.y == x1);
- assert(s2.x == @intCast(u4, x2));
- assert(s2.y == @intCast(u4, x2));
+ expect(s1.x == x1);
+ expect(s1.y == x1);
+ expect(s2.x == @intCast(u4, x2));
+ expect(s2.y == @intCast(u4, x2));
}
var x1 = u4(1);
@@ -400,18 +400,18 @@ test "native bit field understands endianness" {
@memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
- assert(bitfields.f1 == 0x1111);
- assert(bitfields.f2 == 0x2222);
- assert(bitfields.f3 == 0x33);
- assert(bitfields.f4 == 0x44);
- assert(bitfields.f5 == 0x5);
- assert(bitfields.f6 == 0x6);
- assert(bitfields.f7 == 0x77);
+ expect(bitfields.f1 == 0x1111);
+ expect(bitfields.f2 == 0x2222);
+ expect(bitfields.f3 == 0x33);
+ expect(bitfields.f4 == 0x44);
+ expect(bitfields.f5 == 0x5);
+ expect(bitfields.f6 == 0x6);
+ expect(bitfields.f7 == 0x77);
}
test "align 1 field before self referential align 8 field as slice return type" {
const result = alloc(Expr);
- assert(result.len == 0);
+ expect(result.len == 0);
}
const Expr = union(enum) {
@@ -434,10 +434,10 @@ test "call method with mutable reference to struct with no fields" {
};
var s = S{};
- assert(S.doC(&s));
- assert(s.doC());
- assert(S.do(&s));
- assert(s.do());
+ expect(S.doC(&s));
+ expect(s.doC());
+ expect(S.do(&s));
+ expect(s.do());
}
test "implicit cast packed struct field to const ptr" {
@@ -453,7 +453,7 @@ test "implicit cast packed struct field to const ptr" {
var lup: LevelUpMove = undefined;
lup.level = 12;
const res = LevelUpMove.toInt(lup.level);
- assert(res == 12);
+ expect(res == 12);
}
test "pointer to packed struct member in a stack variable" {
@@ -464,7 +464,7 @@ test "pointer to packed struct member in a stack variable" {
var s = S{ .a = 2, .b = 0 };
var b_ptr = &s.b;
- assert(s.b == 0);
+ expect(s.b == 0);
b_ptr.* = 2;
- assert(s.b == 2);
+ expect(s.b == 2);
}
diff --git a/test/cases/struct_contains_null_ptr_itself.zig b/test/stage1/behavior/struct_contains_null_ptr_itself.zig
similarity index 85%
rename from test/cases/struct_contains_null_ptr_itself.zig
rename to test/stage1/behavior/struct_contains_null_ptr_itself.zig
index 21175974b3..991d742cec 100644
--- a/test/cases/struct_contains_null_ptr_itself.zig
+++ b/test/stage1/behavior/struct_contains_null_ptr_itself.zig
@@ -1,9 +1,9 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
test "struct contains null pointer which contains original struct" {
var x: ?*NodeLineComment = null;
- assert(x == null);
+ expect(x == null);
}
pub const Node = struct {
diff --git a/test/stage1/behavior/struct_contains_slice_of_itself.zig b/test/stage1/behavior/struct_contains_slice_of_itself.zig
new file mode 100644
index 0000000000..52c6579654
--- /dev/null
+++ b/test/stage1/behavior/struct_contains_slice_of_itself.zig
@@ -0,0 +1,85 @@
+const expect = @import("std").testing.expect;
+
+const Node = struct {
+ payload: i32,
+ children: []Node,
+};
+
+const NodeAligned = struct {
+ payload: i32,
+ children: []align(@alignOf(NodeAligned)) NodeAligned,
+};
+
+test "struct contains slice of itself" {
+ var other_nodes = []Node{
+ Node{
+ .payload = 31,
+ .children = []Node{},
+ },
+ Node{
+ .payload = 32,
+ .children = []Node{},
+ },
+ };
+ var nodes = []Node{
+ Node{
+ .payload = 1,
+ .children = []Node{},
+ },
+ Node{
+ .payload = 2,
+ .children = []Node{},
+ },
+ Node{
+ .payload = 3,
+ .children = other_nodes[0..],
+ },
+ };
+ const root = Node{
+ .payload = 1234,
+ .children = nodes[0..],
+ };
+ expect(root.payload == 1234);
+ expect(root.children[0].payload == 1);
+ expect(root.children[1].payload == 2);
+ expect(root.children[2].payload == 3);
+ expect(root.children[2].children[0].payload == 31);
+ expect(root.children[2].children[1].payload == 32);
+}
+
+test "struct contains aligned slice of itself" {
+ var other_nodes = []NodeAligned{
+ NodeAligned{
+ .payload = 31,
+ .children = []NodeAligned{},
+ },
+ NodeAligned{
+ .payload = 32,
+ .children = []NodeAligned{},
+ },
+ };
+ var nodes = []NodeAligned{
+ NodeAligned{
+ .payload = 1,
+ .children = []NodeAligned{},
+ },
+ NodeAligned{
+ .payload = 2,
+ .children = []NodeAligned{},
+ },
+ NodeAligned{
+ .payload = 3,
+ .children = other_nodes[0..],
+ },
+ };
+ const root = NodeAligned{
+ .payload = 1234,
+ .children = nodes[0..],
+ };
+ expect(root.payload == 1234);
+ expect(root.children[0].payload == 1);
+ expect(root.children[1].payload == 2);
+ expect(root.children[2].payload == 3);
+ expect(root.children[2].children[0].payload == 31);
+ expect(root.children[2].children[1].payload == 32);
+}
diff --git a/test/cases/switch.zig b/test/stage1/behavior/switch.zig
similarity index 66%
rename from test/cases/switch.zig
rename to test/stage1/behavior/switch.zig
index d5258f0bb1..1059bf28f8 100644
--- a/test/cases/switch.zig
+++ b/test/stage1/behavior/switch.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "switch with numbers" {
testSwitchWithNumbers(13);
@@ -10,14 +10,14 @@ fn testSwitchWithNumbers(x: u32) void {
13 => true,
else => false,
};
- assert(result);
+ expect(result);
}
test "switch with all ranges" {
- assert(testSwitchWithAllRanges(50, 3) == 1);
- assert(testSwitchWithAllRanges(101, 0) == 2);
- assert(testSwitchWithAllRanges(300, 5) == 3);
- assert(testSwitchWithAllRanges(301, 6) == 6);
+ expect(testSwitchWithAllRanges(50, 3) == 1);
+ expect(testSwitchWithAllRanges(101, 0) == 2);
+ expect(testSwitchWithAllRanges(300, 5) == 3);
+ expect(testSwitchWithAllRanges(301, 6) == 6);
}
fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
@@ -40,7 +40,7 @@ test "implicit comptime switch" {
};
comptime {
- assert(result + 1 == 14);
+ expect(result + 1 == 14);
}
}
@@ -71,7 +71,7 @@ fn nonConstSwitch(foo: SwitchStatmentFoo) void {
SwitchStatmentFoo.C => 3,
SwitchStatmentFoo.D => 4,
};
- assert(val == 3);
+ expect(val == 3);
}
const SwitchStatmentFoo = enum {
A,
@@ -93,10 +93,10 @@ const SwitchProngWithVarEnum = union(enum) {
fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
switch (a) {
SwitchProngWithVarEnum.One => |x| {
- assert(x == 13);
+ expect(x == 13);
},
SwitchProngWithVarEnum.Two => |x| {
- assert(x == 13.0);
+ expect(x == 13.0);
},
SwitchProngWithVarEnum.Meh => |x| {
const v: void = x;
@@ -116,7 +116,7 @@ fn testSwitchEnumPtrCapture() void {
else => unreachable,
}
switch (value) {
- SwitchProngWithVarEnum.One => |x| assert(x == 1235),
+ SwitchProngWithVarEnum.One => |x| expect(x == 1235),
else => unreachable,
}
}
@@ -127,7 +127,7 @@ test "switch with multiple expressions" {
4, 5, 6 => 2,
else => i32(3),
};
- assert(x == 2);
+ expect(x == 2);
}
fn returnsFive() i32 {
return 5;
@@ -149,12 +149,12 @@ fn returnsFalse() bool {
}
}
test "switch on const enum with var" {
- assert(!returnsFalse());
+ expect(!returnsFalse());
}
test "switch on type" {
- assert(trueIfBoolFalseOtherwise(bool));
- assert(!trueIfBoolFalseOtherwise(i32));
+ expect(trueIfBoolFalseOtherwise(bool));
+ expect(!trueIfBoolFalseOtherwise(i32));
}
fn trueIfBoolFalseOtherwise(comptime T: type) bool {
@@ -170,16 +170,16 @@ test "switch handles all cases of number" {
}
fn testSwitchHandleAllCases() void {
- assert(testSwitchHandleAllCasesExhaustive(0) == 3);
- assert(testSwitchHandleAllCasesExhaustive(1) == 2);
- assert(testSwitchHandleAllCasesExhaustive(2) == 1);
- assert(testSwitchHandleAllCasesExhaustive(3) == 0);
+ expect(testSwitchHandleAllCasesExhaustive(0) == 3);
+ expect(testSwitchHandleAllCasesExhaustive(1) == 2);
+ expect(testSwitchHandleAllCasesExhaustive(2) == 1);
+ expect(testSwitchHandleAllCasesExhaustive(3) == 0);
- assert(testSwitchHandleAllCasesRange(100) == 0);
- assert(testSwitchHandleAllCasesRange(200) == 1);
- assert(testSwitchHandleAllCasesRange(201) == 2);
- assert(testSwitchHandleAllCasesRange(202) == 4);
- assert(testSwitchHandleAllCasesRange(230) == 3);
+ expect(testSwitchHandleAllCasesRange(100) == 0);
+ expect(testSwitchHandleAllCasesRange(200) == 1);
+ expect(testSwitchHandleAllCasesRange(201) == 2);
+ expect(testSwitchHandleAllCasesRange(202) == 4);
+ expect(testSwitchHandleAllCasesRange(230) == 3);
}
fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
@@ -207,8 +207,8 @@ test "switch all prongs unreachable" {
}
fn testAllProngsUnreachable() void {
- assert(switchWithUnreachable(1) == 2);
- assert(switchWithUnreachable(2) == 10);
+ expect(switchWithUnreachable(1) == 2);
+ expect(switchWithUnreachable(2) == 10);
}
fn switchWithUnreachable(x: i32) i32 {
@@ -230,5 +230,42 @@ test "capture value of switch with all unreachable prongs" {
const x = return_a_number() catch |err| switch (err) {
else => unreachable,
};
- assert(x == 1);
+ expect(x == 1);
+}
+
+test "switching on booleans" {
+ testSwitchOnBools();
+ comptime testSwitchOnBools();
+}
+
+fn testSwitchOnBools() void {
+ expect(testSwitchOnBoolsTrueAndFalse(true) == false);
+ expect(testSwitchOnBoolsTrueAndFalse(false) == true);
+
+ expect(testSwitchOnBoolsTrueWithElse(true) == false);
+ expect(testSwitchOnBoolsTrueWithElse(false) == true);
+
+ expect(testSwitchOnBoolsFalseWithElse(true) == false);
+ expect(testSwitchOnBoolsFalseWithElse(false) == true);
+}
+
+fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
+ return switch (x) {
+ true => false,
+ false => true,
+ };
+}
+
+fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
+ return switch (x) {
+ true => false,
+ else => true,
+ };
+}
+
+fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
+ return switch (x) {
+ false => true,
+ else => false,
+ };
}
diff --git a/test/cases/switch_prong_err_enum.zig b/test/stage1/behavior/switch_prong_err_enum.zig
similarity index 82%
rename from test/cases/switch_prong_err_enum.zig
rename to test/stage1/behavior/switch_prong_err_enum.zig
index 89060690fc..3593eabb5a 100644
--- a/test/cases/switch_prong_err_enum.zig
+++ b/test/stage1/behavior/switch_prong_err_enum.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
var read_count: u64 = 0;
@@ -22,9 +22,9 @@ fn doThing(form_id: u64) anyerror!FormValue {
test "switch prong returns error enum" {
switch (doThing(17) catch unreachable) {
FormValue.Address => |payload| {
- assert(payload == 1);
+ expect(payload == 1);
},
else => unreachable,
}
- assert(read_count == 1);
+ expect(read_count == 1);
}
diff --git a/test/cases/switch_prong_implicit_cast.zig b/test/stage1/behavior/switch_prong_implicit_cast.zig
similarity index 86%
rename from test/cases/switch_prong_implicit_cast.zig
rename to test/stage1/behavior/switch_prong_implicit_cast.zig
index 56d37e290f..da965915ca 100644
--- a/test/cases/switch_prong_implicit_cast.zig
+++ b/test/stage1/behavior/switch_prong_implicit_cast.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const FormValue = union(enum) {
One: void,
@@ -18,5 +18,5 @@ test "switch prong implicit cast" {
FormValue.One => false,
FormValue.Two => |x| x,
};
- assert(result);
+ expect(result);
}
diff --git a/test/cases/syntax.zig b/test/stage1/behavior/syntax.zig
similarity index 99%
rename from test/cases/syntax.zig
rename to test/stage1/behavior/syntax.zig
index 0c8c3c5ed3..451e396142 100644
--- a/test/cases/syntax.zig
+++ b/test/stage1/behavior/syntax.zig
@@ -57,3 +57,4 @@ fn asm_lists() void {
:::"a","b",);
}
}
+
diff --git a/test/cases/this.zig b/test/stage1/behavior/this.zig
similarity index 78%
rename from test/cases/this.zig
rename to test/stage1/behavior/this.zig
index c7be074f36..a0bee3a3ee 100644
--- a/test/cases/this.zig
+++ b/test/stage1/behavior/this.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const module = @This();
@@ -20,7 +20,7 @@ fn add(x: i32, y: i32) i32 {
}
test "this refer to module call private fn" {
- assert(module.add(1, 2) == 3);
+ expect(module.add(1, 2) == 3);
}
test "this refer to container" {
@@ -29,6 +29,7 @@ test "this refer to container" {
.y = 34,
};
pt.addOne();
- assert(pt.x == 13);
- assert(pt.y == 35);
+ expect(pt.x == 13);
+ expect(pt.y == 35);
}
+
diff --git a/test/stage1/behavior/truncate.zig b/test/stage1/behavior/truncate.zig
new file mode 100644
index 0000000000..099b6c3359
--- /dev/null
+++ b/test/stage1/behavior/truncate.zig
@@ -0,0 +1,36 @@
+const std = @import("std");
+const expect = std.testing.expect;
+
+test "truncate u0 to larger integer allowed and has comptime known result" {
+ var x: u0 = 0;
+ const y = @truncate(u8, x);
+ comptime expect(y == 0);
+}
+
+test "truncate.u0.literal" {
+ var z = @truncate(u0, 0);
+ expect(z == 0);
+}
+
+test "truncate.u0.const" {
+ const c0: usize = 0;
+ var z = @truncate(u0, c0);
+ expect(z == 0);
+}
+
+test "truncate.u0.var" {
+ var d: u8 = 2;
+ var z = @truncate(u0, d);
+ expect(z == 0);
+}
+
+test "truncate sign mismatch but comptime known so it works anyway" {
+ const x: u32 = 10;
+ var result = @truncate(i8, x);
+ expect(result == 10);
+}
+
+test "truncate on comptime integer" {
+ var x = @truncate(u16, 9999);
+ expect(x == 9999);
+}
diff --git a/test/cases/try.zig b/test/stage1/behavior/try.zig
similarity index 82%
rename from test/cases/try.zig
rename to test/stage1/behavior/try.zig
index 450a9af6ac..9c700f6260 100644
--- a/test/cases/try.zig
+++ b/test/stage1/behavior/try.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "try on error union" {
tryOnErrorUnionImpl();
@@ -11,7 +11,7 @@ fn tryOnErrorUnionImpl() void {
error.CrappedOut => i32(2),
else => unreachable,
};
- assert(x == 11);
+ expect(x == 11);
}
fn returnsTen() anyerror!i32 {
@@ -20,10 +20,10 @@ fn returnsTen() anyerror!i32 {
test "try without vars" {
const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
- assert(result1 == 2);
+ expect(result1 == 2);
const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
- assert(result2 == 1);
+ expect(result2 == 1);
}
fn failIfTrue(ok: bool) anyerror!void {
@@ -38,6 +38,6 @@ test "try then not executed with assignment" {
if (failIfTrue(true)) {
unreachable;
} else |err| {
- assert(err == error.ItBroke);
+ expect(err == error.ItBroke);
}
}
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
new file mode 100644
index 0000000000..dc185cc960
--- /dev/null
+++ b/test/stage1/behavior/type_info.zig
@@ -0,0 +1,291 @@
+const expect = @import("std").testing.expect;
+const mem = @import("std").mem;
+const TypeInfo = @import("builtin").TypeInfo;
+const TypeId = @import("builtin").TypeId;
+
+test "type info: tag type, void info" {
+ testBasic();
+ comptime testBasic();
+}
+
+fn testBasic() void {
+ expect(@TagType(TypeInfo) == TypeId);
+ const void_info = @typeInfo(void);
+ expect(TypeId(void_info) == TypeId.Void);
+ expect(void_info.Void == {});
+}
+
+test "type info: integer, floating point type info" {
+ testIntFloat();
+ comptime testIntFloat();
+}
+
+fn testIntFloat() void {
+ const u8_info = @typeInfo(u8);
+ expect(TypeId(u8_info) == TypeId.Int);
+ expect(!u8_info.Int.is_signed);
+ expect(u8_info.Int.bits == 8);
+
+ const f64_info = @typeInfo(f64);
+ expect(TypeId(f64_info) == TypeId.Float);
+ expect(f64_info.Float.bits == 64);
+}
+
+test "type info: pointer type info" {
+ testPointer();
+ comptime testPointer();
+}
+
+fn testPointer() void {
+ const u32_ptr_info = @typeInfo(*u32);
+ expect(TypeId(u32_ptr_info) == TypeId.Pointer);
+ expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
+ expect(u32_ptr_info.Pointer.is_const == false);
+ expect(u32_ptr_info.Pointer.is_volatile == false);
+ expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
+ expect(u32_ptr_info.Pointer.child == u32);
+}
+
+test "type info: unknown length pointer type info" {
+ testUnknownLenPtr();
+ comptime testUnknownLenPtr();
+}
+
+fn testUnknownLenPtr() void {
+ const u32_ptr_info = @typeInfo([*]const volatile f64);
+ expect(TypeId(u32_ptr_info) == TypeId.Pointer);
+ expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
+ expect(u32_ptr_info.Pointer.is_const == true);
+ expect(u32_ptr_info.Pointer.is_volatile == true);
+ expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
+ expect(u32_ptr_info.Pointer.child == f64);
+}
+
+test "type info: C pointer type info" {
+ testCPtr();
+ comptime testCPtr();
+}
+
+fn testCPtr() void {
+ const ptr_info = @typeInfo([*c]align(4) const i8);
+ expect(TypeId(ptr_info) == TypeId.Pointer);
+ expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
+ expect(ptr_info.Pointer.is_const);
+ expect(!ptr_info.Pointer.is_volatile);
+ expect(ptr_info.Pointer.alignment == 4);
+ expect(ptr_info.Pointer.child == i8);
+}
+
+test "type info: slice type info" {
+ testSlice();
+ comptime testSlice();
+}
+
+fn testSlice() void {
+ const u32_slice_info = @typeInfo([]u32);
+ expect(TypeId(u32_slice_info) == TypeId.Pointer);
+ expect(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
+ expect(u32_slice_info.Pointer.is_const == false);
+ expect(u32_slice_info.Pointer.is_volatile == false);
+ expect(u32_slice_info.Pointer.alignment == 4);
+ expect(u32_slice_info.Pointer.child == u32);
+}
+
+test "type info: array type info" {
+ testArray();
+ comptime testArray();
+}
+
+fn testArray() void {
+ const arr_info = @typeInfo([42]bool);
+ expect(TypeId(arr_info) == TypeId.Array);
+ expect(arr_info.Array.len == 42);
+ expect(arr_info.Array.child == bool);
+}
+
+test "type info: optional type info" {
+ testOptional();
+ comptime testOptional();
+}
+
+fn testOptional() void {
+ const null_info = @typeInfo(?void);
+ expect(TypeId(null_info) == TypeId.Optional);
+ expect(null_info.Optional.child == void);
+}
+
+test "type info: promise info" {
+ testPromise();
+ comptime testPromise();
+}
+
+fn testPromise() void {
+ const null_promise_info = @typeInfo(promise);
+ expect(TypeId(null_promise_info) == TypeId.Promise);
+ expect(null_promise_info.Promise.child == null);
+
+ const promise_info = @typeInfo(promise->usize);
+ expect(TypeId(promise_info) == TypeId.Promise);
+ expect(promise_info.Promise.child.? == usize);
+}
+
+test "type info: error set, error union info" {
+ testErrorSet();
+ comptime testErrorSet();
+}
+
+fn testErrorSet() void {
+ const TestErrorSet = error{
+ First,
+ Second,
+ Third,
+ };
+
+ const error_set_info = @typeInfo(TestErrorSet);
+ expect(TypeId(error_set_info) == TypeId.ErrorSet);
+ expect(error_set_info.ErrorSet.errors.len == 3);
+ expect(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
+ expect(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
+
+ const error_union_info = @typeInfo(TestErrorSet!usize);
+ expect(TypeId(error_union_info) == TypeId.ErrorUnion);
+ expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
+ expect(error_union_info.ErrorUnion.payload == usize);
+}
+
+test "type info: enum info" {
+ testEnum();
+ comptime testEnum();
+}
+
+fn testEnum() void {
+ const Os = enum {
+ Windows,
+ Macos,
+ Linux,
+ FreeBSD,
+ };
+
+ const os_info = @typeInfo(Os);
+ expect(TypeId(os_info) == TypeId.Enum);
+ expect(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
+ expect(os_info.Enum.fields.len == 4);
+ expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
+ expect(os_info.Enum.fields[3].value == 3);
+ expect(os_info.Enum.tag_type == u2);
+ expect(os_info.Enum.defs.len == 0);
+}
+
+test "type info: union info" {
+ testUnion();
+ comptime testUnion();
+}
+
+fn testUnion() void {
+ const typeinfo_info = @typeInfo(TypeInfo);
+ expect(TypeId(typeinfo_info) == TypeId.Union);
+ expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ expect(typeinfo_info.Union.tag_type.? == TypeId);
+ expect(typeinfo_info.Union.fields.len == 25);
+ expect(typeinfo_info.Union.fields[4].enum_field != null);
+ expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
+ expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
+ expect(typeinfo_info.Union.defs.len == 21);
+
+ const TestNoTagUnion = union {
+ Foo: void,
+ Bar: u32,
+ };
+
+ const notag_union_info = @typeInfo(TestNoTagUnion);
+ expect(TypeId(notag_union_info) == TypeId.Union);
+ expect(notag_union_info.Union.tag_type == null);
+ expect(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
+ expect(notag_union_info.Union.fields.len == 2);
+ expect(notag_union_info.Union.fields[0].enum_field == null);
+ expect(notag_union_info.Union.fields[1].field_type == u32);
+
+ const TestExternUnion = extern union {
+ foo: *c_void,
+ };
+
+ const extern_union_info = @typeInfo(TestExternUnion);
+ expect(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
+ expect(extern_union_info.Union.tag_type == null);
+ expect(extern_union_info.Union.fields[0].enum_field == null);
+ expect(extern_union_info.Union.fields[0].field_type == *c_void);
+}
+
+test "type info: struct info" {
+ testStruct();
+ comptime testStruct();
+}
+
+fn testStruct() void {
+ const struct_info = @typeInfo(TestStruct);
+ expect(TypeId(struct_info) == TypeId.Struct);
+ expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
+ expect(struct_info.Struct.fields.len == 3);
+ expect(struct_info.Struct.fields[1].offset == null);
+ expect(struct_info.Struct.fields[2].field_type == *TestStruct);
+ expect(struct_info.Struct.defs.len == 2);
+ expect(struct_info.Struct.defs[0].is_pub);
+ expect(!struct_info.Struct.defs[0].data.Fn.is_extern);
+ expect(struct_info.Struct.defs[0].data.Fn.lib_name == null);
+ expect(struct_info.Struct.defs[0].data.Fn.return_type == void);
+ expect(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
+}
+
+const TestStruct = packed struct {
+ const Self = @This();
+
+ fieldA: usize,
+ fieldB: void,
+ fieldC: *Self,
+
+ pub fn foo(self: *const Self) void {}
+};
+
+test "type info: function type info" {
+ testFunction();
+ comptime testFunction();
+}
+
+fn testFunction() void {
+ const fn_info = @typeInfo(@typeOf(foo));
+ expect(TypeId(fn_info) == TypeId.Fn);
+ expect(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
+ expect(fn_info.Fn.is_generic);
+ expect(fn_info.Fn.args.len == 2);
+ expect(fn_info.Fn.is_var_args);
+ expect(fn_info.Fn.return_type == null);
+ expect(fn_info.Fn.async_allocator_type == null);
+
+ const test_instance: TestStruct = undefined;
+ const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
+ expect(TypeId(bound_fn_info) == TypeId.BoundFn);
+ expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
+}
+
+fn foo(comptime a: usize, b: bool, args: ...) usize {
+ return 0;
+}
+
+test "typeInfo with comptime parameter in struct fn def" {
+ const S = struct {
+ pub fn func(comptime x: f32) void {}
+ };
+ comptime var info = @typeInfo(S);
+}
+
+test "type info: vectors" {
+ testVector();
+ comptime testVector();
+}
+
+fn testVector() void {
+ const vec_info = @typeInfo(@Vector(4, i32));
+ expect(TypeId(vec_info) == TypeId.Vector);
+ expect(vec_info.Vector.len == 4);
+ expect(vec_info.Vector.child == i32);
+}
diff --git a/test/cases/undefined.zig b/test/stage1/behavior/undefined.zig
similarity index 63%
rename from test/cases/undefined.zig
rename to test/stage1/behavior/undefined.zig
index 83c620d211..4c233576cd 100644
--- a/test/cases/undefined.zig
+++ b/test/stage1/behavior/undefined.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const mem = @import("std").mem;
fn initStaticArray() [10]i32 {
@@ -11,16 +11,16 @@ fn initStaticArray() [10]i32 {
}
const static_array = initStaticArray();
test "init static array to undefined" {
- assert(static_array[0] == 1);
- assert(static_array[4] == 2);
- assert(static_array[7] == 3);
- assert(static_array[9] == 4);
+ expect(static_array[0] == 1);
+ expect(static_array[4] == 2);
+ expect(static_array[7] == 3);
+ expect(static_array[9] == 4);
comptime {
- assert(static_array[0] == 1);
- assert(static_array[4] == 2);
- assert(static_array[7] == 3);
- assert(static_array[9] == 4);
+ expect(static_array[0] == 1);
+ expect(static_array[4] == 2);
+ expect(static_array[7] == 3);
+ expect(static_array[9] == 4);
}
}
@@ -40,12 +40,12 @@ test "assign undefined to struct" {
comptime {
var foo: Foo = undefined;
setFooX(&foo);
- assert(foo.x == 2);
+ expect(foo.x == 2);
}
{
var foo: Foo = undefined;
setFooX(&foo);
- assert(foo.x == 2);
+ expect(foo.x == 2);
}
}
@@ -53,16 +53,17 @@ test "assign undefined to struct with method" {
comptime {
var foo: Foo = undefined;
foo.setFooXMethod();
- assert(foo.x == 3);
+ expect(foo.x == 3);
}
{
var foo: Foo = undefined;
foo.setFooXMethod();
- assert(foo.x == 3);
+ expect(foo.x == 3);
}
}
test "type name of undefined" {
const x = undefined;
- assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
+ expect(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
}
+
diff --git a/test/cases/underscore.zig b/test/stage1/behavior/underscore.zig
similarity index 93%
rename from test/cases/underscore.zig
rename to test/stage1/behavior/underscore.zig
index da1c97659c..fd5aebc87e 100644
--- a/test/cases/underscore.zig
+++ b/test/stage1/behavior/underscore.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
test "ignore lval with underscore" {
_ = false;
diff --git a/test/cases/union.zig b/test/stage1/behavior/union.zig
similarity index 80%
rename from test/cases/union.zig
rename to test/stage1/behavior/union.zig
index 019a7012da..0a4e2cfb92 100644
--- a/test/cases/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const Value = union(enum) {
Int: u64,
@@ -27,11 +27,11 @@ const array = []Value{
test "unions embedded in aggregate types" {
switch (array[1]) {
- Value.Array => |arr| assert(arr[4] == 3),
+ Value.Array => |arr| expect(arr[4] == 3),
else => unreachable,
}
switch ((err catch unreachable).val1) {
- Value.Int => |x| assert(x == 1234),
+ Value.Int => |x| expect(x == 1234),
else => unreachable,
}
}
@@ -43,18 +43,18 @@ const Foo = union {
test "basic unions" {
var foo = Foo{ .int = 1 };
- assert(foo.int == 1);
+ expect(foo.int == 1);
foo = Foo{ .float = 12.34 };
- assert(foo.float == 12.34);
+ expect(foo.float == 12.34);
}
test "comptime union field access" {
comptime {
var foo = Foo{ .int = 0 };
- assert(foo.int == 0);
+ expect(foo.int == 0);
foo = Foo{ .float = 42.42 };
- assert(foo.float == 42.42);
+ expect(foo.float == 42.42);
}
}
@@ -62,10 +62,10 @@ test "init union with runtime value" {
var foo: Foo = undefined;
setFloat(&foo, 12.34);
- assert(foo.float == 12.34);
+ expect(foo.float == 12.34);
setInt(&foo, 42);
- assert(foo.int == 42);
+ expect(foo.int == 42);
}
fn setFloat(foo: *Foo, x: f64) void {
@@ -83,9 +83,9 @@ const FooExtern = extern union {
test "basic extern unions" {
var foo = FooExtern{ .int = 1 };
- assert(foo.int == 1);
+ expect(foo.int == 1);
foo.float = 12.34;
- assert(foo.float == 12.34);
+ expect(foo.float == 12.34);
}
const Letter = enum {
@@ -105,11 +105,11 @@ test "union with specified enum tag" {
}
fn doTest() void {
- assert(bar(Payload{ .A = 1234 }) == -10);
+ expect(bar(Payload{ .A = 1234 }) == -10);
}
fn bar(value: Payload) i32 {
- assert(Letter(value) == Letter.A);
+ expect(Letter(value) == Letter.A);
return switch (value) {
Payload.A => |x| return x - 1244,
Payload.B => |x| if (x == 12.34) i32(20) else 21,
@@ -125,8 +125,8 @@ const MultipleChoice = union(enum(u32)) {
};
test "simple union(enum(u32))" {
var x = MultipleChoice.C;
- assert(x == MultipleChoice.C);
- assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
+ expect(x == MultipleChoice.C);
+ expect(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
}
const MultipleChoice2 = union(enum(u32)) {
@@ -142,14 +142,14 @@ const MultipleChoice2 = union(enum(u32)) {
};
test "union(enum(u32)) with specified and unspecified tag values" {
- comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
+ comptime expect(@TagType(@TagType(MultipleChoice2)) == u32);
testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
}
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
- assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
- assert(1123 == switch (x) {
+ expect(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
+ expect(1123 == switch (x) {
MultipleChoice2.A => 1,
MultipleChoice2.B => 2,
MultipleChoice2.C => |v| i32(1000) + v,
@@ -167,7 +167,7 @@ const ExternPtrOrInt = extern union {
int: u64,
};
test "extern union size" {
- comptime assert(@sizeOf(ExternPtrOrInt) == 8);
+ comptime expect(@sizeOf(ExternPtrOrInt) == 8);
}
const PackedPtrOrInt = packed union {
@@ -175,14 +175,14 @@ const PackedPtrOrInt = packed union {
int: u64,
};
test "extern union size" {
- comptime assert(@sizeOf(PackedPtrOrInt) == 8);
+ comptime expect(@sizeOf(PackedPtrOrInt) == 8);
}
const ZeroBits = union {
OnlyField: void,
};
test "union with only 1 field which is void should be zero bits" {
- comptime assert(@sizeOf(ZeroBits) == 0);
+ comptime expect(@sizeOf(ZeroBits) == 0);
}
const TheTag = enum {
@@ -196,9 +196,9 @@ const TheUnion = union(TheTag) {
C: i32,
};
test "union field access gives the enum values" {
- assert(TheUnion.A == TheTag.A);
- assert(TheUnion.B == TheTag.B);
- assert(TheUnion.C == TheTag.C);
+ expect(TheUnion.A == TheTag.A);
+ expect(TheUnion.B == TheTag.B);
+ expect(TheUnion.C == TheTag.C);
}
test "cast union to tag type of union" {
@@ -207,12 +207,12 @@ test "cast union to tag type of union" {
}
fn testCastUnionToTagType(x: TheUnion) void {
- assert(TheTag(x) == TheTag.B);
+ expect(TheTag(x) == TheTag.B);
}
test "cast tag type of union to union" {
var x: Value2 = Letter2.B;
- assert(Letter2(x) == Letter2.B);
+ expect(Letter2(x) == Letter2.B);
}
const Letter2 = enum {
A,
@@ -227,11 +227,11 @@ const Value2 = union(Letter2) {
test "implicit cast union to its tag type" {
var x: Value2 = Letter2.B;
- assert(x == Letter2.B);
+ expect(x == Letter2.B);
giveMeLetterB(x);
}
fn giveMeLetterB(x: Letter2) void {
- assert(x == Value2.B);
+ expect(x == Value2.B);
}
pub const PackThis = union(enum) {
@@ -244,7 +244,7 @@ test "constant packed union" {
}
fn testConstPackedUnion(expected_tokens: []const PackThis) void {
- assert(expected_tokens[0].StringLiteral == 1);
+ expect(expected_tokens[0].StringLiteral == 1);
}
test "switch on union with only 1 field" {
@@ -256,7 +256,7 @@ test "switch on union with only 1 field" {
z = PartialInstWithPayload{ .Compiled = 1234 };
switch (z) {
PartialInstWithPayload.Compiled => |x| {
- assert(x == 1234);
+ expect(x == 1234);
return;
},
}
@@ -282,11 +282,11 @@ test "access a member of tagged union with conflicting enum tag name" {
const B = void;
};
- comptime assert(Bar.A == u8);
+ comptime expect(Bar.A == u8);
}
test "tagged union initialization with runtime void" {
- assert(testTaggedUnionInit({}));
+ expect(testTaggedUnionInit({}));
}
const TaggedUnionWithAVoid = union(enum) {
@@ -324,9 +324,9 @@ test "union with only 1 field casted to its enum type" {
var e = Expr{ .Literal = Literal{ .Bool = true } };
const Tag = @TagType(Expr);
- comptime assert(@TagType(Tag) == comptime_int);
+ comptime expect(@TagType(Tag) == comptime_int);
var t = Tag(e);
- assert(t == Expr.Literal);
+ expect(t == Expr.Literal);
}
test "union with only 1 field casted to its enum type which has enum value specified" {
@@ -344,9 +344,9 @@ test "union with only 1 field casted to its enum type which has enum value speci
};
var e = Expr{ .Literal = Literal{ .Bool = true } };
- comptime assert(@TagType(Tag) == comptime_int);
+ comptime expect(@TagType(Tag) == comptime_int);
var t = Tag(e);
- assert(t == Expr.Literal);
- assert(@enumToInt(t) == 33);
- comptime assert(@enumToInt(t) == 33);
+ expect(t == Expr.Literal);
+ expect(@enumToInt(t) == 33);
+ comptime expect(@enumToInt(t) == 33);
}
diff --git a/test/cases/var_args.zig b/test/stage1/behavior/var_args.zig
similarity index 60%
rename from test/cases/var_args.zig
rename to test/stage1/behavior/var_args.zig
index 3eb6e30448..cc93b57f06 100644
--- a/test/cases/var_args.zig
+++ b/test/stage1/behavior/var_args.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
fn add(args: ...) i32 {
var sum = i32(0);
@@ -12,9 +12,9 @@ fn add(args: ...) i32 {
}
test "add arbitrary args" {
- assert(add(i32(1), i32(2), i32(3), i32(4)) == 10);
- assert(add(i32(1234)) == 1234);
- assert(add() == 0);
+ expect(add(i32(1), i32(2), i32(3), i32(4)) == 10);
+ expect(add(i32(1234)) == 1234);
+ expect(add() == 0);
}
fn readFirstVarArg(args: ...) void {
@@ -26,9 +26,9 @@ test "send void arg to var args" {
}
test "pass args directly" {
- assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
- assert(addSomeStuff(i32(1234)) == 1234);
- assert(addSomeStuff() == 0);
+ expect(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
+ expect(addSomeStuff(i32(1234)) == 1234);
+ expect(addSomeStuff() == 0);
}
fn addSomeStuff(args: ...) i32 {
@@ -36,24 +36,24 @@ fn addSomeStuff(args: ...) i32 {
}
test "runtime parameter before var args" {
- assert(extraFn(10) == 0);
- assert(extraFn(10, false) == 1);
- assert(extraFn(10, false, true) == 2);
+ expect(extraFn(10) == 0);
+ expect(extraFn(10, false) == 1);
+ expect(extraFn(10, false, true) == 2);
// TODO issue #313
//comptime {
- // assert(extraFn(10) == 0);
- // assert(extraFn(10, false) == 1);
- // assert(extraFn(10, false, true) == 2);
+ // expect(extraFn(10) == 0);
+ // expect(extraFn(10, false) == 1);
+ // expect(extraFn(10, false, true) == 2);
//}
}
fn extraFn(extra: u32, args: ...) usize {
if (args.len >= 1) {
- assert(args[0] == false);
+ expect(args[0] == false);
}
if (args.len >= 2) {
- assert(args[1] == true);
+ expect(args[1] == true);
}
return args.len;
}
@@ -71,8 +71,8 @@ fn foo2(args: ...) bool {
}
test "array of var args functions" {
- assert(foos[0]());
- assert(!foos[1]());
+ expect(foos[0]());
+ expect(!foos[1]());
}
test "pass zero length array to var args param" {
diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig
new file mode 100644
index 0000000000..b0d2871454
--- /dev/null
+++ b/test/stage1/behavior/vector.zig
@@ -0,0 +1,45 @@
+const std = @import("std");
+const mem = std.mem;
+const expect = std.testing.expect;
+
+test "vector wrap operators" {
+ const S = struct {
+ fn doTheTest() void {
+ const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
+ const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
+ expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 }));
+ expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 9, 18, 27, 36 }));
+ expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 10, 40, 90, 160 }));
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
+test "vector float operators" {
+ const S = struct {
+ fn doTheTest() void {
+ const v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
+ const x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
+ expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 }));
+ expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 }));
+ expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 }));
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
+test "vector bit operators" {
+ const S = struct {
+ fn doTheTest() void {
+ const v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
+ const x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
+ expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
+ expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
+ expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/cases/void.zig b/test/stage1/behavior/void.zig
similarity index 71%
rename from test/cases/void.zig
rename to test/stage1/behavior/void.zig
index 7121ac664b..9722791946 100644
--- a/test/cases/void.zig
+++ b/test/stage1/behavior/void.zig
@@ -1,4 +1,4 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
const Foo = struct {
a: void,
@@ -13,14 +13,14 @@ test "compare void with void compile time known" {
.b = 1,
.c = {},
};
- assert(foo.a == {});
+ expect(foo.a == {});
}
}
test "iterate over a void slice" {
var j: usize = 0;
for (times(10)) |_, i| {
- assert(i == j);
+ expect(i == j);
j += 1;
}
}
@@ -28,3 +28,8 @@ test "iterate over a void slice" {
fn times(n: usize) []const void {
return ([*]void)(undefined)[0..n];
}
+
+test "void optional" {
+ var x: ?void = {};
+ expect(x != null);
+}
diff --git a/test/cases/while.zig b/test/stage1/behavior/while.zig
similarity index 86%
rename from test/cases/while.zig
rename to test/stage1/behavior/while.zig
index f774e0ec6b..29ad90ed17 100644
--- a/test/cases/while.zig
+++ b/test/stage1/behavior/while.zig
@@ -1,12 +1,12 @@
-const assert = @import("std").debug.assert;
+const expect = @import("std").testing.expect;
test "while loop" {
var i: i32 = 0;
while (i < 4) {
i += 1;
}
- assert(i == 4);
- assert(whileLoop1() == 1);
+ expect(i == 4);
+ expect(whileLoop1() == 1);
}
fn whileLoop1() i32 {
return whileLoop2();
@@ -16,8 +16,9 @@ fn whileLoop2() i32 {
return 1;
}
}
+
test "static eval while" {
- assert(static_eval_while_number == 1);
+ expect(static_eval_while_number == 1);
}
const static_eval_while_number = staticWhileLoop1();
fn staticWhileLoop1() i32 {
@@ -31,7 +32,7 @@ fn staticWhileLoop2() i32 {
test "continue and break" {
runContinueAndBreakTest();
- assert(continue_and_break_counter == 8);
+ expect(continue_and_break_counter == 8);
}
var continue_and_break_counter: i32 = 0;
fn runContinueAndBreakTest() void {
@@ -44,7 +45,7 @@ fn runContinueAndBreakTest() void {
}
break;
}
- assert(i == 4);
+ expect(i == 4);
}
test "return with implicit cast from while loop" {
@@ -65,7 +66,7 @@ test "while with continue expression" {
sum += i;
}
}
- assert(sum == 40);
+ expect(sum == 40);
}
test "while with else" {
@@ -77,8 +78,8 @@ test "while with else" {
} else {
got_else += 1;
}
- assert(sum == 10);
- assert(got_else == 1);
+ expect(sum == 10);
+ expect(got_else == 1);
}
test "while with optional as condition" {
@@ -87,7 +88,7 @@ test "while with optional as condition" {
while (getNumberOrNull()) |value| {
sum += value;
}
- assert(sum == 45);
+ expect(sum == 45);
}
test "while with optional as condition with else" {
@@ -96,12 +97,12 @@ test "while with optional as condition with else" {
var got_else: i32 = 0;
while (getNumberOrNull()) |value| {
sum += value;
- assert(got_else == 0);
+ expect(got_else == 0);
} else {
got_else += 1;
}
- assert(sum == 45);
- assert(got_else == 1);
+ expect(sum == 45);
+ expect(got_else == 1);
}
test "while with error union condition" {
@@ -111,11 +112,11 @@ test "while with error union condition" {
while (getNumberOrErr()) |value| {
sum += value;
} else |err| {
- assert(err == error.OutOfNumbers);
+ expect(err == error.OutOfNumbers);
got_else += 1;
}
- assert(sum == 45);
- assert(got_else == 1);
+ expect(sum == 45);
+ expect(got_else == 1);
}
var numbers_left: i32 = undefined;
@@ -137,7 +138,7 @@ test "while on optional with else result follow else prong" {
break value;
} else
i32(2);
- assert(result == 2);
+ expect(result == 2);
}
test "while on optional with else result follow break prong" {
@@ -145,7 +146,7 @@ test "while on optional with else result follow break prong" {
break value;
} else
i32(2);
- assert(result == 10);
+ expect(result == 10);
}
test "while on error union with else result follow else prong" {
@@ -153,7 +154,7 @@ test "while on error union with else result follow else prong" {
break value;
} else |err|
i32(2);
- assert(result == 2);
+ expect(result == 2);
}
test "while on error union with else result follow break prong" {
@@ -161,7 +162,7 @@ test "while on error union with else result follow break prong" {
break value;
} else |err|
i32(2);
- assert(result == 10);
+ expect(result == 10);
}
test "while on bool with else result follow else prong" {
@@ -169,7 +170,7 @@ test "while on bool with else result follow else prong" {
break i32(10);
} else
i32(2);
- assert(result == 2);
+ expect(result == 2);
}
test "while on bool with else result follow break prong" {
@@ -177,7 +178,7 @@ test "while on bool with else result follow break prong" {
break i32(10);
} else
i32(2);
- assert(result == 10);
+ expect(result == 10);
}
test "break from outer while loop" {
diff --git a/test/cases/widening.zig b/test/stage1/behavior/widening.zig
similarity index 80%
rename from test/cases/widening.zig
rename to test/stage1/behavior/widening.zig
index cf6ab4ca0f..f7c238ee8d 100644
--- a/test/cases/widening.zig
+++ b/test/stage1/behavior/widening.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assert = std.debug.assert;
+const expect = std.testing.expect;
const mem = std.mem;
test "integer widening" {
@@ -9,13 +9,13 @@ test "integer widening" {
var d: u64 = c;
var e: u64 = d;
var f: u128 = e;
- assert(f == a);
+ expect(f == a);
}
test "implicit unsigned integer to signed integer" {
var a: u8 = 250;
var b: i16 = a;
- assert(b == 250);
+ expect(b == 250);
}
test "float widening" {
@@ -23,5 +23,6 @@ test "float widening" {
var b: f32 = a;
var c: f64 = b;
var d: f128 = c;
- assert(d == a);
+ expect(d == a);
}
+
diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig
index 196311a283..4805fc9896 100644
--- a/test/stage1/c_abi/main.zig
+++ b/test/stage1/c_abi/main.zig
@@ -1,5 +1,5 @@
const std = @import("std");
-const assertOrPanic = std.debug.assertOrPanic;
+const expect = std.testing.expect;
extern fn run_c_tests() void;
@@ -33,28 +33,28 @@ test "C ABI integers" {
}
export fn zig_u8(x: u8) void {
- assertOrPanic(x == 0xff);
+ expect(x == 0xff);
}
export fn zig_u16(x: u16) void {
- assertOrPanic(x == 0xfffe);
+ expect(x == 0xfffe);
}
export fn zig_u32(x: u32) void {
- assertOrPanic(x == 0xfffffffd);
+ expect(x == 0xfffffffd);
}
export fn zig_u64(x: u64) void {
- assertOrPanic(x == 0xfffffffffffffffc);
+ expect(x == 0xfffffffffffffffc);
}
export fn zig_i8(x: i8) void {
- assertOrPanic(x == -1);
+ expect(x == -1);
}
export fn zig_i16(x: i16) void {
- assertOrPanic(x == -2);
+ expect(x == -2);
}
export fn zig_i32(x: i32) void {
- assertOrPanic(x == -3);
+ expect(x == -3);
}
export fn zig_i64(x: i64) void {
- assertOrPanic(x == -4);
+ expect(x == -4);
}
extern fn c_f32(f32) void;
@@ -66,10 +66,10 @@ test "C ABI floats" {
}
export fn zig_f32(x: f32) void {
- assertOrPanic(x == 12.34);
+ expect(x == 12.34);
}
export fn zig_f64(x: f64) void {
- assertOrPanic(x == 56.78);
+ expect(x == 56.78);
}
extern fn c_ptr(*c_void) void;
@@ -79,7 +79,7 @@ test "C ABI pointer" {
}
export fn zig_ptr(x: *c_void) void {
- assertOrPanic(@ptrToInt(x) == 0xdeadbeef);
+ expect(@ptrToInt(x) == 0xdeadbeef);
}
extern fn c_bool(bool) void;
@@ -89,7 +89,7 @@ test "C ABI bool" {
}
export fn zig_bool(x: bool) void {
- assertOrPanic(x);
+ expect(x);
}
extern fn c_array([10]u8) void;
@@ -100,7 +100,7 @@ test "C ABI array" {
}
export fn zig_array(x: [10]u8) void {
- assertOrPanic(std.mem.eql(u8, x, "1234567890"));
+ expect(std.mem.eql(u8, x, "1234567890"));
}
const BigStruct = extern struct {
@@ -124,11 +124,11 @@ test "C ABI big struct" {
}
export fn zig_big_struct(x: BigStruct) void {
- assertOrPanic(x.a == 1);
- assertOrPanic(x.b == 2);
- assertOrPanic(x.c == 3);
- assertOrPanic(x.d == 4);
- assertOrPanic(x.e == 5);
+ expect(x.a == 1);
+ expect(x.b == 2);
+ expect(x.c == 3);
+ expect(x.d == 4);
+ expect(x.e == 5);
}
const BigUnion = extern union {
@@ -150,11 +150,11 @@ test "C ABI big union" {
}
export fn zig_big_union(x: BigUnion) void {
- assertOrPanic(x.a.a == 1);
- assertOrPanic(x.a.b == 2);
- assertOrPanic(x.a.c == 3);
- assertOrPanic(x.a.d == 4);
- assertOrPanic(x.a.e == 5);
+ expect(x.a.a == 1);
+ expect(x.a.b == 2);
+ expect(x.a.c == 3);
+ expect(x.a.d == 4);
+ expect(x.a.e == 5);
}
const SmallStructInts = extern struct {
@@ -176,10 +176,10 @@ test "C ABI small struct of ints" {
}
export fn zig_small_struct_ints(x: SmallStructInts) void {
- assertOrPanic(x.a == 1);
- assertOrPanic(x.b == 2);
- assertOrPanic(x.c == 3);
- assertOrPanic(x.d == 4);
+ expect(x.a == 1);
+ expect(x.b == 2);
+ expect(x.c == 3);
+ expect(x.d == 4);
}
const SplitStructInt = extern struct {
@@ -199,9 +199,9 @@ test "C ABI split struct of ints" {
}
export fn zig_split_struct_ints(x: SplitStructInt) void {
- assertOrPanic(x.a == 1234);
- assertOrPanic(x.b == 100);
- assertOrPanic(x.c == 1337);
+ expect(x.a == 1234);
+ expect(x.b == 100);
+ expect(x.c == 1337);
}
extern fn c_big_struct_both(BigStruct) BigStruct;
@@ -215,19 +215,19 @@ test "C ABI sret and byval together" {
.e = 5,
};
var y = c_big_struct_both(s);
- assertOrPanic(y.a == 10);
- assertOrPanic(y.b == 11);
- assertOrPanic(y.c == 12);
- assertOrPanic(y.d == 13);
- assertOrPanic(y.e == 14);
+ expect(y.a == 10);
+ expect(y.b == 11);
+ expect(y.c == 12);
+ expect(y.d == 13);
+ expect(y.e == 14);
}
export fn zig_big_struct_both(x: BigStruct) BigStruct {
- assertOrPanic(x.a == 30);
- assertOrPanic(x.b == 31);
- assertOrPanic(x.c == 32);
- assertOrPanic(x.d == 33);
- assertOrPanic(x.e == 34);
+ expect(x.a == 30);
+ expect(x.b == 31);
+ expect(x.c == 32);
+ expect(x.d == 33);
+ expect(x.e == 34);
var s = BigStruct{
.a = 20,
.b = 21,
diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig
index 52863d5fa4..f5bcd59ecf 100644
--- a/test/standalone/brace_expansion/main.zig
+++ b/test/standalone/brace_expansion/main.zig
@@ -3,6 +3,7 @@ const io = std.io;
const mem = std.mem;
const debug = std.debug;
const assert = debug.assert;
+const testing = std.testing;
const Buffer = std.Buffer;
const ArrayList = std.ArrayList;
const maxInt = std.math.maxInt;
@@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {
var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;
defer output_buf.deinit();
- if (expandString(test_input, &output_buf)) {
- unreachable;
- } else |err| {
- assert(expected_err == err);
- }
+ testing.expectError(expected_err, expandString(test_input, &output_buf));
}
test "valid inputs" {
@@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {
expandString(test_input, &result) catch unreachable;
- assert(mem.eql(u8, result.toSlice(), expected_result));
+ testing.expectEqualSlices(u8, expected_result, result.toSlice());
}
diff --git a/test/standalone/issue_794/main.zig b/test/standalone/issue_794/main.zig
index 356a106418..191bdc9b4f 100644
--- a/test/standalone/issue_794/main.zig
+++ b/test/standalone/issue_794/main.zig
@@ -1,7 +1,7 @@
const c = @cImport(@cInclude("foo.h"));
const std = @import("std");
-const assert = std.debug.assert;
+const testing = std.testing;
test "c import" {
- comptime assert(c.NUMBER == 1234);
+ comptime testing.expect(c.NUMBER == 1234);
}
diff --git a/test/tests.zig b/test/tests.zig
index 1ca06b4b34..800ddc1ccd 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -48,13 +48,14 @@ const test_targets = []TestTarget{
const max_stdout_size = 1 * 1024 * 1024; // 1 MB
pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(CompareOutputContext{
+ const cases = b.allocator.create(CompareOutputContext) catch unreachable;
+ cases.* = CompareOutputContext{
.b = b,
.step = b.step("test-compare-output", "Run the compare output tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
- }) catch unreachable;
+ };
compare_output.addCases(cases);
@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
}
pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(CompareOutputContext{
+ const cases = b.allocator.create(CompareOutputContext) catch unreachable;
+ cases.* = CompareOutputContext{
.b = b,
.step = b.step("test-runtime-safety", "Run the runtime safety tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
- }) catch unreachable;
+ };
runtime_safety.addCases(cases);
@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
}
pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(CompileErrorContext{
+ const cases = b.allocator.create(CompileErrorContext) catch unreachable;
+ cases.* = CompileErrorContext{
.b = b,
.step = b.step("test-compile-errors", "Run the compile error tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
- }) catch unreachable;
+ };
compile_errors.addCases(cases);
@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:
}
pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(BuildExamplesContext{
+ const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
+ cases.* = BuildExamplesContext{
.b = b,
.step = b.step("test-build-examples", "Build the examples"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
- }) catch unreachable;
+ };
build_examples.addCases(cases);
@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
}
pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
- const cases = b.allocator.create(CompareOutputContext{
+ const cases = b.allocator.create(CompareOutputContext) catch unreachable;
+ cases.* = CompareOutputContext{
.b = b,
.step = b.step("test-asm-link", "Run the assemble and link tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
- }) catch unreachable;
+ };
assemble_and_link.addCases(cases);
@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode
}
pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
- const cases = b.allocator.create(TranslateCContext{
+ const cases = b.allocator.create(TranslateCContext) catch unreachable;
+ cases.* = TranslateCContext{
.b = b,
.step = b.step("test-translate-c", "Run the C transation tests"),
.test_index = 0,
.test_filter = test_filter,
- }) catch unreachable;
+ };
translate_c.addCases(cases);
@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
}
pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
- const cases = b.allocator.create(GenHContext{
+ const cases = b.allocator.create(GenHContext) catch unreachable;
+ cases.* = GenHContext{
.b = b,
.step = b.step("test-gen-h", "Run the C header file generation tests"),
.test_index = 0,
.test_filter = test_filter,
- }) catch unreachable;
+ };
gen_h.addCases(cases);
@@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
for (test_targets) |test_target| {
const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
for (modes) |mode| {
- for ([]bool{
- false,
- true,
- }) |link_libc| {
- if (link_libc and !is_native) {
- // don't assume we have a cross-compiling libc set up
- continue;
+ for ([]bool{ false, true }) |link_libc| {
+ for ([]bool{ false, true }) |single_threaded| {
+ if (link_libc and !is_native) {
+ // don't assume we have a cross-compiling libc set up
+ continue;
+ }
+ const these_tests = b.addTest(root_src);
+ these_tests.setNamePrefix(b.fmt(
+ "{}-{}-{}-{}-{}-{} ",
+ name,
+ @tagName(test_target.os),
+ @tagName(test_target.arch),
+ @tagName(mode),
+ if (link_libc) "c" else "bare",
+ if (single_threaded) "single" else "multi",
+ ));
+ these_tests.setFilter(test_filter);
+ these_tests.setBuildMode(mode);
+ if (!is_native) {
+ these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
+ }
+ if (link_libc) {
+ these_tests.linkSystemLibrary("c");
+ }
+ if (mem.eql(u8, name, "std")) {
+ these_tests.overrideStdDir("std");
+ }
+ step.dependOn(&these_tests.step);
}
- const these_tests = b.addTest(root_src);
- these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
- these_tests.setFilter(test_filter);
- these_tests.setBuildMode(mode);
- if (!is_native) {
- these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
- }
- if (link_libc) {
- these_tests.linkSystemLibrary("c");
- }
- step.dependOn(&these_tests.step);
}
}
}
@@ -237,7 +254,8 @@ pub const CompareOutputContext = struct {
pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {
const allocator = context.b.allocator;
- const ptr = allocator.create(RunCompareOutputStep{
+ const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
+ ptr.* = RunCompareOutputStep{
.context = context,
.exe_path = exe_path,
.name = name,
@@ -245,7 +263,7 @@ pub const CompareOutputContext = struct {
.test_index = context.test_index,
.step = build.Step.init("RunCompareOutput", allocator, make),
.cli_args = cli_args,
- }) catch unreachable;
+ };
context.test_index += 1;
return ptr;
}
@@ -324,13 +342,14 @@ pub const CompareOutputContext = struct {
pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {
const allocator = context.b.allocator;
- const ptr = allocator.create(RuntimeSafetyRunStep{
+ const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
+ ptr.* = RuntimeSafetyRunStep{
.context = context,
.exe_path = exe_path,
.name = name,
.test_index = context.test_index,
.step = build.Step.init("RuntimeSafetyRun", allocator, make),
- }) catch unreachable;
+ };
context.test_index += 1;
return ptr;
@@ -420,7 +439,10 @@ pub const CompareOutputContext = struct {
pub fn addCase(self: *CompareOutputContext, case: TestCase) void {
const b = self.b;
- const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable;
+ const root_src = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, case.sources.items[0].filename },
+ ) catch unreachable;
switch (case.special) {
Special.Asm => {
@@ -433,7 +455,10 @@ pub const CompareOutputContext = struct {
exe.addAssemblyFile(root_src);
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
@@ -457,7 +482,10 @@ pub const CompareOutputContext = struct {
}
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
@@ -480,7 +508,10 @@ pub const CompareOutputContext = struct {
}
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
exe.step.dependOn(&write_src.step);
}
@@ -507,6 +538,7 @@ pub const CompileErrorContext = struct {
expected_errors: ArrayList([]const u8),
link_libc: bool,
is_exe: bool,
+ is_test: bool,
const SourceFile = struct {
filename: []const u8,
@@ -535,14 +567,15 @@ pub const CompileErrorContext = struct {
pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
const allocator = context.b.allocator;
- const ptr = allocator.create(CompileCmpOutputStep{
+ const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
+ ptr.* = CompileCmpOutputStep{
.step = build.Step.init("CompileCmpOutput", allocator, make),
.context = context,
.name = name,
.test_index = context.test_index,
.case = case,
.build_mode = build_mode,
- }) catch unreachable;
+ };
context.test_index += 1;
return ptr;
@@ -552,13 +585,25 @@ pub const CompileErrorContext = struct {
const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
const b = self.context.b;
- const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable;
- const obj_path = os.path.join(b.allocator, b.cache_root, "test.o") catch unreachable;
+ const root_src = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
+ ) catch unreachable;
+ const obj_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, "test.o" },
+ ) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;
- zig_args.append(if (self.case.is_exe) "build-exe" else "build-obj") catch unreachable;
+ if (self.case.is_exe) {
+ try zig_args.append("build-exe");
+ } else if (self.case.is_test) {
+ try zig_args.append("test");
+ } else {
+ try zig_args.append("build-obj");
+ }
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
zig_args.append("--name") catch unreachable;
@@ -654,13 +699,15 @@ pub const CompileErrorContext = struct {
}
pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
- const tc = self.b.allocator.create(TestCase{
+ const tc = self.b.allocator.create(TestCase) catch unreachable;
+ tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_errors = ArrayList([]const u8).init(self.b.allocator),
.link_libc = false,
.is_exe = false,
- }) catch unreachable;
+ .is_test = false,
+ };
tc.addSourceFile(".tmp_source.zig", source);
comptime var arg_i = 0;
@@ -687,6 +734,12 @@ pub const CompileErrorContext = struct {
self.addCase(tc);
}
+ pub fn addTest(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
+ const tc = self.create(name, source, expected_lines);
+ tc.is_test = true;
+ self.addCase(tc);
+ }
+
pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
const b = self.b;
@@ -700,7 +753,10 @@ pub const CompileErrorContext = struct {
self.step.dependOn(&compile_and_cmp_errors.step);
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
compile_and_cmp_errors.step.dependOn(&write_src.step);
}
@@ -814,13 +870,14 @@ pub const TranslateCContext = struct {
pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
const allocator = context.b.allocator;
- const ptr = allocator.create(TranslateCCmpOutputStep{
+ const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
+ ptr.* = TranslateCCmpOutputStep{
.step = build.Step.init("ParseCCmpOutput", allocator, make),
.context = context,
.name = name,
.test_index = context.test_index,
.case = case,
- }) catch unreachable;
+ };
context.test_index += 1;
return ptr;
@@ -830,7 +887,10 @@ pub const TranslateCContext = struct {
const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
const b = self.context.b;
- const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable;
+ const root_src = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
+ ) catch unreachable;
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;
@@ -921,12 +981,13 @@ pub const TranslateCContext = struct {
}
pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
- const tc = self.b.allocator.create(TestCase{
+ const tc = self.b.allocator.create(TestCase) catch unreachable;
+ tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
.allow_warnings = allow_warnings,
- }) catch unreachable;
+ };
tc.addSourceFile(filename, source);
comptime var arg_i = 0;
@@ -963,7 +1024,10 @@ pub const TranslateCContext = struct {
self.step.dependOn(&translate_c_and_cmp.step);
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
translate_c_and_cmp.step.dependOn(&write_src.step);
}
@@ -1008,14 +1072,15 @@ pub const GenHContext = struct {
pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {
const allocator = context.b.allocator;
- const ptr = allocator.create(GenHCmpOutputStep{
+ const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
+ ptr.* = GenHCmpOutputStep{
.step = build.Step.init("ParseCCmpOutput", allocator, make),
.context = context,
.h_path = h_path,
.name = name,
.test_index = context.test_index,
.case = case,
- }) catch unreachable;
+ };
context.test_index += 1;
return ptr;
@@ -1055,11 +1120,12 @@ pub const GenHContext = struct {
}
pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
- const tc = self.b.allocator.create(TestCase{
+ const tc = self.b.allocator.create(TestCase) catch unreachable;
+ tc.* = TestCase{
.name = name,
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
- }) catch unreachable;
+ };
tc.addSourceFile(filename, source);
comptime var arg_i = 0;
@@ -1076,7 +1142,10 @@ pub const GenHContext = struct {
pub fn addCase(self: *GenHContext, case: *const TestCase) void {
const b = self.b;
- const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable;
+ const root_src = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, case.sources.items[0].filename },
+ ) catch unreachable;
const mode = builtin.Mode.Debug;
const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
@@ -1088,7 +1157,10 @@ pub const GenHContext = struct {
obj.setBuildMode(mode);
for (case.sources.toSliceConst()) |src_file| {
- const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;
+ const expanded_src_path = os.path.join(
+ b.allocator,
+ [][]const u8{ b.cache_root, src_file.filename },
+ ) catch unreachable;
const write_src = b.addWriteFile(expanded_src_path, src_file.source);
obj.step.dependOn(&write_src.step);
}
diff --git a/test/translate_c.zig b/test/translate_c.zig
index 13f2a964d0..6a26b99104 100644
--- a/test/translate_c.zig
+++ b/test/translate_c.zig
@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
,
\\pub const struct_Foo = extern struct {
- \\ a: ?[*]Foo,
+ \\ a: [*c]Foo,
\\};
\\pub const Foo = struct_Foo;
\\pub const struct_Bar = extern struct {
- \\ a: ?[*]Foo,
+ \\ a: [*c]Foo,
\\};
);
@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\const struct_Foo = extern struct {
\\ x: c_int,
- \\ y: ?[*]u8,
+ \\ y: [*c]u8,
\\};
,
\\pub const Foo = struct_Foo;
@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub const BarB = enum_Bar.B;
,
- \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void;
+ \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
,
\\pub const Foo = struct_Foo;
,
@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("constant size array",
\\void func(int array[20]);
,
- \\pub extern fn func(array: ?[*]c_int) void;
+ \\pub extern fn func(array: [*c]c_int) void;
);
cases.add("self referential struct with function pointer",
@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
,
\\pub const struct_Foo = extern struct {
- \\ derp: ?extern fn(?[*]struct_Foo) void,
+ \\ derp: ?extern fn([*c]struct_Foo) void,
\\};
,
\\pub const Foo = struct_Foo;
@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\};
,
\\pub const struct_Bar = extern struct {
- \\ next: ?[*]struct_Foo,
+ \\ next: [*c]struct_Foo,
\\};
,
\\pub const struct_Foo = extern struct {
- \\ next: ?[*]struct_Bar,
+ \\ next: [*c]struct_Bar,
\\};
);
@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ if ((a != 0) and (b != 0)) return 0;
- \\ if ((b != 0) and (c != null)) return 1;
- \\ if ((a != 0) and (c != null)) return 2;
+ \\ if ((b != 0) and (c != 0)) return 1;
+ \\ if ((a != 0) and (c != 0)) return 2;
\\ if ((a != 0) or (b != 0)) return 3;
- \\ if ((b != 0) or (c != null)) return 4;
- \\ if ((a != 0) or (c != null)) return 5;
+ \\ if ((b != 0) or (c != 0)) return 4;
+ \\ if ((a != 0) or (c != 0)) return 5;
\\ return 6;
\\}
);
@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub const struct_Foo = extern struct {
\\ field: c_int,
\\};
- \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {
+ \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
\\ return foo.?.field;
\\}
);
@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return x;
\\}
,
- \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {
+ \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
\\ return @ptrCast(?*c_void, x);
\\}
);
@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return 0;
\\}
,
- \\pub export fn foo() ?[*]c_int {
- \\ return null;
+ \\pub export fn foo() [*c]c_int {
+ \\ return 0;
\\}
);
@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ *x = 1;
\\}
,
- \\pub export fn foo(x: ?[*]c_int) void {
+ \\pub export fn foo(x: [*c]c_int) void {
\\ x.?.* = 1;
\\}
);
@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
,
\\pub fn foo() c_int {
\\ var x: c_int = 1234;
- \\ var ptr: ?[*]c_int = &x;
+ \\ var ptr: [*c]c_int = &x;
\\ return ptr.?.*;
\\}
);
@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return "bar";
\\}
,
- \\pub fn foo() ?[*]const u8 {
+ \\pub fn foo() [*c]const u8 {
\\ return c"bar";
\\}
);
@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return (float *)a;
\\}
,
- \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {
- \\ return @ptrCast(?[*]f32, a);
+ \\fn ptrcast(a: [*c]c_int) [*c]f32 {
+ \\ return @ptrCast([*c]f32, a);
\\}
);
@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ return !(a == 0);
\\ return !(a != 0);
\\ return !(b != 0);
- \\ return !(c != null);
+ \\ return !(c != 0);
\\}
);
@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("const ptr initializer",
\\static const char *v0 = "0.0.0";
,
- \\pub var v0: ?[*]const u8 = c"0.0.0";
+ \\pub var v0: [*c]const u8 = c"0.0.0";
);
cases.add("static incomplete array inside function",
@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\pub fn foo() void {
- \\ const v2: [*]const u8 = c"2.2.2";
+ \\ const v2: [*c]const u8 = c"2.2.2";
\\}
);
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
,
- \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE);
+ \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*c]NRF_GPIO_Type)(NRF_GPIO_BASE);
);
- cases.add("if on none bool",
+ cases.add("if on non-bool",
\\enum SomeEnum { A, B, C };
\\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
\\ if (a) return 0;
@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
\\ if (a != 0) return 0;
\\ if (b != 0) return 1;
- \\ if (c != null) return 2;
+ \\ if (c != 0) return 2;
\\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
\\ return 4;
\\}
);
- cases.add("while on none bool",
+ cases.add("while on non-bool",
\\int while_none_bool(int a, float b, void *c) {
\\ while (a) return 0;
\\ while (b) return 1;
@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
- \\ while (c != null) return 2;
+ \\ while (c != 0) return 2;
\\ return 3;
\\}
);
- cases.add("for on none bool",
+ cases.add("for on non-bool",
\\int for_none_bool(int a, float b, void *c) {
\\ for (;a;) return 0;
\\ for (;b;) return 1;
@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
\\ while (a != 0) return 0;
\\ while (b != 0) return 1;
- \\ while (c != null) return 2;
+ \\ while (c != 0) return 2;
\\ return 3;
\\}
);
@@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ }
\\}
);
+
+ // cases.add("empty array with initializer",
+ // "int a[4] = {};"
+ // ,
+ // "pub var a: [4]c_int = [1]c_int{0} ** 4;"
+ // );
+
+ // cases.add("array with initialization",
+ // "int a[4] = {1, 2, 3, 4};"
+ // ,
+ // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};"
+ // );
+
+ // cases.add("array with incomplete initialization",
+ // "int a[4] = {3, 4};"
+ // ,
+ // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);"
+ // );
+
+ // cases.add("2D array with initialization",
+ // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };"
+ // ,
+ // "pub var a: [3][3]c_int = [3][3]c_int{[3]c_int{1, 2, 3}, [3]c_int{4, 5, 6}, [3]c_int{7, 8, 9}};"
+ // );
+
+ // cases.add("2D array with incomplete initialization",
+ // "int a[3][3] = { {1, 2}, {4, 5, 6} };"
+ // ,
+ // "pub var a: [3][3]c_int = [2][3]c_int{[2]c_int{1, 2} ++ [1]c_int{0}, [3]c_int{4, 5, 6}} ++ [1][3]c_int{[1]c_int{0} ** 3};"
+ // );
}