Merge remote-tracking branch 'origin/master' into llvm8

This commit is contained in:
Andrew Kelley 2018-11-05 10:56:42 -05:00
commit f8d6f5daff
281 changed files with 98146 additions and 94893 deletions

View File

@ -1,22 +0,0 @@
sudo: required
services:
- docker
os:
- linux
- osx
dist: trusty
osx_image: xcode8.3
language: cpp
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ci/travis_linux_before_install; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ci/travis_osx_before_install; fi
install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ci/travis_linux_install; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ci/travis_osx_install; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ci/travis_linux_script; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ci/travis_osx_script; fi
env:
global:
- secure: QmJ+eLOxj3Irl5SHxt6lQvrj7++1AIz8bYri6RScAQGHQPIztkmbpBjAkpFgYaWPkZ04ROtamFXdS7oHtJHSECesgPoqM/CHIychQkgpDq30+TsFyYbBpDGHY+N6r2WnQTvg+9EuAp6P365us6qFS0D5zQ3P40c56uMbazFu3J4W1HZP+pLWlLjEXaN88ePhHWqNZyvwGMkLpYl3ghcrE9H4vGZQ7jenRW4UmskLEkuhUPJbQiow3Td8arJiRmLVISzWqneqNraLUpGyUVr4F3Rbjzacfoo3r9ZZynhY0mFsEye82x6TMGgH2xsNGkd91zpQuckWUT+pQv/G6FXpnEnjIJSO2Z5WAxXrx6xB1k2HZ17/4NWLF3fJVhdQJm3mS6odeGzUjgGrl1A42evxU+7VbcofEJq1aMiLgU1jUT2pt+pefCwmKJYLpEsSzuyrVxgvskQz0QpC053TAYSNf2Jj6Qhg9YDWyOeemYmDgffTqErF7AYhc6NKH0s0XKkIiNFSxorkEsfG/Ck1o+15slHNmWZXlmXToxDqFkLDoPvfGKg7koU5YTGvci/F9ZKb1juhGLxZbwap/18zN40BqA+Ip2yDBJAKxsIiwSjSIguy6g/Z1I50s0xNGOr36urfRRQX5H+rqr/xCZ63B6WSe6qBcZboWAQMDn8HLS9Xiwc=
- secure: dnb7r5guUeMOX9e7XlPUSZzmga8VW3G9Q1aa7LxEKiTjSnWhu5KpPDe8o1X3Rj6nc5iXDqmBH/C/7eNXPDyXJJWPvpE2YRpGymyUkRaakul0QBKJEaMvwy2SuAfS69CWC+TSzfGRvtSYkdpBhhLvs0h5S819S5jYbCNSCmOKfFucaP5NsHNIZ/I19oIeTPTa0/UnVm7DLFZXZjvbS+czkdyH1DhbT85sLj+XqNTzLePImE68efrjaHnlSy/CzBVJzj55UgD5i9fxNCQWzGWim/SD5xZ0zKtLycSOf6wQN2lCo0lkjw9rDlYz69mM5L9ikfYL9oHDPZnh84oXKglQ5miOHCgqs/qs4439I05lIu8i/EfbFA55YG4NyO3rL9YVOOt5gwiwvJYhDcnkVVzSl0o5bsoZgQfYvPWaIQKNkl3C53zfDQjgqS54CeDzlZpFrQTDQ1RrH8oeVC1gfYAeMabMDadox5rfZmLIN5JTf/F8iD/QdxGcoUvkEENcQgfP9PnubExtexgHGsEmqbm6ORSZ1MkEh2m3fo0f8KE6TbN1UigmcQ8nTkWBHsSmfHnB8HwJQp8mwQmDamXA+Hl3e3w4LOdYkJVlNW1/TTyJJOOvjMQCjF8SJmPHuh+QpqKbSaT9XM/vBhxbIZEufH8kawJKCBBcCNspGMNjhXfNjM0=

View File

@ -15,7 +15,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(ZIG_VERSION_MAJOR 0)
set(ZIG_VERSION_MINOR 2)
set(ZIG_VERSION_MINOR 3)
set(ZIG_VERSION_PATCH 0)
set(ZIG_VERSION "${ZIG_VERSION_MAJOR}.${ZIG_VERSION_MINOR}.${ZIG_VERSION_PATCH}")
@ -50,20 +50,12 @@ option(ZIG_FORCE_EXTERNAL_LLD "If your system has the LLD patches use it instead
find_package(llvm)
find_package(clang)
if(NOT MSVC)
find_library(LIBXML2 NAMES xml2 libxml2)
if(${LIBXML2} STREQUAL "LIBXML2-NOTFOUND")
message(FATAL_ERROR "Could not find libxml2")
else()
message("${LIBXML2} found")
endif()
if(APPLE AND ZIG_STATIC)
list(REMOVE_ITEM LLVM_LIBRARIES "-lz")
list(REMOVE_ITEM LLVM_LIBRARIES "-lcurses")
find_library(ZLIB NAMES z zlib libz)
if(${ZLIB} STREQUAL "ZLIB-NOTFOUND")
message(FATAL_ERROR "Could not find zlib")
else()
message("${ZLIB} found")
endif()
find_library(LIBNCURSES NAMES libncurses.a)
list(APPEND LLVM_LIBRARIES "${LIBNCURSES}" "${ZLIB}")
endif()
set(ZIG_CPP_LIB_DIR "${CMAKE_BINARY_DIR}/zig_cpp")
@ -200,6 +192,9 @@ else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
else()
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
if(MINGW)
set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format")
endif()
endif()
set_target_properties(embedded_lld_lib PROPERTIES
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
@ -475,12 +470,13 @@ set(ZIG_STD_FILES
"event/fs.zig"
"event/future.zig"
"event/group.zig"
"event/io.zig"
"event/lock.zig"
"event/locked.zig"
"event/loop.zig"
"event/net.zig"
"event/rwlock.zig"
"event/rwlocked.zig"
"event/tcp.zig"
"fmt/errol/enum3.zig"
"fmt/errol/index.zig"
"fmt/errol/lookup.zig"
@ -558,6 +554,7 @@ set(ZIG_STD_FILES
"math/modf.zig"
"math/nan.zig"
"math/pow.zig"
"math/powi.zig"
"math/round.zig"
"math/scalbn.zig"
"math/signbit.zig"
@ -567,6 +564,8 @@ set(ZIG_STD_FILES
"math/tan.zig"
"math/tanh.zig"
"math/trunc.zig"
"meta/index.zig"
"meta/trait.zig"
"mem.zig"
"mutex.zig"
"net.zig"
@ -582,6 +581,7 @@ set(ZIG_STD_FILES
"os/linux/index.zig"
"os/linux/vdso.zig"
"os/linux/x86_64.zig"
"os/linux/arm64.zig"
"os/path.zig"
"os/time.zig"
"os/windows/advapi32.zig"
@ -627,6 +627,7 @@ set(ZIG_STD_FILES
"special/compiler_rt/floatuntitf.zig"
"special/compiler_rt/index.zig"
"special/compiler_rt/muloti4.zig"
"special/compiler_rt/multi3.zig"
"special/compiler_rt/truncXfYf2.zig"
"special/compiler_rt/udivmod.zig"
"special/compiler_rt/udivmoddi4.zig"
@ -639,6 +640,7 @@ set(ZIG_STD_FILES
"special/init-lib/src/main.zig"
"special/panic.zig"
"special/test_runner.zig"
"spinlock.zig"
"unicode.zig"
"zig/ast.zig"
"zig/index.zig"
@ -652,7 +654,9 @@ set(ZIG_C_HEADER_FILES
"__clang_cuda_builtin_vars.h"
"__clang_cuda_cmath.h"
"__clang_cuda_complex_builtins.h"
"__clang_cuda_device_functions.h"
"__clang_cuda_intrinsics.h"
"__clang_cuda_libdevice_declares.h"
"__clang_cuda_math_forward_declares.h"
"__clang_cuda_runtime_wrapper.h"
"__stddef_max_align_t.h"
@ -663,6 +667,7 @@ set(ZIG_C_HEADER_FILES
"ammintrin.h"
"arm64intr.h"
"arm_acle.h"
"arm_fp16.h"
"arm_neon.h"
"armintr.h"
"avx2intrin.h"
@ -692,6 +697,7 @@ set(ZIG_C_HEADER_FILES
"bmi2intrin.h"
"bmiintrin.h"
"cetintrin.h"
"cldemoteintrin.h"
"clflushoptintrin.h"
"clwbintrin.h"
"clzerointrin.h"
@ -712,6 +718,7 @@ set(ZIG_C_HEADER_FILES
"immintrin.h"
"intrin.h"
"inttypes.h"
"invpcidintrin.h"
"iso646.h"
"limits.h"
"lwpintrin.h"
@ -720,17 +727,21 @@ set(ZIG_C_HEADER_FILES
"mm_malloc.h"
"mmintrin.h"
"module.modulemap"
"movdirintrin.h"
"msa.h"
"mwaitxintrin.h"
"nmmintrin.h"
"opencl-c.h"
"pconfigintrin.h"
"pkuintrin.h"
"pmmintrin.h"
"popcntintrin.h"
"prfchwintrin.h"
"ptwriteintrin.h"
"rdseedintrin.h"
"rtmintrin.h"
"s390intrin.h"
"sgxintrin.h"
"shaintrin.h"
"smmintrin.h"
"stdalign.h"
@ -749,6 +760,8 @@ set(ZIG_C_HEADER_FILES
"varargs.h"
"vecintrin.h"
"vpclmulqdqintrin.h"
"waitpkgintrin.h"
"wbnoinvdintrin.h"
"wmmintrin.h"
"x86intrin.h"
"xmmintrin.h"
@ -812,7 +825,11 @@ if(MINGW)
elseif(MSVC)
set(EXE_LDFLAGS "/STACK:16777216")
elseif(ZIG_STATIC)
if(APPLE)
set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")
else()
set(EXE_LDFLAGS "-static")
endif()
else()
set(EXE_LDFLAGS " ")
endif()

View File

@ -79,6 +79,9 @@ that counts as "freestanding" for the purposes of this table.
[![Build Status](https://travis-ci.org/ziglang/zig.svg?branch=master)](https://travis-ci.org/ziglang/zig)
[![Build status](https://ci.appveyor.com/api/projects/status/4t80mk2dmucrc38i/branch/master?svg=true)](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master)
Note that you can
[download a binary of master branch](https://ziglang.org/download/#release-master).
### Stage 1: Build Zig from C++ Source Code
#### Dependencies
@ -88,7 +91,6 @@ that counts as "freestanding" for the purposes of this table.
* cmake >= 2.8.5
* gcc >= 5.0.0 or clang >= 3.6.0
* LLVM, Clang, LLD development libraries == 8.x, compiled with the same gcc or clang version above
- These depend on zlib and libxml2.
##### Windows

116
build.zig
View File

@ -17,7 +17,7 @@ pub fn build(b: *Builder) !void {
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;
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8.{
docgen_exe.getOutputPath(),
rel_zig_exe,
"doc" ++ os.path.sep_str ++ "langref.html.in",
@ -31,12 +31,12 @@ pub fn build(b: *Builder) !void {
const test_step = b.step("test", "Run all the tests");
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
const build_info = try b.exec([][]const u8{
const build_info = try b.exec([][]const u8.{
b.zig_exe,
"BUILD_INFO",
});
var index: usize = 0;
var ctx = Context{
var ctx = Context.{
.cmake_binary_dir = nextValue(&index, build_info),
.cxx_compiler = nextValue(&index, build_info),
.llvm_config_exe = nextValue(&index, build_info),
@ -121,13 +121,24 @@ pub fn build(b: *Builder) !void {
test_step.dependOn(docs_step);
}
fn dependOnLib(lib_exe_obj: var, dep: *const LibraryDep) void {
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;
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 have_static = fileExists(static_lib_name) catch unreachable;
if (have_static) {
lib_exe_obj.addObjectFile(static_lib_name);
} else {
lib_exe_obj.linkSystemLibrary(lib);
}
}
for (dep.libs.toSliceConst()) |lib| {
lib_exe_obj.addObjectFile(lib);
}
@ -136,12 +147,23 @@ fn dependOnLib(lib_exe_obj: var, dep: *const LibraryDep) void {
}
}
fn fileExists(filename: []const u8) !bool {
os.File.access(filename) catch |err| switch (err) {
error.PermissionDenied,
error.FileNotFound,
=> return false,
else => return err,
};
return true;
}
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);
}
const LibraryDep = struct {
const LibraryDep = struct.{
prefix: []const u8,
libdirs: ArrayList([]const u8),
libs: ArrayList([]const u8),
system_libs: ArrayList([]const u8),
@ -149,21 +171,25 @@ const LibraryDep = struct {
};
fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
const libs_output = try b.exec([][]const u8{
const shared_mode = try b.exec([][]const u8.{ llvm_config_exe, "--shared-mode" });
const is_static = mem.startsWith(u8, shared_mode, "static");
const libs_output = if (is_static)
try b.exec([][]const u8.{
llvm_config_exe,
"--libfiles",
"--system-libs",
})
else
try b.exec([][]const u8.{
llvm_config_exe,
"--libs",
"--system-libs",
});
const includes_output = try b.exec([][]const u8{
llvm_config_exe,
"--includedir",
});
const libdir_output = try b.exec([][]const u8{
llvm_config_exe,
"--libdir",
});
const includes_output = try b.exec([][]const u8.{ llvm_config_exe, "--includedir" });
const libdir_output = try b.exec([][]const u8.{ llvm_config_exe, "--libdir" });
const prefix_output = try b.exec([][]const u8.{ llvm_config_exe, "--prefix" });
var result = LibraryDep{
var result = LibraryDep.{
.prefix = mem.split(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),
@ -244,10 +270,6 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 {
}
fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
// This is for finding /lib/libz.a on alpine linux.
// TODO turn this into -Dextra-lib-path=/lib option
exe.addLibPath("/lib");
exe.setNoRoSegment(ctx.no_rosegment);
exe.addIncludeDir("src");
@ -265,40 +287,64 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_coff");
addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_lib");
}
dependOnLib(exe, ctx.llvm);
dependOnLib(b, exe, ctx.llvm);
if (exe.target.getOs() == builtin.Os.linux) {
const libstdcxx_path_padded = try b.exec([][]const u8{
ctx.cxx_compiler,
"-print-file-name=libstdc++.a",
});
const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?;
if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
warn(
try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
\\Unable to determine path to libstdc++.a
\\On Fedora, install libstdc++-static and try again.
\\
);
return error.RequiredLibraryNotFound;
}
exe.addObjectFile(libstdcxx_path);
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);
exe.linkSystemLibrary("pthread");
// TODO LLD cannot perform this link.
// See https://github.com/ziglang/zig/issues/1535
exe.enableSystemLinkerHack();
} else |err| switch (err) {
error.RequiredLibraryNotFound => {
// System compiler, not gcc.
exe.linkSystemLibrary("c++");
},
else => return err,
}
}
if (ctx.dia_guids_lib.len != 0) {
exe.addObjectFile(ctx.dia_guids_lib);
}
if (exe.target.getOs() != builtin.Os.windows) {
exe.linkSystemLibrary("xml2");
}
exe.linkSystemLibrary("c");
}
const Context = struct {
fn addCxxKnownPath(
b: *Builder,
ctx: Context,
exe: var,
objname: []const u8,
errtxt: ?[]const u8,
) !void {
const path_padded = try b.exec([][]const u8.{
ctx.cxx_compiler,
b.fmt("-print-file-name={}", objname),
});
const path_unpadded = mem.split(path_padded, "\r\n").next().?;
if (mem.eql(u8, path_unpadded, objname)) {
if (errtxt) |msg| {
warn("{}", msg);
} else {
warn("Unable to determine path to {}\n", objname);
}
return error.RequiredLibraryNotFound;
}
exe.addObjectFile(path_unpadded);
}
const Context = struct.{
cmake_binary_dir: []const u8,
cxx_compiler: []const u8,
llvm_config_exe: []const u8,

View File

@ -1,16 +0,0 @@
@echo on
cd %APPVEYOR_BUILD_FOLDER%
build-msvc-release\bin\zig.exe version >version.txt
set /p ZIGVERSION=<version.txt
appveyor UpdateBuild -Version "%ZIGVERSION%"
SET "RELEASEDIR=zig-%ZIGVERSION%"
mkdir "%RELEASEDIR%"
move build-msvc-release\bin\zig.exe "%RELEASEDIR%"
move build-msvc-release\lib "%RELEASEDIR%"
move zig-cache\langref.html "%RELEASEDIR%"
SET "RELEASEZIP=zig-%ZIGVERSION%.zip"
7z a "%RELEASEZIP%" "%RELEASEDIR%"
appveyor PushArtifact "%RELEASEZIP%"

View File

@ -1,10 +0,0 @@
image: Visual Studio 2017
platform:
- x64
build_script:
- '%APPVEYOR_BUILD_FOLDER%\ci\appveyor\build_script.bat'
after_build:
- '%APPVEYOR_BUILD_FOLDER%\ci\appveyor\after_build.bat'
cache:
- 'llvm+clang-7.0.0-win64-msvc-release.tar.xz'
- 'llvm+clang-8.0.0-win64-msvc-release.tar.xz'

View File

@ -1,26 +0,0 @@
@echo on
cd %APPVEYOR_BUILD_FOLDER%
SET "PREVPATH=%PATH%"
SET "PREVMSYSEM=%MSYSTEM%"
SET "PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH%"
SET "MSYSTEM=MINGW64"
SET "APPVEYOR_CACHE_ENTRY_ZIP_ARGS=-m0=Copy"
bash -lc "cd ${APPVEYOR_BUILD_FOLDER} && if [ -s ""llvm+clang-8.0.0-win64-msvc-release.tar.xz"" ]; then echo 'skipping LLVM download'; else wget 'https://s3.amazonaws.com/ziglang.org/deps/llvm%%2bclang-8.0.0-win64-msvc-release.tar.xz'; fi && tar xf llvm+clang-8.0.0-win64-msvc-release.tar.xz" || exit /b
SET "PATH=%PREVPATH%"
SET "MSYSTEM=%PREVMSYSTEM%"
SET "ZIGBUILDDIR=%APPVEYOR_BUILD_FOLDER%\build-msvc-release"
SET "ZIGPREFIXPATH=%APPVEYOR_BUILD_FOLDER%\llvm+clang-8.0.0-win64-msvc-release"
call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64
call "C:\Program Files (x86)\Microsoft Visual Studio 15.0\VC\vcvarsall.bat" x86_amd64
mkdir %ZIGBUILDDIR%
cd %ZIGBUILDDIR%
cmake.exe .. -Thost=x64 -G"Visual Studio 15 2017 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGBUILDDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b
bin\zig.exe build --build-file ..\build.zig test -Dskip-release || exit /b

40
ci/azure/linux_script Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
set -x
set -e
BUILDDIR="$(pwd)"
sudo sh -c 'echo "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main" >> /etc/apt/sources.list'
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update -q
sudo apt-get remove -y llvm-*
sudo rm -rf /usr/local/*
sudo apt-get install -y libxml2-dev libclang-7-dev llvm-7 llvm-7-dev cmake s3cmd gcc-7 g++-7
export CC=gcc-7
export CXX=g++-7
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j2 install
./zig build --build-file ../build.zig test
if [ "${BUILD_REASON}" != "PullRequest" ]; then
ARTIFACTSDIR="$BUILDDIR/artifacts"
mkdir "$ARTIFACTSDIR"
docker run -i --mount type=bind,source="$ARTIFACTSDIR",target=/z ziglang/static-base:llvm7-1 -j2 $BUILD_SOURCEVERSION
TARBALL="$(ls $ARTIFACTSDIR)"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P "$ARTIFACTSDIR/$TARBALL" s3://ziglang.org/builds/
touch empty
s3cmd put -P empty s3://ziglang.org/builds/zig-linux-x86_64-$BUILD_SOURCEBRANCHNAME.tar.xz --add-header="Cache-Control: max-age=0, must-revalidate" --add-header=x-amz-website-redirect-location:/builds/$TARBALL
SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
fi

104
ci/azure/macos_script Executable file
View File

@ -0,0 +1,104 @@
#!/bin/sh
set -x
set -e
brew install s3cmd gcc@8
ZIGDIR="$(pwd)"
CACHE_BASENAME="llvm+clang-7.0.0-macos-x86_64-gcc8-release-static"
PREFIX="$HOME/$CACHE_BASENAME"
TMPDIR="$HOME/tmpz"
JOBS="-j2"
# I tried using the system default compiler (clang), but it couldn't statically link libc++.
# So we use gcc-8 from homebrew.
export CC=gcc-8
export CXX=g++-8
rm -rf $PREFIX
rm -rf $TMPDIR
mkdir $TMPDIR
cd $HOME
HAVE_CACHE="true"
wget "https://ziglang.org/builds/$CACHE_BASENAME.tar.xz" || HAVE_CACHE="false"
if [ "${HAVE_CACHE}" = "true" ]; then
tar xf "$CACHE_BASENAME.tar.xz"
else
if [ "${BUILD_REASON}" == "PullRequest" ]; then
echo "Need cached llvm+clang for pull request builds."
exit 1
fi
cd $TMPDIR
wget https://zlib.net/zlib-1.2.11.tar.xz
tar xf zlib-1.2.11.tar.xz
cd zlib-1.2.11/
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$PREFIX
make $JOBS install
rm $PREFIX/lib/libz*dylib
cd $TMPDIR
wget ftp://ftp.invisible-island.net/ncurses/ncurses.tar.gz
tar xf ncurses.tar.gz
cd ncurses-6.1/
./configure --without-shared --prefix=$PREFIX
make $JOBS install
cd $TMPDIR
wget https://releases.llvm.org/7.0.0/llvm-7.0.0.src.tar.xz
tar xf llvm-7.0.0.src.tar.xz
cd llvm-7.0.0.src/
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_BUILD_TYPE=Release -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="WebAssembly;AVR;RISCV" -DLLVM_ENABLE_LIBXML2=OFF
make $JOBS install
cd $TMPDIR
wget https://releases.llvm.org/7.0.0/cfe-7.0.0.src.tar.xz
tar xf cfe-7.0.0.src.tar.xz
cd cfe-7.0.0.src/
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_BUILD_TYPE=Release
make $JOBS install
cd $HOME
tar cfJ "$CACHE_BASENAME.tar.xz" "$CACHE_BASENAME"
cp "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P "$CACHE_BASENAME.tar.xz" "s3://ziglang.org/builds/$CACHE_BASENAME.tar.xz"
fi
cd $ZIGDIR
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX -DCMAKE_INSTALL_PREFIX=$(pwd)/release -DZIG_STATIC=ON
make $JOBS install
release/bin/zig build --build-file ../build.zig test
if [ "${BUILD_REASON}" != "PullRequest" ]; then
mv ../LICENSE release/
mv ../zig-cache/langref.html release/
mv release/bin/zig release/
rmdir release/bin
VERSION=$(release/zig version)
DIRNAME="zig-macos-x86_64-$VERSION"
TARBALL="$DIRNAME.tar.xz"
mv release "$DIRNAME"
tar cfJ "$TARBALL" "$DIRNAME"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P "$TARBALL" s3://ziglang.org/builds/
touch empty
s3cmd put -P empty s3://ziglang.org/builds/zig-macos-x86_64-$BUILD_SOURCEBRANCHNAME.tar.xz --add-header="Cache-Control: max-age=0, must-revalidate" --add-header="x-amz-website-redirect-location:/builds/$TARBALL"
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
fi

72
ci/azure/pipelines.yml Normal file
View File

@ -0,0 +1,72 @@
jobs:
- job: BuildMacOS
pool:
vmImage: 'macOS 10.13'
timeoutInMinutes: 360
steps:
- task: DownloadSecureFile@1
inputs:
secureFile: s3cfg
- script: ci/azure/macos_script
name: main
displayName: 'Build and test'
- job: BuildLinux
pool:
vmImage: 'ubuntu-16.04'
timeoutInMinutes: 360
steps:
- task: DownloadSecureFile@1
inputs:
secureFile: s3cfg
- script: ci/azure/linux_script
name: main
displayName: 'Build and test'
- job: BuildWindows
pool:
vmImage: 'vs2017-win2016'
timeoutInMinutes: 360
steps:
- script: |
git clone https://github.com/lazka/msys2-ci-base.git %CD:~0,2%\msys64
%CD:~0,2%\msys64\usr\bin\rm -rf %CD:~0,2%\msys64\.git
set PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem
%CD:~0,2%\msys64\usr\bin\pacman --noconfirm -Syyuu
displayName: Install and Update MSYS2
- task: DownloadSecureFile@1
inputs:
secureFile: s3cfg
- script: ci/azure/windows_script.bat
name: main
displayName: 'Build and test'
- job: UpdateDownloadPage
dependsOn:
- BuildMacOS
- BuildLinux
- BuildWindows
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
strategy:
maxParallel: 1
pool:
vmImage: 'ubuntu-16.04'
variables:
macos_tarball: $[ dependencies.BuildMacOS.outputs['main.tarball'] ]
macos_shasum: $[ dependencies.BuildMacOS.outputs['main.shasum'] ]
macos_bytesize: $[ dependencies.BuildMacOS.outputs['main.bytesize'] ]
linux_tarball: $[ dependencies.BuildLinux.outputs['main.tarball'] ]
linux_shasum: $[ dependencies.BuildLinux.outputs['main.shasum'] ]
linux_bytesize: $[ dependencies.BuildLinux.outputs['main.bytesize'] ]
windows_tarball: $[ dependencies.BuildWindows.outputs['main.tarball'] ]
windows_shasum: $[ dependencies.BuildWindows.outputs['main.shasum'] ]
windows_bytesize: $[ dependencies.BuildWindows.outputs['main.bytesize'] ]
steps:
- task: DownloadSecureFile@1
inputs:
secureFile: s3cfg
- script: ci/azure/update_download_page
displayName: 'Update download page'

33
ci/azure/update_download_page Executable file
View File

@ -0,0 +1,33 @@
#!/bin/sh
set -x
set -e
SRCDIR=$(pwd)
rm -rf .git
sudo apt-get install -y s3cmd
cd "$HOME"
wget "https://ziglang.org/builds/$LINUX_TARBALL"
tar xf $LINUX_TARBALL
ZIGDIR=$(basename -s .tar.xz $LINUX_TARBALL)
ZIG="$ZIGDIR/zig"
LANGREF="$ZIGDIR/langref.html"
VERSION=$($ZIG version)
SRCTARBALLDIR="zig-$VERSION"
export SRC_TARBALL="$SRCTARBALLDIR.tar.xz"
mv "$SRCDIR" "$SRCTARBALLDIR"
tar cfJ "$SRC_TARBALL" "$SRCTARBALLDIR"
export SRC_SHASUM=$(sha256sum $SRC_TARBALL | cut '-d ' -f1)
export SRC_BYTESIZE=$(wc -c < $SRC_TARBALL)
git clone https://github.com/ziglang/www.ziglang.org --depth 1
cd www.ziglang.org
export MASTER_DATE=$(date +%Y-%m-%d)
env
"../$ZIG" run update-download-page.zig
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P "../$SRC_TARBALL" s3://ziglang.org/builds/
s3cmd put -P "../$LANGREF" s3://ziglang.org/documentation/master/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
s3cmd put -P www/download/index.html s3://ziglang.org/download/index.html --add-header="Cache-Control: max-age=0, must-revalidate"

9
ci/azure/windows_install Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
set -x
set -e
pacman -S --needed --noconfirm wget zip python3-pip
pip install s3cmd
wget "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz"
tar xf llvm+clang-7.0.0-win64-msvc-release.tar.xz

View File

@ -0,0 +1,27 @@
@echo on
SET "SRCROOT=%cd%"
SET "PREVPATH=%PATH%"
SET "PREVMSYSEM=%MSYSTEM%"
set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem"
SET "MSYSTEM=MINGW64"
bash -lc "cd ${SRCROOT} && ci/azure/windows_install" || exit /b
SET "PATH=%PREVPATH%"
SET "MSYSTEM=%PREVMSYSTEM%"
SET "ZIGBUILDDIR=%SRCROOT%\build"
SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\release"
SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang-7.0.0-win64-msvc-release"
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
mkdir %ZIGBUILDDIR%
cd %ZIGBUILDDIR%
cmake.exe .. -Thost=x64 -G"Visual Studio 15 2017 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b
"%ZIGINSTALLDIR%\bin\zig.exe" build --build-file ..\build.zig test || exit /b
set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem"
SET "MSYSTEM=MINGW64"
bash -lc "cd ${SRCROOT} && ci/azure/windows_upload" || exit /b

30
ci/azure/windows_upload Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
set -x
set -e
if [ "${BUILD_REASON}" != "PullRequest" ]; then
cd "$ZIGBUILDDIR"
mv ../LICENSE release/
mv ../zig-cache/langref.html release/
mv release/bin/zig.exe release/
rmdir release/bin
VERSION=$(release/zig.exe version)
DIRNAME="zig-windows-x86_64-$VERSION"
TARBALL="$DIRNAME.zip"
mv release "$DIRNAME"
zip -r "$TARBALL" "$DIRNAME"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
s3cmd put -P "$TARBALL" s3://ziglang.org/builds/
touch empty
s3cmd put -P empty s3://ziglang.org/builds/zig-windows-x86_64-$BUILD_SOURCEBRANCHNAME.tar.xz --add-header="Cache-Control: max-age=0, must-revalidate" --add-header="x-amz-website-redirect-location:/builds/$TARBALL"
SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
fi

View File

@ -1,8 +0,0 @@
#!/bin/sh
set -x
sudo sh -c 'echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-8 main" >> /etc/apt/sources.list'
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update -q

View File

@ -1,7 +0,0 @@
#!/bin/sh
set -x
sudo apt-get remove -y llvm-*
sudo rm -rf /usr/local/*
sudo apt-get install -y libxml2-dev libclang-8-dev llvm-8 llvm-8-dev cmake s3cmd gcc-7 g++-7

View File

@ -1,23 +0,0 @@
#!/bin/sh
set -x
set -e
export CC=gcc-7
export CXX=g++-7
echo $PATH
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j2 install
./zig build --build-file ../build.zig test -Dskip-release-small
if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then
mkdir $TRAVIS_BUILD_DIR/artifacts
docker run -it --mount type=bind,source="$TRAVIS_BUILD_DIR/artifacts",target=/z ziglang/static-base:llvm8-1 -j2 $TRAVIS_COMMIT
echo "access_key = $AWS_ACCESS_KEY_ID" >> ~/.s3cfg
echo "secret_key = $AWS_SECRET_ACCESS_KEY" >> ~/.s3cfg
s3cmd put -P $TRAVIS_BUILD_DIR/artifacts/* s3://ziglang.org/builds/
touch empty
s3cmd put -P empty s3://ziglang.org/builds/zig-linux-x86_64-$TRAVIS_BRANCH.tar.xz --add-header="Cache-Control: max-age=0, must-revalidate" --add-header=x-amz-website-redirect-location:/builds/$(ls $TRAVIS_BUILD_DIR/artifacts)
fi

View File

@ -1,5 +0,0 @@
#!/bin/sh
set -x
brew update

View File

@ -1,7 +0,0 @@
#!/bin/sh
set -x
brew install llvm@8
brew outdated llvm@8 || brew upgrade llvm@8

View File

@ -1,12 +0,0 @@
#!/bin/sh
set -x
set -e
mkdir build
cd build
cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm@8/ -DCMAKE_BUILD_TYPE=Release
make VERBOSE=1
make install
./zig build --build-file ../build.zig test -Dskip-release-small

View File

@ -8,7 +8,7 @@
# LLVM_LIBDIRS
find_program(LLVM_CONFIG_EXE
NAMES llvm-config llvm-config-8 llvm-config-8.0
NAMES llvm-config-8 llvm-config-8.0 llvm-config
PATHS
"/mingw64/bin"
"/c/msys64/mingw64/bin"

View File

@ -41,12 +41,12 @@ pub fn main() !void {
var out_file = try os.File.openWrite(out_file_name);
defer out_file.close();
var file_in_stream = io.FileInStream.init(in_file);
var file_in_stream = in_file.inStream();
const input_file_bytes = try file_in_stream.stream.readAllAlloc(allocator, max_doc_file_size);
var file_out_stream = io.FileOutStream.init(out_file);
var buffered_out_stream = io.BufferedOutStream(io.FileOutStream.Error).init(&file_out_stream.stream);
var file_out_stream = out_file.outStream();
var buffered_out_stream = io.BufferedOutStream(os.File.WriteError).init(&file_out_stream.stream);
var tokenizer = Tokenizer.init(in_file_name, input_file_bytes);
var toc = try genToc(allocator, &tokenizer);
@ -58,12 +58,12 @@ pub fn main() !void {
try buffered_out_stream.flush();
}
const Token = struct {
const Token = struct.{
id: Id,
start: usize,
end: usize,
const Id = enum {
const Id = enum.{
Invalid,
Content,
BracketOpen,
@ -74,14 +74,14 @@ const Token = struct {
};
};
const Tokenizer = struct {
const Tokenizer = struct.{
buffer: []const u8,
index: usize,
state: State,
source_file_name: []const u8,
code_node_count: usize,
const State = enum {
const State = enum.{
Start,
LBracket,
Hash,
@ -90,7 +90,7 @@ const Tokenizer = struct {
};
fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer {
return Tokenizer{
return Tokenizer.{
.buffer = buffer,
.index = 0,
.state = State.Start,
@ -100,7 +100,7 @@ const Tokenizer = struct {
}
fn next(self: *Tokenizer) Token {
var result = Token{
var result = Token.{
.id = Token.Id.Eof,
.start = self.index,
.end = undefined,
@ -184,15 +184,15 @@ const Tokenizer = struct {
return result;
}
const Location = struct {
const Location = struct.{
line: usize,
column: usize,
line_start: usize,
line_end: usize,
};
fn getTokenLocation(self: *Tokenizer, token: *const Token) Location {
var loc = Location{
fn getTokenLocation(self: *Tokenizer, token: Token) Location {
var loc = Location.{
.line = 0,
.column = 0,
.line_start = 0,
@ -216,7 +216,7 @@ const Tokenizer = struct {
}
};
fn parseError(tokenizer: *Tokenizer, token: *const Token, comptime fmt: []const u8, args: ...) error {
fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: ...) error {
const loc = tokenizer.getTokenLocation(token);
warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args);
if (loc.line_start <= loc.line_end) {
@ -239,7 +239,7 @@ fn parseError(tokenizer: *Tokenizer, token: *const Token, comptime fmt: []const
return error.ParseError;
}
fn assertToken(tokenizer: *Tokenizer, token: *const Token, id: Token.Id) !void {
fn assertToken(tokenizer: *Tokenizer, token: Token, id: Token.Id) !void {
if (token.id != id) {
return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
}
@ -251,23 +251,23 @@ fn eatToken(tokenizer: *Tokenizer, id: Token.Id) !Token {
return token;
}
const HeaderOpen = struct {
const HeaderOpen = struct.{
name: []const u8,
url: []const u8,
n: usize,
};
const SeeAlsoItem = struct {
const SeeAlsoItem = struct.{
name: []const u8,
token: Token,
};
const ExpectedOutcome = enum {
const ExpectedOutcome = enum.{
Succeed,
Fail,
};
const Code = struct {
const Code = struct.{
id: Id,
name: []const u8,
source_token: Token,
@ -277,7 +277,7 @@ const Code = struct {
target_windows: bool,
link_libc: bool,
const Id = union(enum) {
const Id = union(enum).{
Test,
TestError: []const u8,
TestSafety: []const u8,
@ -286,16 +286,16 @@ const Code = struct {
};
};
const Link = struct {
const Link = struct.{
url: []const u8,
name: []const u8,
token: Token,
};
const Node = union(enum) {
const Node = union(enum).{
Content: []const u8,
Nav,
Builtin,
Builtin: Token,
HeaderOpen: HeaderOpen,
SeeAlso: []const SeeAlsoItem,
Code: Code,
@ -303,13 +303,13 @@ const Node = union(enum) {
Syntax: Token,
};
const Toc = struct {
const Toc = struct.{
nodes: []Node,
toc: []u8,
urls: std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8),
};
const Action = enum {
const Action = enum.{
Open,
Close,
};
@ -343,7 +343,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
break;
},
Token.Id.Content => {
try nodes.append(Node{ .Content = tokenizer.buffer[token.start..token.end] });
try nodes.append(Node.{ .Content = tokenizer.buffer[token.start..token.end] });
},
Token.Id.BracketOpen => {
const tag_token = try eatToken(tokenizer, Token.Id.TagContent);
@ -355,7 +355,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
try nodes.append(Node.Nav);
} else if (mem.eql(u8, tag_name, "builtin")) {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
try nodes.append(Node.Builtin);
try nodes.append(Node.{ .Builtin = tag_token });
} else if (mem.eql(u8, tag_name, "header_open")) {
_ = try eatToken(tokenizer, Token.Id.Separator);
const content_token = try eatToken(tokenizer, Token.Id.TagContent);
@ -365,8 +365,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
header_stack_size += 1;
const urlized = try urlize(allocator, content);
try nodes.append(Node{
.HeaderOpen = HeaderOpen{
try nodes.append(Node.{
.HeaderOpen = HeaderOpen.{
.name = content,
.url = urlized,
.n = header_stack_size,
@ -409,14 +409,14 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
switch (see_also_tok.id) {
Token.Id.TagContent => {
const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end];
try list.append(SeeAlsoItem{
try list.append(SeeAlsoItem.{
.name = content,
.token = see_also_tok,
});
},
Token.Id.Separator => {},
Token.Id.BracketClose => {
try nodes.append(Node{ .SeeAlso = list.toOwnedSlice() });
try nodes.append(Node.{ .SeeAlso = list.toOwnedSlice() });
break;
},
else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),
@ -440,8 +440,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
}
};
try nodes.append(Node{
.Link = Link{
try nodes.append(Node.{
.Link = Link.{
.url = try urlize(allocator, url_name),
.name = name,
.token = name_tok,
@ -465,24 +465,24 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
var code_kind_id: Code.Id = undefined;
var is_inline = false;
if (mem.eql(u8, code_kind_str, "exe")) {
code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Succeed };
code_kind_id = Code.Id.{ .Exe = ExpectedOutcome.Succeed };
} else if (mem.eql(u8, code_kind_str, "exe_err")) {
code_kind_id = Code.Id{ .Exe = ExpectedOutcome.Fail };
code_kind_id = Code.Id.{ .Exe = ExpectedOutcome.Fail };
} else if (mem.eql(u8, code_kind_str, "test")) {
code_kind_id = Code.Id.Test;
} else if (mem.eql(u8, code_kind_str, "test_err")) {
code_kind_id = Code.Id{ .TestError = name };
code_kind_id = Code.Id.{ .TestError = name };
name = "test";
} else if (mem.eql(u8, code_kind_str, "test_safety")) {
code_kind_id = Code.Id{ .TestSafety = name };
code_kind_id = Code.Id.{ .TestSafety = name };
name = "test";
} else if (mem.eql(u8, code_kind_str, "obj")) {
code_kind_id = Code.Id{ .Obj = null };
code_kind_id = Code.Id.{ .Obj = null };
} else if (mem.eql(u8, code_kind_str, "obj_err")) {
code_kind_id = Code.Id{ .Obj = name };
code_kind_id = Code.Id.{ .Obj = name };
name = "test";
} else if (mem.eql(u8, code_kind_str, "syntax")) {
code_kind_id = Code.Id{ .Obj = null };
code_kind_id = Code.Id.{ .Obj = null };
is_inline = true;
} else {
return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);
@ -518,8 +518,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
_ = try eatToken(tokenizer, Token.Id.BracketClose);
} else
unreachable; // TODO issue #707
try nodes.append(Node{
.Code = Code{
try nodes.append(Node.{
.Code = Code.{
.id = code_kind_id,
.name = name,
.source_token = source_token,
@ -541,7 +541,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
return parseError(tokenizer, end_syntax_tag, "invalid token inside syntax: {}", end_tag_name);
}
_ = try eatToken(tokenizer, Token.Id.BracketClose);
try nodes.append(Node{ .Syntax = content_tok });
try nodes.append(Node.{ .Syntax = content_tok });
} else {
return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
}
@ -550,7 +550,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
}
}
return Toc{
return Toc.{
.nodes = nodes.toOwnedSlice(),
.toc = toc_buf.toOwnedSlice(),
.urls = urls,
@ -606,7 +606,7 @@ fn writeEscaped(out: var, input: []const u8) !void {
//#define VT_BOLD "\x1b[0;1m"
//#define VT_RESET "\x1b[0m"
const TermState = enum {
const TermState = enum.{
Start,
Escape,
LBracket,
@ -703,7 +703,7 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
return buf.toOwnedSlice();
}
const builtin_types = [][]const u8{
const builtin_types = [][]const u8.{
"f16", "f32", "f64", "f128", "c_longdouble", "c_short",
"c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong",
"c_ulonglong", "c_char", "c_void", "void", "bool", "isize",
@ -718,8 +718,7 @@ fn isType(name: []const u8) bool {
return false;
}
fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Token, raw_src: []const u8) !void {
const src = mem.trim(u8, raw_src, " \n");
try out.write("<code class=\"zig\">");
var tokenizer = std.zig.Tokenizer.init(src);
@ -928,13 +927,18 @@ fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out
try out.write("</code>");
}
fn tokenizeAndPrint(docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
return tokenizeAndPrintRaw(docgen_tokenizer, out, source_token, raw_src);
}
fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
var code_progress_index: usize = 0;
var env_map = try os.getEnvMap(allocator);
try env_map.set("ZIG_DEBUG_COLOR", "1");
const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, &env_map, zig_exe));
const builtin_code = try getBuiltinCode(allocator, &env_map, zig_exe);
for (toc.nodes) |node| {
switch (node) {
@ -950,11 +954,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
Node.Nav => {
try out.write(toc.toc);
},
Node.Builtin => {
try out.print("<pre><code class=\"zig\">{}</code></pre>", builtin_code);
Node.Builtin => |tok| {
try out.write("<pre>");
try tokenizeAndPrintRaw(tokenizer, out, tok, builtin_code);
try out.write("</pre>");
},
Node.HeaderOpen => |info| {
try out.print("<h{} id=\"{}\">{}</h{}>\n", info.n, info.url, info.name, info.n);
try out.print("<h{} id=\"{}\"><a href=\"#{}\">{}</a></h{}>\n", info.n, info.url, info.url, info.name, info.n);
},
Node.SeeAlso => |items| {
try out.write("<p>See also:</p><ul>\n");
@ -968,7 +974,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.write("</ul>\n");
},
Node.Syntax => |content_tok| {
try tokenizeAndPrint(allocator, tokenizer, out, content_tok);
try tokenizeAndPrint(tokenizer, out, content_tok);
},
Node.Code => |code| {
code_progress_index += 1;
@ -980,7 +986,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
try out.print("<p class=\"file\">{}.zig</p>", code.name);
}
try out.write("<pre>");
try tokenizeAndPrint(allocator, tokenizer, out, code.source_token);
try tokenizeAndPrint(tokenizer, out, code.source_token);
try out.write("</pre>");
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);
@ -992,7 +998,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
const tmp_bin_file_name = try os.path.join(allocator, 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{
try build_args.appendSlice([][]const u8.{
zig_exe,
"build-exe",
tmp_source_file_name,
@ -1029,7 +1035,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
}
_ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
const run_args = [][]const u8{tmp_bin_file_name};
const run_args = [][]const u8.{tmp_bin_file_name};
const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
const result = try os.ChildProcess.exec(allocator, run_args, null, &env_map, max_doc_file_size);
@ -1063,7 +1069,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([][]const u8.{
zig_exe,
"test",
tmp_source_file_name,
@ -1087,7 +1093,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
},
}
if (code.target_windows) {
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([][]const u8.{
"--target-os",
"windows",
"--target-arch",
@ -1105,7 +1111,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([][]const u8.{
zig_exe,
"test",
"--color",
@ -1164,7 +1170,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
var test_args = std.ArrayList([]const u8).init(allocator);
defer test_args.deinit();
try test_args.appendSlice([][]const u8{
try test_args.appendSlice([][]const u8.{
zig_exe,
"test",
tmp_source_file_name,
@ -1216,7 +1222,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
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);
try build_args.appendSlice([][]const u8{
try build_args.appendSlice([][]const u8.{
zig_exe,
"build-obj",
tmp_source_file_name,
@ -1326,7 +1332,7 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
}
fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
const result = try exec(allocator, env_map, []const []const u8{
const result = try exec(allocator, env_map, []const []const u8.{
zig_exe,
"builtin",
});

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,7 @@ const os = std.os;
pub fn main() !void {
var stdout_file = try io.getStdOut();
var stdout_file_stream = io.FileOutStream.init(stdout_file);
const stdout = &stdout_file_stream.stream;
const stdout = &stdout_file.outStream().stream;
try stdout.print("Welcome to the Guess Number Game in Zig.\n");

View File

@ -4,13 +4,13 @@ pub fn build(b: *Builder) void {
const obj = b.addObject("base64", "base64.zig");
const exe = b.addCExecutable("test");
exe.addCompileFlags([][]const u8{"-std=c99"});
exe.addCompileFlags([][]const u8.{"-std=c99"});
exe.addSourceFile("test.c");
exe.addObject(obj);
b.default_step.dependOn(&exe.step);
const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
const run_cmd = b.addCommand(".", b.env_map, [][]const u8.{exe.getOutputPath()});
run_cmd.step.dependOn(&exe.step);
const test_step = b.step("test", "Test the program");

View File

@ -4,13 +4,13 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
const exe = b.addCExecutable("test");
exe.addCompileFlags([][]const u8{"-std=c99"});
exe.addCompileFlags([][]const u8.{"-std=c99"});
exe.addSourceFile("test.c");
exe.linkLibrary(lib);
b.default_step.dependOn(&exe.step);
const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
const run_cmd = b.addCommand(".", b.env_map, [][]const u8.{exe.getOutputPath()});
run_cmd.step.dependOn(&exe.step);
const test_step = b.step("test", "Test the program");

View File

@ -5,7 +5,9 @@ comptime {
@export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak);
}
}
var _mh_execute_header = extern struct {x: usize}{.x = 0};
var _mh_execute_header = extern struct.{
x: usize,
}.{ .x = 0 };
export fn add(a: i32, b: i32) i32 {
return a + b;

View File

@ -32,7 +32,7 @@ fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool {
// Modifies the current argument index during iteration
fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: *usize) !FlagArg {
switch (required) {
0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value?
0 => return FlagArg.{ .None = undefined }, // TODO: Required to force non-tag but value?
1 => {
if (index.* + 1 >= args.len) {
return error.MissingFlagArguments;
@ -45,7 +45,7 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required:
return error.ArgumentNotInAllowedSet;
}
return FlagArg{ .Single = arg };
return FlagArg.{ .Single = arg };
},
else => |needed| {
var extra = ArrayList([]const u8).init(allocator);
@ -67,7 +67,7 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required:
try extra.append(arg);
}
return FlagArg{ .Many = extra };
return FlagArg.{ .Many = extra };
},
}
}
@ -75,12 +75,12 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required:
const HashMapFlags = HashMap([]const u8, FlagArg, std.hash.Fnv1a_32.hash, mem.eql_slice_u8);
// A store for querying found flags and positional arguments.
pub const Args = struct {
pub const Args = struct.{
flags: HashMapFlags,
positionals: ArrayList([]const u8),
pub fn parse(allocator: *Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
var parsed = Args{
var parsed = Args.{
.flags = HashMapFlags.init(allocator),
.positionals = ArrayList([]const u8).init(allocator),
};
@ -123,7 +123,7 @@ pub const Args = struct {
FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
}
_ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
_ = try parsed.flags.put(flag_name_trimmed, FlagArg.{ .Many = prev });
} else {
_ = try parsed.flags.put(flag_name_trimmed, flag_args);
}
@ -177,20 +177,20 @@ pub const Args = struct {
else => @panic("attempted to retrieve flag with wrong type"),
}
} else {
return []const []const u8{};
return []const []const u8.{};
}
}
};
// Arguments for a flag. e.g. arg1, arg2 in `--command arg1 arg2`.
const FlagArg = union(enum) {
const FlagArg = union(enum).{
None,
Single: []const u8,
Many: ArrayList([]const u8),
};
// Specification for how a flag should be parsed.
pub const Flag = struct {
pub const Flag = struct.{
name: []const u8,
required: usize,
mergable: bool,
@ -205,7 +205,7 @@ pub const Flag = struct {
}
pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
return Flag{
return Flag.{
.name = name,
.required = n,
.mergable = false,
@ -218,7 +218,7 @@ pub const Flag = struct {
@compileError("n must be greater than 0");
}
return Flag{
return Flag.{
.name = name,
.required = n,
.mergable = true,
@ -227,7 +227,7 @@ pub const Flag = struct {
}
pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
return Flag{
return Flag.{
.name = name,
.required = 1,
.mergable = false,
@ -237,11 +237,11 @@ pub const Flag = struct {
};
test "parse arguments" {
const spec1 = comptime []const Flag{
const spec1 = comptime []const Flag.{
Flag.Bool("--help"),
Flag.Bool("--init"),
Flag.Arg1("--build-file"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", []const []const u8.{
"on",
"off",
"auto",
@ -251,7 +251,7 @@ test "parse arguments" {
Flag.ArgN("--library", 1),
};
const cliargs = []const []const u8{
const cliargs = []const []const u8.{
"build",
"--help",
"pos1",

View File

@ -1,10 +1,10 @@
pub const CInt = struct {
pub const CInt = struct.{
id: Id,
zig_name: []const u8,
c_name: []const u8,
is_signed: bool,
pub const Id = enum {
pub const Id = enum.{
Short,
UShort,
Int,
@ -15,50 +15,50 @@ pub const CInt = struct {
ULongLong,
};
pub const list = []CInt{
CInt{
pub const list = []CInt.{
CInt.{
.id = Id.Short,
.zig_name = "c_short",
.c_name = "short",
.is_signed = true,
},
CInt{
CInt.{
.id = Id.UShort,
.zig_name = "c_ushort",
.c_name = "unsigned short",
.is_signed = false,
},
CInt{
CInt.{
.id = Id.Int,
.zig_name = "c_int",
.c_name = "int",
.is_signed = true,
},
CInt{
CInt.{
.id = Id.UInt,
.zig_name = "c_uint",
.c_name = "unsigned int",
.is_signed = false,
},
CInt{
CInt.{
.id = Id.Long,
.zig_name = "c_long",
.c_name = "long",
.is_signed = true,
},
CInt{
CInt.{
.id = Id.ULong,
.zig_name = "c_ulong",
.c_name = "unsigned long",
.is_signed = false,
},
CInt{
CInt.{
.id = Id.LongLong,
.zig_name = "c_longlong",
.c_name = "long long",
.is_signed = true,
},
CInt{
CInt.{
.id = Id.ULongLong,
.zig_name = "c_ulonglong",
.c_name = "unsigned long long",

View File

@ -10,6 +10,7 @@ const Scope = @import("scope.zig").Scope;
const event = std.event;
const assert = std.debug.assert;
const DW = std.dwarf;
const maxInt = std.math.maxInt;
pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
fn_val.base.ref();
@ -72,7 +73,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
!comp.strip,
) orelse return error.OutOfMemory;
var ofile = ObjectFile{
var ofile = ObjectFile.{
.comp = comp,
.module = module,
.builder = builder,
@ -134,7 +135,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
}
}
pub const ObjectFile = struct {
pub const ObjectFile = struct.{
comp: *Compilation,
module: llvm.ModuleRef,
builder: llvm.BuilderRef,
@ -362,15 +363,15 @@ fn addLLVMAttrInt(
}
fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {
return addLLVMAttr(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name);
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 {
return addLLVMAttrStr(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name, attr_val);
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 {
return addLLVMAttrInt(ofile, fn_val, @maxValue(llvm.AttributeIndex), attr_name, attr_val);
return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
}
fn renderLoadUntyped(

View File

@ -35,7 +35,7 @@ const fs = event.fs;
const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
/// Data that is local to the event loop.
pub const ZigCompiler = struct {
pub const ZigCompiler = struct.{
loop: *event.Loop,
llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
lld_lock: event.Lock,
@ -57,7 +57,7 @@ pub const ZigCompiler = struct {
try std.os.getRandomBytes(seed_bytes[0..]);
const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
return ZigCompiler{
return ZigCompiler.{
.loop = loop,
.lld_lock = event.Lock.init(loop),
.llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
@ -78,18 +78,18 @@ pub const ZigCompiler = struct {
/// Gets an exclusive handle on any LlvmContext.
/// Caller must release the handle when done.
pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
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 node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node.{
.next = undefined,
.data = context_ref,
});
errdefer self.loop.allocator.destroy(node);
return LlvmHandle{ .node = node };
return LlvmHandle.{ .node = node };
}
pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
@ -102,8 +102,8 @@ pub const ZigCompiler = struct {
/// Must be called only once, ever. Sets global state.
pub fn setLlvmArgv(allocator: *Allocator, llvm_argv: []const []const u8) !void {
if (llvm_argv.len != 0) {
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(allocator, [][]const []const u8{
[][]const u8{"zig (LLVM option parsing)"},
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(allocator, [][]const []const u8.{
[][]const u8.{"zig (LLVM option parsing)"},
llvm_argv,
});
defer c_compatible_args.deinit();
@ -112,7 +112,7 @@ pub const ZigCompiler = struct {
}
};
pub const LlvmHandle = struct {
pub const LlvmHandle = struct.{
node: *std.atomic.Stack(llvm.ContextRef).Node,
pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
@ -120,7 +120,7 @@ pub const LlvmHandle = struct {
}
};
pub const Compilation = struct {
pub const Compilation = struct.{
zig_compiler: *ZigCompiler,
loop: *event.Loop,
name: Buffer,
@ -254,7 +254,7 @@ pub const Compilation = struct {
const CompileErrList = std.ArrayList(*Msg);
// TODO handle some of these earlier and report them in a way other than error codes
pub const BuildError = error{
pub const BuildError = error.{
OutOfMemory,
EndOfStream,
IsDir,
@ -302,25 +302,25 @@ pub const Compilation = struct {
BadPathName,
};
pub const Event = union(enum) {
pub const Event = union(enum).{
Ok,
Error: BuildError,
Fail: []*Msg,
};
pub const DarwinVersionMin = union(enum) {
pub const DarwinVersionMin = union(enum).{
None,
MacOS: []const u8,
Ios: []const u8,
};
pub const Kind = enum {
pub const Kind = enum.{
Exe,
Lib,
Obj,
};
pub const LinkLib = struct {
pub const LinkLib = struct.{
name: []const u8,
path: ?[]const u8,
@ -329,7 +329,7 @@ pub const Compilation = struct {
provided_explicitly: bool,
};
pub const Emit = enum {
pub const Emit = enum.{
Binary,
Assembly,
LlvmIr,
@ -380,7 +380,7 @@ pub const Compilation = struct {
}
const loop = zig_compiler.loop;
var comp = Compilation{
var comp = Compilation.{
.loop = loop,
.arena_allocator = std.heap.ArenaAllocator.init(loop.allocator),
.zig_compiler = zig_compiler,
@ -419,20 +419,20 @@ pub const Compilation = struct {
.strip = false,
.is_static = is_static,
.linker_rdynamic = false,
.clang_argv = [][]const u8{},
.lib_dirs = [][]const u8{},
.rpath_list = [][]const u8{},
.assembly_files = [][]const u8{},
.link_objects = [][]const u8{},
.clang_argv = [][]const u8.{},
.lib_dirs = [][]const u8.{},
.rpath_list = [][]const u8.{},
.assembly_files = [][]const u8.{},
.link_objects = [][]const u8.{},
.fn_link_set = event.Locked(FnLinkSet).init(loop, FnLinkSet.init()),
.windows_subsystem_windows = false,
.windows_subsystem_console = false,
.link_libs_list = undefined,
.libc_link_lib = null,
.err_color = errmsg.Color.Auto,
.darwin_frameworks = [][]const u8{},
.darwin_frameworks = [][]const u8.{},
.darwin_version_min = DarwinVersionMin.None,
.test_filters = [][]const u8{},
.test_filters = [][]const u8.{},
.test_name_prefix = null,
.emit_file_type = Emit.Binary,
.link_out_file = null,
@ -575,7 +575,7 @@ pub const Compilation = struct {
error.Overflow => return error.Overflow,
error.InvalidCharacter => unreachable, // we just checked the characters above
};
const int_type = try await (async Type.Int.get(comp, Type.Int.Key{
const int_type = try await (async Type.Int.get(comp, Type.Int.Key.{
.bit_count = bit_count,
.is_signed = is_signed,
}) catch unreachable);
@ -595,10 +595,10 @@ pub const Compilation = struct {
}
fn initTypes(comp: *Compilation) !void {
comp.meta_type = try comp.arena().create(Type.MetaType{
.base = Type{
comp.meta_type = try comp.arena().create(Type.MetaType.{
.base = Type.{
.name = "type",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = undefined,
.ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
@ -612,10 +612,10 @@ pub const Compilation = struct {
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{
.base = Type{
comp.void_type = try comp.arena().create(Type.Void.{
.base = Type.{
.name = "void",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -626,10 +626,10 @@ pub const Compilation = struct {
});
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{
.base = Type{
comp.noreturn_type = try comp.arena().create(Type.NoReturn.{
.base = Type.{
.name = "noreturn",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -640,10 +640,10 @@ pub const Compilation = struct {
});
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{
.base = Type{
comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt.{
.base = Type.{
.name = "comptime_int",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -654,10 +654,10 @@ pub const Compilation = struct {
});
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{
.base = Type{
comp.bool_type = try comp.arena().create(Type.Bool.{
.base = Type.{
.name = "bool",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -668,16 +668,16 @@ pub const Compilation = struct {
});
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{
.base = Value{
comp.void_value = try comp.arena().create(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{
.base = Value{
comp.true_value = try comp.arena().create(Value.Bool.{
.base = Value.{
.id = Value.Id.Bool,
.typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -685,8 +685,8 @@ pub const Compilation = struct {
.x = true,
});
comp.false_value = try comp.arena().create(Value.Bool{
.base = Value{
comp.false_value = try comp.arena().create(Value.Bool.{
.base = Value.{
.id = Value.Id.Bool,
.typ = &Type.Bool.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -694,8 +694,8 @@ pub const Compilation = struct {
.x = false,
});
comp.noreturn_value = try comp.arena().create(Value.NoReturn{
.base = Value{
comp.noreturn_value = try comp.arena().create(Value.NoReturn.{
.base = Value.{
.id = Value.Id.NoReturn,
.typ = &Type.NoReturn.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -703,10 +703,10 @@ pub const Compilation = struct {
});
for (CInt.list) |cint, i| {
const c_int_type = try comp.arena().create(Type.Int{
.base = Type{
const c_int_type = try comp.arena().create(Type.Int.{
.base = Type.{
.name = cint.zig_name,
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -714,7 +714,7 @@ pub const Compilation = struct {
.id = builtin.TypeId.Int,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
.key = Type.Int.Key{
.key = Type.Int.Key.{
.is_signed = cint.is_signed,
.bit_count = comp.target.cIntTypeSizeInBits(cint.id),
},
@ -723,10 +723,10 @@ pub const Compilation = struct {
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{
.base = Type{
comp.u8_type = try comp.arena().create(Type.Int.{
.base = Type.{
.name = "u8",
.base = Value{
.base = Value.{
.id = Value.Id.Type,
.typ = &Type.MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -734,7 +734,7 @@ pub const Compilation = struct {
.id = builtin.TypeId.Int,
.abi_alignment = Type.AbiAlignment.init(comp.loop),
},
.key = Type.Int.Key{
.key = Type.Int.Key.{
.is_signed = false,
.bit_count = 8,
},
@ -777,13 +777,13 @@ pub const Compilation = struct {
if (compile_errors.len == 0) {
await (async self.events.put(Event.Ok) catch unreachable);
} else {
await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
await (async self.events.put(Event.{ .Fail = compile_errors }) catch unreachable);
}
} else |err| {
// if there's an error then the compile errors have dangling references
self.gpa().free(compile_errors);
await (async self.events.put(Event{ .Error = err }) catch unreachable);
await (async self.events.put(Event.{ .Error = err }) catch unreachable);
}
// First, get an item from the watch channel, waiting on the channel.
@ -894,7 +894,7 @@ pub const Compilation = struct {
const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else {
try self.addCompileError(tree_scope, Span{
try self.addCompileError(tree_scope, Span.{
.first = fn_proto.fn_token,
.last = fn_proto.fn_token + 1,
}, "missing function name");
@ -924,8 +924,8 @@ pub const Compilation = struct {
}
} else {
// add new decl
const fn_decl = try self.gpa().create(Decl.Fn{
.base = Decl{
const fn_decl = try self.gpa().create(Decl.Fn.{
.base = Decl.{
.id = Decl.Id.Fn,
.name = name,
.visib = parseVisibToken(tree_scope.tree, fn_proto.visib_token),
@ -933,7 +933,7 @@ pub const Compilation = struct {
.parent_scope = &decl_scope.base,
.tree_scope = tree_scope,
},
.value = Decl.Fn.Val{ .Unresolved = {} },
.value = Decl.Fn.Val.{ .Unresolved = {} },
.fn_proto = fn_proto,
});
tree_scope.base.ref();
@ -1139,7 +1139,7 @@ pub const Compilation = struct {
}
}
const link_lib = try self.gpa().create(LinkLib{
const link_lib = try self.gpa().create(LinkLib.{
.name = name,
.path = null,
.provided_explicitly = provided_explicitly,
@ -1307,7 +1307,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
// The Decl.Fn owns the initial 1 reference count
const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
fn_decl.value = Decl.Fn.Val{ .Fn = fn_val };
fn_decl.value = Decl.Fn.Val.{ .Fn = fn_val };
symbol_name_consumed = true;
// Define local parameter variables
@ -1315,7 +1315,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
//AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);
const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", fn_decl.fn_proto.params.at(i).*);
const name_token = param_decl.name_token orelse {
try comp.addCompileError(tree_scope, Span{
try comp.addCompileError(tree_scope, Span.{
.first = param_decl.firstToken(),
.last = param_decl.type_node.firstToken(),
}, "missing parameter name");
@ -1402,17 +1402,17 @@ async fn analyzeFnType(
const param_node = param_node_ptr.*.cast(ast.Node.ParamDecl).?;
const param_type = try await (async comp.analyzeTypeExpr(tree_scope, scope, param_node.type_node) catch unreachable);
errdefer param_type.base.deref(comp);
try params.append(Type.Fn.Param{
try params.append(Type.Fn.Param.{
.typ = param_type,
.is_noalias = param_node.noalias_token != null,
});
}
}
const key = Type.Fn.Key{
const key = Type.Fn.Key.{
.alignment = null,
.data = Type.Fn.Key.Data{
.Normal = Type.Fn.Key.Normal{
.data = Type.Fn.Key.Data.{
.Normal = Type.Fn.Key.Normal.{
.return_type = return_type,
.params = params.toOwnedSlice(),
.is_var_args = false, // TODO
@ -1451,7 +1451,7 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
// The Decl.Fn owns the initial 1 reference count
const fn_proto_val = try Value.FnProto.create(comp, fn_type, symbol_name);
fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };
fn_decl.value = Decl.Fn.Val.{ .FnProto = fn_proto_val };
symbol_name_consumed = true;
}

View File

@ -10,7 +10,7 @@ const errmsg = @import("errmsg.zig");
const Scope = @import("scope.zig").Scope;
const Compilation = @import("compilation.zig").Compilation;
pub const Decl = struct {
pub const Decl = struct.{
id: Id,
name: []const u8,
visib: Visib,
@ -44,7 +44,7 @@ pub const Decl = struct {
const fn_proto = fn_decl.fn_proto;
const start = fn_proto.fn_token;
const end = fn_proto.name_token orelse start;
return errmsg.Span{
return errmsg.Span.{
.first = start,
.last = end + 1,
};
@ -57,23 +57,23 @@ pub const Decl = struct {
return base.parent_scope.findRoot();
}
pub const Id = enum {
pub const Id = enum.{
Var,
Fn,
CompTime,
};
pub const Var = struct {
pub const Var = struct.{
base: Decl,
};
pub const Fn = struct {
pub const Fn = struct.{
base: Decl,
value: Val,
fn_proto: *ast.Node.FnProto,
// TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
pub const Val = union(enum) {
pub const Val = union(enum).{
Unresolved: void,
Fn: *Value.Fn,
FnProto: *Value.FnProto,
@ -99,7 +99,7 @@ pub const Decl = struct {
}
};
pub const CompTime = struct {
pub const CompTime = struct.{
base: Decl,
};
};

View File

@ -7,55 +7,55 @@ const TokenIndex = std.zig.ast.TokenIndex;
const Compilation = @import("compilation.zig").Compilation;
const Scope = @import("scope.zig").Scope;
pub const Color = enum {
pub const Color = enum.{
Auto,
Off,
On,
};
pub const Span = struct {
pub const Span = struct.{
first: ast.TokenIndex,
last: ast.TokenIndex,
pub fn token(i: TokenIndex) Span {
return Span{
return Span.{
.first = i,
.last = i,
};
}
pub fn node(n: *ast.Node) Span {
return Span{
return Span.{
.first = n.firstToken(),
.last = n.lastToken(),
};
}
};
pub const Msg = struct {
pub const Msg = struct.{
text: []u8,
realpath: []u8,
data: Data,
const Data = union(enum) {
const Data = union(enum).{
Cli: Cli,
PathAndTree: PathAndTree,
ScopeAndComp: ScopeAndComp,
};
const PathAndTree = struct {
const PathAndTree = struct.{
span: Span,
tree: *ast.Tree,
allocator: *mem.Allocator,
};
const ScopeAndComp = struct {
const ScopeAndComp = struct.{
span: Span,
tree_scope: *Scope.AstTree,
compilation: *Compilation,
};
const Cli = struct {
const Cli = struct.{
allocator: *mem.Allocator,
};
@ -118,11 +118,11 @@ 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.{
.text = text,
.realpath = realpath,
.data = Data{
.ScopeAndComp = ScopeAndComp{
.data = Data.{
.ScopeAndComp = ScopeAndComp.{
.tree_scope = tree_scope,
.compilation = comp,
.span = span,
@ -139,11 +139,11 @@ 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.{
.text = text,
.realpath = realpath_copy,
.data = Data{
.Cli = Cli{ .allocator = comp.gpa() },
.data = Data.{
.Cli = Cli.{ .allocator = comp.gpa() },
},
});
return msg;
@ -164,14 +164,14 @@ 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.{
.text = undefined,
.realpath = realpath_copy,
.data = Data{
.ScopeAndComp = ScopeAndComp{
.data = Data.{
.ScopeAndComp = ScopeAndComp.{
.tree_scope = tree_scope,
.compilation = comp,
.span = Span{
.span = Span.{
.first = loc_token,
.last = loc_token,
},
@ -203,14 +203,14 @@ 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.{
.text = undefined,
.realpath = realpath_copy,
.data = Data{
.PathAndTree = PathAndTree{
.data = Data.{
.PathAndTree = PathAndTree.{
.allocator = allocator,
.tree = tree,
.span = Span{
.span = Span.{
.first = loc_token,
.last = loc_token,
},
@ -278,7 +278,7 @@ pub const Msg = struct {
Color.On => true,
Color.Off => false,
};
var stream = &std.io.FileOutStream.init(file).stream;
var stream = &file.outStream().stream;
return msg.printToStream(stream, color_on);
}
};

View File

@ -15,17 +15,17 @@ const ObjectFile = codegen.ObjectFile;
const Decl = @import("decl.zig").Decl;
const mem = std.mem;
pub const LVal = enum {
pub const LVal = enum.{
None,
Ptr,
};
pub const IrVal = union(enum) {
pub const IrVal = union(enum).{
Unknown,
KnownType: *Type,
KnownValue: *Value,
const Init = enum {
const Init = enum.{
Unknown,
NoReturn,
Void,
@ -48,7 +48,7 @@ pub const IrVal = union(enum) {
}
};
pub const Inst = struct {
pub const Inst = struct.{
id: Id,
scope: *Scope,
debug_id: usize,
@ -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.ValueRef) {
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),
@ -242,7 +242,7 @@ pub const Inst = struct {
parent.child = self;
}
pub const Id = enum {
pub const Id = enum.{
Return,
Const,
Ref,
@ -258,11 +258,11 @@ pub const Inst = struct {
LoadPtr,
};
pub const Call = struct {
pub const Call = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
fn_ref: *Inst,
args: []*Inst,
};
@ -305,11 +305,11 @@ pub const Inst = struct {
for (self.params.args) |arg, i| {
args[i] = try arg.getAsParam();
}
const new_inst = try ira.irb.build(Call, self.base.scope, self.base.span, Params{
const new_inst = try ira.irb.build(Call, self.base.scope, self.base.span, Params.{
.fn_ref = fn_ref,
.args = args,
});
new_inst.val = IrVal{ .KnownType = fn_type.key.data.Normal.return_type };
new_inst.val = IrVal.{ .KnownType = fn_type.key.data.Normal.return_type };
return new_inst;
}
@ -336,11 +336,11 @@ pub const Inst = struct {
}
};
pub const Const = struct {
pub const Const = struct.{
base: Inst,
params: Params,
const Params = struct {};
const Params = struct.{};
// Use Builder.buildConst* methods, or, after building a Const instruction,
// manually set the ir_val field.
@ -355,8 +355,8 @@ pub const Inst = struct {
}
pub fn analyze(self: *const Const, ira: *Analyze) !*Inst {
const new_inst = try ira.irb.build(Const, self.base.scope, self.base.span, Params{});
new_inst.val = IrVal{ .KnownValue = self.base.val.KnownValue.getRef() };
const new_inst = try ira.irb.build(Const, self.base.scope, self.base.span, Params.{});
new_inst.val = IrVal.{ .KnownValue = self.base.val.KnownValue.getRef() };
return new_inst;
}
@ -365,11 +365,11 @@ pub const Inst = struct {
}
};
pub const Return = struct {
pub const Return = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
return_value: *Inst,
};
@ -389,7 +389,7 @@ pub const Inst = struct {
// TODO detect returning local variable address
return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
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 {
@ -405,11 +405,11 @@ pub const Inst = struct {
}
};
pub const Ref = struct {
pub const Ref = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
target: *Inst,
mut: Type.Pointer.Mut,
volatility: Type.Pointer.Vol,
@ -435,13 +435,13 @@ pub const Inst = struct {
);
}
const new_inst = try ira.irb.build(Ref, self.base.scope, self.base.span, Params{
const new_inst = try ira.irb.build(Ref, self.base.scope, self.base.span, Params.{
.target = target,
.mut = self.params.mut,
.volatility = self.params.volatility,
});
const elem_type = target.getKnownType();
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key.{
.child_type = elem_type,
.mut = self.params.mut,
.vol = self.params.volatility,
@ -450,17 +450,17 @@ pub const Inst = struct {
}) catch unreachable);
// TODO: potentially set the hint that this is a stack pointer. But it might not be - this
// could be a ref of a global, for example
new_inst.val = IrVal{ .KnownType = &ptr_type.base };
new_inst.val = IrVal.{ .KnownType = &ptr_type.base };
// TODO potentially add an alloca entry here
return new_inst;
}
};
pub const DeclRef = struct {
pub const DeclRef = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
decl: *Decl,
lval: LVal,
};
@ -499,11 +499,11 @@ pub const Inst = struct {
}
};
pub const VarPtr = struct {
pub const VarPtr = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
var_scope: *Scope.Var,
};
@ -525,16 +525,16 @@ pub const Inst = struct {
Inst.VarPtr,
self.base.scope,
self.base.span,
Inst.VarPtr.Params{ .var_scope = self.params.var_scope },
Inst.VarPtr.Params.{ .var_scope = self.params.var_scope },
);
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key.{
.child_type = param.typ,
.mut = Type.Pointer.Mut.Const,
.vol = Type.Pointer.Vol.Non,
.size = Type.Pointer.Size.One,
.alignment = Type.Pointer.Align.Abi,
}) catch unreachable);
new_inst.val = IrVal{ .KnownType = &ptr_type.base };
new_inst.val = IrVal.{ .KnownType = &ptr_type.base };
return new_inst;
},
}
@ -548,11 +548,11 @@ pub const Inst = struct {
}
};
pub const LoadPtr = struct {
pub const LoadPtr = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
target: *Inst,
};
@ -590,9 +590,9 @@ pub const Inst = struct {
Inst.LoadPtr,
self.base.scope,
self.base.span,
Inst.LoadPtr.Params{ .target = target },
Inst.LoadPtr.Params.{ .target = target },
);
new_inst.val = IrVal{ .KnownType = ptr_type.key.child_type };
new_inst.val = IrVal.{ .KnownType = ptr_type.key.child_type };
return new_inst;
}
@ -626,11 +626,11 @@ pub const Inst = struct {
}
};
pub const PtrType = struct {
pub const PtrType = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
child_type: *Inst,
mut: Type.Pointer.Mut,
vol: Type.Pointer.Vol,
@ -657,11 +657,11 @@ pub const Inst = struct {
// }
const alignment = if (self.params.alignment) |align_inst| blk: {
const amt = try align_inst.getAsConstAlign(ira);
break :blk Type.Pointer.Align{ .Override = amt };
break :blk Type.Pointer.Align.{ .Override = amt };
} else blk: {
break :blk Type.Pointer.Align{ .Abi = {} };
break :blk Type.Pointer.Align.{ .Abi = {} };
};
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key.{
.child_type = child_type,
.mut = self.params.mut,
.vol = self.params.vol,
@ -674,11 +674,11 @@ pub const Inst = struct {
}
};
pub const DeclVar = struct {
pub const DeclVar = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
variable: *Variable,
};
@ -695,11 +695,11 @@ pub const Inst = struct {
}
};
pub const CheckVoidStmt = struct {
pub const CheckVoidStmt = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
target: *Inst,
};
@ -723,11 +723,11 @@ pub const Inst = struct {
}
};
pub const Phi = struct {
pub const Phi = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
incoming_blocks: []*BasicBlock,
incoming_values: []*Inst,
};
@ -745,11 +745,11 @@ pub const Inst = struct {
}
};
pub const Br = struct {
pub const Br = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
dest_block: *BasicBlock,
is_comptime: *Inst,
};
@ -767,11 +767,11 @@ pub const Inst = struct {
}
};
pub const CondBr = struct {
pub const CondBr = struct.{
base: Inst,
params: Params,
const Params = struct {
const Params = struct.{
condition: *Inst,
then_block: *BasicBlock,
else_block: *BasicBlock,
@ -791,11 +791,11 @@ pub const Inst = struct {
}
};
pub const AddImplicitReturnType = struct {
pub const AddImplicitReturnType = struct.{
base: Inst,
params: Params,
pub const Params = struct {
pub const Params = struct.{
target: *Inst,
};
@ -816,11 +816,11 @@ pub const Inst = struct {
}
};
pub const TestErr = struct {
pub const TestErr = struct.{
base: Inst,
params: Params,
pub const Params = struct {
pub const Params = struct.{
target: *Inst,
};
@ -878,11 +878,11 @@ pub const Inst = struct {
}
};
pub const TestCompTime = struct {
pub const TestCompTime = struct.{
base: Inst,
params: Params,
pub const Params = struct {
pub const Params = struct.{
target: *Inst,
};
@ -902,11 +902,11 @@ pub const Inst = struct {
}
};
pub const SaveErrRetAddr = struct {
pub const SaveErrRetAddr = struct.{
base: Inst,
params: Params,
const Params = struct {};
const Params = struct.{};
const ir_val_init = IrVal.Init.Unknown;
@ -917,16 +917,16 @@ pub const Inst = struct {
}
pub fn analyze(self: *const SaveErrRetAddr, ira: *Analyze) !*Inst {
return ira.irb.build(Inst.SaveErrRetAddr, self.base.scope, self.base.span, Params{});
return ira.irb.build(Inst.SaveErrRetAddr, self.base.scope, self.base.span, Params.{});
}
};
};
pub const Variable = struct {
pub const Variable = struct.{
child_scope: *Scope,
};
pub const BasicBlock = struct {
pub const BasicBlock = struct.{
ref_count: usize,
name_hint: [*]const u8, // must be a C string literal
debug_id: usize,
@ -957,7 +957,7 @@ pub const BasicBlock = struct {
};
/// Stuff that survives longer than Builder
pub const Code = struct {
pub const Code = struct.{
basic_block_list: std.ArrayList(*BasicBlock),
arena: std.heap.ArenaAllocator,
return_type: ?*Type,
@ -1009,7 +1009,7 @@ pub const Code = struct {
}
};
pub const Builder = struct {
pub const Builder = struct.{
comp: *Compilation,
code: *Code,
current_basic_block: *BasicBlock,
@ -1021,7 +1021,7 @@ 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.{
.basic_block_list = undefined,
.arena = std.heap.ArenaAllocator.init(comp.gpa()),
.return_type = null,
@ -1030,7 +1030,7 @@ pub const Builder = struct {
code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
errdefer code.destroy(comp.gpa());
return Builder{
return Builder.{
.comp = comp,
.current_basic_block = undefined,
.code = code,
@ -1052,7 +1052,7 @@ 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.{
.ref_count = 0,
.name_hint = name_hint,
.debug_id = self.next_debug_id,
@ -1208,7 +1208,7 @@ pub const Builder = struct {
// }
//}
return irb.build(Inst.Call, scope, Span.token(suffix_op.rtoken), Inst.Call.Params{
return irb.build(Inst.Call, scope, Span.token(suffix_op.rtoken), Inst.Call.Params.{
.fn_ref = fn_ref,
.args = args,
});
@ -1272,7 +1272,7 @@ pub const Builder = struct {
// return irb->codegen->invalid_instruction;
//}
return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{
return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params.{
.child_type = child_type,
.mut = Type.Pointer.Mut.Mut,
.vol = Type.Pointer.Vol.Non,
@ -1336,8 +1336,8 @@ pub const Builder = struct {
};
errdefer int_val.base.deref(irb.comp);
const inst = try irb.build(Inst.Const, scope, Span.token(int_lit.token), Inst.Const.Params{});
inst.val = IrVal{ .KnownValue = &int_val.base };
const inst = try irb.build(Inst.Const, scope, Span.token(int_lit.token), Inst.Const.Params.{});
inst.val = IrVal.{ .KnownValue = &int_val.base };
return inst;
}
@ -1455,11 +1455,11 @@ pub const Builder = struct {
_ = irb.build(
Inst.CheckVoidStmt,
child_scope,
Span{
Span.{
.first = statement_node.firstToken(),
.last = statement_node.lastToken(),
},
Inst.CheckVoidStmt.Params{ .target = statement_value },
Inst.CheckVoidStmt.Params.{ .target = statement_value },
);
}
}
@ -1471,7 +1471,7 @@ pub const Builder = struct {
}
try irb.setCursorAtEndAndAppendBlock(block_scope.end_block);
return irb.build(Inst.Phi, parent_scope, Span.token(block.rbrace), Inst.Phi.Params{
return irb.build(Inst.Phi, parent_scope, Span.token(block.rbrace), Inst.Phi.Params.{
.incoming_blocks = block_scope.incoming_blocks.toOwnedSlice(),
.incoming_values = block_scope.incoming_values.toOwnedSlice(),
});
@ -1484,14 +1484,14 @@ pub const Builder = struct {
);
_ = try await (async irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
_ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{
_ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params.{
.dest_block = block_scope.end_block,
.is_comptime = block_scope.is_comptime,
});
try irb.setCursorAtEndAndAppendBlock(block_scope.end_block);
return irb.build(Inst.Phi, parent_scope, Span.token(block.rbrace), Inst.Phi.Params{
return irb.build(Inst.Phi, parent_scope, Span.token(block.rbrace), Inst.Phi.Params.{
.incoming_blocks = block_scope.incoming_blocks.toOwnedSlice(),
.incoming_values = block_scope.incoming_values.toOwnedSlice(),
});
@ -1553,12 +1553,12 @@ pub const Builder = struct {
Inst.TestErr,
scope,
src_span,
Inst.TestErr.Params{ .target = return_value },
Inst.TestErr.Params.{ .target = return_value },
);
const err_is_comptime = try irb.buildTestCompTime(scope, src_span, is_err);
_ = try irb.buildGen(Inst.CondBr, scope, src_span, Inst.CondBr.Params{
_ = try irb.buildGen(Inst.CondBr, scope, src_span, Inst.CondBr.Params.{
.condition = is_err,
.then_block = err_block,
.else_block = ok_block,
@ -1572,9 +1572,9 @@ pub const Builder = struct {
_ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ErrorExit) catch unreachable);
}
if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) {
_ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{});
_ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params.{});
}
_ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{
_ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params.{
.dest_block = ret_stmt_block,
.is_comptime = err_is_comptime,
});
@ -1583,7 +1583,7 @@ pub const Builder = struct {
if (have_err_defers) {
_ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
}
_ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{
_ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params.{
.dest_block = ret_stmt_block,
.is_comptime = err_is_comptime,
});
@ -1631,17 +1631,17 @@ pub const Builder = struct {
switch (await (async irb.findIdent(scope, name) catch unreachable)) {
Ident.Decl => |decl| {
return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{
return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params.{
.decl = decl,
.lval = lval,
});
},
Ident.VarScope => |var_scope| {
const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope });
const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params.{ .var_scope = var_scope });
switch (lval) {
LVal.Ptr => return var_ptr,
LVal.None => {
return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr });
return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params.{ .target = var_ptr });
},
}
},
@ -1661,13 +1661,13 @@ pub const Builder = struct {
return error.SemanticAnalysisFailed;
}
const DeferCounts = struct {
const DeferCounts = struct.{
scope_exit: usize,
error_exit: usize,
};
fn countDefers(irb: *Builder, inner_scope: *Scope, outer_scope: *Scope) DeferCounts {
var result = DeferCounts{ .scope_exit = 0, .error_exit = 0 };
var result = DeferCounts.{ .scope_exit = 0, .error_exit = 0 };
var scope = inner_scope;
while (scope != outer_scope) {
@ -1726,7 +1726,7 @@ pub const Builder = struct {
Inst.CheckVoidStmt,
&defer_expr_scope.base,
Span.token(defer_expr_scope.expr_node.lastToken()),
Inst.CheckVoidStmt.Params{ .target = instruction },
Inst.CheckVoidStmt.Params.{ .target = instruction },
);
}
}
@ -1753,7 +1753,7 @@ pub const Builder = struct {
LVal.Ptr => {
// We needed a pointer to a value, but we got a value. So we create
// an instruction which just makes a const pointer of it.
return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{
return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params.{
.target = instruction,
.mut = Type.Pointer.Mut.Const,
.volatility = Type.Pointer.Vol.Non,
@ -1774,16 +1774,16 @@ pub const Builder = struct {
params: I.Params,
is_generated: bool,
) !*Inst {
const inst = try self.arena().create(I{
.base = Inst{
const inst = try self.arena().create(I.{
.base = Inst.{
.id = Inst.typeToId(I),
.is_generated = is_generated,
.scope = scope,
.debug_id = self.next_debug_id,
.val = switch (I.ir_val_init) {
IrVal.Init.Unknown => IrVal.Unknown,
IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
IrVal.Init.NoReturn => IrVal.{ .KnownValue = &Value.NoReturn.get(self.comp).base },
IrVal.Init.Void => IrVal.{ .KnownValue = &Value.Void.get(self.comp).base },
},
.ref_count = 0,
.span = span,
@ -1852,20 +1852,20 @@ pub const Builder = struct {
}
fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Inst {
const inst = try self.build(Inst.Const, scope, span, Inst.Const.Params{});
inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.comp, x).base };
const inst = try self.build(Inst.Const, scope, span, Inst.Const.Params.{});
inst.val = IrVal.{ .KnownValue = &Value.Bool.get(self.comp, x).base };
return inst;
}
fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Inst {
const inst = try self.buildExtra(Inst.Const, scope, span, Inst.Const.Params{}, is_generated);
inst.val = IrVal{ .KnownValue = &Value.Void.get(self.comp).base };
const inst = try self.buildExtra(Inst.Const, scope, span, Inst.Const.Params.{}, is_generated);
inst.val = IrVal.{ .KnownValue = &Value.Void.get(self.comp).base };
return inst;
}
fn buildConstValue(self: *Builder, scope: *Scope, span: Span, v: *Value) !*Inst {
const inst = try self.build(Inst.Const, scope, span, Inst.Const.Params{});
inst.val = IrVal{ .KnownValue = v.getRef() };
const inst = try self.build(Inst.Const, scope, span, Inst.Const.Params.{});
inst.val = IrVal.{ .KnownValue = v.getRef() };
return inst;
}
@ -1879,7 +1879,7 @@ pub const Builder = struct {
Inst.TestCompTime,
scope,
span,
Inst.TestCompTime.Params{ .target = target },
Inst.TestCompTime.Params.{ .target = target },
);
}
}
@ -1889,7 +1889,7 @@ pub const Builder = struct {
Inst.AddImplicitReturnType,
scope,
span,
Inst.AddImplicitReturnType.Params{ .target = result },
Inst.AddImplicitReturnType.Params.{ .target = result },
);
if (!irb.is_async) {
@ -1897,7 +1897,7 @@ pub const Builder = struct {
Inst.Return,
scope,
span,
Inst.Return.Params{ .return_value = result },
Inst.Return.Params.{ .return_value = result },
is_gen,
);
}
@ -1919,7 +1919,7 @@ pub const Builder = struct {
//// the above blocks are rendered by ir_gen after the rest of codegen
}
const Ident = union(enum) {
const Ident = union(enum).{
NotFound,
Decl: *Decl,
VarScope: *Scope.Var,
@ -1935,13 +1935,13 @@ pub const Builder = struct {
const locked_table = await (async decls.table.acquireRead() catch unreachable);
defer locked_table.release();
if (locked_table.value.get(name)) |entry| {
return Ident{ .Decl = entry.value };
return Ident.{ .Decl = entry.value };
}
},
Scope.Id.Var => {
const var_scope = @fieldParentPtr(Scope.Var, "base", s);
if (mem.eql(u8, var_scope.name, name)) {
return Ident{ .VarScope = var_scope };
return Ident.{ .VarScope = var_scope };
}
},
else => {},
@ -1951,7 +1951,7 @@ pub const Builder = struct {
}
};
const Analyze = struct {
const Analyze = struct.{
irb: Builder,
old_bb_index: usize,
const_predecessor_bb: ?*BasicBlock,
@ -1960,7 +1960,7 @@ const Analyze = struct {
src_implicit_return_type_list: std.ArrayList(*Inst),
explicit_return_type: ?*Type,
pub const Error = error{
pub const Error = error.{
/// This is only for when we have already reported a compile error. It is the poison value.
SemanticAnalysisFailed,
@ -1975,7 +1975,7 @@ const Analyze = struct {
var irb = try Builder.init(comp, tree_scope, null);
errdefer irb.abort();
return Analyze{
return Analyze.{
.irb = irb,
.old_bb_index = 0,
.const_predecessor_bb = null,

View File

@ -5,7 +5,7 @@ const Target = @import("target.zig").Target;
const c = @import("c.zig");
/// See the render function implementation for documentation of the fields.
pub const LibCInstallation = struct {
pub const LibCInstallation = struct.{
include_dir: []const u8,
lib_dir: ?[]const u8,
static_lib_dir: ?[]const u8,
@ -13,7 +13,7 @@ pub const LibCInstallation = struct {
kernel32_lib_dir: ?[]const u8,
dynamic_linker_path: ?[]const u8,
pub const FindError = error{
pub const FindError = error.{
OutOfMemory,
FileSystem,
UnableToSpawnCCompiler,
@ -30,11 +30,11 @@ pub const LibCInstallation = struct {
self: *LibCInstallation,
allocator: *std.mem.Allocator,
libc_file: []const u8,
stderr: *std.io.OutStream(std.io.FileOutStream.Error),
stderr: *std.io.OutStream(std.os.File.WriteError),
) !void {
self.initEmpty();
const keys = []const []const u8{
const keys = []const []const u8.{
"include_dir",
"lib_dir",
"static_lib_dir",
@ -42,11 +42,11 @@ pub const LibCInstallation = struct {
"kernel32_lib_dir",
"dynamic_linker_path",
};
const FoundKey = struct {
const FoundKey = struct.{
found: bool,
allocated: ?[]u8,
};
var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** keys.len;
var found_keys = [1]FoundKey.{FoundKey.{ .found = false, .allocated = null }} ** keys.len;
errdefer {
self.initEmpty();
for (found_keys) |found_key| {
@ -100,7 +100,7 @@ pub const LibCInstallation = struct {
}
}
pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.io.FileOutStream.Error)) !void {
pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.os.File.WriteError)) !void {
@setEvalBranchQuota(4000);
try out.print(
\\# The directory that contains `stdlib.h`.
@ -182,7 +182,7 @@ pub const LibCInstallation = struct {
async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {
const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
const argv = []const []const u8{
const argv = []const []const u8.{
cc_exe,
"-E",
"-Wp,-v",
@ -280,7 +280,7 @@ pub const LibCInstallation = struct {
switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86"),
builtin.Arch.x86_64 => try stream.write("x64"),
builtin.Arch.aarch64 => try stream.write("arm"),
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");
@ -302,12 +302,12 @@ pub const LibCInstallation = struct {
}
async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {
var dyn_tests = []DynTest{
DynTest{
var dyn_tests = []DynTest.{
DynTest.{
.name = "ld-linux-x86-64.so.2",
.result = null,
},
DynTest{
DynTest.{
.name = "ld-musl-x86_64.so.1",
.result = null,
},
@ -326,7 +326,7 @@ pub const LibCInstallation = struct {
}
}
const DynTest = struct {
const DynTest = struct.{
name: []const u8,
result: ?[]const u8,
};
@ -355,7 +355,7 @@ pub const LibCInstallation = struct {
switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86\\"),
builtin.Arch.x86_64 => try stream.write("x64\\"),
builtin.Arch.aarch64 => try stream.write("arm\\"),
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");
@ -369,7 +369,7 @@ pub const LibCInstallation = struct {
}
fn initEmpty(self: *LibCInstallation) void {
self.* = LibCInstallation{
self.* = LibCInstallation.{
.include_dir = ([*]const u8)(undefined)[0..0],
.lib_dir = null,
.static_lib_dir = null,
@ -385,7 +385,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
defer loop.allocator.free(arg1);
const argv = []const []const u8{ cc_exe, arg1 };
const argv = []const []const u8.{ cc_exe, arg1 };
// TODO This simulates evented I/O for the child process exec
await (async loop.yield() catch unreachable);
@ -421,7 +421,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
}
}
const Search = struct {
const Search = struct.{
path: []const u8,
version: []const u8,
};
@ -430,7 +430,7 @@ 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| {
search_buf[search_end] = Search{
search_buf[search_end] = Search.{
.path = path10_ptr[0..sdk.path10_len],
.version = ver10_ptr[0..sdk.version10_len],
};
@ -439,7 +439,7 @@ fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
}
if (sdk.path81_ptr) |path81_ptr| {
if (sdk.version81_ptr) |ver81_ptr| {
search_buf[search_end] = Search{
search_buf[search_end] = Search.{
.path = path81_ptr[0..sdk.path81_len],
.version = ver81_ptr[0..sdk.version81_len],
};

View File

@ -8,13 +8,13 @@ const Target = @import("target.zig").Target;
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const assert = std.debug.assert;
const Context = struct {
const Context = struct.{
comp: *Compilation,
arena: std.heap.ArenaAllocator,
args: std.ArrayList([*]const u8),
link_in_crt: bool,
link_err: error{OutOfMemory}!void,
link_err: error.{OutOfMemory}!void,
link_msg: std.Buffer,
libc: *LibCInstallation,
@ -22,7 +22,7 @@ const Context = struct {
};
pub async fn link(comp: *Compilation) !void {
var ctx = Context{
var ctx = Context.{
.comp = comp,
.arena = std.heap.ArenaAllocator.init(comp.gpa()),
.args = undefined,
@ -330,7 +330,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
switch (ctx.comp.target.getArch()) {
builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),
builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
builtin.Arch.aarch64v8 => try ctx.args.append(c"-MACHINE:ARM"),
else => return error.UnsupportedLinkArchitecture,
}
@ -556,7 +556,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
}
},
DarwinPlatform.Kind.IPhoneOS => {
if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
if (ctx.comp.target.getArch() == builtin.Arch.aarch64v8) {
// iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) {
try ctx.args.append(c"-lcrt1.o");
@ -648,13 +648,13 @@ fn addFnObjects(ctx: *Context) !void {
}
}
const DarwinPlatform = struct {
const DarwinPlatform = struct.{
kind: Kind,
major: u32,
minor: u32,
micro: u32,
const Kind = enum {
const Kind = enum.{
MacOS,
IPhoneOS,
IPhoneOSSimulator,
@ -726,7 +726,7 @@ fn darwinGetReleaseVersion(str: []const u8, major: *u32, minor: *u32, micro: *u3
return error.InvalidDarwinVersionString;
var start_pos: usize = 0;
for ([]*u32{ major, minor, micro }) |v| {
for ([]*u32.{ major, minor, micro }) |v| {
const dot_pos = mem.indexOfScalarPos(u8, str, start_pos, '.');
const end_pos = dot_pos orelse str.len;
v.* = std.fmt.parseUnsigned(u32, str[start_pos..end_pos], 10) catch return error.InvalidDarwinVersionString;

View File

@ -183,7 +183,7 @@ pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;
pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;
pub const CallConv = c.LLVMCallConv;
pub const FnInline = extern enum {
pub const FnInline = extern enum.{
Auto,
Always,
Never,

View File

@ -21,8 +21,8 @@ const errmsg = @import("errmsg.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
var stderr_file: os.File = undefined;
var stderr: *io.OutStream(io.FileOutStream.Error) = undefined;
var stdout: *io.OutStream(io.FileOutStream.Error) = 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
@ -43,7 +43,7 @@ const usage =
\\
;
const Command = struct {
const Command = struct.{
name: []const u8,
exec: fn (*Allocator, []const []const u8) error!void,
};
@ -55,11 +55,11 @@ pub fn main() !void {
const allocator = std.heap.c_allocator;
var stdout_file = try std.io.getStdOut();
var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
var stdout_out_stream = stdout_file.outStream();
stdout = &stdout_out_stream.stream;
stderr_file = try std.io.getStdErr();
var stderr_out_stream = std.io.FileOutStream.init(stderr_file);
var stderr_out_stream = stderr_file.outStream();
stderr = &stderr_out_stream.stream;
const args = try os.argsAlloc(allocator);
@ -72,46 +72,46 @@ pub fn main() !void {
os.exit(1);
}
const commands = []Command{
Command{
const commands = []Command.{
Command.{
.name = "build-exe",
.exec = cmdBuildExe,
},
Command{
Command.{
.name = "build-lib",
.exec = cmdBuildLib,
},
Command{
Command.{
.name = "build-obj",
.exec = cmdBuildObj,
},
Command{
Command.{
.name = "fmt",
.exec = cmdFmt,
},
Command{
Command.{
.name = "libc",
.exec = cmdLibC,
},
Command{
Command.{
.name = "targets",
.exec = cmdTargets,
},
Command{
Command.{
.name = "version",
.exec = cmdVersion,
},
Command{
Command.{
.name = "zen",
.exec = cmdZen,
},
// undocumented commands
Command{
Command.{
.name = "help",
.exec = cmdHelp,
},
Command{
Command.{
.name = "internal",
.exec = cmdInternal,
},
@ -190,14 +190,14 @@ const usage_build_generic =
\\
;
const args_build_generic = []Flag{
const args_build_generic = []Flag.{
Flag.Bool("--help"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", []const []const u8.{
"auto",
"off",
"on",
}),
Flag.Option("--mode", []const []const u8{
Flag.Option("--mode", []const []const u8.{
"debug",
"release-fast",
"release-safe",
@ -205,7 +205,7 @@ const args_build_generic = []Flag{
}),
Flag.ArgMergeN("--assembly", 1),
Flag.Option("--emit", []const []const u8{
Flag.Option("--emit", []const []const u8.{
"asm",
"bin",
"llvm-ir",
@ -456,10 +456,10 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
}
if (flags.single("mmacosx-version-min")) |ver| {
comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
comp.darwin_version_min = Compilation.DarwinVersionMin.{ .MacOS = ver };
}
if (flags.single("mios-version-min")) |ver| {
comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
comp.darwin_version_min = Compilation.DarwinVersionMin.{ .Ios = ver };
}
comp.emit_file_type = emit_type;
@ -523,9 +523,9 @@ const usage_fmt =
\\
;
const args_fmt_spec = []Flag{
const args_fmt_spec = []Flag.{
Flag.Bool("--help"),
Flag.Option("--color", []const []const u8{
Flag.Option("--color", []const []const u8.{
"auto",
"off",
"on",
@ -533,7 +533,7 @@ const args_fmt_spec = []Flag{
Flag.Bool("--stdin"),
};
const Fmt = struct {
const Fmt = struct.{
seen: event.Locked(SeenMap),
any_error: bool,
color: errmsg.Color,
@ -619,7 +619,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
}
var stdin_file = try io.getStdIn();
var stdin = io.FileInStream.init(stdin_file);
var stdin = stdin_file.inStream();
const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size);
defer allocator.free(source_code);
@ -658,7 +658,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
const main_handle = try async<allocator> asyncFmtMainChecked(
&result,
&loop,
flags,
&flags,
color,
);
defer cancel main_handle;
@ -675,7 +675,7 @@ async fn asyncFmtMainChecked(
result.* = await (async asyncFmtMain(loop, flags, color) catch unreachable);
}
const FmtError = error{
const FmtError = error.{
SystemResources,
OperationAborted,
IoPending,
@ -704,7 +704,7 @@ async fn asyncFmtMain(
suspend {
resume @handle();
}
var fmt = Fmt{
var fmt = Fmt.{
.seen = event.Locked(Fmt.SeenMap).init(loop, Fmt.SeenMap.init(loop.allocator)),
.any_error = false,
.color = color,
@ -836,7 +836,7 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
try stdout.print("{}\n", std.cstr.toSliceConst(c.ZIG_VERSION_STRING));
}
const args_test_spec = []Flag{Flag.Bool("--help")};
const args_test_spec = []Flag.{Flag.Bool("--help")};
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(usage);
@ -878,7 +878,7 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
os.exit(1);
}
const sub_commands = []Command{Command{
const sub_commands = []Command.{Command.{
.name = "build-info",
.exec = cmdInternalBuildInfo,
}};
@ -917,14 +917,14 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
);
}
const CliPkg = struct {
const CliPkg = struct.{
name: []const u8,
path: []const u8,
children: ArrayList(*CliPkg),
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.{
.name = name,
.path = path,
.children = ArrayList(*CliPkg).init(allocator),

View File

@ -3,7 +3,7 @@ const mem = std.mem;
const assert = std.debug.assert;
const Buffer = std.Buffer;
pub const Package = struct {
pub const Package = struct.{
root_src_dir: Buffer,
root_src_path: Buffer,
@ -15,7 +15,7 @@ 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{
return allocator.create(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),

View File

@ -13,7 +13,7 @@ const assert = std.debug.assert;
const event = std.event;
const llvm = @import("llvm.zig");
pub const Scope = struct {
pub const Scope = struct.{
id: Id,
parent: ?*Scope,
ref_count: std.atomic.Int(usize),
@ -92,7 +92,7 @@ pub const Scope = struct {
}
fn init(base: *Scope, id: Id, parent: *Scope) void {
base.* = Scope{
base.* = Scope.{
.id = id,
.parent = parent,
.ref_count = std.atomic.Int(usize).init(1),
@ -100,7 +100,7 @@ pub const Scope = struct {
parent.ref();
}
pub const Id = enum {
pub const Id = enum.{
Root,
AstTree,
Decls,
@ -112,7 +112,7 @@ pub const Scope = struct {
Var,
};
pub const Root = struct {
pub const Root = struct.{
base: Scope,
realpath: []const u8,
decls: *Decls,
@ -121,8 +121,8 @@ pub const Scope = struct {
/// Takes ownership of realpath
pub fn create(comp: *Compilation, realpath: []u8) !*Root {
const self = try comp.gpa().createOne(Root);
self.* = Root{
.base = Scope{
self.* = Root.{
.base = Scope.{
.id = Id.Root,
.parent = null,
.ref_count = std.atomic.Int(usize).init(1),
@ -143,7 +143,7 @@ pub const Scope = struct {
}
};
pub const AstTree = struct {
pub const AstTree = struct.{
base: Scope,
tree: *ast.Tree,
@ -151,7 +151,7 @@ pub const Scope = struct {
/// 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);
self.* = AstTree{
self.* = AstTree.{
.base = undefined,
.tree = tree,
};
@ -172,7 +172,7 @@ pub const Scope = struct {
}
};
pub const Decls = struct {
pub const Decls = struct.{
base: Scope,
/// This table remains Write Locked when the names are incomplete or possibly outdated.
@ -183,7 +183,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);
self.* = Decls{
self.* = Decls.{
.base = undefined,
.table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
};
@ -197,7 +197,7 @@ pub const Scope = struct {
}
};
pub const Block = struct {
pub const Block = struct.{
base: Scope,
incoming_values: std.ArrayList(*ir.Inst),
incoming_blocks: std.ArrayList(*ir.BasicBlock),
@ -206,11 +206,11 @@ pub const Scope = struct {
safety: Safety,
const Safety = union(enum) {
const Safety = union(enum).{
Auto,
Manual: Manual,
const Manual = struct {
const Manual = struct.{
/// the source span that disabled the safety value
span: Span,
@ -236,7 +236,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);
self.* = Block{
self.* = Block.{
.base = undefined,
.incoming_values = undefined,
.incoming_blocks = undefined,
@ -253,7 +253,7 @@ pub const Scope = struct {
}
};
pub const FnDef = struct {
pub const FnDef = struct.{
base: Scope,
/// This reference is not counted so that the scope can get destroyed with the function
@ -263,7 +263,7 @@ pub const Scope = struct {
/// Must set the fn_val later
pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
const self = try comp.gpa().createOne(FnDef);
self.* = FnDef{
self.* = FnDef.{
.base = undefined,
.fn_val = null,
};
@ -276,13 +276,13 @@ pub const Scope = struct {
}
};
pub const CompTime = struct {
pub const CompTime = struct.{
base: Scope,
/// Creates a CompTime scope with 1 reference
pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
const self = try comp.gpa().createOne(CompTime);
self.* = CompTime{ .base = undefined };
self.* = CompTime.{ .base = undefined };
self.base.init(Id.CompTime, parent);
return self;
}
@ -292,12 +292,12 @@ pub const Scope = struct {
}
};
pub const Defer = struct {
pub const Defer = struct.{
base: Scope,
defer_expr_scope: *DeferExpr,
kind: Kind,
pub const Kind = enum {
pub const Kind = enum.{
ScopeExit,
ErrorExit,
};
@ -310,7 +310,7 @@ pub const Scope = struct {
defer_expr_scope: *DeferExpr,
) !*Defer {
const self = try comp.gpa().createOne(Defer);
self.* = Defer{
self.* = Defer.{
.base = undefined,
.defer_expr_scope = defer_expr_scope,
.kind = kind,
@ -326,7 +326,7 @@ pub const Scope = struct {
}
};
pub const DeferExpr = struct {
pub const DeferExpr = struct.{
base: Scope,
expr_node: *ast.Node,
reported_err: bool,
@ -334,7 +334,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);
self.* = DeferExpr{
self.* = DeferExpr.{
.base = undefined,
.expr_node = expr_node,
.reported_err = false,
@ -348,18 +348,18 @@ pub const Scope = struct {
}
};
pub const Var = struct {
pub const Var = struct.{
base: Scope,
name: []const u8,
src_node: *ast.Node,
data: Data,
pub const Data = union(enum) {
pub const Data = union(enum).{
Param: Param,
Const: *Value,
};
pub const Param = struct {
pub const Param = struct.{
index: usize,
typ: *Type,
llvm_value: llvm.ValueRef,
@ -374,8 +374,8 @@ pub const Scope = struct {
param_type: *Type,
) !*Var {
const self = try create(comp, parent, name, src_node);
self.data = Data{
.Param = Param{
self.data = Data.{
.Param = Param.{
.index = param_index,
.typ = param_type,
.llvm_value = undefined,
@ -392,14 +392,14 @@ pub const Scope = struct {
value: *Value,
) !*Var {
const self = try create(comp, parent, name, src_node);
self.data = Data{ .Const = value };
self.data = Data.{ .Const = value };
value.ref();
return self;
}
fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
const self = try comp.gpa().createOne(Var);
self.* = Var{
self.* = Var.{
.base = undefined,
.name = name,
.src_node = src_node,

View File

@ -3,17 +3,17 @@ const builtin = @import("builtin");
const llvm = @import("llvm.zig");
const CInt = @import("c_int.zig").CInt;
pub const FloatAbi = enum {
pub const FloatAbi = enum.{
Hard,
Soft,
SoftFp,
};
pub const Target = union(enum) {
pub const Target = union(enum).{
Native,
Cross: Cross,
pub const Cross = struct {
pub const Cross = struct.{
arch: builtin.Arch,
os: builtin.Os,
environ: builtin.Environ,
@ -250,8 +250,20 @@ pub const Target = union(enum) {
builtin.Arch.renderscript32,
=> return 32,
builtin.Arch.aarch64,
builtin.Arch.aarch64_be,
builtin.Arch.aarch64v8_3a,
builtin.Arch.aarch64v8_2a,
builtin.Arch.aarch64v8_1a,
builtin.Arch.aarch64v8,
builtin.Arch.aarch64v8r,
builtin.Arch.aarch64v8m_baseline,
builtin.Arch.aarch64v8m_mainline,
builtin.Arch.aarch64_bev8_3a,
builtin.Arch.aarch64_bev8_2a,
builtin.Arch.aarch64_bev8_1a,
builtin.Arch.aarch64_bev8,
builtin.Arch.aarch64_bev8r,
builtin.Arch.aarch64_bev8m_baseline,
builtin.Arch.aarch64_bev8m_mainline,
builtin.Arch.mips64,
builtin.Arch.mips64el,
builtin.Arch.powerpc64,
@ -316,8 +328,23 @@ pub const Target = union(enum) {
builtin.Arch.sparcel,
=> return "/lib/ld-linux.so.2",
builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
builtin.Arch.aarch64v8_3a,
builtin.Arch.aarch64v8_2a,
builtin.Arch.aarch64v8_1a,
builtin.Arch.aarch64v8,
builtin.Arch.aarch64v8r,
builtin.Arch.aarch64v8m_baseline,
builtin.Arch.aarch64v8m_mainline,
=> return "/lib/ld-linux-aarch64.so.1",
builtin.Arch.aarch64_bev8_3a,
builtin.Arch.aarch64_bev8_2a,
builtin.Arch.aarch64_bev8_1a,
builtin.Arch.aarch64_bev8,
builtin.Arch.aarch64_bev8r,
builtin.Arch.aarch64_bev8m_baseline,
builtin.Arch.aarch64_bev8m_mainline,
=> return "/lib/ld-linux-aarch64_be.so.1",
builtin.Arch.armv8_3a,
builtin.Arch.armv8_2a,
@ -530,7 +557,14 @@ pub const Target = union(enum) {
pub fn getDarwinArchString(self: Target) []const u8 {
const arch = self.getArch();
switch (arch) {
builtin.Arch.aarch64 => return "arm64",
builtin.Arch.aarch64v8_3a,
builtin.Arch.aarch64v8_2a,
builtin.Arch.aarch64v8_1a,
builtin.Arch.aarch64v8,
builtin.Arch.aarch64v8r,
builtin.Arch.aarch64v8m_baseline,
builtin.Arch.aarch64v8m_mainline,
=> return "arm64",
builtin.Arch.thumb,
builtin.Arch.armv8_3a,
builtin.Arch.armv8_2a,

View File

@ -23,7 +23,7 @@ test "stage2" {
const file1 = "1.zig";
const allocator = std.heap.c_allocator;
pub const TestContext = struct {
pub const TestContext = struct.{
loop: std.event.Loop,
zig_compiler: ZigCompiler,
zig_lib_dir: []u8,
@ -34,7 +34,7 @@ pub const TestContext = struct {
const tmp_dir_name = "stage2_test_tmp";
fn init(self: *TestContext) !void {
self.* = TestContext{
self.* = TestContext.{
.any_err = {},
.loop = undefined,
.zig_compiler = undefined,
@ -162,7 +162,7 @@ pub const TestContext = struct {
switch (build_event) {
Compilation.Event.Ok => {
const argv = []const []const u8{exe_file_2};
const argv = []const []const u8.{exe_file_2};
// TODO use event loop
const child = try std.os.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
switch (child.term) {

View File

@ -8,13 +8,13 @@ const event = std.event;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
pub const Type = struct {
pub const Type = struct.{
base: Value,
id: Id,
name: []const u8,
abi_alignment: AbiAlignment,
pub const AbiAlignment = event.Future(error{OutOfMemory}!u32);
pub const AbiAlignment = event.Future(error.{OutOfMemory}!u32);
pub const Id = builtin.TypeId;
@ -51,7 +51,7 @@ pub const Type = struct {
base: *Type,
allocator: *Allocator,
llvm_context: llvm.ContextRef,
) (error{OutOfMemory}!llvm.TypeRef) {
) (error.{OutOfMemory}!llvm.TypeRef) {
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),
@ -162,8 +162,8 @@ pub const Type = struct {
}
fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {
base.* = Type{
.base = Value{
base.* = Type.{
.base = Value.{
.id = Value.Id.Type,
.typ = &MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
@ -206,7 +206,7 @@ pub const Type = struct {
return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
}
pub const Struct = struct {
pub const Struct = struct.{
base: Type,
decls: *Scope.Decls,
@ -219,47 +219,47 @@ pub const Type = struct {
}
};
pub const Fn = struct {
pub const Fn = struct.{
base: Type,
key: Key,
non_key: NonKey,
garbage_node: std.atomic.Stack(*Fn).Node,
pub const Kind = enum {
pub const Kind = enum.{
Normal,
Generic,
};
pub const NonKey = union {
pub const NonKey = union.{
Normal: Normal,
Generic: void,
pub const Normal = struct {
pub const Normal = struct.{
variable_list: std.ArrayList(*Scope.Var),
};
};
pub const Key = struct {
pub const Key = struct.{
data: Data,
alignment: ?u32,
pub const Data = union(Kind) {
pub const Data = union(Kind).{
Generic: Generic,
Normal: Normal,
};
pub const Normal = struct {
pub const Normal = struct.{
params: []Param,
return_type: *Type,
is_var_args: bool,
cc: CallingConvention,
};
pub const Generic = struct {
pub const Generic = struct.{
param_count: usize,
cc: CC,
pub const CC = union(CallingConvention) {
pub const CC = union(CallingConvention).{
Auto,
C,
Cold,
@ -362,7 +362,7 @@ pub const Type = struct {
}
};
pub const CallingConvention = enum {
pub const CallingConvention = enum.{
Auto,
C,
Cold,
@ -371,7 +371,7 @@ pub const Type = struct {
Async,
};
pub const Param = struct {
pub const Param = struct.{
is_noalias: bool,
typ: *Type,
};
@ -410,7 +410,7 @@ pub const Type = struct {
errdefer key.deref(comp);
const self = try comp.gpa().createOne(Fn);
self.* = Fn{
self.* = Fn.{
.base = undefined,
.key = key,
.non_key = undefined,
@ -425,7 +425,7 @@ pub const Type = struct {
switch (key.data) {
Kind.Generic => |generic| {
self.non_key = NonKey{ .Generic = {} };
self.non_key = NonKey.{ .Generic = {} };
switch (generic.cc) {
CallingConvention.Async => |async_allocator_type| {
try name_stream.print("async<{}> ", async_allocator_type.name);
@ -448,8 +448,8 @@ pub const Type = struct {
try name_stream.write(" var");
},
Kind.Normal => |normal| {
self.non_key = NonKey{
.Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },
self.non_key = NonKey.{
.Normal = NonKey.Normal.{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },
};
const cc_str = ccFnTypeStr(normal.cc);
try name_stream.print("{}fn(", cc_str);
@ -513,7 +513,7 @@ pub const Type = struct {
}
};
pub const MetaType = struct {
pub const MetaType = struct.{
base: Type,
value: *Type,
@ -528,7 +528,7 @@ pub const Type = struct {
}
};
pub const Void = struct {
pub const Void = struct.{
base: Type,
/// Adds 1 reference to the resulting type
@ -542,7 +542,7 @@ pub const Type = struct {
}
};
pub const Bool = struct {
pub const Bool = struct.{
base: Type,
/// Adds 1 reference to the resulting type
@ -560,7 +560,7 @@ pub const Type = struct {
}
};
pub const NoReturn = struct {
pub const NoReturn = struct.{
base: Type,
/// Adds 1 reference to the resulting type
@ -574,12 +574,12 @@ pub const Type = struct {
}
};
pub const Int = struct {
pub const Int = struct.{
base: Type,
key: Key,
garbage_node: std.atomic.Stack(*Int).Node,
pub const Key = struct {
pub const Key = struct.{
bit_count: u32,
is_signed: bool,
@ -611,7 +611,7 @@ pub const Type = struct {
}
}
const self = try comp.gpa().create(Int{
const self = try comp.gpa().create(Int.{
.base = undefined,
.key = key,
.garbage_node = undefined,
@ -634,7 +634,7 @@ pub const Type = struct {
}
pub fn destroy(self: *Int, comp: *Compilation) void {
self.garbage_node = std.atomic.Stack(*Int).Node{
self.garbage_node = std.atomic.Stack(*Int).Node.{
.data = self,
.next = undefined,
};
@ -658,7 +658,7 @@ pub const Type = struct {
}
};
pub const Float = struct {
pub const Float = struct.{
base: Type,
pub fn destroy(self: *Float, comp: *Compilation) void {
@ -669,12 +669,12 @@ pub const Type = struct {
@panic("TODO");
}
};
pub const Pointer = struct {
pub const Pointer = struct.{
base: Type,
key: Key,
garbage_node: std.atomic.Stack(*Pointer).Node,
pub const Key = struct {
pub const Key = struct.{
child_type: *Type,
mut: Mut,
vol: Vol,
@ -710,17 +710,17 @@ pub const Type = struct {
}
};
pub const Mut = enum {
pub const Mut = enum.{
Mut,
Const,
};
pub const Vol = enum {
pub const Vol = enum.{
Non,
Volatile,
};
pub const Align = union(enum) {
pub const Align = union(enum).{
Abi,
Override: u32,
};
@ -728,7 +728,7 @@ pub const Type = struct {
pub const Size = builtin.TypeInfo.Pointer.Size;
pub fn destroy(self: *Pointer, comp: *Compilation) void {
self.garbage_node = std.atomic.Stack(*Pointer).Node{
self.garbage_node = std.atomic.Stack(*Pointer).Node.{
.data = self,
.next = undefined,
};
@ -777,7 +777,7 @@ pub const Type = struct {
}
}
const self = try comp.gpa().create(Pointer{
const self = try comp.gpa().create(Pointer.{
.base = undefined,
.key = normal_key,
.garbage_node = undefined,
@ -835,12 +835,12 @@ pub const Type = struct {
}
};
pub const Array = struct {
pub const Array = struct.{
base: Type,
key: Key,
garbage_node: std.atomic.Stack(*Array).Node,
pub const Key = struct {
pub const Key = struct.{
elem_type: *Type,
len: usize,
@ -875,7 +875,7 @@ pub const Type = struct {
}
}
const self = try comp.gpa().create(Array{
const self = try comp.gpa().create(Array.{
.base = undefined,
.key = key,
.garbage_node = undefined,
@ -902,7 +902,7 @@ pub const Type = struct {
}
};
pub const ComptimeFloat = struct {
pub const ComptimeFloat = struct.{
base: Type,
pub fn destroy(self: *ComptimeFloat, comp: *Compilation) void {
@ -910,7 +910,7 @@ pub const Type = struct {
}
};
pub const ComptimeInt = struct {
pub const ComptimeInt = struct.{
base: Type,
/// Adds 1 reference to the resulting type
@ -924,7 +924,7 @@ pub const Type = struct {
}
};
pub const Undefined = struct {
pub const Undefined = struct.{
base: Type,
pub fn destroy(self: *Undefined, comp: *Compilation) void {
@ -932,7 +932,7 @@ pub const Type = struct {
}
};
pub const Null = struct {
pub const Null = struct.{
base: Type,
pub fn destroy(self: *Null, comp: *Compilation) void {
@ -940,7 +940,7 @@ pub const Type = struct {
}
};
pub const Optional = struct {
pub const Optional = struct.{
base: Type,
pub fn destroy(self: *Optional, comp: *Compilation) void {
@ -952,7 +952,7 @@ pub const Type = struct {
}
};
pub const ErrorUnion = struct {
pub const ErrorUnion = struct.{
base: Type,
pub fn destroy(self: *ErrorUnion, comp: *Compilation) void {
@ -964,7 +964,7 @@ pub const Type = struct {
}
};
pub const ErrorSet = struct {
pub const ErrorSet = struct.{
base: Type,
pub fn destroy(self: *ErrorSet, comp: *Compilation) void {
@ -976,7 +976,7 @@ pub const Type = struct {
}
};
pub const Enum = struct {
pub const Enum = struct.{
base: Type,
pub fn destroy(self: *Enum, comp: *Compilation) void {
@ -988,7 +988,7 @@ pub const Type = struct {
}
};
pub const Union = struct {
pub const Union = struct.{
base: Type,
pub fn destroy(self: *Union, comp: *Compilation) void {
@ -1000,7 +1000,7 @@ pub const Type = struct {
}
};
pub const Namespace = struct {
pub const Namespace = struct.{
base: Type,
pub fn destroy(self: *Namespace, comp: *Compilation) void {
@ -1008,7 +1008,7 @@ pub const Type = struct {
}
};
pub const BoundFn = struct {
pub const BoundFn = struct.{
base: Type,
pub fn destroy(self: *BoundFn, comp: *Compilation) void {
@ -1020,7 +1020,7 @@ pub const Type = struct {
}
};
pub const ArgTuple = struct {
pub const ArgTuple = struct.{
base: Type,
pub fn destroy(self: *ArgTuple, comp: *Compilation) void {
@ -1028,7 +1028,7 @@ pub const Type = struct {
}
};
pub const Opaque = struct {
pub const Opaque = struct.{
base: Type,
pub fn destroy(self: *Opaque, comp: *Compilation) void {
@ -1040,7 +1040,7 @@ pub const Type = struct {
}
};
pub const Promise = struct {
pub const Promise = struct.{
base: Type,
pub fn destroy(self: *Promise, comp: *Compilation) void {
@ -1074,7 +1074,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
builtin.TypeId.Bool => {
comptime var rng = comptime std.rand.DefaultPrng.init(seed);
const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) };
const vals = comptime [2]u32.{ rng.random.scalar(u32), rng.random.scalar(u32) };
return vals[@boolToInt(x)];
},
builtin.TypeId.Optional => {

View File

@ -9,7 +9,7 @@ const assert = std.debug.assert;
/// Values are ref-counted, heap-allocated, and copy-on-write
/// If there is only 1 ref then write need not copy
pub const Value = struct {
pub const Value = struct.{
id: Id,
typ: *Type,
ref_count: std.atomic.Int(usize),
@ -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.ValueRef) {
switch (base.id) {
Id.Type => unreachable,
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
@ -71,7 +71,7 @@ pub const Value = struct {
}
}
pub fn derefAndCopy(self: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
pub fn derefAndCopy(self: *Value, comp: *Compilation) (error.{OutOfMemory}!*Value) {
if (self.ref_count.get() == 1) {
// ( ͡° ͜ʖ ͡°)
return self;
@ -81,7 +81,7 @@ pub const Value = struct {
return self.copy(comp);
}
pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
pub fn copy(base: *Value, comp: *Compilation) (error.{OutOfMemory}!*Value) {
switch (base.id) {
Id.Type => unreachable,
Id.Fn => unreachable,
@ -95,25 +95,25 @@ pub const Value = struct {
}
}
pub const Parent = union(enum) {
pub const Parent = union(enum).{
None,
BaseStruct: BaseStruct,
BaseArray: BaseArray,
BaseUnion: *Value,
BaseScalar: *Value,
pub const BaseStruct = struct {
pub const BaseStruct = struct.{
val: *Value,
field_index: usize,
};
pub const BaseArray = struct {
pub const BaseArray = struct.{
val: *Value,
elem_index: usize,
};
};
pub const Id = enum {
pub const Id = enum.{
Type,
Fn,
Void,
@ -127,7 +127,7 @@ pub const Value = struct {
pub const Type = @import("type.zig").Type;
pub const FnProto = struct {
pub const FnProto = struct.{
base: Value,
/// The main external name that is used in the .o file.
@ -135,8 +135,8 @@ 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{
.base = Value{
const self = try comp.gpa().create(FnProto.{
.base = Value.{
.id = Value.Id.FnProto,
.typ = &fn_type.base,
.ref_count = std.atomic.Int(usize).init(1),
@ -166,7 +166,7 @@ pub const Value = struct {
}
};
pub const Fn = struct {
pub const Fn = struct.{
base: Value,
/// The main external name that is used in the .o file.
@ -190,15 +190,15 @@ 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.{
.data = null,
.next = undefined,
.prev = undefined,
});
errdefer comp.gpa().destroy(link_set_node);
const self = try comp.gpa().create(Fn{
.base = Value{
const self = try comp.gpa().create(Fn.{
.base = Value.{
.id = Value.Id.Fn,
.typ = &fn_type.base,
.ref_count = std.atomic.Int(usize).init(1),
@ -249,7 +249,7 @@ pub const Value = struct {
}
};
pub const Void = struct {
pub const Void = struct.{
base: Value,
pub fn get(comp: *Compilation) *Void {
@ -262,7 +262,7 @@ pub const Value = struct {
}
};
pub const Bool = struct {
pub const Bool = struct.{
base: Value,
x: bool,
@ -290,7 +290,7 @@ pub const Value = struct {
}
};
pub const NoReturn = struct {
pub const NoReturn = struct.{
base: Value,
pub fn get(comp: *Compilation) *NoReturn {
@ -303,18 +303,18 @@ pub const Value = struct {
}
};
pub const Ptr = struct {
pub const Ptr = struct.{
base: Value,
special: Special,
mut: Mut,
pub const Mut = enum {
pub const Mut = enum.{
CompTimeConst,
CompTimeVar,
RunTime,
};
pub const Special = union(enum) {
pub const Special = union(enum).{
Scalar: *Value,
BaseArray: BaseArray,
BaseStruct: BaseStruct,
@ -322,12 +322,12 @@ pub const Value = struct {
Discard,
};
pub const BaseArray = struct {
pub const BaseArray = struct.{
val: *Value,
elem_index: usize,
};
pub const BaseStruct = struct {
pub const BaseStruct = struct.{
val: *Value,
field_index: usize,
};
@ -343,7 +343,7 @@ pub const Value = struct {
errdefer array_val.base.deref(comp);
const elem_type = array_val.base.typ.cast(Type.Array).?.key.elem_type;
const ptr_type = try await (async Type.Pointer.get(comp, Type.Pointer.Key{
const ptr_type = try await (async Type.Pointer.get(comp, Type.Pointer.Key.{
.child_type = elem_type,
.mut = mut,
.vol = Type.Pointer.Vol.Non,
@ -353,14 +353,14 @@ 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{
.base = Value{
const self = try comp.gpa().create(Value.Ptr.{
.base = Value.{
.id = Value.Id.Ptr,
.typ = &ptr_type.base,
.ref_count = std.atomic.Int(usize).init(1),
},
.special = Special{
.BaseArray = BaseArray{
.special = Special.{
.BaseArray = BaseArray.{
.val = &array_val.base,
.elem_index = 0,
},
@ -387,7 +387,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.ValueRef.{
llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
};
@ -404,17 +404,17 @@ pub const Value = struct {
}
};
pub const Array = struct {
pub const Array = struct.{
base: Value,
special: Special,
pub const Special = union(enum) {
pub const Special = union(enum).{
Undefined,
OwnedBuffer: []u8,
Explicit: Data,
};
pub const Data = struct {
pub const Data = struct.{
parent: Parent,
elements: []*Value,
};
@ -424,19 +424,19 @@ pub const Value = struct {
const u8_type = Type.Int.get_u8(comp);
defer u8_type.base.base.deref(comp);
const array_type = try await (async Type.Array.get(comp, Type.Array.Key{
const array_type = try await (async Type.Array.get(comp, Type.Array.Key.{
.elem_type = &u8_type.base,
.len = buffer.len,
}) catch unreachable);
errdefer array_type.base.base.deref(comp);
const self = try comp.gpa().create(Value.Array{
.base = Value{
const self = try comp.gpa().create(Value.Array.{
.base = Value.{
.id = Value.Id.Array,
.typ = &array_type.base,
.ref_count = std.atomic.Int(usize).init(1),
},
.special = Special{ .OwnedBuffer = buffer },
.special = Special.{ .OwnedBuffer = buffer },
});
errdefer comp.gpa().destroy(self);
@ -504,13 +504,13 @@ pub const Value = struct {
}
};
pub const Int = struct {
pub const Int = struct.{
base: Value,
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{
.base = Value{
const self = try comp.gpa().create(Value.Int.{
.base = Value.{
.id = Value.Id.Int,
.typ = typ,
.ref_count = std.atomic.Int(usize).init(1),
@ -557,8 +557,8 @@ pub const Value = struct {
old.base.typ.base.ref();
errdefer old.base.typ.base.deref(comp);
const new = try comp.gpa().create(Value.Int{
.base = Value{
const new = try comp.gpa().create(Value.Int.{
.base = Value.{
.id = Value.Id.Int,
.typ = old.base.typ,
.ref_count = std.atomic.Int(usize).init(1),

View File

@ -1,4 +1,4 @@
pub const Visib = enum {
pub const Visib = enum.{
Private,
Pub,
};

View File

@ -130,14 +130,18 @@ struct ConstUnionValue {
enum ConstArraySpecial {
ConstArraySpecialNone,
ConstArraySpecialUndef,
ConstArraySpecialBuf,
};
struct ConstArrayValue {
ConstArraySpecial special;
union {
struct {
ConstExprValue *elements;
ConstParent parent;
} s_none;
Buf *s_buf;
} data;
};
enum ConstPtrSpecial {
@ -660,7 +664,7 @@ struct AstNodePointerType {
Token *star_token;
AstNode *align_expr;
BigInt *bit_offset_start;
BigInt *bit_offset_end;
BigInt *host_int_bytes;
bool is_const;
bool is_volatile;
AstNode *op_expr;
@ -983,6 +987,7 @@ struct FnTypeParamInfo {
};
struct GenericFnTypeId {
CodeGen *codegen;
ZigFn *fn_entry;
ConstExprValue *params;
size_t param_count;
@ -1015,8 +1020,8 @@ struct ZigTypePointer {
ZigType *slice_parent;
PtrLen ptr_len;
uint32_t explicit_alignment; // 0 means use ABI alignment
uint32_t bit_offset;
uint32_t unaligned_bit_count;
uint32_t bit_offset_in_host;
uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
bool is_const;
bool is_volatile;
};
@ -1040,10 +1045,7 @@ struct TypeStructField {
ZigType *type_entry;
size_t src_index;
size_t gen_index;
// offset from the memory at gen_index
size_t packed_bits_offset;
size_t packed_bits_size;
size_t unaligned_bit_count;
uint32_t bit_offset_in_host; // offset from the memory at gen_index
AstNode *decl_node;
};
@ -1291,6 +1293,7 @@ struct FnExport {
};
struct ZigFn {
CodeGen *codegen;
LLVMValueRef llvm_value;
const char *llvm_name;
AstNode *proto_node;
@ -1340,8 +1343,6 @@ enum BuiltinFnId {
BuiltinFnIdMemset,
BuiltinFnIdSizeof,
BuiltinFnIdAlignOf,
BuiltinFnIdMaxValue,
BuiltinFnIdMinValue,
BuiltinFnIdMemberCount,
BuiltinFnIdMemberType,
BuiltinFnIdMemberName,
@ -1403,7 +1404,8 @@ enum BuiltinFnId {
BuiltinFnIdTagName,
BuiltinFnIdTagType,
BuiltinFnIdFieldParentPtr,
BuiltinFnIdOffsetOf,
BuiltinFnIdByteOffsetOf,
BuiltinFnIdBitOffsetOf,
BuiltinFnIdInlineCall,
BuiltinFnIdNoInlineCall,
BuiltinFnIdNewStackCall,
@ -1463,8 +1465,8 @@ struct TypeId {
bool is_const;
bool is_volatile;
uint32_t alignment;
uint32_t bit_offset;
uint32_t unaligned_bit_count;
uint32_t bit_offset_in_host;
uint32_t host_int_bytes;
} pointer;
struct {
ZigType *child_type;
@ -1686,6 +1688,7 @@ struct CodeGen {
Buf cache_dir;
IrInstruction *invalid_instruction;
IrInstruction *unreach_instruction;
ConstExprValue const_void_val;
ConstExprValue panic_msg_vals[PanicMsgIdCount];
@ -1709,7 +1712,6 @@ struct CodeGen {
uint32_t target_environ_index;
uint32_t target_oformat_index;
bool is_big_endian;
bool want_h_file;
bool have_pub_main;
bool have_c_main;
bool have_winmain;
@ -1729,6 +1731,7 @@ struct CodeGen {
bool generate_error_name_table;
bool enable_cache;
bool enable_time_report;
bool system_linker_hack;
//////////////////////////// Participates in Input Parameter Cache Hash
ZigList<LinkLib *> link_libs_list;
@ -1759,6 +1762,7 @@ struct CodeGen {
bool linker_rdynamic;
bool no_rosegment_workaround;
bool each_lib_rpath;
bool disable_pic;
Buf *mmacosx_version_min;
Buf *mios_version_min;
@ -1848,13 +1852,14 @@ enum ScopeId {
};
struct Scope {
ScopeId id;
CodeGen *codegen;
AstNode *source_node;
// if the scope has a parent, this is it
Scope *parent;
ZigLLVMDIScope *di_scope;
ScopeId id;
};
// This scope comes from global declarations or from
@ -2075,8 +2080,6 @@ enum IrInstructionId {
IrInstructionIdCUndef,
IrInstructionIdArrayLen,
IrInstructionIdRef,
IrInstructionIdMinValue,
IrInstructionIdMaxValue,
IrInstructionIdCompileErr,
IrInstructionIdCompileLog,
IrInstructionIdErrName,
@ -2127,7 +2130,8 @@ enum IrInstructionId {
IrInstructionIdTagName,
IrInstructionIdTagType,
IrInstructionIdFieldParentPtr,
IrInstructionIdOffsetOf,
IrInstructionIdByteOffsetOf,
IrInstructionIdBitOffsetOf,
IrInstructionIdTypeInfo,
IrInstructionIdTypeId,
IrInstructionIdSetEvalBranchQuota,
@ -2178,7 +2182,10 @@ struct IrInstruction {
// if ref_count is zero and the instruction has no side effects,
// the instruction can be omitted in codegen
size_t ref_count;
IrInstruction *other;
// When analyzing IR, instructions that point to this instruction in the "old ir"
// can find the instruction that corresponds to this value in the "new ir"
// with this child field.
IrInstruction *child;
IrBasicBlock *owner_bb;
// true if this instruction was generated by zig and not from user code
bool is_gen;
@ -2501,7 +2508,7 @@ struct IrInstructionPtrType {
IrInstruction *align_value;
IrInstruction *child_type;
uint32_t bit_offset_start;
uint32_t bit_offset_end;
uint32_t host_int_bytes;
PtrLen ptr_len;
bool is_const;
bool is_volatile;
@ -2599,18 +2606,6 @@ struct IrInstructionRef {
bool is_volatile;
};
struct IrInstructionMinValue {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionMaxValue {
IrInstruction base;
IrInstruction *value;
};
struct IrInstructionCompileErr {
IrInstruction base;
@ -3030,7 +3025,14 @@ struct IrInstructionFieldParentPtr {
TypeStructField *field;
};
struct IrInstructionOffsetOf {
struct IrInstructionByteOffsetOf {
IrInstruction base;
IrInstruction *type_value;
IrInstruction *field_name;
};
struct IrInstructionBitOffsetOf {
IrInstruction base;
IrInstruction *type_value;

View File

@ -92,62 +92,63 @@ ScopeDecls *get_container_scope(ZigType *type_entry) {
return *get_container_scope_ptr(type_entry);
}
void init_scope(Scope *dest, ScopeId id, AstNode *source_node, Scope *parent) {
void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope *parent) {
dest->codegen = g;
dest->id = id;
dest->source_node = source_node;
dest->parent = parent;
}
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import) {
ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import) {
assert(node == nullptr || node->type == NodeTypeRoot || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr);
ScopeDecls *scope = allocate<ScopeDecls>(1);
init_scope(&scope->base, ScopeIdDecls, node, parent);
init_scope(g, &scope->base, ScopeIdDecls, node, parent);
scope->decl_table.init(4);
scope->container_type = container_type;
scope->import = import;
return scope;
}
ScopeBlock *create_block_scope(AstNode *node, Scope *parent) {
ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeBlock);
ScopeBlock *scope = allocate<ScopeBlock>(1);
init_scope(&scope->base, ScopeIdBlock, node, parent);
init_scope(g, &scope->base, ScopeIdBlock, node, parent);
scope->name = node->data.block.name;
return scope;
}
ScopeDefer *create_defer_scope(AstNode *node, Scope *parent) {
ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeDefer);
ScopeDefer *scope = allocate<ScopeDefer>(1);
init_scope(&scope->base, ScopeIdDefer, node, parent);
init_scope(g, &scope->base, ScopeIdDefer, node, parent);
return scope;
}
ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent) {
ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeDefer);
ScopeDeferExpr *scope = allocate<ScopeDeferExpr>(1);
init_scope(&scope->base, ScopeIdDeferExpr, node, parent);
init_scope(g, &scope->base, ScopeIdDeferExpr, node, parent);
return scope;
}
Scope *create_var_scope(AstNode *node, Scope *parent, ZigVar *var) {
Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var) {
ScopeVarDecl *scope = allocate<ScopeVarDecl>(1);
init_scope(&scope->base, ScopeIdVarDecl, node, parent);
init_scope(g, &scope->base, ScopeIdVarDecl, node, parent);
scope->var = var;
return &scope->base;
}
ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent) {
ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeFnCallExpr);
ScopeCImport *scope = allocate<ScopeCImport>(1);
init_scope(&scope->base, ScopeIdCImport, node, parent);
init_scope(g, &scope->base, ScopeIdCImport, node, parent);
buf_resize(&scope->buf, 0);
return scope;
}
ScopeLoop *create_loop_scope(AstNode *node, Scope *parent) {
ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent) {
ScopeLoop *scope = allocate<ScopeLoop>(1);
init_scope(&scope->base, ScopeIdLoop, node, parent);
init_scope(g, &scope->base, ScopeIdLoop, node, parent);
if (node->type == NodeTypeWhileExpr) {
scope->name = node->data.while_expr.name;
} else if (node->type == NodeTypeForExpr) {
@ -158,37 +159,37 @@ ScopeLoop *create_loop_scope(AstNode *node, Scope *parent) {
return scope;
}
Scope *create_runtime_scope(AstNode *node, Scope *parent, IrInstruction *is_comptime) {
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime) {
ScopeRuntime *scope = allocate<ScopeRuntime>(1);
scope->is_comptime = is_comptime;
init_scope(&scope->base, ScopeIdRuntime, node, parent);
init_scope(g, &scope->base, ScopeIdRuntime, node, parent);
return &scope->base;
}
ScopeSuspend *create_suspend_scope(AstNode *node, Scope *parent) {
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeSuspend);
ScopeSuspend *scope = allocate<ScopeSuspend>(1);
init_scope(&scope->base, ScopeIdSuspend, node, parent);
init_scope(g, &scope->base, ScopeIdSuspend, node, parent);
return scope;
}
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, ZigFn *fn_entry) {
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry) {
ScopeFnDef *scope = allocate<ScopeFnDef>(1);
init_scope(&scope->base, ScopeIdFnDef, node, parent);
init_scope(g, &scope->base, ScopeIdFnDef, node, parent);
scope->fn_entry = fn_entry;
return scope;
}
Scope *create_comptime_scope(AstNode *node, Scope *parent) {
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {
assert(node->type == NodeTypeCompTime || node->type == NodeTypeSwitchExpr);
ScopeCompTime *scope = allocate<ScopeCompTime>(1);
init_scope(&scope->base, ScopeIdCompTime, node, parent);
init_scope(g, &scope->base, ScopeIdCompTime, node, parent);
return &scope->base;
}
Scope *create_coro_prelude_scope(AstNode *node, Scope *parent) {
Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent) {
ScopeCoroPrelude *scope = allocate<ScopeCoroPrelude>(1);
init_scope(&scope->base, ScopeIdCoroPrelude, node, parent);
init_scope(g, &scope->base, ScopeIdCoroPrelude, node, parent);
return &scope->base;
}
@ -204,9 +205,9 @@ ImportTableEntry *get_scope_import(Scope *scope) {
zig_unreachable();
}
static ZigType *new_container_type_entry(ZigTypeId id, AstNode *source_node, Scope *parent_scope) {
static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *source_node, Scope *parent_scope) {
ZigType *entry = new_type_table_entry(id);
*get_container_scope_ptr(entry) = create_decls_scope(source_node, parent_scope, entry, get_scope_import(parent_scope));
*get_container_scope_ptr(entry) = create_decls_scope(g, source_node, parent_scope, entry, get_scope_import(parent_scope));
return entry;
}
@ -418,7 +419,7 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
}
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)
{
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
@ -429,23 +430,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
byte_alignment = 0;
}
if (host_int_bytes != 0) {
uint32_t child_type_bits = type_size_bits(g, child_type);
if (host_int_bytes * 8 == child_type_bits) {
assert(bit_offset_in_host == 0);
host_int_bytes = 0;
}
}
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
type_id.data.pointer.is_volatile = is_volatile;
type_id.data.pointer.alignment = byte_alignment;
type_id.data.pointer.bit_offset = bit_offset;
type_id.data.pointer.unaligned_bit_count = unaligned_bit_count;
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;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
return existing_entry->value;
} else {
assert(bit_offset == 0);
assert(bit_offset_in_host == 0);
parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
if (*parent_pointer) {
assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
@ -462,17 +471,17 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
buf_resize(&entry->name, 0);
if (unaligned_bit_count == 0 && byte_alignment == 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));
} else if (unaligned_bit_count == 0) {
} 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));
} else if (byte_alignment == 0) {
buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
} else {
buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
}
assert(child_type->id != ZigTypeIdInvalid);
@ -480,20 +489,27 @@ 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 || unaligned_bit_count != 0 || byte_alignment != 0 ||
ptr_len != PtrLenSingle)
{
ZigType *peer_type = get_pointer_to_type(g, child_type, false);
if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
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;
entry->di_type = peer_type->di_type;
} else {
if (host_int_bytes == 0) {
entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref);
assert(child_type->di_type);
entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type,
debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
} else {
ZigType *host_int_type = get_int_type(g, false, host_int_bytes * 8);
entry->type_ref = LLVMPointerType(host_int_type->type_ref, 0);
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, host_int_type->type_ref);
uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, host_int_type->type_ref);
entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, host_int_type->di_type,
debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name));
}
}
} else {
assert(byte_alignment == 0);
@ -505,8 +521,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.is_const = is_const;
entry->data.pointer.is_volatile = is_volatile;
entry->data.pointer.explicit_alignment = byte_alignment;
entry->data.pointer.bit_offset = bit_offset;
entry->data.pointer.unaligned_bit_count = unaligned_bit_count;
entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
entry->data.pointer.host_int_bytes = host_int_bytes;
if (parent_pointer) {
*parent_pointer = entry;
@ -657,7 +673,7 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion);
entry->is_copyable = true;
assert(payload_type->di_type);
assertNoError(ensure_complete_type(g, payload_type));
assert(type_is_complete(payload_type));
buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name));
@ -1042,7 +1058,10 @@ ZigType *get_ptr_to_stack_trace_type(CodeGen *g) {
if (g->stack_trace_type == nullptr) {
ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");
assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
g->stack_trace_type = stack_trace_type_val->data.x_type;
assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false);
}
return g->ptr_to_stack_trace_type;
@ -1065,6 +1084,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
}
zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
buf_ptr(&fn_type_id->return_type->name));
} else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) {
return type_size(g, fn_type_id->return_type) > 16;
}
zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
}
@ -1183,11 +1204,14 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
gen_param_info->src_index = i;
gen_param_info->gen_index = SIZE_MAX;
if ((err = ensure_complete_type(g, type_entry)))
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return g->builtin_types.entry_invalid;
if (is_c_abi)
if (is_c_abi) {
if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown)))
return g->builtin_types.entry_invalid;
continue;
}
if (type_has_bits(type_entry)) {
ZigType *gen_type;
@ -1245,7 +1269,7 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
AstNode *decl_node, const char *name, ContainerLayout layout)
{
ZigTypeId type_id = container_to_type(kind);
ZigType *entry = new_container_type_entry(type_id, decl_node, scope);
ZigType *entry = new_container_type_entry(g, type_id, decl_node, scope);
switch (kind) {
case ContainerKindStruct:
@ -1372,13 +1396,17 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
if (array_val->data.x_array.special == ConstArraySpecialBuf) {
*out_buffer = array_val->data.x_array.data.s_buf;
return true;
}
expand_undef_array(g, array_val);
size_t len = bigint_as_unsigned(&len_field->data.x_bigint);
Buf *result = buf_alloc();
buf_resize(result, len);
for (size_t i = 0; i < len; i += 1) {
size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i;
ConstExprValue *char_val = &array_val->data.x_array.s_none.elements[new_index];
ConstExprValue *char_val = &array_val->data.x_array.data.s_none.elements[new_index];
if (char_val->special == ConstValSpecialUndef) {
add_node_error(g, node, buf_sprintf("use of undefined value"));
return false;
@ -1661,6 +1689,8 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
if (fn_proto->auto_err_set) {
ZigType *inferred_err_set_type = get_auto_err_set_type(g, fn_entry);
if ((err = type_resolve(g, specified_return_type, ResolveStatusSizeKnown)))
return g->builtin_types.entry_invalid;
fn_type_id.return_type = get_error_union_type(g, inferred_err_set_type, specified_return_type);
} else {
fn_type_id.return_type = specified_return_type;
@ -1999,12 +2029,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
size_t field_size_in_bits = type_size_bits(g, field_type);
size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits;
type_struct_field->packed_bits_size = field_size_in_bits;
if (first_packed_bits_offset_misalign != SIZE_MAX) {
// this field is not byte-aligned; it is part of the previous field with a bit offset
type_struct_field->packed_bits_offset = packed_bits_offset - first_packed_bits_offset_misalign;
type_struct_field->unaligned_bit_count = field_size_in_bits;
type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign;
size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign;
LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count));
@ -2017,13 +2044,11 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
}
} else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) {
first_packed_bits_offset_misalign = packed_bits_offset;
type_struct_field->packed_bits_offset = 0;
type_struct_field->unaligned_bit_count = field_size_in_bits;
type_struct_field->bit_offset_in_host = 0;
} else {
// This is a byte-aligned field (both start and end) in a packed struct.
element_types[gen_field_index] = field_type->type_ref;
type_struct_field->packed_bits_offset = 0;
type_struct_field->unaligned_bit_count = 0;
type_struct_field->bit_offset_in_host = 0;
gen_field_index += 1;
}
packed_bits_offset = next_packed_bits_offset;
@ -2116,10 +2141,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
uint64_t debug_align_in_bits;
uint64_t debug_offset_in_bits;
if (packed) {
debug_size_in_bits = type_struct_field->packed_bits_size;
debug_size_in_bits = type_size_bits(g, type_struct_field->type_entry);
debug_align_in_bits = 1;
debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref,
(unsigned)gen_field_index) + type_struct_field->packed_bits_offset;
(unsigned)gen_field_index) + type_struct_field->bit_offset_in_host;
} else {
debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref);
debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref);
@ -2690,6 +2715,11 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
// be resolving ResolveStatusZeroBitsKnown
assert(field->type_entry != nullptr);
if (type_is_invalid(field->type_entry)) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
if (!type_has_bits(field->type_entry))
continue;
@ -3093,9 +3123,10 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) {
buf_append_buf(buf, tld->name);
}
ZigFn *create_fn_raw(FnInline inline_value) {
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value) {
ZigFn *fn_entry = allocate<ZigFn>(1);
fn_entry->codegen = g;
fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
fn_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota;
fn_entry->analyzed_executable.fn_entry = fn_entry;
@ -3105,12 +3136,12 @@ ZigFn *create_fn_raw(FnInline inline_value) {
return fn_entry;
}
ZigFn *create_fn(AstNode *proto_node) {
ZigFn *create_fn(CodeGen *g, AstNode *proto_node) {
assert(proto_node->type == NodeTypeFnProto);
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto;
ZigFn *fn_entry = create_fn_raw(inline_value);
ZigFn *fn_entry = create_fn_raw(g, inline_value);
fn_entry->proto_node = proto_node;
fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
@ -3209,7 +3240,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
AstNode *fn_def_node = fn_proto->fn_def_node;
ZigFn *fn_table_entry = create_fn(source_node);
ZigFn *fn_table_entry = create_fn(g, source_node);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
if (fn_proto->is_export) {
@ -3220,7 +3251,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
tld_fn->fn_entry = fn_table_entry;
if (fn_table_entry->body_node) {
fn_table_entry->fndef_scope = create_fndef_scope(
fn_table_entry->fndef_scope = create_fndef_scope(g,
fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry);
for (size_t i = 0; i < fn_proto->params.length; i += 1) {
@ -3270,14 +3301,14 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
}
}
} else if (source_node->type == NodeTypeTestDecl) {
ZigFn *fn_table_entry = create_fn_raw(FnInlineAuto);
ZigFn *fn_table_entry = create_fn_raw(g, FnInlineAuto);
get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
tld_fn->fn_entry = fn_table_entry;
fn_table_entry->proto_node = source_node;
fn_table_entry->fndef_scope = create_fndef_scope(source_node, tld_fn->base.parent_scope, fn_table_entry);
fn_table_entry->fndef_scope = create_fndef_scope(g, source_node, tld_fn->base.parent_scope, fn_table_entry);
fn_table_entry->type_entry = get_test_fn_type(g);
fn_table_entry->body_node = source_node->data.test_decl.body;
fn_table_entry->is_test = true;
@ -3557,6 +3588,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
bool is_const, ConstExprValue *value, Tld *src_tld)
{
Error err;
assert(value);
ZigVar *variable_entry = allocate<ZigVar>(1);
@ -3569,7 +3601,9 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
assert(name);
buf_init_from_buf(&variable_entry->name, name);
if (!type_is_invalid(value->type)) {
if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
variable_entry->value->type = g->builtin_types.entry_invalid;
} else {
variable_entry->align_bytes = get_abi_alignment(g, value->type);
ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
@ -3606,7 +3640,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
Scope *child_scope;
if (source_node && source_node->type == NodeTypeParamDecl) {
child_scope = create_var_scope(source_node, parent_scope, variable_entry);
child_scope = create_var_scope(g, source_node, parent_scope, variable_entry);
} else {
// it's already in the decls table
child_scope = parent_scope;
@ -4329,7 +4363,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
g->import_table.put(resolved_path, import_entry);
g->import_queue.append(import_entry);
import_entry->decls_scope = create_decls_scope(import_entry->root, nullptr, nullptr, import_entry);
import_entry->decls_scope = create_decls_scope(g, import_entry->root, nullptr, nullptr, import_entry);
assert(import_entry->root->type == NodeTypeRoot);
@ -4458,7 +4492,7 @@ bool handle_is_ptr(ZigType *type_entry) {
return type_has_bits(type_entry->data.maybe.child_type) &&
!type_is_codegen_pointer(type_entry->data.maybe.child_type);
case ZigTypeIdUnion:
assert(type_entry->data.unionation.complete);
assert(type_entry->data.unionation.zero_bits_known);
if (type_entry->data.unionation.gen_field_count == 0)
return false;
if (!type_has_bits(type_entry))
@ -4880,7 +4914,7 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
if (a_val->special != ConstValSpecialRuntime && b_val->special != ConstValSpecialRuntime) {
assert(a_val->special == ConstValSpecialStatic);
assert(b_val->special == ConstValSpecialStatic);
if (!const_values_equal(a_val, b_val)) {
if (!const_values_equal(a->fn_entry->codegen, a_val, b_val)) {
return false;
}
} else {
@ -4920,14 +4954,18 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case ZigTypeIdArray:
if (value->type->data.array.len == 0)
return false;
if (value->data.x_array.special == ConstArraySpecialUndef)
switch (value->data.x_array.special) {
case ConstArraySpecialUndef:
case ConstArraySpecialBuf:
return false;
case ConstArraySpecialNone:
for (uint32_t i = 0; i < value->type->data.array.len; i += 1) {
if (can_mutate_comptime_var_state(&value->data.x_array.s_none.elements[i]))
if (can_mutate_comptime_var_state(&value->data.x_array.data.s_none.elements[i]))
return true;
}
return false;
}
zig_unreachable();
case ZigTypeIdStruct:
for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) {
if (can_mutate_comptime_var_state(&value->data.x_struct.fields[i]))
@ -5039,6 +5077,8 @@ uint32_t fn_eval_hash(Scope* scope) {
}
bool fn_eval_eql(Scope *a, Scope *b) {
assert(a->codegen != nullptr);
assert(b->codegen != nullptr);
while (a && b) {
if (a->id != b->id)
return false;
@ -5048,7 +5088,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
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_var_scope->var->value, b_var_scope->var->value))
if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
return false;
} else if (a->id == ScopeIdFnDef) {
ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
@ -5130,14 +5170,8 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
const_val->special = ConstValSpecialStatic;
const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
const_val->data.x_array.s_none.elements = create_const_vals(buf_len(str));
for (size_t i = 0; i < buf_len(str); i += 1) {
ConstExprValue *this_char = &const_val->data.x_array.s_none.elements[i];
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
}
const_val->data.x_array.special = ConstArraySpecialBuf;
const_val->data.x_array.data.s_buf = str;
g->string_literals_table.put(str, const_val);
}
@ -5154,14 +5188,15 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
array_val->data.x_array.s_none.elements = create_const_vals(len_with_null);
// TODO buf optimization
array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);
for (size_t i = 0; i < buf_len(str); i += 1) {
ConstExprValue *this_char = &array_val->data.x_array.s_none.elements[i];
ConstExprValue *this_char = &array_val->data.x_array.data.s_none.elements[i];
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
}
ConstExprValue *null_char = &array_val->data.x_array.s_none.elements[len_with_null - 1];
ConstExprValue *null_char = &array_val->data.x_array.data.s_none.elements[len_with_null - 1];
null_char->special = ConstValSpecialStatic;
null_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&null_char->data.x_bigint, 0);
@ -5482,10 +5517,19 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
}
bool ir_get_var_is_comptime(ZigVar *var) {
if (!var->is_comptime)
// The is_comptime field can be left null, which means not comptime.
if (var->is_comptime == nullptr)
return false;
if (var->is_comptime->other)
return var->is_comptime->other->value.data.x_bool;
// When the is_comptime field references an instruction that has to get analyzed, this
// is the value.
if (var->is_comptime->child != nullptr) {
assert(var->is_comptime->child->value.type->id == ZigTypeIdBool);
return var->is_comptime->child->value.data.x_bool;
}
// As an optimization, is_comptime values which are constant are allowed
// to be omitted from analysis. In this case, there is no child instruction
// and we simply look at the unanalyzed const parent instruction.
assert(var->is_comptime->value.type->id == ZigTypeIdBool);
return var->is_comptime->value.data.x_bool;
}
@ -5535,7 +5579,7 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
zig_unreachable();
}
bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
assert(a->type->id == b->type->id);
assert(a->special == ConstValSpecialStatic);
assert(b->special == ConstValSpecialStatic);
@ -5593,13 +5637,20 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
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.s_none.elements;
ConstExprValue *b_elems = b->data.x_array.s_none.elements;
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(&a_elems[i], &b_elems[i]))
if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
return false;
}
@ -5609,7 +5660,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
ConstExprValue *field_a = &a->data.x_struct.fields[i];
ConstExprValue *field_b = &b->data.x_struct.fields[i];
if (!const_values_equal(field_a, field_b))
if (!const_values_equal(g, field_a, field_b))
return false;
}
return true;
@ -5623,7 +5674,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_optional == nullptr || b->data.x_optional == nullptr) {
return (a->data.x_optional == nullptr && b->data.x_optional == nullptr);
} else {
return const_values_equal(a->data.x_optional, b->data.x_optional);
return const_values_equal(g, a->data.x_optional, b->data.x_optional);
}
case ZigTypeIdErrorUnion:
zig_panic("TODO");
@ -5808,26 +5859,15 @@ 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:
{
ZigType *child_type = type_entry->data.array.child_type;
uint64_t len = type_entry->data.array.len;
if (const_val->data.x_array.special == ConstArraySpecialUndef) {
switch (const_val->data.x_array.special) {
case ConstArraySpecialUndef:
buf_append_str(buf, "undefined");
return;
}
// if it's []u8, assume UTF-8 and output a string
if (child_type->id == ZigTypeIdInt &&
child_type->data.integral.bit_count == 8 &&
!child_type->data.integral.is_signed)
{
case ConstArraySpecialBuf: {
Buf *array_buf = const_val->data.x_array.data.s_buf;
buf_append_char(buf, '"');
for (uint64_t i = 0; i < len; i += 1) {
ConstExprValue *child_value = &const_val->data.x_array.s_none.elements[i];
uint64_t big_c = bigint_as_unsigned(&child_value->data.x_bigint);
assert(big_c <= UINT8_MAX);
uint8_t c = (uint8_t)big_c;
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 {
@ -5837,17 +5877,20 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
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.s_none.elements[i];
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 ZigTypeIdNull:
{
buf_appendf(buf, "null");
@ -5998,8 +6041,8 @@ uint32_t type_id_hash(TypeId x) {
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
(((uint32_t)x.data.pointer.bit_offset) ^ (uint32_t)2639019452) +
(((uint32_t)x.data.pointer.unaligned_bit_count) ^ (uint32_t)529908881);
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
case ZigTypeIdArray:
return hash_ptr(x.data.array.child_type) +
((uint32_t)x.data.array.size ^ (uint32_t)2122979968);
@ -6046,8 +6089,8 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
a.data.pointer.alignment == b.data.pointer.alignment &&
a.data.pointer.bit_offset == b.data.pointer.bit_offset &&
a.data.pointer.unaligned_bit_count == b.data.pointer.unaligned_bit_count;
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;
case ZigTypeIdArray:
return a.data.array.child_type == b.data.array.child_type &&
a.data.array.size == b.data.array.size;
@ -6102,14 +6145,18 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
zig_unreachable();
}
// Canonicalize the array value as ConstArraySpecialNone
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
assert(const_val->type->id == ZigTypeIdArray);
if (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.s_none.elements = create_const_vals(elem_count);
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.s_none.elements[i];
ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
element_val->type = const_val->type->data.array.child_type;
init_const_undefined(g, element_val);
ConstParent *parent = get_const_val_parent(g, element_val);
@ -6119,7 +6166,28 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
parent->data.p_array.elem_index = i;
}
}
return;
}
case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf;
// If we're doing this it means that we are potentially modifying the data,
// so we can't have it be in the string literals table
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) {
ConstExprValue *this_char = &const_val->data.x_array.data.s_none.elements[i];
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]);
}
return;
}
}
zig_unreachable();
}
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
@ -6127,7 +6195,7 @@ ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
ZigType *type_entry = value->type;
if (type_entry->id == ZigTypeIdArray) {
expand_undef_array(g, value);
return &value->data.x_array.s_none.parent;
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) {
@ -6500,3 +6568,12 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
ty->id == ZigTypeIdUnreachable ||
get_codegen_ptr_type(ty) != nullptr);
}
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) {
assert(struct_type->id == ZigTypeIdStruct);
if (struct_type->data.structure.layout != ContainerLayoutPacked) {
return 0;
}
LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
return LLVMStoreSizeOfType(g->target_data_ref, field_type);
}

View File

@ -84,8 +84,8 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
bool is_const, ConstExprValue *init_value, Tld *src_tld);
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
ZigFn *create_fn(AstNode *proto_node);
ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
bool type_requires_comptime(ZigType *type_entry);
@ -93,25 +93,25 @@ Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
void complete_enum(CodeGen *g, ZigType *enum_type);
bool ir_get_var_is_comptime(ZigVar *var);
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b);
void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_val, bool is_max);
void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node);
ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);
Scope *create_var_scope(AstNode *node, Scope *parent, ZigVar *var);
ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, ZigFn *fn_entry);
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
Scope *create_comptime_scope(AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(AstNode *node, Scope *parent);
Scope *create_runtime_scope(AstNode *node, Scope *parent, IrInstruction *is_comptime);
ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var);
ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_coro_prelude_scope(CodeGen *g, AstNode *node, Scope *parent);
Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
@ -216,4 +216,6 @@ 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);
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
#endif

View File

@ -635,7 +635,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, "align(");
render_node_grouped(ar, node->data.pointer_type.align_expr);
if (node->data.pointer_type.bit_offset_start != nullptr) {
assert(node->data.pointer_type.bit_offset_end != nullptr);
assert(node->data.pointer_type.host_int_bytes != nullptr);
Buf offset_start_buf = BUF_INIT;
buf_resize(&offset_start_buf, 0);
@ -643,7 +643,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
Buf offset_end_buf = BUF_INIT;
buf_resize(&offset_end_buf, 0);
bigint_append_buf(&offset_end_buf, node->data.pointer_type.bit_offset_end, 10);
bigint_append_buf(&offset_end_buf, node->data.pointer_type.host_int_bytes, 10);
fprintf(ar->f, ":%s:%s ", buf_ptr(&offset_start_buf), buf_ptr(&offset_end_buf));
}
@ -737,7 +737,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, ")");
}
fprintf(ar->f, " {\n");
fprintf(ar->f, ".{\n");
ar->indent += ar->indent_size;
for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
AstNode *field_node = node->data.container_decl.fields.at(field_i);
@ -763,10 +763,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
case NodeTypeContainerInitExpr:
render_node_ungrouped(ar, node->data.container_init_expr.type);
if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
fprintf(ar->f, "{\n");
fprintf(ar->f, ".{\n");
ar->indent += ar->indent_size;
} else {
fprintf(ar->f, "{");
fprintf(ar->f, ".{");
}
for (size_t i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
AstNode *entry = node->data.container_init_expr.entries.at(i);

View File

@ -1188,7 +1188,6 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_bigint(dest, op1);
}
if (op1->is_negative || op2->is_negative) {
// TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@ -1211,13 +1210,9 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
bigint_normalize(dest);
return;
}
// TODO this code path is untested
uint64_t first_digit = dest->data.digit;
dest->digit_count = max(op1->digit_count, op2->digit_count);
dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
dest->data.digits[0] = first_digit;
size_t i = 1;
for (; i < dest->digit_count; i += 1) {
for (size_t i = 0; i < dest->digit_count; i += 1) {
uint64_t digit = 0;
if (i < op1->digit_count) {
digit |= op1_digits[i];
@ -1236,7 +1231,6 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_unsigned(dest, 0);
}
if (op1->is_negative || op2->is_negative) {
// TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@ -1282,7 +1276,6 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
return bigint_init_bigint(dest, op1);
}
if (op1->is_negative || op2->is_negative) {
// TODO this code path is untested
size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
BigInt twos_comp_op1 = {0};
@ -1301,27 +1294,25 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
const uint64_t *op2_digits = bigint_ptr(op2);
assert(op1->digit_count > 0 && op2->digit_count > 0);
uint64_t first_digit = op1_digits[0] ^ op2_digits[0];
if (op1->digit_count == 1 && op2->digit_count == 1) {
dest->digit_count = 1;
dest->data.digit = first_digit;
dest->data.digit = op1_digits[0] ^ op2_digits[0];
bigint_normalize(dest);
return;
}
// TODO this code path is untested
dest->digit_count = max(op1->digit_count, op2->digit_count);
dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
dest->data.digits[0] = first_digit;
size_t i = 1;
size_t i = 0;
for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
dest->data.digits[i] = op1_digits[i] ^ op2_digits[i];
}
for (; i < dest->digit_count; i += 1) {
if (i < op1->digit_count) {
dest->data.digits[i] = op1_digits[i];
}
if (i < op2->digit_count) {
} else if (i < op2->digit_count) {
dest->data.digits[i] = op2_digits[i];
} else {
zig_unreachable();
}
}
bigint_normalize(dest);
@ -1485,8 +1476,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
bigint_normalize(dest);
return;
}
// TODO this code path is untested
dest->digit_count = bit_count / 64;
dest->digit_count = (bit_count + 63) / 64;
assert(dest->digit_count >= op->digit_count);
dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
size_t i = 0;
@ -1496,9 +1486,9 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
for (; i < dest->digit_count; i += 1) {
dest->data.digits[i] = 0xffffffffffffffffULL;
}
size_t digit_index = dest->digit_count - (bit_count / 64) - 1;
size_t digit_index = dest->digit_count - 1;
size_t digit_bit_index = bit_count % 64;
if (digit_index < dest->digit_count) {
if (digit_bit_index != 0) {
uint64_t mask = (1ULL << digit_bit_index) - 1;
dest->data.digits[digit_index] &= mask;
}
@ -1555,7 +1545,6 @@ void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) {
buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit);
return;
}
// TODO this code path is untested
size_t first_digit_index = buf_len(buf);
BigInt digit_bi = {0};

View File

@ -118,7 +118,6 @@ 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->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
buf_resize(&g->global_asm, 0);
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
@ -446,6 +445,21 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
return first_arg_ret ? 1 : 0;
}
static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
}
}
static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
// TODO come up with a good explanation/understanding for why we never do
// DLLImportStorageClass. Empirically it only causes problems. But let's have
// this documented and then clean up the code accordingly.
//LLVMSetDLLStorageClass(global_value, LLVMDLLImportStorageClass);
}
}
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
if (fn_table_entry->llvm_value)
return fn_table_entry->llvm_value;
@ -539,6 +553,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
}
if (fn_table_entry->body_node != nullptr) {
maybe_export_dll(g, fn_table_entry->llvm_value, linkage);
bool want_fn_safety = g->build_mode != BuildModeFastRelease &&
g->build_mode != BuildModeSmallRelease &&
!fn_table_entry->def_scope->safety_off;
@ -548,6 +564,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
}
}
} else {
maybe_import_dll(g, fn_table_entry->llvm_value, linkage);
}
if (fn_table_entry->alignstack_value != 0) {
@ -1795,8 +1813,8 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
return nullptr;
}
uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
if (unaligned_bit_count == 0) {
uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
if (host_int_bytes == 0) {
gen_store(g, value, ptr, ptr_type);
return nullptr;
}
@ -1804,10 +1822,12 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
bool big_endian = g->is_big_endian;
LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset;
assert(host_bit_count == host_int_bytes * 8);
uint32_t size_in_bits = type_size_bits(g, child_type);
uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref);
@ -3209,18 +3229,20 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
ZigType *ptr_type = instruction->ptr->value.type;
assert(ptr_type->id == ZigTypeIdPointer);
uint32_t unaligned_bit_count = ptr_type->data.pointer.unaligned_bit_count;
if (unaligned_bit_count == 0)
uint32_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
if (host_int_bytes == 0)
return get_handle_value(g, ptr, child_type, ptr_type);
bool big_endian = g->is_big_endian;
assert(!handle_is_ptr(child_type));
LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
uint32_t bit_offset = ptr_type->data.pointer.bit_offset;
uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - unaligned_bit_count : bit_offset;
assert(host_bit_count == host_int_bytes * 8);
uint32_t size_in_bits = type_size_bits(g, child_type);
uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host;
uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset;
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
@ -3276,20 +3298,22 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
array_type->data.array.len, false);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
}
if (array_ptr_type->data.pointer.unaligned_bit_count != 0) {
if (array_ptr_type->data.pointer.host_int_bytes != 0) {
return array_ptr_ptr;
}
ZigType *child_type = array_type->data.array.child_type;
if (child_type->id == ZigTypeIdStruct &&
child_type->data.structure.layout == ContainerLayoutPacked)
{
size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
if (unaligned_bit_count != 0) {
ZigType *ptr_type = instruction->base.value.type;
size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes;
if (host_int_bytes != 0) {
uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type);
LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
assert(unaligned_bit_count % 8 == 0);
assert(size_in_bits % 8 == 0);
LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
unaligned_bit_count / 8, false);
size_in_bits / 8, false);
LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
LLVMValueRef indices[] = {
byte_offset
@ -3505,7 +3529,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
return nullptr;
if (struct_ptr_type->id == ZigTypeIdPointer &&
struct_ptr_type->data.pointer.unaligned_bit_count != 0)
struct_ptr_type->data.pointer.host_int_bytes != 0)
{
return struct_ptr;
}
@ -4671,10 +4695,11 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
LLVMValueRef value = ir_llvm_value(g, field->value);
uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
false, false, PtrLenSingle, field_align_bytes,
(uint32_t)type_struct_field->packed_bits_offset, (uint32_t)type_struct_field->unaligned_bit_count);
(uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes);
gen_assign_raw(g, field_ptr, ptr_type, value);
}
@ -5075,8 +5100,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSizeOf:
case IrInstructionIdSwitchTarget:
case IrInstructionIdContainerInitFields:
case IrInstructionIdMinValue:
case IrInstructionIdMaxValue:
case IrInstructionIdCompileErr:
case IrInstructionIdCompileLog:
case IrInstructionIdArrayLen:
@ -5098,7 +5121,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdTypeName:
case IrInstructionIdDeclRef:
case IrInstructionIdSwitchVar:
case IrInstructionIdOffsetOf:
case IrInstructionIdByteOffsetOf:
case IrInstructionIdBitOffsetOf:
case IrInstructionIdTypeInfo:
case IrInstructionIdTypeId:
case IrInstructionIdSetEvalBranchQuota:
@ -5336,7 +5360,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.s_none.parent;
ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
@ -5458,15 +5482,16 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
continue;
}
LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]);
uint32_t packed_bits_size = type_size_bits(g, field->type_entry);
if (is_big_endian) {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, field->packed_bits_size, false);
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
val = LLVMConstShl(val, shift_amt);
val = LLVMConstOr(val, child_val);
} else {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
val = LLVMConstOr(val, child_val_shifted);
used_bits += field->packed_bits_size;
used_bits += packed_bits_size;
}
}
return val;
@ -5676,16 +5701,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
}
LLVMValueRef child_val = pack_const_int(g, big_int_type_ref,
&const_val->data.x_struct.fields[i]);
uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry);
if (is_big_endian) {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref,
it_field->packed_bits_size, false);
packed_bits_size, false);
val = LLVMConstShl(val, shift_amt);
val = LLVMConstOr(val, child_val);
} else {
LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
val = LLVMConstOr(val, child_val_shifted);
used_bits += it_field->packed_bits_size;
used_bits += packed_bits_size;
}
}
fields[type_struct_field->gen_index] = val;
@ -5716,15 +5742,15 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
case ZigTypeIdArray:
{
uint64_t len = type_entry->data.array.len;
if (const_val->data.x_array.special == ConstArraySpecialUndef) {
switch (const_val->data.x_array.special) {
case ConstArraySpecialUndef:
return LLVMGetUndef(type_entry->type_ref);
}
case ConstArraySpecialNone: {
LLVMValueRef *values = allocate<LLVMValueRef>(len);
LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref;
bool make_unnamed_struct = false;
for (uint64_t i = 0; i < len; i += 1) {
ConstExprValue *elem_value = &const_val->data.x_array.s_none.elements[i];
ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
LLVMValueRef val = gen_const_val(g, elem_value, "");
values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val);
@ -5735,6 +5761,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
return LLVMConstArray(element_type_ref, values, (unsigned)len);
}
}
case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf;
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
}
}
}
case ZigTypeIdUnion:
{
LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
@ -6091,6 +6123,7 @@ static void do_code_gen(CodeGen *g) {
// 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);
}
@ -6103,6 +6136,7 @@ static void do_code_gen(CodeGen *g) {
if (exported) {
LLVMSetLinkage(global_value, LLVMExternalLinkage);
maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
LLVMSetSection(global_value, buf_ptr(tld_var->section_name));
@ -6615,8 +6649,6 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
create_builtin_fn(g, BuiltinFnIdAlignOf, "alignOf", 1);
create_builtin_fn(g, BuiltinFnIdMaxValue, "maxValue", 1);
create_builtin_fn(g, BuiltinFnIdMinValue, "minValue", 1);
create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1);
create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2);
create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
@ -6665,7 +6697,8 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdTagName, "tagName", 1);
create_builtin_fn(g, BuiltinFnIdTagType, "TagType", 1);
create_builtin_fn(g, BuiltinFnIdFieldParentPtr, "fieldParentPtr", 3);
create_builtin_fn(g, BuiltinFnIdOffsetOf, "offsetOf", 2);
create_builtin_fn(g, BuiltinFnIdByteOffsetOf, "byteOffsetOf", 2);
create_builtin_fn(g, BuiltinFnIdBitOffsetOf, "bitOffsetOf", 2);
create_builtin_fn(g, BuiltinFnIdDivExact, "divExact", 2);
create_builtin_fn(g, BuiltinFnIdDivTrunc, "divTrunc", 2);
create_builtin_fn(g, BuiltinFnIdDivFloor, "divFloor", 2);
@ -6713,14 +6746,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
// Modifications to this struct must be coordinated with code that does anything with
// g->stack_trace_type. There are hard-coded references to the field indexes.
buf_append_str(contents,
"pub const StackTrace = struct {\n"
"pub const StackTrace = struct.{\n"
" index: usize,\n"
" instruction_addresses: []usize,\n"
"};\n\n");
const char *cur_os = nullptr;
{
buf_appendf(contents, "pub const Os = enum {\n");
buf_appendf(contents, "pub const Os = enum.{\n");
uint32_t field_count = (uint32_t)target_os_count();
for (uint32_t i = 0; i < field_count; i += 1) {
Os os_type = get_target_os(i);
@ -6738,7 +6771,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
const char *cur_arch = nullptr;
{
buf_appendf(contents, "pub const Arch = enum {\n");
buf_appendf(contents, "pub const Arch = enum.{\n");
uint32_t field_count = (uint32_t)target_arch_count();
for (uint32_t i = 0; i < field_count; i += 1) {
const ArchType *arch_type = get_target_arch(i);
@ -6762,7 +6795,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
const char *cur_environ = nullptr;
{
buf_appendf(contents, "pub const Environ = enum {\n");
buf_appendf(contents, "pub const Environ = enum.{\n");
uint32_t field_count = (uint32_t)target_environ_count();
for (uint32_t i = 0; i < field_count; i += 1) {
ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
@ -6780,7 +6813,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
const char *cur_obj_fmt = nullptr;
{
buf_appendf(contents, "pub const ObjectFormat = enum {\n");
buf_appendf(contents, "pub const ObjectFormat = enum.{\n");
uint32_t field_count = (uint32_t)target_oformat_count();
for (uint32_t i = 0; i < field_count; i += 1) {
ZigLLVM_ObjectFormatType oformat = get_target_oformat(i);
@ -6798,7 +6831,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
assert(cur_obj_fmt != nullptr);
{
buf_appendf(contents, "pub const GlobalLinkage = enum {\n");
buf_appendf(contents, "pub const GlobalLinkage = enum.{\n");
uint32_t field_count = array_length(global_linkage_values);
for (uint32_t i = 0; i < field_count; i += 1) {
const GlobalLinkageValue *value = &global_linkage_values[i];
@ -6808,7 +6841,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const AtomicOrder = enum {\n"
"pub const AtomicOrder = enum.{\n"
" Unordered,\n"
" Monotonic,\n"
" Acquire,\n"
@ -6819,7 +6852,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const AtomicRmwOp = enum {\n"
"pub const AtomicRmwOp = enum.{\n"
" Xchg,\n"
" Add,\n"
" Sub,\n"
@ -6833,7 +6866,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const Mode = enum {\n"
"pub const Mode = enum.{\n"
" Debug,\n"
" ReleaseSafe,\n"
" ReleaseFast,\n"
@ -6841,7 +6874,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
"};\n\n");
}
{
buf_appendf(contents, "pub const TypeId = enum {\n");
buf_appendf(contents, "pub const TypeId = enum.{\n");
size_t field_count = type_id_len();
for (size_t i = 0; i < field_count; i += 1) {
const ZigTypeId id = type_id_at_index(i);
@ -6851,7 +6884,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const TypeInfo = union(TypeId) {\n"
"pub const TypeInfo = union(TypeId).{\n"
" Type: void,\n"
" Void: void,\n"
" Bool: void,\n"
@ -6877,96 +6910,96 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" Opaque: void,\n"
" Promise: Promise,\n"
"\n\n"
" pub const Int = struct {\n"
" pub const Int = struct.{\n"
" is_signed: bool,\n"
" bits: u8,\n"
" };\n"
"\n"
" pub const Float = struct {\n"
" pub const Float = struct.{\n"
" bits: u8,\n"
" };\n"
"\n"
" pub const Pointer = struct {\n"
" pub const Pointer = struct.{\n"
" size: Size,\n"
" is_const: bool,\n"
" is_volatile: bool,\n"
" alignment: u32,\n"
" child: type,\n"
"\n"
" pub const Size = enum {\n"
" pub const Size = enum.{\n"
" One,\n"
" Many,\n"
" Slice,\n"
" };\n"
" };\n"
"\n"
" pub const Array = struct {\n"
" pub const Array = struct.{\n"
" len: usize,\n"
" child: type,\n"
" };\n"
"\n"
" pub const ContainerLayout = enum {\n"
" pub const ContainerLayout = enum.{\n"
" Auto,\n"
" Extern,\n"
" Packed,\n"
" };\n"
"\n"
" pub const StructField = struct {\n"
" pub const StructField = struct.{\n"
" name: []const u8,\n"
" offset: ?usize,\n"
" field_type: type,\n"
" };\n"
"\n"
" pub const Struct = struct {\n"
" pub const Struct = struct.{\n"
" layout: ContainerLayout,\n"
" fields: []StructField,\n"
" defs: []Definition,\n"
" };\n"
"\n"
" pub const Optional = struct {\n"
" pub const Optional = struct.{\n"
" child: type,\n"
" };\n"
"\n"
" pub const ErrorUnion = struct {\n"
" pub const ErrorUnion = struct.{\n"
" error_set: type,\n"
" payload: type,\n"
" };\n"
"\n"
" pub const Error = struct {\n"
" pub const Error = struct.{\n"
" name: []const u8,\n"
" value: usize,\n"
" };\n"
"\n"
" pub const ErrorSet = struct {\n"
" pub const ErrorSet = struct.{\n"
" errors: []Error,\n"
" };\n"
"\n"
" pub const EnumField = struct {\n"
" pub const EnumField = struct.{\n"
" name: []const u8,\n"
" value: usize,\n"
" };\n"
"\n"
" pub const Enum = struct {\n"
" pub const Enum = struct.{\n"
" layout: ContainerLayout,\n"
" tag_type: type,\n"
" fields: []EnumField,\n"
" defs: []Definition,\n"
" };\n"
"\n"
" pub const UnionField = struct {\n"
" pub const UnionField = struct.{\n"
" name: []const u8,\n"
" enum_field: ?EnumField,\n"
" field_type: type,\n"
" };\n"
"\n"
" pub const Union = struct {\n"
" pub const Union = struct.{\n"
" layout: ContainerLayout,\n"
" tag_type: ?type,\n"
" fields: []UnionField,\n"
" defs: []Definition,\n"
" };\n"
"\n"
" pub const CallingConvention = enum {\n"
" pub const CallingConvention = enum.{\n"
" Unspecified,\n"
" C,\n"
" Cold,\n"
@ -6975,13 +7008,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" Async,\n"
" };\n"
"\n"
" pub const FnArg = struct {\n"
" pub const FnArg = struct.{\n"
" is_generic: bool,\n"
" is_noalias: bool,\n"
" arg_type: ?type,\n"
" };\n"
"\n"
" pub const Fn = struct {\n"
" pub const Fn = struct.{\n"
" calling_convention: CallingConvention,\n"
" is_generic: bool,\n"
" is_var_args: bool,\n"
@ -6990,21 +7023,21 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" args: []FnArg,\n"
" };\n"
"\n"
" pub const Promise = struct {\n"
" pub const Promise = struct.{\n"
" child: ?type,\n"
" };\n"
"\n"
" pub const Definition = struct {\n"
" pub const Definition = struct.{\n"
" name: []const u8,\n"
" is_pub: bool,\n"
" data: Data,\n"
"\n"
" pub const Data = union(enum) {\n"
" pub const Data = union(enum).{\n"
" Type: type,\n"
" Var: type,\n"
" Fn: FnDef,\n"
"\n"
" pub const FnDef = struct {\n"
" pub const FnDef = struct.{\n"
" fn_type: type,\n"
" inline_type: Inline,\n"
" calling_convention: CallingConvention,\n"
@ -7015,7 +7048,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" return_type: type,\n"
" arg_names: [][] const u8,\n"
"\n"
" pub const Inline = enum {\n"
" pub const Inline = enum.{\n"
" Auto,\n"
" Always,\n"
" Never,\n"
@ -7041,7 +7074,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const FloatMode = enum {\n"
"pub const FloatMode = enum.{\n"
" Strict,\n"
" Optimized,\n"
"};\n\n");
@ -7050,7 +7083,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
}
{
buf_appendf(contents,
"pub const Endian = enum {\n"
"pub const Endian = enum.{\n"
" Big,\n"
" Little,\n"
"};\n\n");
@ -7191,7 +7224,10 @@ static void init(CodeGen *g) {
bool is_optimized = g->build_mode != BuildModeDebug;
LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
if (g->out_type == OutTypeExe && g->is_static) {
g->disable_pic = true;
}
LLVMRelocMode reloc_mode = g->disable_pic ? LLVMRelocStatic : LLVMRelocPIC;
const char *target_specific_cpu_args;
const char *target_specific_features;
@ -7242,10 +7278,15 @@ static void init(CodeGen *g) {
define_builtin_types(g);
g->invalid_instruction = allocate<IrInstruction>(1);
IrInstruction *sentinel_instructions = allocate<IrInstruction>(2);
g->invalid_instruction = &sentinel_instructions[0];
g->invalid_instruction->value.type = g->builtin_types.entry_invalid;
g->invalid_instruction->value.global_refs = allocate<ConstGlobalRefs>(1);
g->unreach_instruction = &sentinel_instructions[1];
g->unreach_instruction->value.type = g->builtin_types.entry_unreachable;
g->unreach_instruction->value.global_refs = allocate<ConstGlobalRefs>(1);
g->const_void_val.special = ConstValSpecialStatic;
g->const_void_val.type = g->builtin_types.entry_void;
g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);
@ -7278,7 +7319,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
import->source_code = nullptr;
import->path = full_path;
g->root_import = import;
import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);
import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);
init(g);
@ -7352,12 +7393,12 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
ConstExprValue *test_fn_array = create_const_vals(1);
test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);
test_fn_array->special = ConstValSpecialStatic;
test_fn_array->data.x_array.s_none.elements = create_const_vals(g->test_fns.length);
test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);
for (size_t i = 0; i < g->test_fns.length; i += 1) {
ZigFn *test_fn_entry = g->test_fns.at(i);
ConstExprValue *this_val = &test_fn_array->data.x_array.s_none.elements[i];
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;
@ -7445,7 +7486,9 @@ static void gen_root_source(CodeGen *g) {
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
}
if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib) {
if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && !g->is_static)
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
}
@ -8003,6 +8046,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->no_rosegment_workaround);
cache_bool(ch, g->each_lib_rpath);
cache_bool(ch, g->disable_pic);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
cache_usize(ch, g->version_major);
@ -8089,17 +8133,6 @@ static void resolve_out_paths(CodeGen *g) {
} else {
zig_unreachable();
}
if (g->want_h_file && !g->out_h_path) {
assert(g->root_out_name);
Buf *h_basename = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
if (g->enable_cache) {
g->out_h_path = buf_alloc();
os_path_join(&g->artifact_dir, h_basename, g->out_h_path);
} else {
g->out_h_path = h_basename;
}
}
}
@ -8155,11 +8188,11 @@ void codegen_build_and_link(CodeGen *g) {
codegen_add_time_event(g, "LLVM Emit Output");
zig_llvm_emit_output(g);
if (g->want_h_file) {
if (g->out_h_path != nullptr) {
codegen_add_time_event(g, "Generate .h");
gen_h_file(g);
}
if (g->out_type != OutTypeObj) {
if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
codegen_link(g);
}
}

4582
src/ir.cpp

File diff suppressed because it is too large Load Diff

View File

@ -565,18 +565,6 @@ static void ir_print_ref(IrPrint *irp, IrInstructionRef *instruction) {
ir_print_other_instruction(irp, instruction->value);
}
static void ir_print_min_value(IrPrint *irp, IrInstructionMinValue *instruction) {
fprintf(irp->f, "@minValue(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_max_value(IrPrint *irp, IrInstructionMaxValue *instruction) {
fprintf(irp->f, "@maxValue(");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
static void ir_print_compile_err(IrPrint *irp, IrInstructionCompileErr *instruction) {
fprintf(irp->f, "@compileError(");
ir_print_other_instruction(irp, instruction->msg);
@ -1015,7 +1003,7 @@ static void ir_print_ptr_type(IrPrint *irp, IrInstructionPtrType *instruction) {
}
const char *const_str = instruction->is_const ? "const " : "";
const char *volatile_str = instruction->is_volatile ? "volatile " : "";
fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end,
fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->host_int_bytes,
const_str, volatile_str);
ir_print_other_instruction(irp, instruction->child_type);
}
@ -1041,8 +1029,16 @@ static void ir_print_field_parent_ptr(IrPrint *irp, IrInstructionFieldParentPtr
fprintf(irp->f, ")");
}
static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction) {
fprintf(irp->f, "@offset_of(");
static void ir_print_byte_offset_of(IrPrint *irp, IrInstructionByteOffsetOf *instruction) {
fprintf(irp->f, "@byte_offset_of(");
ir_print_other_instruction(irp, instruction->type_value);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->field_name);
fprintf(irp->f, ")");
}
static void ir_print_bit_offset_of(IrPrint *irp, IrInstructionBitOffsetOf *instruction) {
fprintf(irp->f, "@bit_offset_of(");
ir_print_other_instruction(irp, instruction->type_value);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->field_name);
@ -1472,12 +1468,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdRef:
ir_print_ref(irp, (IrInstructionRef *)instruction);
break;
case IrInstructionIdMinValue:
ir_print_min_value(irp, (IrInstructionMinValue *)instruction);
break;
case IrInstructionIdMaxValue:
ir_print_max_value(irp, (IrInstructionMaxValue *)instruction);
break;
case IrInstructionIdCompileErr:
ir_print_compile_err(irp, (IrInstructionCompileErr *)instruction);
break;
@ -1649,8 +1639,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFieldParentPtr:
ir_print_field_parent_ptr(irp, (IrInstructionFieldParentPtr *)instruction);
break;
case IrInstructionIdOffsetOf:
ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction);
case IrInstructionIdByteOffsetOf:
ir_print_byte_offset_of(irp, (IrInstructionByteOffsetOf *)instruction);
break;
case IrInstructionIdBitOffsetOf:
ir_print_bit_offset_of(irp, (IrInstructionBitOffsetOf *)instruction);
break;
case IrInstructionIdTypeInfo:
ir_print_type_info(irp, (IrInstructionTypeInfo *)instruction);

View File

@ -29,12 +29,22 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
return buf_ptr(out_buf);
}
static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) {
static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {
ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode,
parent_gen->zig_lib_dir);
child_gen->want_h_file = false;
// The Mach-O LLD code is not well maintained, and trips an assertion
// when we link compiler_rt and builtin as libraries rather than objects.
// Here we workaround this by having compiler_rt and builtin be objects.
// TODO write our own linker. https://github.com/ziglang/zig/issues/1535
OutType child_out_type = OutTypeLib;
if (parent_gen->zig_target.os == OsMacOSX) {
child_out_type = OutTypeObj;
}
CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
parent_gen->build_mode, parent_gen->zig_lib_dir);
child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
child_gen->verbose_ast = parent_gen->verbose_ast;
child_gen->verbose_link = parent_gen->verbose_link;
@ -43,19 +53,22 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
child_gen->verbose_cimport = parent_gen->verbose_cimport;
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
codegen_set_is_static(child_gen, parent_gen->is_static);
codegen_set_is_static(child_gen, true);
child_gen->disable_pic = parent_gen->disable_pic;
codegen_set_out_name(child_gen, buf_create_from_str(oname));
codegen_set_out_name(child_gen, buf_create_from_str(aname));
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
for (size_t i = 0; i < parent_gen->link_libs_list.length; i += 1) {
LinkLib *link_lib = parent_gen->link_libs_list.at(i);
LinkLib *new_link_lib = codegen_add_link_lib(child_gen, link_lib->name);
new_link_lib->provided_explicitly = link_lib->provided_explicitly;
// This is so that compiler_rt and builtin libraries know whether they
// will eventually be linked with libc. They make different decisions
// about what to export depending on whether libc is linked.
if (parent_gen->libc_link_lib != nullptr) {
LinkLib *new_link_lib = codegen_add_link_lib(child_gen, parent_gen->libc_link_lib->name);
new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly;
}
child_gen->enable_cache = true;
@ -63,12 +76,12 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
return &child_gen->output_file_path;
}
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
Buf *source_basename = buf_sprintf("%s.zig", oname);
static Buf *build_a(CodeGen *parent_gen, const char *aname) {
Buf *source_basename = buf_sprintf("%s.zig", aname);
Buf *full_path = buf_alloc();
os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
return build_o_raw(parent_gen, oname, full_path);
return build_a_raw(parent_gen, aname, full_path);
}
static Buf *build_compiler_rt(CodeGen *parent_gen) {
@ -77,7 +90,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
Buf *full_path = buf_alloc();
os_path_join(dir_path, buf_create_from_str("index.zig"), full_path);
return build_o_raw(parent_gen, "compiler_rt", full_path);
return build_a_raw(parent_gen, "compiler_rt", full_path);
}
static const char *get_darwin_arch_string(const ZigTarget *t) {
@ -197,6 +210,8 @@ static Buf *get_dynamic_linker_path(CodeGen *g) {
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
lj->args.append("-error-limit=0");
if (g->libc_link_lib != nullptr) {
find_libc_lib_path(g);
}
@ -314,10 +329,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
if (g->libc_link_lib == nullptr) {
Buf *builtin_o_path = build_o(g, "builtin");
lj->args.append(buf_ptr(builtin_o_path));
Buf *builtin_a_path = build_a(g, "builtin");
lj->args.append(buf_ptr(builtin_a_path));
}
// sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage
@ -386,7 +401,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
static void construct_linker_job_wasm(LinkJob *lj) {
CodeGen *g = lj->codegen;
lj->args.append("--relocatable"); // So lld doesn't look for _start.
lj->args.append("-error-limit=0");
lj->args.append("--no-entry"); // So lld doesn't look for _start.
lj->args.append("-o");
lj->args.append(buf_ptr(&g->output_file_path));
@ -424,6 +440,8 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
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);
}
@ -434,6 +452,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
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) {
@ -540,10 +563,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
if (g->libc_link_lib == nullptr) {
Buf *builtin_o_path = build_o(g, "builtin");
lj->args.append(buf_ptr(builtin_o_path));
Buf *builtin_a_path = build_a(g, "builtin");
lj->args.append(buf_ptr(builtin_a_path));
}
// msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
@ -755,6 +778,8 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
static void construct_linker_job_macho(LinkJob *lj) {
CodeGen *g = lj->codegen;
// LLD MACH-O has no error limit option.
//lj->args.append("-error-limit=0");
lj->args.append("-demangle");
if (g->linker_rdynamic) {
@ -872,7 +897,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
}
// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
Buf *compiler_rt_o_path = build_compiler_rt(g);
lj->args.append(buf_ptr(compiler_rt_o_path));
}
@ -954,9 +979,18 @@ void codegen_link(CodeGen *g) {
}
if (g->out_type == OutTypeLib && g->is_static) {
fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");
ZigList<const char *> file_names = {};
for (size_t i = 0; i < g->link_objects.length; i += 1) {
file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
}
ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os);
codegen_add_time_event(g, "LLVM Link");
if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
exit(1);
}
return;
}
lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
@ -974,7 +1008,17 @@ void codegen_link(CodeGen *g) {
Buf diag = BUF_INIT;
codegen_add_time_event(g, "LLVM Link");
if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
if (g->system_linker_hack && g->zig_target.os == OsMacOSX) {
Termination term;
ZigList<const char *> args = {};
for (size_t i = 1; i < lj.args.length; i += 1) {
args.append(lj.args.at(i));
}
os_spawn_process("ld", args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
exit(1);
}
} else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
exit(1);
}

View File

@ -16,14 +16,22 @@
#include <stdio.h>
static int usage(const char *arg0) {
fprintf(stderr, "Usage: %s [command] [options]\n"
static int print_error_usage(const char *arg0) {
fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
return EXIT_FAILURE;
}
static int print_full_usage(const char *arg0) {
fprintf(stdout,
"Usage: %s [command] [options]\n"
"\n"
"Commands:\n"
" build build project from build.zig\n"
" build-exe [source] create executable from source or object files\n"
" 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"
" 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"
" init-lib initialize a `zig build` library in the cwd\n"
@ -33,17 +41,19 @@ static int usage(const char *arg0) {
" test [source] create and run a test build\n"
" version print version number and exit\n"
" zen print zen of zig and exit\n"
"\n"
"Compile Options:\n"
" --assembly [source] add assembly file to build\n"
" --cache-dir [path] override the cache directory\n"
" --cache [auto|off|on] build in global cache, print out paths to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --disable-pic disable Position Independent Code for libraries\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" -ftime-report print timing diagnostics\n"
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
" --output-h [file] override generated header file path\n"
" --output-h [file] generate header file\n"
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
" --pkg-end pop current pkg\n"
" --release-fast build with optimizations on and safety off\n"
@ -63,6 +73,7 @@ static int 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"
"\n"
"Link Options:\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
@ -87,13 +98,14 @@ static int usage(const char *arg0) {
" --ver-major [ver] dynamic library semver major version\n"
" --ver-minor [ver] dynamic library semver minor version\n"
" --ver-patch [ver] dynamic library semver patch version\n"
"\n"
"Test Options:\n"
" --test-filter [text] skip tests that do not match filter\n"
" --test-name-prefix [text] add prefix to all tests\n"
" --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_FAILURE;
return EXIT_SUCCESS;
}
static const char *ZIG_ZEN = "\n"
@ -144,15 +156,16 @@ static int print_target_list(FILE *f) {
}
enum Cmd {
CmdInvalid,
CmdNone,
CmdBuild,
CmdBuiltin,
CmdHelp,
CmdRun,
CmdTargets,
CmdTest,
CmdTranslateC,
CmdVersion,
CmdZen,
CmdTranslateC,
CmdTargets,
};
static const char *default_zig_cache_name = "zig-cache";
@ -251,7 +264,7 @@ int main(int argc, char **argv) {
if (init_kind != InitKindNone) {
if (argc >= 3) {
fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]);
return usage(arg0);
return print_error_usage(arg0);
}
Buf *cmd_template_path = buf_alloc();
os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path);
@ -326,7 +339,7 @@ int main(int argc, char **argv) {
}
}
Cmd cmd = CmdInvalid;
Cmd cmd = CmdNone;
EmitFileType emit_file_type = EmitFileTypeBinary;
const char *in_file = nullptr;
const char *out_file = nullptr;
@ -374,15 +387,22 @@ int main(int argc, char **argv) {
size_t ver_minor = 0;
size_t ver_patch = 0;
bool timing_info = false;
bool disable_pic = false;
const char *cache_dir = nullptr;
CliPkg *cur_pkg = allocate<CliPkg>(1);
BuildMode build_mode = BuildModeDebug;
ZigList<const char *> test_exec_args = {0};
int runtime_args_start = -1;
bool no_rosegment_workaround = false;
bool system_linker_hack = false;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
const char *zig_exe_path = arg0;
Buf zig_exe_path_buf = BUF_INIT;
if ((err = os_self_exe_path(&zig_exe_path_buf))) {
fprintf(stderr, "Unable to determine path to zig's own executable\n");
return EXIT_FAILURE;
}
const char *zig_exe_path = buf_ptr(&zig_exe_path_buf);
const char *build_file = "build.zig";
bool asked_for_help = false;
@ -539,6 +559,10 @@ int main(int argc, char **argv) {
each_lib_rpath = true;
} else if (strcmp(arg, "-ftime-report") == 0) {
timing_info = true;
} else if (strcmp(arg, "--disable-pic") == 0) {
disable_pic = true;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
@ -547,7 +571,7 @@ int main(int argc, char **argv) {
} else if (strcmp(arg, "--pkg-begin") == 0) {
if (i + 2 >= argc) {
fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
return usage(arg0);
return print_error_usage(arg0);
}
CliPkg *new_cur_pkg = allocate<CliPkg>(1);
i += 1;
@ -565,7 +589,7 @@ int main(int argc, char **argv) {
cur_pkg = cur_pkg->parent;
} else if (i + 1 >= argc) {
fprintf(stderr, "Expected another argument after %s\n", arg);
return usage(arg0);
return print_error_usage(arg0);
} else {
i += 1;
if (strcmp(arg, "--output") == 0) {
@ -581,7 +605,7 @@ int main(int argc, char **argv) {
color = ErrColorOff;
} else {
fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
return usage(arg0);
return print_error_usage(arg0);
}
} else if (strcmp(arg, "--cache") == 0) {
if (strcmp(argv[i], "auto") == 0) {
@ -592,7 +616,7 @@ int main(int argc, char **argv) {
enable_cache = CacheOptOff;
} else {
fprintf(stderr, "--cache options are 'auto', 'on', or 'off'\n");
return usage(arg0);
return print_error_usage(arg0);
}
} else if (strcmp(arg, "--emit") == 0) {
if (strcmp(argv[i], "asm") == 0) {
@ -603,7 +627,7 @@ int main(int argc, char **argv) {
emit_file_type = EmitFileTypeLLVMIr;
} else {
fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
return usage(arg0);
return print_error_usage(arg0);
}
} else if (strcmp(arg, "--name") == 0) {
out_name = argv[i];
@ -672,10 +696,10 @@ int main(int argc, char **argv) {
test_exec_args.append(argv[i]);
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return usage(arg0);
return print_error_usage(arg0);
}
}
} else if (cmd == CmdInvalid) {
} else if (cmd == CmdNone) {
if (strcmp(arg, "build-exe") == 0) {
cmd = CmdBuild;
out_type = OutTypeExe;
@ -685,6 +709,8 @@ int main(int argc, char **argv) {
} else if (strcmp(arg, "build-lib") == 0) {
cmd = CmdBuild;
out_type = OutTypeLib;
} else if (strcmp(arg, "help") == 0) {
cmd = CmdHelp;
} else if (strcmp(arg, "run") == 0) {
cmd = CmdRun;
out_type = OutTypeExe;
@ -703,7 +729,7 @@ int main(int argc, char **argv) {
cmd = CmdBuiltin;
} else {
fprintf(stderr, "Unrecognized command: %s\n", arg);
return usage(arg0);
return print_error_usage(arg0);
}
} else {
switch (cmd) {
@ -719,16 +745,17 @@ int main(int argc, char **argv) {
}
} else {
fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
return usage(arg0);
return print_error_usage(arg0);
}
break;
case CmdBuiltin:
case CmdHelp:
case CmdVersion:
case CmdZen:
case CmdTargets:
fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
return usage(arg0);
case CmdInvalid:
return print_error_usage(arg0);
case CmdNone:
zig_unreachable();
}
}
@ -751,19 +778,19 @@ int main(int argc, char **argv) {
if (target_arch) {
if (parse_target_arch(target_arch, &target->arch)) {
fprintf(stderr, "invalid --target-arch argument\n");
return usage(arg0);
return print_error_usage(arg0);
}
}
if (target_os) {
if (parse_target_os(target_os, &target->os)) {
fprintf(stderr, "invalid --target-os argument\n");
return usage(arg0);
return print_error_usage(arg0);
}
}
if (target_environ) {
if (parse_target_environ(target_environ, &target->env_type)) {
fprintf(stderr, "invalid --target-environ argument\n");
return usage(arg0);
return print_error_usage(arg0);
}
}
}
@ -785,13 +812,13 @@ int main(int argc, char **argv) {
{
if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
return usage(arg0);
return print_error_usage(arg0);
} else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
fprintf(stderr, "Expected source file argument.\n");
return usage(arg0);
return print_error_usage(arg0);
} else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
return usage(arg0);
return print_error_usage(arg0);
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
@ -820,7 +847,7 @@ int main(int argc, char **argv) {
if (need_name && buf_out_name == nullptr) {
fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
return usage(arg0);
return print_error_usage(arg0);
}
Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
@ -829,6 +856,14 @@ int main(int argc, char **argv) {
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());
if (disable_pic) {
if (out_type != OutTypeLib || !is_static) {
fprintf(stderr, "--disable-pic only applies to static libraries");
return EXIT_FAILURE;
}
g->disable_pic = true;
}
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_out_name);
@ -861,6 +896,7 @@ int main(int argc, char **argv) {
g->verbose_llvm_ir = verbose_llvm_ir;
g->verbose_cimport = verbose_cimport;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
for (size_t i = 0; i < lib_dirs.length; i += 1) {
codegen_add_lib_dir(g, lib_dirs.at(i));
@ -906,7 +942,7 @@ int main(int argc, char **argv) {
if (out_file)
codegen_set_output_path(g, buf_create_from_str(out_file));
if (out_file_h)
if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))
codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
@ -1012,6 +1048,8 @@ int main(int argc, char **argv) {
zig_unreachable();
}
}
case CmdHelp:
return print_full_usage(arg0);
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
@ -1020,7 +1058,8 @@ int main(int argc, char **argv) {
return EXIT_SUCCESS;
case CmdTargets:
return print_target_list(stdout);
case CmdInvalid:
return usage(arg0);
case CmdNone:
fprintf(stderr, "Zig programming language\n");
return print_error_usage(arg0);
}
}

View File

@ -46,6 +46,7 @@ typedef SSIZE_T ssize_t;
#include <sys/wait.h>
#include <fcntl.h>
#include <limits.h>
#include <spawn.h>
#endif
@ -70,6 +71,12 @@ static clock_serv_t cclock;
#include <errno.h>
#include <time.h>
// Apple doesn't provide the environ global variable
#if defined(__APPLE__) && !defined(environ)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#endif
#if defined(ZIG_OS_POSIX)
static void populate_termination(Termination *term, int status) {
if (WIFEXITED(status)) {
@ -88,26 +95,23 @@ static void populate_termination(Termination *term, int status) {
}
static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {
pid_t pid = fork();
if (pid == -1)
zig_panic("fork failed");
if (pid == 0) {
// child
const char **argv = allocate<const char *>(args.length + 2);
argv[0] = exe;
argv[args.length + 1] = nullptr;
for (size_t i = 0; i < args.length; i += 1) {
argv[i + 1] = args.at(i);
}
execvp(exe, const_cast<char * const *>(argv));
zig_panic("execvp failed: %s", strerror(errno));
} else {
// parent
pid_t pid;
int rc = posix_spawnp(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ);
if (rc != 0) {
zig_panic("posix_spawn failed: %s", strerror(rc));
}
int status;
waitpid(pid, &status, 0);
populate_termination(term, status);
}
}
#endif
#if defined(ZIG_OS_WINDOWS)
@ -806,7 +810,7 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
pid_t pid = fork();
if (pid == -1)
zig_panic("fork failed");
zig_panic("fork failed: %s", strerror(errno));
if (pid == 0) {
// child
if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
@ -1378,8 +1382,6 @@ int os_init(void) {
#if defined(ZIG_OS_WINDOWS)
_setmode(fileno(stdout), _O_BINARY);
_setmode(fileno(stderr), _O_BINARY);
#endif
#if defined(ZIG_OS_WINDOWS)
unsigned __int64 frequency;
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) {
win32_time_resolution = 1.0 / (double) frequency;

View File

@ -701,7 +701,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
/*
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend"
ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
ErrorSetDecl = "error" Token(Dot) "{" list(Symbol, ",") "}"
*/
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@ -774,10 +774,16 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
}
return node;
} else if (token->id == TokenIdKeywordError) {
Token *next_token = &pc->tokens->at(*token_index + 1);
if (next_token->id == TokenIdLBrace) {
Token *dot_token = &pc->tokens->at(*token_index + 1);
Token *brace_token = &pc->tokens->at(*token_index + 2);
if (dot_token->id != TokenIdDot || brace_token->id != TokenIdLBrace) {
AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
*token_index += 1;
return node;
}
AstNode *node = ast_create_node(pc, NodeTypeErrorSetDecl, token);
*token_index += 2;
*token_index += 3;
for (;;) {
Token *item_tok = &pc->tokens->at(*token_index);
if (item_tok->id == TokenIdRBrace) {
@ -794,11 +800,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
ast_invalid_token_error(pc, item_tok);
}
}
} else {
AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
*token_index += 1;
return node;
}
} else if (token->id == TokenIdAtSign) {
*token_index += 1;
Token *name_tok = &pc->tokens->at(*token_index);
@ -870,7 +871,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
/*
CurlySuffixExpression : PrefixOpExpression option(ContainerInitExpression)
ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace)
ContainerInitExpression : token(Dot) token(LBrace) ContainerInitBody token(RBrace)
ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma))
*/
static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
@ -881,8 +882,9 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde
while (true) {
Token *first_token = &pc->tokens->at(*token_index);
if (first_token->id == TokenIdLBrace) {
*token_index += 1;
Token *second_token = &pc->tokens->at(*token_index + 1);
if (first_token->id == TokenIdDot && second_token->id == TokenIdLBrace) {
*token_index += 2;
AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, first_token);
node->data.container_init_expr.type = prefix_op_expr;
@ -1098,12 +1100,10 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
ast_invalid_token_error(pc, ellipsis_or_r_bracket);
}
} else if (first_token->id == TokenIdDot) {
*token_index += 1;
Token *token = &pc->tokens->at(*token_index);
Token *token = &pc->tokens->at(*token_index + 1);
if (token->id == TokenIdSymbol) {
*token_index += 1;
*token_index += 2;
AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
node->data.field_access_expr.struct_expr = primary_expr;
@ -1111,23 +1111,22 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
primary_expr = node;
} else if (token->id == TokenIdStar) {
*token_index += 1;
*token_index += 2;
AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token);
node->data.ptr_deref_expr.target = primary_expr;
primary_expr = node;
} else if (token->id == TokenIdQuestion) {
*token_index += 1;
*token_index += 2;
AstNode *node = ast_create_node(pc, NodeTypeUnwrapOptional, first_token);
node->data.unwrap_optional.expr = primary_expr;
primary_expr = node;
} else {
ast_invalid_token_error(pc, token);
return primary_expr;
}
} else {
return primary_expr;
}
@ -1161,10 +1160,10 @@ static AstNode *ast_parse_pointer_type(ParseContext *pc, size_t *token_index, To
*token_index += 1;
Token *bit_offset_start_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
ast_eat_token(pc, token_index, TokenIdColon);
Token *bit_offset_end_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
Token *host_int_bytes_tok = ast_eat_token(pc, token_index, TokenIdIntLiteral);
node->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start_tok);
node->data.pointer_type.bit_offset_end = token_bigint(bit_offset_end_tok);
node->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes_tok);
}
ast_eat_token(pc, token_index, TokenIdRParen);
token = &pc->tokens->at(*token_index);
@ -2726,6 +2725,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
node->data.container_decl.init_arg_expr = ast_parse_grouped_expr(pc, token_index, false);
}
ast_eat_token(pc, token_index, TokenIdDot);
ast_eat_token(pc, token_index, TokenIdLBrace);
for (;;) {

View File

@ -55,8 +55,22 @@ static const ArchType arch_list[] = {
{ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5te},
{ZigLLVM_armeb, ZigLLVM_ARMSubArch_v4t},
{ZigLLVM_aarch64, ZigLLVM_NoSubArch},
{ZigLLVM_aarch64_be, ZigLLVM_NoSubArch},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_3a},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_2a},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_1a},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8r},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_baseline},
{ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_mainline},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_3a},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_2a},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_1a},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8r},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_baseline},
{ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_mainline},
{ZigLLVM_arc, ZigLLVM_NoSubArch},
{ZigLLVM_avr, ZigLLVM_NoSubArch},
{ZigLLVM_bpfel, ZigLLVM_NoSubArch},
@ -237,7 +251,7 @@ Os get_target_os(size_t index) {
return os_list[index];
}
static ZigLLVM_OSType get_llvm_os_type(Os os_type) {
ZigLLVM_OSType get_llvm_os_type(Os os_type) {
switch (os_type) {
case OsFreestanding:
case OsZen:
@ -947,11 +961,12 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
case ZigLLVM_UnknownArch:
zig_unreachable();
case ZigLLVM_x86:
return "sp";
return "esp";
case ZigLLVM_x86_64:
return "rsp";
case ZigLLVM_aarch64:
return "sp";
case ZigLLVM_arm:
case ZigLLVM_thumb:
case ZigLLVM_aarch64_be:

View File

@ -120,6 +120,6 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
Buf *target_dynamic_linker(ZigTarget *target);
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
ZigLLVM_OSType get_llvm_os_type(Os os_type);
#endif

View File

@ -92,10 +92,9 @@
case 'c'
#define SYMBOL_CHAR \
ALPHA_EXCEPT_C: \
ALPHA: \
case DIGIT: \
case '_': \
case 'c'
case '_'
#define SYMBOL_START \
ALPHA: \

View File

@ -15,10 +15,19 @@
#include "parser.hpp"
#if __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#include <clang/Frontend/ASTUnit.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/AST/Expr.h>
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#include <string.h>
using namespace clang;
@ -458,7 +467,13 @@ static const char *decl_name(const Decl *decl) {
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<BigInt>(1);
bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative());
bool is_negative = aps_int.isNegative();
if (!is_negative) {
bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
return node;
}
llvm::APSInt negated = -aps_int;
bigint_init_data(node->data.int_literal.bigint, negated.getRawData(), negated.getNumWords(), true);
return node;
}

View File

@ -13,6 +13,8 @@
#include <inttypes.h>
#include <assert.h>
const char *ZIG_WINDOWS_KIT_REG_KEY = "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots";
struct ZigWindowsSDKPrivate {
ZigWindowsSDK base;
};
@ -179,57 +181,53 @@ com_done:;
}
static ZigFindWindowsSdkError find_10_version(ZigWindowsSDKPrivate *priv) {
if (priv->base.path10_ptr == nullptr)
if (priv->base.path10_ptr == nullptr) {
return ZigFindWindowsSdkErrorNone;
}
char sdk_lib_dir[4096];
int n = snprintf(sdk_lib_dir, 4096, "%s\\Lib\\*", priv->base.path10_ptr);
if (n < 0 || n >= 4096) {
char reg_query[MAX_PATH] = { 0 };
int n = snprintf(reg_query, MAX_PATH, "%s\\%s.0\\Installed Options", ZIG_WINDOWS_KIT_REG_KEY, priv->base.version10_ptr);
if (n < 0 || n >= MAX_PATH) {
return ZigFindWindowsSdkErrorPathTooLong;
}
// enumerate files in sdk path looking for latest version
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFileA(sdk_lib_dir, &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
HKEY options_key;
HRESULT rc;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_query, 0,
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &options_key);
if (rc != ERROR_SUCCESS) {
return ZigFindWindowsSdkErrorNotFound;
}
int v0 = 0, v1 = 0, v2 = 0, v3 = 0;
for (;;) {
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
int c0 = 0, c1 = 0, c2 = 0, c3 = 0;
sscanf(ffd.cFileName, "%d.%d.%d.%d", &c0, &c1, &c2, &c3);
if (c0 == 10 && c1 == 0 && c2 == 10240 && c3 == 0) {
// Microsoft released 26624 as 10240 accidentally.
// https://developer.microsoft.com/en-us/windows/downloads/sdk-archive
c2 = 26624;
const char *option_name = nullptr;
switch (native_arch) {
case NativeArchArm:
option_name = "OptionId.DesktopCPParm";
break;
case NativeArchx86_64:
option_name = "OptionId.DesktopCPPx64";
break;
case NativeArchi386:
option_name = "OptionId.DesktopCPPx86";
break;
default:
return ZigFindWindowsSdkErrorNotFound;
}
if ( (c0 > v0)
|| (c0 == v0 && c1 > v1)
|| (c0 == v0 && c1 == v1 && c2 > v2)
|| (c0 == v0 && c1 == v1 && c2 == v2 && c3 > v3) ) {
v0 = c0, v1 = c1, v2 = c2, v3 = c3;
free((void*)priv->base.version10_ptr);
priv->base.version10_ptr = strdup(ffd.cFileName);
if (priv->base.version10_ptr == nullptr) {
FindClose(hFind);
return ZigFindWindowsSdkErrorOutOfMemory;
DWORD val_sz = sizeof(DWORD);
DWORD reg_val = 0;
DWORD type = REG_DWORD;
rc = RegQueryValueEx(options_key, option_name, NULL, &type, (LPBYTE)&reg_val, &val_sz);
if (rc != ERROR_SUCCESS || reg_val != 1) {
return ZigFindWindowsSdkErrorNotFound;
}
}
}
if (FindNextFile(hFind, &ffd) == 0) {
FindClose(hFind);
break;
}
}
priv->base.version10_len = strlen(priv->base.version10_ptr);
return ZigFindWindowsSdkErrorNone;
}
static ZigFindWindowsSdkError find_81_version(ZigWindowsSDKPrivate *priv) {
if (priv->base.path81_ptr == nullptr)
if (priv->base.path81_ptr == nullptr) {
return ZigFindWindowsSdkErrorNone;
}
char sdk_lib_dir[4096];
int n = snprintf(sdk_lib_dir, 4096, "%s\\Lib\\winv*", priv->base.path81_ptr);
@ -274,23 +272,32 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
return ZigFindWindowsSdkErrorOutOfMemory;
}
HKEY key;
HRESULT rc;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", 0,
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &key);
//note(dimenus): If this key doesn't exist, neither the Win 8 SDK nor the Win 10 SDK is installed
HKEY roots_key;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ZIG_WINDOWS_KIT_REG_KEY, 0,
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &roots_key);
if (rc != ERROR_SUCCESS) {
zig_free_windows_sdk(&priv->base);
return ZigFindWindowsSdkErrorNotFound;
}
{
HKEY v10_key;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\v10.0", 0,
KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &v10_key);
if (rc != ERROR_SUCCESS) {
goto find_win10_sdk_done;
}
DWORD tmp_buf_len = MAX_PATH;
priv->base.path10_ptr = (const char *)calloc(tmp_buf_len, 1);
if (priv->base.path10_ptr == nullptr) {
zig_free_windows_sdk(&priv->base);
return ZigFindWindowsSdkErrorOutOfMemory;
}
rc = RegQueryValueEx(key, "KitsRoot10", NULL, NULL, (LPBYTE)priv->base.path10_ptr, &tmp_buf_len);
rc = RegQueryValueEx(v10_key, "InstallationFolder", NULL, NULL, (LPBYTE)priv->base.path10_ptr, &tmp_buf_len);
if (rc == ERROR_SUCCESS) {
priv->base.path10_len = tmp_buf_len - 1;
if (priv->base.path10_ptr[priv->base.path10_len - 1] == '\\') {
@ -300,7 +307,18 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
free((void*)priv->base.path10_ptr);
priv->base.path10_ptr = nullptr;
}
priv->base.version10_ptr = (const char*)calloc(tmp_buf_len, 1);
rc = RegQueryValueEx(v10_key, "ProductVersion", NULL, NULL, (LPBYTE)priv->base.version10_ptr, &tmp_buf_len);
if (rc == ERROR_SUCCESS) {
snprintf((char*)priv->base.version10_ptr, MAX_PATH, "%s.0", priv->base.version10_ptr);
priv->base.version10_len = tmp_buf_len - 1 + 2; // note(dimenus): Microsoft doesn't include the .0 in the ProductVersion key....
} else {
free((void*)priv->base.version10_ptr);
priv->base.version10_ptr = nullptr;
}
}
find_win10_sdk_done:
{
DWORD tmp_buf_len = MAX_PATH;
priv->base.path81_ptr = (const char *)calloc(tmp_buf_len, 1);
@ -308,7 +326,7 @@ ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk) {
zig_free_windows_sdk(&priv->base);
return ZigFindWindowsSdkErrorOutOfMemory;
}
rc = RegQueryValueEx(key, "KitsRoot81", NULL, NULL, (LPBYTE)priv->base.path81_ptr, &tmp_buf_len);
rc = RegQueryValueEx(roots_key, "KitsRoot81", NULL, NULL, (LPBYTE)priv->base.path81_ptr, &tmp_buf_len);
if (rc == ERROR_SUCCESS) {
priv->base.path81_len = tmp_buf_len - 1;
if (priv->base.path81_ptr[priv->base.path81_len - 1] == '\\') {

View File

@ -15,6 +15,11 @@
#include "zig_llvm.h"
#if __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#include <llvm/Analysis/TargetLibraryInfo.h>
#include <llvm/Analysis/TargetTransformInfo.h>
#include <llvm/IR/DIBuilder.h>
@ -27,6 +32,8 @@
#include <llvm/IR/Verifier.h>
#include <llvm/InitializePasses.h>
#include <llvm/MC/SubtargetFeature.h>
#include <llvm/Object/Archive.h>
#include <llvm/Object/ArchiveWriter.h>
#include <llvm/PassRegistry.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/TargetParser.h>
@ -35,13 +42,17 @@
#include <llvm/Target/TargetMachine.h>
#include <llvm/Transforms/Coroutines.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/IPO/AlwaysInliner.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/Utils.h>
#include <lld/Common/Driver.h>
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#include <new>
#include <stdlib.h>
@ -703,7 +714,7 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
ZigLLVM_ObjectFormatType *oformat)
{
char *native_triple = LLVMGetDefaultTargetTriple();
Triple triple(native_triple);
Triple triple(Triple::normalize(native_triple));
*arch_type = (ZigLLVM_ArchType)triple.getArch();
*sub_arch_type = (ZigLLVM_SubArchType)triple.getSubArch();
@ -845,6 +856,42 @@ class MyOStream: public raw_ostream {
size_t pos;
};
bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
ZigLLVM_OSType os_type)
{
object::Archive::Kind kind;
switch (os_type) {
case ZigLLVM_Win32:
// For some reason llvm-lib passes K_GNU on windows.
// See lib/ToolDrivers/llvm-lib/LibDriver.cpp:168 in libDriverMain
kind = object::Archive::K_GNU;
break;
case ZigLLVM_Linux:
kind = object::Archive::K_GNU;
break;
case ZigLLVM_Darwin:
case ZigLLVM_IOS:
kind = object::Archive::K_DARWIN;
break;
case ZigLLVM_OpenBSD:
case ZigLLVM_FreeBSD:
kind = object::Archive::K_BSD;
break;
default:
kind = object::Archive::K_GNU;
}
SmallVector<NewArchiveMember, 4> new_members;
for (size_t i = 0; i < file_name_count; i += 1) {
Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
Error err = new_member.takeError();
if (err) return true;
new_members.push_back(std::move(*new_member));
}
Error err = writeArchive(archive_name, new_members, true, kind, true, false, nullptr);
if (err) return true;
return false;
}
bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
void (*append_diagnostic)(void *, const char *, size_t), void *context)

View File

@ -407,6 +407,9 @@ ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentT
ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
void (*append_diagnostic)(void *, const char *, size_t), void *context);
ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
enum ZigLLVM_OSType os_type);
ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,
enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
enum ZigLLVM_ObjectFormatType *oformat);

View File

@ -10,7 +10,7 @@ pub fn ArrayList(comptime T: type) type {
}
pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
return struct {
return struct.{
const Self = @This();
/// Use toSlice instead of slicing this directly, because if you don't
@ -22,8 +22,8 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn init(allocator: *Allocator) Self {
return Self{
.items = []align(A) T{},
return Self.{
.items = []align(A) T.{},
.len = 0,
.allocator = allocator,
};
@ -70,7 +70,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
/// allocated with `allocator`.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn fromOwnedSlice(allocator: *Allocator, slice: []align(A) T) Self {
return Self{
return Self.{
.items = slice,
.len = slice.len,
.allocator = allocator,
@ -179,7 +179,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
return self.pop();
}
pub const Iterator = struct {
pub const Iterator = struct.{
list: *const Self,
// how many items have we returned
count: usize,
@ -197,7 +197,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
};
pub fn iterator(self: *const Self) Iterator {
return Iterator{
return Iterator.{
.list = self,
.count = 0,
};
@ -251,7 +251,7 @@ test "std.ArrayList.basic" {
assert(list.pop() == 10);
assert(list.len == 9);
list.appendSlice([]const i32{
list.appendSlice([]const i32.{
1,
2,
3,
@ -262,7 +262,7 @@ test "std.ArrayList.basic" {
assert(list.pop() == 1);
assert(list.len == 9);
list.appendSlice([]const i32{}) catch unreachable;
list.appendSlice([]const i32.{}) catch unreachable;
assert(list.len == 9);
// can only set on indices < self.len
@ -382,7 +382,7 @@ test "std.ArrayList.insertSlice" {
try list.append(2);
try list.append(3);
try list.append(4);
try list.insertSlice(1, []const i32{
try list.insertSlice(1, []const i32.{
9,
8,
});
@ -393,7 +393,7 @@ test "std.ArrayList.insertSlice" {
assert(list.items[4] == 3);
assert(list.items[5] == 4);
const items = []const i32{1};
const items = []const i32.{1};
try list.insertSlice(0, items[0..0]);
assert(list.len == 6);
assert(list.items[0] == 1);

View File

@ -3,13 +3,13 @@ const AtomicOrder = builtin.AtomicOrder;
/// Thread-safe, lock-free integer
pub fn Int(comptime T: type) type {
return struct {
return struct.{
unprotected_value: T,
pub const Self = @This();
pub fn init(init_val: T) Self {
return Self{ .unprotected_value = init_val };
return Self.{ .unprotected_value = init_val };
}
/// Returns previous value
@ -29,5 +29,9 @@ pub fn Int(comptime T: type) type {
pub fn xchg(self: *Self, new_value: T) T {
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
}
pub fn fetchAdd(self: *Self, op: T) T {
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Add, op, AtomicOrder.SeqCst);
}
};
}

View File

@ -7,7 +7,7 @@ const assert = std.debug.assert;
/// Many producer, many consumer, non-allocating, thread-safe.
/// Uses a mutex to protect access.
pub fn Queue(comptime T: type) type {
return struct {
return struct.{
head: ?*Node,
tail: ?*Node,
mutex: std.Mutex,
@ -16,7 +16,7 @@ pub fn Queue(comptime T: type) type {
pub const Node = std.LinkedList(T).Node;
pub fn init() Self {
return Self{
return Self.{
.head = null,
.tail = null,
.mutex = std.Mutex.init(),
@ -103,30 +103,37 @@ pub fn Queue(comptime T: type) type {
}
pub fn dump(self: *Self) void {
var stderr_file = std.io.getStdErr() catch return;
const stderr = &stderr_file.outStream().stream;
const Error = @typeInfo(@typeOf(stderr)).Pointer.child.Error;
self.dumpToStream(Error, stderr) catch return;
}
pub fn dumpToStream(self: *Self, comptime Error: type, stream: *std.io.OutStream(Error)) Error!void {
const S = struct.{
fn dumpRecursive(s: *std.io.OutStream(Error), optional_node: ?*Node, indent: usize) Error!void {
try s.writeByteNTimes(' ', indent);
if (optional_node) |node| {
try s.print("0x{x}={}\n", @ptrToInt(node), node.data);
try dumpRecursive(s, node.next, indent + 1);
} else {
try s.print("(null)\n");
}
}
};
const held = self.mutex.acquire();
defer held.release();
std.debug.warn("head: ");
dumpRecursive(self.head, 0);
std.debug.warn("tail: ");
dumpRecursive(self.tail, 0);
}
fn dumpRecursive(optional_node: ?*Node, indent: usize) void {
var stderr_file = std.io.getStdErr() catch return;
const stderr = &std.io.FileOutStream.init(stderr_file).stream;
stderr.writeByteNTimes(' ', indent) catch return;
if (optional_node) |node| {
std.debug.warn("0x{x}={}\n", @ptrToInt(node), node.data);
dumpRecursive(node.next, indent + 1);
} else {
std.debug.warn("(null)\n");
}
try stream.print("head: ");
try S.dumpRecursive(stream, self.head, 0);
try stream.print("tail: ");
try S.dumpRecursive(stream, self.tail, 0);
}
};
}
const Context = struct {
const Context = struct.{
allocator: *std.mem.Allocator,
queue: *Queue(i32),
put_sum: isize,
@ -154,7 +161,7 @@ test "std.atomic.Queue" {
var a = &fixed_buffer_allocator.allocator;
var queue = Queue(i32).init();
var context = Context{
var context = Context.{
.allocator = a,
.queue = &queue,
.put_sum = 0,
@ -196,9 +203,9 @@ fn startPuts(ctx: *Context) u8 {
var put_count: usize = puts_per_thread;
var r = std.rand.DefaultPrng.init(0xdeadbeef);
while (put_count != 0) : (put_count -= 1) {
std.os.time.sleep(0, 1); // let the os scheduler be our fuzz
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.{
.prev = undefined,
.next = undefined,
.data = x,
@ -214,7 +221,7 @@ fn startGets(ctx: *Context) u8 {
const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
while (ctx.queue.get()) |node| {
std.os.time.sleep(0, 1); // let the os scheduler be our fuzz
std.os.time.sleep(1); // let the os scheduler be our fuzz
_ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
_ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
}
@ -226,14 +233,14 @@ fn startGets(ctx: *Context) u8 {
test "std.atomic.Queue single-threaded" {
var queue = Queue(i32).init();
var node_0 = Queue(i32).Node{
var node_0 = Queue(i32).Node.{
.data = 0,
.next = undefined,
.prev = undefined,
};
queue.put(&node_0);
var node_1 = Queue(i32).Node{
var node_1 = Queue(i32).Node.{
.data = 1,
.next = undefined,
.prev = undefined,
@ -242,14 +249,14 @@ test "std.atomic.Queue single-threaded" {
assert(queue.get().?.data == 0);
var node_2 = Queue(i32).Node{
var node_2 = Queue(i32).Node.{
.data = 2,
.next = undefined,
.prev = undefined,
};
queue.put(&node_2);
var node_3 = Queue(i32).Node{
var node_3 = Queue(i32).Node.{
.data = 3,
.next = undefined,
.prev = undefined,
@ -260,7 +267,7 @@ test "std.atomic.Queue single-threaded" {
assert(queue.get().?.data == 2);
var node_4 = Queue(i32).Node{
var node_4 = Queue(i32).Node.{
.data = 4,
.next = undefined,
.prev = undefined,
@ -274,3 +281,63 @@ test "std.atomic.Queue single-threaded" {
assert(queue.get() == null);
}
test "std.atomic.Queue dump" {
const mem = std.mem;
const SliceOutStream = std.io.SliceOutStream;
var buffer: [1024]u8 = undefined;
var expected_buffer: [1024]u8 = undefined;
var sos = SliceOutStream.init(buffer[0..]);
var queue = Queue(i32).init();
// Test empty stream
sos.reset();
try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
assert(mem.eql(u8, buffer[0..sos.pos],
\\head: (null)
\\tail: (null)
\\
));
// Test a stream with one element
var node_0 = Queue(i32).Node.{
.data = 1,
.next = undefined,
.prev = undefined,
};
queue.put(&node_0);
sos.reset();
try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
var expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ (null)
\\tail: 0x{x}=1
\\ (null)
\\
, @ptrToInt(queue.head), @ptrToInt(queue.tail));
assert(mem.eql(u8, buffer[0..sos.pos], expected));
// Test a stream with two elements
var node_1 = Queue(i32).Node.{
.data = 2,
.next = undefined,
.prev = undefined,
};
queue.put(&node_1);
sos.reset();
try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
expected = try std.fmt.bufPrint(expected_buffer[0..],
\\head: 0x{x}=1
\\ 0x{x}=2
\\ (null)
\\tail: 0x{x}=2
\\ (null)
\\
, @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail));
assert(mem.eql(u8, buffer[0..sos.pos], expected));
}

View File

@ -5,19 +5,19 @@ const AtomicOrder = builtin.AtomicOrder;
/// Many reader, many writer, non-allocating, thread-safe
/// Uses a spinlock to protect push() and pop()
pub fn Stack(comptime T: type) type {
return struct {
return struct.{
root: ?*Node,
lock: u8,
pub const Self = @This();
pub const Node = struct {
pub const Node = struct.{
next: ?*Node,
data: T,
};
pub fn init() Self {
return Self{
return Self.{
.root = null,
.lock = 0,
};
@ -54,7 +54,7 @@ pub fn Stack(comptime T: type) type {
}
const std = @import("../index.zig");
const Context = struct {
const Context = struct.{
allocator: *std.mem.Allocator,
stack: *Stack(i32),
put_sum: isize,
@ -81,7 +81,7 @@ test "std.atomic.stack" {
var a = &fixed_buffer_allocator.allocator;
var stack = Stack(i32).init();
var context = Context{
var context = Context.{
.allocator = a,
.stack = &stack,
.put_sum = 0,
@ -123,9 +123,9 @@ fn startPuts(ctx: *Context) u8 {
var put_count: usize = puts_per_thread;
var r = std.rand.DefaultPrng.init(0xdeadbeef);
while (put_count != 0) : (put_count -= 1) {
std.os.time.sleep(0, 1); // let the os scheduler be our fuzz
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.{
.next = undefined,
.data = x,
}) catch unreachable;
@ -140,7 +140,7 @@ fn startGets(ctx: *Context) u8 {
const last = @atomicLoad(u8, &ctx.puts_done, builtin.AtomicOrder.SeqCst) == 1;
while (ctx.stack.pop()) |node| {
std.os.time.sleep(0, 1); // let the os scheduler be our fuzz
std.os.time.sleep(1); // let the os scheduler be our fuzz
_ = @atomicRmw(isize, &ctx.get_sum, builtin.AtomicRmwOp.Add, node.data, builtin.AtomicOrder.SeqCst);
_ = @atomicRmw(usize, &ctx.get_count, builtin.AtomicRmwOp.Add, 1, builtin.AtomicOrder.SeqCst);
}

View File

@ -6,21 +6,21 @@ pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopq
pub const standard_pad_char = '=';
pub const standard_encoder = Base64Encoder.init(standard_alphabet_chars, standard_pad_char);
pub const Base64Encoder = struct {
pub const Base64Encoder = struct.{
alphabet_chars: []const u8,
pad_char: u8,
/// a bunch of assertions, then simply pass the data right through.
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Encoder {
assert(alphabet_chars.len == 64);
var char_in_alphabet = []bool{false} ** 256;
var char_in_alphabet = []bool.{false} ** 256;
for (alphabet_chars) |c| {
assert(!char_in_alphabet[c]);
assert(c != pad_char);
char_in_alphabet[c] = true;
}
return Base64Encoder{
return Base64Encoder.{
.alphabet_chars = alphabet_chars,
.pad_char = pad_char,
};
@ -77,7 +77,7 @@ pub const Base64Encoder = struct {
pub const standard_decoder = Base64Decoder.init(standard_alphabet_chars, standard_pad_char);
pub const Base64Decoder = struct {
pub const Base64Decoder = struct.{
/// e.g. 'A' => 0.
/// undefined for any value not in the 64 alphabet chars.
char_to_index: [256]u8,
@ -89,9 +89,9 @@ pub const Base64Decoder = struct {
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Decoder {
assert(alphabet_chars.len == 64);
var result = Base64Decoder{
var result = Base64Decoder.{
.char_to_index = undefined,
.char_in_alphabet = []bool{false} ** 256,
.char_in_alphabet = []bool.{false} ** 256,
.pad_char = pad_char,
};
@ -153,13 +153,13 @@ pub const Base64Decoder = struct {
}
};
pub const Base64DecoderWithIgnore = struct {
pub const Base64DecoderWithIgnore = struct.{
decoder: Base64Decoder,
char_is_ignored: [256]bool,
pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
var result = Base64DecoderWithIgnore{
var result = Base64DecoderWithIgnore.{
.decoder = Base64Decoder.init(alphabet_chars, pad_char),
.char_is_ignored = []bool{false} ** 256,
.char_is_ignored = []bool.{false} ** 256,
};
for (ignore_chars) |c| {
@ -270,7 +270,7 @@ pub const Base64DecoderWithIgnore = struct {
pub const standard_decoder_unsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, standard_pad_char);
pub const Base64DecoderUnsafe = struct {
pub const Base64DecoderUnsafe = struct.{
/// e.g. 'A' => 0.
/// undefined for any value not in the 64 alphabet chars.
char_to_index: [256]u8,
@ -278,7 +278,7 @@ pub const Base64DecoderUnsafe = struct {
pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe {
assert(alphabet_chars.len == 64);
var result = Base64DecoderUnsafe{
var result = Base64DecoderUnsafe.{
.char_to_index = undefined,
.pad_char = pad_char,
};

View File

@ -6,13 +6,13 @@ const assert = std.debug.assert;
/// BufMap copies keys and values before they go into the map, and
/// frees them when they get removed.
pub const BufMap = struct {
pub const BufMap = struct.{
hash_map: BufMapHashMap,
const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);
pub fn init(allocator: *Allocator) BufMap {
var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) };
var self = BufMap.{ .hash_map = BufMapHashMap.init(allocator) };
return self;
}

View File

@ -4,13 +4,13 @@ const mem = @import("mem.zig");
const Allocator = mem.Allocator;
const assert = std.debug.assert;
pub const BufSet = struct {
pub const BufSet = struct.{
hash_map: BufSetHashMap,
const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
pub fn init(a: *Allocator) BufSet {
var self = BufSet{ .hash_map = BufSetHashMap.init(a) };
var self = BufSet.{ .hash_map = BufSetHashMap.init(a) };
return self;
}

View File

@ -6,7 +6,7 @@ const assert = debug.assert;
const ArrayList = std.ArrayList;
/// A buffer that allocates memory and maintains a null byte at the end.
pub const Buffer = struct {
pub const Buffer = struct.{
list: ArrayList(u8),
/// Must deinitialize with deinit.
@ -28,11 +28,11 @@ pub const Buffer = struct {
/// * ::replaceContents
/// * ::resize
pub fn initNull(allocator: *Allocator) Buffer {
return Buffer{ .list = ArrayList(u8).init(allocator) };
return Buffer.{ .list = ArrayList(u8).init(allocator) };
}
/// Must deinitialize with deinit.
pub fn initFromBuffer(buffer: *const Buffer) !Buffer {
pub fn initFromBuffer(buffer: Buffer) !Buffer {
return Buffer.init(buffer.list.allocator, buffer.toSliceConst());
}
@ -40,7 +40,7 @@ pub const Buffer = struct {
/// allocated with `allocator`.
/// Must deinitialize with deinit.
pub fn fromOwnedSlice(allocator: *Allocator, slice: []u8) !Buffer {
var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) };
var self = Buffer.{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) };
try self.list.append(0);
return self;
}
@ -55,13 +55,13 @@ pub const Buffer = struct {
}
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: ...) !Buffer {
const countSize = struct {
fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
const countSize = struct.{
fn countSize(size: *usize, bytes: []const u8) (error.{}!void) {
size.* += bytes.len;
}
}.countSize;
var size: usize = 0;
std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
std.fmt.format(&size, error.{}, countSize, format, args) catch |err| switch (err) {};
var self = try Buffer.initSize(allocator, size);
assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
return self;
@ -148,7 +148,7 @@ test "simple Buffer" {
assert(buf.eql("hello world"));
assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
var buf2 = try Buffer.initFromBuffer(&buf);
var buf2 = try Buffer.initFromBuffer(buf);
assert(buf.eql(buf2.toSliceConst()));
assert(buf.startsWith("hell"));

View File

@ -15,7 +15,7 @@ const BufSet = std.BufSet;
const BufMap = std.BufMap;
const fmt_lib = std.fmt;
pub const Builder = struct {
pub const Builder = struct.{
uninstall_tls: TopLevelStep,
install_tls: TopLevelStep,
have_uninstall_step: bool,
@ -37,7 +37,7 @@ pub const Builder = struct {
invalid_user_input: bool,
zig_exe: []const u8,
default_step: *Step,
env_map: BufMap,
env_map: *const BufMap,
top_level_steps: ArrayList(*TopLevelStep),
prefix: []const u8,
search_prefixes: ArrayList([]const u8),
@ -48,7 +48,7 @@ pub const Builder = struct {
cache_root: []const u8,
release_mode: ?builtin.Mode,
pub const CStd = enum {
pub const CStd = enum.{
C89,
C99,
C11,
@ -57,25 +57,25 @@ pub const Builder = struct {
const UserInputOptionsMap = HashMap([]const u8, UserInputOption, mem.hash_slice_u8, mem.eql_slice_u8);
const AvailableOptionsMap = HashMap([]const u8, AvailableOption, mem.hash_slice_u8, mem.eql_slice_u8);
const AvailableOption = struct {
const AvailableOption = struct.{
name: []const u8,
type_id: TypeId,
description: []const u8,
};
const UserInputOption = struct {
const UserInputOption = struct.{
name: []const u8,
value: UserValue,
used: bool,
};
const UserValue = union(enum) {
const UserValue = union(enum).{
Flag: void,
Scalar: []const u8,
List: ArrayList([]const u8),
};
const TypeId = enum {
const TypeId = enum.{
Bool,
Int,
Float,
@ -83,13 +83,15 @@ pub const Builder = struct {
List,
};
const TopLevelStep = struct {
const TopLevelStep = struct.{
step: Step,
description: []const u8,
};
pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
var self = Builder{
const env_map = allocator.createOne(BufMap) catch unreachable;
env_map.* = os.getEnvMap(allocator) catch unreachable;
var self = Builder.{
.zig_exe = zig_exe,
.build_root = build_root,
.cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable,
@ -110,18 +112,18 @@ pub const Builder = struct {
.available_options_list = ArrayList(AvailableOption).init(allocator),
.top_level_steps = ArrayList(*TopLevelStep).init(allocator),
.default_step = undefined,
.env_map = os.getEnvMap(allocator) catch unreachable,
.env_map = env_map,
.prefix = undefined,
.search_prefixes = ArrayList([]const u8).init(allocator),
.lib_dir = undefined,
.exe_dir = undefined,
.installed_files = ArrayList([]const u8).init(allocator),
.uninstall_tls = TopLevelStep{
.uninstall_tls = TopLevelStep.{
.step = Step.init("uninstall", allocator, makeUninstall),
.description = "Remove build artifacts from prefix path",
},
.have_uninstall_step = false,
.install_tls = TopLevelStep{
.install_tls = TopLevelStep.{
.step = Step.initNoOp("install", allocator),
.description = "Copy build artifacts to prefix path",
},
@ -155,7 +157,7 @@ pub const Builder = struct {
return LibExeObjStep.createObject(self, name, root_src);
}
pub fn addSharedLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8, ver: *const Version) *LibExeObjStep {
pub fn addSharedLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
}
@ -178,7 +180,7 @@ pub const Builder = struct {
return LibExeObjStep.createCStaticLibrary(self, name);
}
pub fn addCSharedLibrary(self: *Builder, name: []const u8, ver: *const Version) *LibExeObjStep {
pub fn addCSharedLibrary(self: *Builder, name: []const u8, ver: Version) *LibExeObjStep {
return LibExeObjStep.createCSharedLibrary(self, name, ver);
}
@ -212,7 +214,7 @@ pub const Builder = struct {
}
pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {
return Version{
return Version.{
.major = major,
.minor = minor,
.patch = patch,
@ -356,7 +358,7 @@ pub const Builder = struct {
pub fn option(self: *Builder, comptime T: type, name: []const u8, description: []const u8) ?T {
const type_id = comptime typeToEnum(T);
const available_option = AvailableOption{
const available_option = AvailableOption.{
.name = name,
.type_id = type_id,
.description = description,
@ -408,7 +410,7 @@ 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.{
.step = Step.initNoOp(name, self.allocator),
.description = description,
}) catch unreachable;
@ -435,9 +437,9 @@ pub const Builder = struct {
pub fn addUserInputOption(self: *Builder, name: []const u8, value: []const u8) !bool {
const gop = try self.user_input_options.getOrPut(name);
if (!gop.found_existing) {
gop.kv.value = UserInputOption{
gop.kv.value = UserInputOption.{
.name = name,
.value = UserValue{ .Scalar = value },
.value = UserValue.{ .Scalar = value },
.used = false,
};
return false;
@ -450,18 +452,18 @@ pub const Builder = struct {
var list = ArrayList([]const u8).init(self.allocator);
list.append(s) catch unreachable;
list.append(value) catch unreachable;
_ = self.user_input_options.put(name, UserInputOption{
_ = self.user_input_options.put(name, UserInputOption.{
.name = name,
.value = UserValue{ .List = list },
.value = UserValue.{ .List = list },
.used = false,
}) catch unreachable;
},
UserValue.List => |*list| {
// append to the list
list.append(value) catch unreachable;
_ = self.user_input_options.put(name, UserInputOption{
_ = self.user_input_options.put(name, UserInputOption.{
.name = name,
.value = UserValue{ .List = list.* },
.value = UserValue.{ .List = list.* },
.used = false,
}) catch unreachable;
},
@ -476,9 +478,9 @@ pub const Builder = struct {
pub fn addUserInputFlag(self: *Builder, name: []const u8) !bool {
const gop = try self.user_input_options.getOrPut(name);
if (!gop.found_existing) {
gop.kv.value = UserInputOption{
gop.kv.value = UserInputOption.{
.name = name,
.value = UserValue{ .Flag = {} },
.value = UserValue.{ .Flag = {} },
.used = false,
};
return false;
@ -541,7 +543,7 @@ pub const Builder = struct {
}
fn spawnChild(self: *Builder, argv: []const []const u8) !void {
return self.spawnChildEnvMap(null, &self.env_map, argv);
return self.spawnChildEnvMap(null, self.env_map, argv);
}
fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void {
@ -634,7 +636,7 @@ pub const Builder = struct {
warn("Unable to create path {}: {}\n", dirname, @errorName(err));
return err;
};
os.copyFileMode(self.allocator, abs_source_path, dest_path, mode) catch |err| {
os.copyFileMode(abs_source_path, dest_path, mode) catch |err| {
warn("Unable to copy {} to {}: {}\n", abs_source_path, dest_path, @errorName(err));
return err;
};
@ -658,7 +660,7 @@ pub const Builder = struct {
pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
// TODO report error for ambiguous situations
const exe_extension = (Target{ .Native = {} }).exeFileExt();
const exe_extension = (Target.{ .Native = {} }).exeFileExt();
for (self.search_prefixes.toSliceConst()) |search_prefix| {
for (names) |name| {
if (os.path.isAbsolute(name)) {
@ -677,7 +679,7 @@ pub const Builder = struct {
if (os.path.isAbsolute(name)) {
return name;
}
var it = mem.split(PATH, []u8{os.path.delimiter});
var it = mem.split(PATH, []u8.{os.path.delimiter});
while (it.next()) |path| {
const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));
if (os.path.real(self.allocator, full_path)) |real_path| {
@ -731,19 +733,19 @@ pub const Builder = struct {
}
};
const Version = struct {
const Version = struct.{
major: u32,
minor: u32,
patch: u32,
};
const CrossTarget = struct {
const CrossTarget = struct.{
arch: builtin.Arch,
os: builtin.Os,
environ: builtin.Environ,
};
pub const Target = union(enum) {
pub const Target = union(enum).{
Native: void,
Cross: CrossTarget,
@ -798,7 +800,7 @@ pub const Target = union(enum) {
}
};
pub const LibExeObjStep = struct {
pub const LibExeObjStep = struct.{
step: Step,
builder: *Builder,
name: []const u8,
@ -834,28 +836,29 @@ pub const LibExeObjStep = struct {
assembly_files: ArrayList([]const u8),
packages: ArrayList(Pkg),
build_options_contents: std.Buffer,
system_linker_hack: bool,
// C only stuff
source_files: ArrayList([]const u8),
object_src: []const u8,
const Pkg = struct {
const Pkg = struct.{
name: []const u8,
path: []const u8,
};
const Kind = enum {
const Kind = enum.{
Exe,
Lib,
Obj,
};
pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: *const Version) *LibExeObjStep {
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;
return self;
}
pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: *const Version) *LibExeObjStep {
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;
return self;
}
@ -891,8 +894,8 @@ pub const LibExeObjStep = struct {
return self;
}
fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: *const Version) LibExeObjStep {
var self = LibExeObjStep{
fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: Version) LibExeObjStep {
var self = LibExeObjStep.{
.no_rosegment = false,
.strip = false,
.builder = builder,
@ -909,7 +912,7 @@ pub const LibExeObjStep = struct {
.step = Step.init(name, builder.allocator, make),
.output_path = null,
.output_h_path = null,
.version = ver.*,
.version = ver,
.out_filename = undefined,
.out_h_filename = builder.fmt("{}.h", name),
.major_only_filename = undefined,
@ -928,18 +931,19 @@ pub const LibExeObjStep = struct {
.disable_libc = true,
.build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
.c_std = Builder.CStd.C99,
.system_linker_hack = false,
};
self.computeOutFileNames();
return self;
}
fn initC(builder: *Builder, name: []const u8, kind: Kind, version: *const Version, static: bool) LibExeObjStep {
var self = LibExeObjStep{
fn initC(builder: *Builder, name: []const u8, kind: Kind, version: Version, static: bool) LibExeObjStep {
var self = LibExeObjStep.{
.no_rosegment = false,
.builder = builder,
.name = name,
.kind = kind,
.version = version.*,
.version = version,
.static = static,
.target = Target.Native,
.cflags = ArrayList([]const u8).init(builder.allocator),
@ -963,6 +967,7 @@ pub const LibExeObjStep = struct {
.is_zig = false,
.linker_script = null,
.c_std = Builder.CStd.C99,
.system_linker_hack = false,
.root_src = undefined,
.verbose_link = false,
@ -1013,8 +1018,8 @@ pub const LibExeObjStep = struct {
}
pub fn setTarget(self: *LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
self.target = Target{
.Cross = CrossTarget{
self.target = Target.{
.Cross = CrossTarget.{
.arch = target_arch,
.os = target_os,
.environ = target_environ,
@ -1143,7 +1148,7 @@ pub const LibExeObjStep = struct {
pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
assert(self.is_zig);
self.packages.append(Pkg{
self.packages.append(Pkg.{
.name = name,
.path = pkg_index_path,
}) catch unreachable;
@ -1160,6 +1165,10 @@ pub const LibExeObjStep = struct {
self.disable_libc = disable;
}
pub fn enableSystemLinkerHack(self: *LibExeObjStep) void {
self.system_linker_hack = true;
}
fn make(step: *Step) !void {
const self = @fieldParentPtr(LibExeObjStep, "step", step);
return if (self.is_zig) self.makeZig() else self.makeC();
@ -1336,6 +1345,9 @@ pub const LibExeObjStep = struct {
if (self.no_rosegment) {
try zig_args.append("--no-rosegment");
}
if (self.system_linker_hack) {
try zig_args.append("--system-linker-hack");
}
try builder.spawnChild(zig_args.toSliceConst());
@ -1628,7 +1640,7 @@ pub const LibExeObjStep = struct {
}
};
pub const TestStep = struct {
pub const TestStep = struct.{
step: Step,
builder: *Builder,
root_src: []const u8,
@ -1644,10 +1656,11 @@ pub const TestStep = struct {
object_files: ArrayList([]const u8),
no_rosegment: bool,
output_path: ?[]const u8,
system_linker_hack: bool,
pub fn init(builder: *Builder, root_src: []const u8) TestStep {
const step_name = builder.fmt("test {}", root_src);
return TestStep{
return TestStep.{
.step = Step.init(step_name, builder.allocator, make),
.builder = builder,
.root_src = root_src,
@ -1656,13 +1669,14 @@ pub const TestStep = struct {
.name_prefix = "",
.filter = null,
.link_libs = BufSet.init(builder.allocator),
.target = Target{ .Native = {} },
.target = Target.{ .Native = {} },
.exec_cmd_args = null,
.include_dirs = ArrayList([]const u8).init(builder.allocator),
.lib_paths = ArrayList([]const u8).init(builder.allocator),
.object_files = ArrayList([]const u8).init(builder.allocator),
.no_rosegment = false,
.output_path = null,
.system_linker_hack = false,
};
}
@ -1732,8 +1746,8 @@ pub const TestStep = struct {
}
pub fn setTarget(self: *TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
self.target = Target{
.Cross = CrossTarget{
self.target = Target.{
.Cross = CrossTarget.{
.arch = target_arch,
.os = target_os,
.environ = target_environ,
@ -1745,6 +1759,10 @@ pub const TestStep = struct {
self.exec_cmd_args = args;
}
pub fn enableSystemLinkerHack(self: *TestStep) void {
self.system_linker_hack = true;
}
fn make(step: *Step) !void {
const self = @fieldParentPtr(TestStep, "step", step);
const builder = self.builder;
@ -1849,12 +1867,15 @@ pub const TestStep = struct {
if (self.no_rosegment) {
try zig_args.append("--no-rosegment");
}
if (self.system_linker_hack) {
try zig_args.append("--system-linker-hack");
}
try builder.spawnChild(zig_args.toSliceConst());
}
};
pub const CommandStep = struct {
pub const CommandStep = struct.{
step: Step,
builder: *Builder,
argv: [][]const u8,
@ -1863,7 +1884,7 @@ 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.{
.builder = builder,
.step = Step.init(argv[0], builder.allocator, make),
.argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
@ -1884,7 +1905,7 @@ pub const CommandStep = struct {
}
};
const InstallArtifactStep = struct {
const InstallArtifactStep = struct.{
step: Step,
builder: *Builder,
artifact: *LibExeObjStep,
@ -1898,7 +1919,7 @@ 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.{
.builder = builder,
.step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
.artifact = artifact,
@ -1932,14 +1953,14 @@ const InstallArtifactStep = struct {
}
};
pub const InstallFileStep = struct {
pub const InstallFileStep = struct.{
step: Step,
builder: *Builder,
src_path: []const u8,
dest_path: []const u8,
pub fn init(builder: *Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep {
return InstallFileStep{
return InstallFileStep.{
.builder = builder,
.step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make),
.src_path = src_path,
@ -1953,14 +1974,14 @@ pub const InstallFileStep = struct {
}
};
pub const WriteFileStep = struct {
pub const WriteFileStep = struct.{
step: Step,
builder: *Builder,
file_path: []const u8,
data: []const u8,
pub fn init(builder: *Builder, file_path: []const u8, data: []const u8) WriteFileStep {
return WriteFileStep{
return WriteFileStep.{
.builder = builder,
.step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make),
.file_path = file_path,
@ -1983,13 +2004,13 @@ pub const WriteFileStep = struct {
}
};
pub const LogStep = struct {
pub const LogStep = struct.{
step: Step,
builder: *Builder,
data: []const u8,
pub fn init(builder: *Builder, data: []const u8) LogStep {
return LogStep{
return LogStep.{
.builder = builder,
.step = Step.init(builder.fmt("log {}", data), builder.allocator, make),
.data = data,
@ -2002,13 +2023,13 @@ pub const LogStep = struct {
}
};
pub const RemoveDirStep = struct {
pub const RemoveDirStep = struct.{
step: Step,
builder: *Builder,
dir_path: []const u8,
pub fn init(builder: *Builder, dir_path: []const u8) RemoveDirStep {
return RemoveDirStep{
return RemoveDirStep.{
.builder = builder,
.step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make),
.dir_path = dir_path,
@ -2026,7 +2047,7 @@ pub const RemoveDirStep = struct {
}
};
pub const Step = struct {
pub const Step = struct.{
name: []const u8,
makeFn: fn (self: *Step) error!void,
dependencies: ArrayList(*Step),
@ -2034,7 +2055,7 @@ pub const Step = struct {
done_flag: bool,
pub fn init(name: []const u8, allocator: *Allocator, makeFn: fn (*Step) error!void) Step {
return Step{
return Step.{
.name = name,
.makeFn = makeFn,
.dependencies = ArrayList(*Step).init(allocator),

View File

@ -52,18 +52,18 @@ pub const _errno = __error;
pub const in_port_t = u16;
pub const sa_family_t = u8;
pub const socklen_t = u32;
pub const sockaddr = extern union {
pub const sockaddr = extern union.{
in: sockaddr_in,
in6: sockaddr_in6,
};
pub const sockaddr_in = extern struct {
pub const sockaddr_in = extern struct.{
len: u8,
family: sa_family_t,
port: in_port_t,
addr: u32,
zero: [8]u8,
};
pub const sockaddr_in6 = extern struct {
pub const sockaddr_in6 = extern struct.{
len: u8,
family: sa_family_t,
port: in_port_t,
@ -72,23 +72,23 @@ pub const sockaddr_in6 = extern struct {
scope_id: u32,
};
pub const timeval = extern struct {
pub const timeval = extern struct.{
tv_sec: isize,
tv_usec: isize,
};
pub const timezone = extern struct {
pub const timezone = extern struct.{
tz_minuteswest: i32,
tz_dsttime: i32,
};
pub const mach_timebase_info_data = extern struct {
pub const mach_timebase_info_data = extern struct.{
numer: u32,
denom: u32,
};
/// Renamed to Stat to not conflict with the stat function.
pub const Stat = extern struct {
pub const Stat = extern struct.{
dev: i32,
mode: u16,
nlink: u16,
@ -113,7 +113,7 @@ pub const Stat = extern struct {
qspare: [2]i64,
};
pub const timespec = extern struct {
pub const timespec = extern struct.{
tv_sec: isize,
tv_nsec: isize,
};
@ -121,13 +121,13 @@ pub const timespec = extern struct {
pub const sigset_t = u32;
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
pub const Sigaction = extern struct {
pub const Sigaction = extern struct.{
handler: extern fn (c_int) void,
sa_mask: sigset_t,
sa_flags: c_int,
};
pub const dirent = extern struct {
pub const dirent = extern struct.{
d_ino: usize,
d_seekoff: usize,
d_reclen: u16,
@ -136,13 +136,13 @@ pub const dirent = extern struct {
d_name: u8, // field address is address of first byte of name
};
pub const pthread_attr_t = extern struct {
pub const pthread_attr_t = extern struct.{
__sig: c_long,
__opaque: [56]u8,
};
/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
pub const Kevent = extern struct {
pub const Kevent = extern struct.{
ident: usize,
filter: i16,
flags: u16,
@ -158,15 +158,15 @@ const std = @import("../index.zig");
const assert = std.debug.assert;
comptime {
assert(@offsetOf(Kevent, "ident") == 0);
assert(@offsetOf(Kevent, "filter") == 8);
assert(@offsetOf(Kevent, "flags") == 10);
assert(@offsetOf(Kevent, "fflags") == 12);
assert(@offsetOf(Kevent, "data") == 16);
assert(@offsetOf(Kevent, "udata") == 24);
assert(@byteOffsetOf(Kevent, "ident") == 0);
assert(@byteOffsetOf(Kevent, "filter") == 8);
assert(@byteOffsetOf(Kevent, "flags") == 10);
assert(@byteOffsetOf(Kevent, "fflags") == 12);
assert(@byteOffsetOf(Kevent, "data") == 16);
assert(@byteOffsetOf(Kevent, "udata") == 24);
}
pub const kevent64_s = extern struct {
pub const kevent64_s = extern struct.{
ident: u64,
filter: i16,
flags: u16,
@ -180,11 +180,11 @@ pub const kevent64_s = extern struct {
// to make sure the struct is laid out the same. These values were
// produced from C code using the offsetof macro.
comptime {
assert(@offsetOf(kevent64_s, "ident") == 0);
assert(@offsetOf(kevent64_s, "filter") == 8);
assert(@offsetOf(kevent64_s, "flags") == 10);
assert(@offsetOf(kevent64_s, "fflags") == 12);
assert(@offsetOf(kevent64_s, "data") == 16);
assert(@offsetOf(kevent64_s, "udata") == 24);
assert(@offsetOf(kevent64_s, "ext") == 32);
assert(@byteOffsetOf(kevent64_s, "ident") == 0);
assert(@byteOffsetOf(kevent64_s, "filter") == 8);
assert(@byteOffsetOf(kevent64_s, "flags") == 10);
assert(@byteOffsetOf(kevent64_s, "fflags") == 12);
assert(@byteOffsetOf(kevent64_s, "data") == 16);
assert(@byteOffsetOf(kevent64_s, "udata") == 24);
assert(@byteOffsetOf(kevent64_s, "ext") == 32);
}

View File

@ -4,7 +4,7 @@ pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int
extern "c" fn __errno_location() *c_int;
pub const _errno = __errno_location;
pub const pthread_attr_t = extern struct {
pub const pthread_attr_t = extern struct.{
__size: [56]u8,
__align: c_long,
};

View File

@ -20,14 +20,14 @@ const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
const DEBUG_DIRECTORY = 6;
pub const CoffError = error{
pub const CoffError = error.{
InvalidPEMagic,
InvalidPEHeader,
InvalidMachine,
MissingCoffSection,
};
pub const Coff = struct {
pub const Coff = struct.{
in_file: os.File,
allocator: *mem.Allocator,
@ -41,7 +41,7 @@ pub const Coff = struct {
pub fn loadHeader(self: *Coff) !void {
const pe_pointer_offset = 0x3C;
var file_stream = io.FileInStream.init(self.in_file);
var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var magic: [2]u8 = undefined;
@ -56,10 +56,10 @@ pub const Coff = struct {
var pe_header_magic: [4]u8 = undefined;
try in.readNoEof(pe_header_magic[0..]);
if (!mem.eql(u8, pe_header_magic, []u8{ 'P', 'E', 0, 0 }))
if (!mem.eql(u8, pe_header_magic, []u8.{ 'P', 'E', 0, 0 }))
return error.InvalidPEHeader;
self.coff_header = CoffHeader{
self.coff_header = CoffHeader.{
.machine = try in.readIntLe(u16),
.number_of_sections = try in.readIntLe(u16),
.timedate_stamp = try in.readIntLe(u32),
@ -77,7 +77,7 @@ pub const Coff = struct {
try self.loadOptionalHeader(&file_stream);
}
fn loadOptionalHeader(self: *Coff, file_stream: *io.FileInStream) !void {
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
const in = &file_stream.stream;
self.pe_header.magic = try in.readIntLe(u16);
// For now we're only interested in finding the reference to the .pdb,
@ -98,7 +98,7 @@ pub const Coff = struct {
return error.InvalidPEHeader;
for (self.pe_header.data_directory) |*data_dir| {
data_dir.* = OptionalHeader.DataDirectory{
data_dir.* = OptionalHeader.DataDirectory.{
.virtual_address = try in.readIntLe(u32),
.size = try in.readIntLe(u32),
};
@ -115,7 +115,7 @@ pub const Coff = struct {
const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
try self.in_file.seekTo(file_offset + debug_dir.size);
var file_stream = io.FileInStream.init(self.in_file);
var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var cv_signature: [4]u8 = undefined; // CodeView signature
@ -146,7 +146,7 @@ pub const Coff = struct {
self.sections = ArrayList(Section).init(self.allocator);
var file_stream = io.FileInStream.init(self.in_file);
var file_stream = self.in_file.inStream();
const in = &file_stream.stream;
var name: [8]u8 = undefined;
@ -154,10 +154,10 @@ pub const Coff = struct {
var i: u16 = 0;
while (i < self.coff_header.number_of_sections) : (i += 1) {
try in.readNoEof(name[0..]);
try self.sections.append(Section{
.header = SectionHeader{
try self.sections.append(Section.{
.header = SectionHeader.{
.name = name,
.misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
.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),
@ -181,7 +181,7 @@ pub const Coff = struct {
}
};
const CoffHeader = struct {
const CoffHeader = struct.{
machine: u16,
number_of_sections: u16,
timedate_stamp: u32,
@ -191,8 +191,8 @@ const CoffHeader = struct {
characteristics: u16,
};
const OptionalHeader = struct {
const DataDirectory = struct {
const OptionalHeader = struct.{
const DataDirectory = struct.{
virtual_address: u32,
size: u32,
};
@ -201,12 +201,12 @@ const OptionalHeader = struct {
data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory,
};
pub const Section = struct {
pub const Section = struct.{
header: SectionHeader,
};
const SectionHeader = struct {
const Misc = union {
const SectionHeader = struct.{
const Misc = union.{
physical_address: u32,
virtual_size: u32,
};

View File

@ -5,7 +5,7 @@ const debug = @import("../debug/index.zig");
const builtin = @import("builtin");
const htest = @import("test.zig");
const RoundParam = struct {
const RoundParam = struct.{
a: usize,
b: usize,
c: usize,
@ -15,7 +15,7 @@ const RoundParam = struct {
};
fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
return RoundParam{
return RoundParam.{
.a = a,
.b = b,
.c = c,
@ -32,12 +32,12 @@ pub const Blake2s224 = Blake2s(224);
pub const Blake2s256 = Blake2s(256);
fn Blake2s(comptime out_len: usize) type {
return struct {
return struct.{
const Self = @This();
const block_length = 64;
const digest_length = out_len / 8;
const iv = [8]u32{
const iv = [8]u32.{
0x6A09E667,
0xBB67AE85,
0x3C6EF372,
@ -48,17 +48,17 @@ fn Blake2s(comptime out_len: usize) type {
0x5BE0CD19,
};
const sigma = [10][16]u8{
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
const sigma = [10][16]u8.{
[]const u8.{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8.{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8.{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8.{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8.{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8.{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8.{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8.{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8.{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8.{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
};
h: [8]u32,
@ -147,7 +147,7 @@ fn Blake2s(comptime out_len: usize) type {
v[13] ^= @intCast(u32, d.t >> 32);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
const rounds = comptime []RoundParam.{
Rp(0, 4, 8, 12, 0, 1),
Rp(1, 5, 9, 13, 2, 3),
Rp(2, 6, 10, 14, 4, 5),
@ -250,7 +250,7 @@ test "blake2s256 streaming" {
}
test "blake2s256 aligned final" {
var block = []u8{0} ** Blake2s256.block_length;
var block = []u8.{0} ** Blake2s256.block_length;
var out: [Blake2s256.digest_length]u8 = undefined;
var h = Blake2s256.init();
@ -265,12 +265,12 @@ pub const Blake2b384 = Blake2b(384);
pub const Blake2b512 = Blake2b(512);
fn Blake2b(comptime out_len: usize) type {
return struct {
return struct.{
const Self = @This();
const block_length = 128;
const digest_length = out_len / 8;
const iv = [8]u64{
const iv = [8]u64.{
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
@ -281,19 +281,19 @@ fn Blake2b(comptime out_len: usize) type {
0x5be0cd19137e2179,
};
const sigma = [12][16]u8{
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
[]const u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
const sigma = [12][16]u8.{
[]const u8.{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8.{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
[]const u8.{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
[]const u8.{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
[]const u8.{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
[]const u8.{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
[]const u8.{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
[]const u8.{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
[]const u8.{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
[]const u8.{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
[]const u8.{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
[]const u8.{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
};
h: [8]u64,
@ -380,7 +380,7 @@ fn Blake2b(comptime out_len: usize) type {
v[13] ^= @intCast(u64, d.t >> 64);
if (last) v[14] = ~v[14];
const rounds = comptime []RoundParam{
const rounds = comptime []RoundParam.{
Rp(0, 4, 8, 12, 0, 1),
Rp(1, 5, 9, 13, 2, 3),
Rp(2, 6, 10, 14, 4, 5),
@ -483,7 +483,7 @@ test "blake2b512 streaming" {
}
test "blake2b512 aligned final" {
var block = []u8{0} ** Blake2b512.block_length;
var block = []u8.{0} ** Blake2b512.block_length;
var out: [Blake2b512.digest_length]u8 = undefined;
var h = Blake2b512.init();

View File

@ -5,8 +5,9 @@ const mem = std.mem;
const endian = std.endian;
const assert = std.debug.assert;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
const QuarterRound = struct {
const QuarterRound = struct.{
a: usize,
b: usize,
c: usize,
@ -14,7 +15,7 @@ const QuarterRound = struct {
};
fn Rp(a: usize, b: usize, c: usize, d: usize) QuarterRound {
return QuarterRound{
return QuarterRound.{
.a = a,
.b = b,
.c = c,
@ -31,7 +32,7 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
for (x) |_, i|
x[i] = input[i];
const rounds = comptime []QuarterRound{
const rounds = comptime []QuarterRound.{
Rp(0, 4, 8, 12),
Rp(1, 5, 9, 13),
Rp(2, 6, 10, 14),
@ -68,7 +69,7 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
var cursor: usize = 0;
const c = "expand 32-byte k";
const constant_le = []u32{
const constant_le = []u32.{
mem.readIntLE(u32, c[0..4]),
mem.readIntLE(u32, c[4..8]),
mem.readIntLE(u32, c[8..12]),
@ -111,7 +112,7 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
/// counter, nonce, and key.
pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce: [12]u8) void {
assert(in.len >= out.len);
assert((in.len >> 6) + counter <= @maxValue(u32));
assert((in.len >> 6) + counter <= maxInt(u32));
var k: [8]u32 = undefined;
var c: [4]u32 = undefined;
@ -161,7 +162,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
const big_block = (block_size << 32);
// first partial big block
if (((@intCast(u64, @maxValue(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
if (((@intCast(u64, maxInt(u32) - @truncate(u32, counter)) + 1) << 6) < in.len) {
chaCha20_internal(out[cursor..big_block], in[cursor..big_block], k, c);
cursor = big_block - cursor;
c[1] += 1;
@ -182,7 +183,7 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
// https://tools.ietf.org/html/rfc7539#section-2.4.2
test "crypto.chacha20 test vector sunscreen" {
const expected_result = []u8{
const expected_result = []u8.{
0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80,
0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81,
0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2,
@ -201,13 +202,13 @@ test "crypto.chacha20 test vector sunscreen" {
};
const input = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
var result: [114]u8 = undefined;
const key = []u8{
const key = []u8.{
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
};
const nonce = []u8{
const nonce = []u8.{
0, 0, 0, 0,
0, 0, 0, 0x4a,
0, 0, 0, 0,
@ -224,7 +225,7 @@ test "crypto.chacha20 test vector sunscreen" {
// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
test "crypto.chacha20 test vector 1" {
const expected_result = []u8{
const expected_result = []u8.{
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
@ -234,7 +235,7 @@ test "crypto.chacha20 test vector 1" {
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
};
const input = []u8{
const input = []u8.{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -245,20 +246,20 @@ test "crypto.chacha20 test vector 1" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = []u8.{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
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));
}
test "crypto.chacha20 test vector 2" {
const expected_result = []u8{
const expected_result = []u8.{
0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
@ -268,7 +269,7 @@ test "crypto.chacha20 test vector 2" {
0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
};
const input = []u8{
const input = []u8.{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -279,20 +280,20 @@ test "crypto.chacha20 test vector 2" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = []u8.{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
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));
}
test "crypto.chacha20 test vector 3" {
const expected_result = []u8{
const expected_result = []u8.{
0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
@ -302,7 +303,7 @@ test "crypto.chacha20 test vector 3" {
0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
0x44, 0x5f, 0x41, 0xe3,
};
const input = []u8{
const input = []u8.{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -313,20 +314,20 @@ test "crypto.chacha20 test vector 3" {
0x00, 0x00, 0x00, 0x00,
};
var result: [60]u8 = undefined;
const key = []u8{
const key = []u8.{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
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));
}
test "crypto.chacha20 test vector 4" {
const expected_result = []u8{
const expected_result = []u8.{
0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
@ -336,7 +337,7 @@ test "crypto.chacha20 test vector 4" {
0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
};
const input = []u8{
const input = []u8.{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -347,20 +348,20 @@ test "crypto.chacha20 test vector 4" {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
var result: [64]u8 = undefined;
const key = []u8{
const key = []u8.{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
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));
}
test "crypto.chacha20 test vector 5" {
const expected_result = []u8{
const expected_result = []u8.{
0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
@ -397,7 +398,7 @@ test "crypto.chacha20 test vector 5" {
0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
};
const input = []u8{
const input = []u8.{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -417,13 +418,13 @@ test "crypto.chacha20 test vector 5" {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
var result: [256]u8 = undefined;
const key = []u8{
const key = []u8.{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
const nonce = []u8{
const nonce = []u8.{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
};

View File

@ -6,9 +6,10 @@ const mem = std.mem;
pub const HmacMd5 = Hmac(crypto.Md5);
pub const HmacSha1 = Hmac(crypto.Sha1);
pub const HmacSha256 = Hmac(crypto.Sha256);
pub const HmacBlake2s256 = Hmac(crypto.Blake2s256);
pub fn Hmac(comptime Hash: type) type {
return struct {
return struct.{
const Self = @This();
pub const mac_length = Hash.digest_length;
pub const minimum_key_length = 0;

View File

@ -23,6 +23,7 @@ const hmac = @import("hmac.zig");
pub const HmacMd5 = hmac.HmacMd5;
pub const HmacSha1 = hmac.HmacSha1;
pub const HmacSha256 = hmac.HmacSha256;
pub const HmacBlake2s256 = hmac.HmacBlake2s256;
const import_chaCha20 = @import("chacha20.zig");
pub const chaCha20IETF = import_chaCha20.chaCha20IETF;

View File

@ -5,7 +5,7 @@ const builtin = @import("builtin");
const debug = @import("../debug/index.zig");
const fmt = @import("../fmt/index.zig");
const RoundParam = struct {
const RoundParam = struct.{
a: usize,
b: usize,
c: usize,
@ -16,7 +16,7 @@ const RoundParam = struct {
};
fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam {
return RoundParam{
return RoundParam.{
.a = a,
.b = b,
.c = c,
@ -27,7 +27,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar
};
}
pub const Md5 = struct {
pub const Md5 = struct.{
const Self = @This();
const block_length = 64;
const digest_length = 16;
@ -131,14 +131,14 @@ pub const Md5 = struct {
s[i] |= u32(b[i * 4 + 3]) << 24;
}
var v: [4]u32 = []u32{
var v: [4]u32 = []u32.{
d.s[0],
d.s[1],
d.s[2],
d.s[3],
};
const round0 = comptime []RoundParam{
const round0 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
@ -161,7 +161,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round1 = comptime []RoundParam{
const round1 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),
@ -184,7 +184,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round2 = comptime []RoundParam{
const round2 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),
@ -207,7 +207,7 @@ pub const Md5 = struct {
v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
}
const round3 = comptime []RoundParam{
const round3 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),
@ -271,7 +271,7 @@ test "md5 streaming" {
}
test "md5 aligned final" {
var block = []u8{0} ** Md5.block_length;
var block = []u8.{0} ** Md5.block_length;
var out: [Md5.digest_length]u8 = undefined;
var h = Md5.init();

View File

@ -9,7 +9,7 @@ const Endian = builtin.Endian;
const readInt = std.mem.readInt;
const writeInt = std.mem.writeInt;
pub const Poly1305 = struct {
pub const Poly1305 = struct.{
const Self = @This();
pub const mac_length = 16;

View File

@ -4,7 +4,7 @@ const endian = @import("../endian.zig");
const debug = @import("../debug/index.zig");
const builtin = @import("builtin");
const RoundParam = struct {
const RoundParam = struct.{
a: usize,
b: usize,
c: usize,
@ -14,7 +14,7 @@ const RoundParam = struct {
};
fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
return RoundParam{
return RoundParam.{
.a = a,
.b = b,
.c = c,
@ -24,7 +24,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
};
}
pub const Sha1 = struct {
pub const Sha1 = struct.{
const Self = @This();
const block_length = 64;
const digest_length = 20;
@ -118,7 +118,7 @@ pub const Sha1 = struct {
var s: [16]u32 = undefined;
var v: [5]u32 = []u32{
var v: [5]u32 = []u32.{
d.s[0],
d.s[1],
d.s[2],
@ -126,7 +126,7 @@ pub const Sha1 = struct {
d.s[4],
};
const round0a = comptime []RoundParam{
const round0a = comptime []RoundParam.{
Rp(0, 1, 2, 3, 4, 0),
Rp(4, 0, 1, 2, 3, 1),
Rp(3, 4, 0, 1, 2, 2),
@ -151,7 +151,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round0b = comptime []RoundParam{
const round0b = comptime []RoundParam.{
Rp(4, 0, 1, 2, 3, 16),
Rp(3, 4, 0, 1, 2, 17),
Rp(2, 3, 4, 0, 1, 18),
@ -165,7 +165,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round1 = comptime []RoundParam{
const round1 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 4, 20),
Rp(4, 0, 1, 2, 3, 21),
Rp(3, 4, 0, 1, 2, 22),
@ -195,7 +195,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round2 = comptime []RoundParam{
const round2 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 4, 40),
Rp(4, 0, 1, 2, 3, 41),
Rp(3, 4, 0, 1, 2, 42),
@ -225,7 +225,7 @@ pub const Sha1 = struct {
v[r.b] = math.rotl(u32, v[r.b], u32(30));
}
const round3 = comptime []RoundParam{
const round3 = comptime []RoundParam.{
Rp(0, 1, 2, 3, 4, 60),
Rp(4, 0, 1, 2, 3, 61),
Rp(3, 4, 0, 1, 2, 62),
@ -292,7 +292,7 @@ test "sha1 streaming" {
}
test "sha1 aligned final" {
var block = []u8{0} ** Sha1.block_length;
var block = []u8.{0} ** Sha1.block_length;
var out: [Sha1.digest_length]u8 = undefined;
var h = Sha1.init();

View File

@ -8,7 +8,7 @@ const htest = @import("test.zig");
/////////////////////
// Sha224 + Sha256
const RoundParam256 = struct {
const RoundParam256 = struct.{
a: usize,
b: usize,
c: usize,
@ -22,7 +22,7 @@ const RoundParam256 = struct {
};
fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 {
return RoundParam256{
return RoundParam256.{
.a = a,
.b = b,
.c = c,
@ -36,7 +36,7 @@ fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h
};
}
const Sha2Params32 = struct {
const Sha2Params32 = struct.{
iv0: u32,
iv1: u32,
iv2: u32,
@ -48,7 +48,7 @@ const Sha2Params32 = struct {
out_len: usize,
};
const Sha224Params = Sha2Params32{
const Sha224Params = Sha2Params32.{
.iv0 = 0xC1059ED8,
.iv1 = 0x367CD507,
.iv2 = 0x3070DD17,
@ -60,7 +60,7 @@ const Sha224Params = Sha2Params32{
.out_len = 224,
};
const Sha256Params = Sha2Params32{
const Sha256Params = Sha2Params32.{
.iv0 = 0x6A09E667,
.iv1 = 0xBB67AE85,
.iv2 = 0x3C6EF372,
@ -76,7 +76,7 @@ pub const Sha224 = Sha2_32(Sha224Params);
pub const Sha256 = Sha2_32(Sha256Params);
fn Sha2_32(comptime params: Sha2Params32) type {
return struct {
return struct.{
const Self = @This();
const block_length = 64;
const digest_length = params.out_len / 8;
@ -188,7 +188,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], u32(7)) ^ math.rotr(u32, s[i - 15], u32(18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], u32(17)) ^ math.rotr(u32, s[i - 2], u32(19)) ^ (s[i - 2] >> 10));
}
var v: [8]u32 = []u32{
var v: [8]u32 = []u32.{
d.s[0],
d.s[1],
d.s[2],
@ -199,7 +199,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
d.s[7],
};
const round0 = comptime []RoundParam256{
const round0 = comptime []RoundParam256.{
Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),
Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),
Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),
@ -338,7 +338,7 @@ test "sha256 streaming" {
}
test "sha256 aligned final" {
var block = []u8{0} ** Sha256.block_length;
var block = []u8.{0} ** Sha256.block_length;
var out: [Sha256.digest_length]u8 = undefined;
var h = Sha256.init();
@ -349,7 +349,7 @@ test "sha256 aligned final" {
/////////////////////
// Sha384 + Sha512
const RoundParam512 = struct {
const RoundParam512 = struct.{
a: usize,
b: usize,
c: usize,
@ -363,7 +363,7 @@ const RoundParam512 = struct {
};
fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 {
return RoundParam512{
return RoundParam512.{
.a = a,
.b = b,
.c = c,
@ -377,7 +377,7 @@ fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h
};
}
const Sha2Params64 = struct {
const Sha2Params64 = struct.{
iv0: u64,
iv1: u64,
iv2: u64,
@ -389,7 +389,7 @@ const Sha2Params64 = struct {
out_len: usize,
};
const Sha384Params = Sha2Params64{
const Sha384Params = Sha2Params64.{
.iv0 = 0xCBBB9D5DC1059ED8,
.iv1 = 0x629A292A367CD507,
.iv2 = 0x9159015A3070DD17,
@ -401,7 +401,7 @@ const Sha384Params = Sha2Params64{
.out_len = 384,
};
const Sha512Params = Sha2Params64{
const Sha512Params = Sha2Params64.{
.iv0 = 0x6A09E667F3BCC908,
.iv1 = 0xBB67AE8584CAA73B,
.iv2 = 0x3C6EF372FE94F82B,
@ -417,7 +417,7 @@ pub const Sha384 = Sha2_64(Sha384Params);
pub const Sha512 = Sha2_64(Sha512Params);
fn Sha2_64(comptime params: Sha2Params64) type {
return struct {
return struct.{
const Self = @This();
const block_length = 128;
const digest_length = params.out_len / 8;
@ -533,7 +533,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u64, s[i - 15], u64(1)) ^ math.rotr(u64, s[i - 15], u64(8)) ^ (s[i - 15] >> 7)) +% (math.rotr(u64, s[i - 2], u64(19)) ^ math.rotr(u64, s[i - 2], u64(61)) ^ (s[i - 2] >> 6));
}
var v: [8]u64 = []u64{
var v: [8]u64 = []u64.{
d.s[0],
d.s[1],
d.s[2],
@ -544,7 +544,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
d.s[7],
};
const round0 = comptime []RoundParam512{
const round0 = comptime []RoundParam512.{
Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22),
Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD),
Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F),
@ -715,7 +715,7 @@ test "sha512 streaming" {
}
test "sha512 aligned final" {
var block = []u8{0} ** Sha512.block_length;
var block = []u8.{0} ** Sha512.block_length;
var out: [Sha512.digest_length]u8 = undefined;
var h = Sha512.init();

View File

@ -11,7 +11,7 @@ pub const Sha3_384 = Keccak(384, 0x06);
pub const Sha3_512 = Keccak(512, 0x06);
fn Keccak(comptime bits: usize, comptime delim: u8) type {
return struct {
return struct.{
const Self = @This();
const block_length = 200;
const digest_length = bits / 8;
@ -86,7 +86,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
};
}
const RC = []const u64{
const RC = []const u64.{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
@ -95,15 +95,15 @@ const RC = []const u64{
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
};
const ROTC = []const usize{
const ROTC = []const usize.{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
};
const PIL = []const usize{
const PIL = []const usize.{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
};
const M5 = []const usize{
const M5 = []const usize.{
0, 1, 2, 3, 4, 0, 1, 2, 3, 4,
};
@ -115,9 +115,9 @@ fn keccak_f(comptime F: usize, d: []u8) void {
break :x 12 + 2 * math.log2(B);
};
var s = []const u64{0} ** 25;
var t = []const u64{0} ** 1;
var c = []const u64{0} ** 5;
var s = []const u64.{0} ** 25;
var t = []const u64.{0} ** 1;
var c = []const u64.{0} ** 5;
for (s) |*r, i| {
r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);
@ -224,7 +224,7 @@ test "sha3-256 streaming" {
}
test "sha3-256 aligned final" {
var block = []u8{0} ** Sha3_256.block_length;
var block = []u8.{0} ** Sha3_256.block_length;
var out: [Sha3_256.digest_length]u8 = undefined;
var h = Sha3_256.init();
@ -295,7 +295,7 @@ test "sha3-512 streaming" {
}
test "sha3-512 aligned final" {
var block = []u8{0} ** Sha3_512.block_length;
var block = []u8.{0} ** Sha3_512.block_length;
var out: [Sha3_512.digest_length]u8 = undefined;
var h = Sha3_512.init();

View File

@ -9,20 +9,20 @@ const MiB = 1024 * KiB;
var prng = std.rand.DefaultPrng.init(0);
const Crypto = struct {
const Crypto = struct.{
ty: type,
name: []const u8,
};
const hashes = []Crypto{
Crypto{ .ty = crypto.Md5, .name = "md5" },
Crypto{ .ty = crypto.Sha1, .name = "sha1" },
Crypto{ .ty = crypto.Sha256, .name = "sha256" },
Crypto{ .ty = crypto.Sha512, .name = "sha512" },
Crypto{ .ty = crypto.Sha3_256, .name = "sha3-256" },
Crypto{ .ty = crypto.Sha3_512, .name = "sha3-512" },
Crypto{ .ty = crypto.Blake2s256, .name = "blake2s" },
Crypto{ .ty = crypto.Blake2b512, .name = "blake2b" },
const hashes = []Crypto.{
Crypto.{ .ty = crypto.Md5, .name = "md5" },
Crypto.{ .ty = crypto.Sha1, .name = "sha1" },
Crypto.{ .ty = crypto.Sha256, .name = "sha256" },
Crypto.{ .ty = crypto.Sha512, .name = "sha512" },
Crypto.{ .ty = crypto.Sha3_256, .name = "sha3-256" },
Crypto.{ .ty = crypto.Sha3_512, .name = "sha3-512" },
Crypto.{ .ty = crypto.Blake2s256, .name = "blake2s" },
Crypto.{ .ty = crypto.Blake2b512, .name = "blake2b" },
};
pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 {
@ -45,11 +45,11 @@ pub fn benchmarkHash(comptime Hash: var, comptime bytes: comptime_int) !u64 {
return throughput;
}
const macs = []Crypto{
Crypto{ .ty = crypto.Poly1305, .name = "poly1305" },
Crypto{ .ty = crypto.HmacMd5, .name = "hmac-md5" },
Crypto{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },
Crypto{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },
const macs = []Crypto.{
Crypto.{ .ty = crypto.Poly1305, .name = "poly1305" },
Crypto.{ .ty = crypto.HmacMd5, .name = "hmac-md5" },
Crypto.{ .ty = crypto.HmacSha1, .name = "hmac-sha1" },
Crypto.{ .ty = crypto.HmacSha256, .name = "hmac-sha256" },
};
pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 {
@ -75,7 +75,7 @@ pub fn benchmarkMac(comptime Mac: var, comptime bytes: comptime_int) !u64 {
return throughput;
}
const exchanges = []Crypto{Crypto{ .ty = crypto.X25519, .name = "x25519" }};
const exchanges = []Crypto.{Crypto.{ .ty = crypto.X25519, .name = "x25519" }};
pub fn benchmarkKeyExchange(comptime DhKeyExchange: var, comptime exchange_count: comptime_int) !u64 {
std.debug.assert(DhKeyExchange.minimum_key_length >= DhKeyExchange.secret_length);
@ -130,7 +130,7 @@ fn printPad(stdout: var, s: []const u8) !void {
pub fn main() !void {
var stdout_file = try std.io.getStdOut();
var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
var stdout_out_stream = stdout_file.outStream();
const stdout = &stdout_out_stream.stream;
var buffer: [1024]u8 = undefined;

View File

@ -11,7 +11,7 @@ const readInt = std.mem.readInt;
const writeInt = std.mem.writeInt;
// Based on Supercop's ref10 implementation.
pub const X25519 = struct {
pub const X25519 = struct.{
pub const secret_length = 32;
pub const minimum_key_length = 32;
@ -116,7 +116,7 @@ pub const X25519 = struct {
}
pub fn createPublicKey(public_key: []u8, private_key: []const u8) bool {
var base_point = []u8{9} ++ []u8{0} ** 31;
var base_point = []u8.{9} ++ []u8.{0} ** 31;
return create(public_key, private_key, base_point);
}
};
@ -137,7 +137,7 @@ fn zerocmp(comptime T: type, a: []const T) bool {
// A bit bigger than TweetNaCl, over 4 times faster.
// field element
const Fe = struct {
const Fe = struct.{
b: [10]i32,
fn secureZero(self: *Fe) void {

View File

@ -55,7 +55,7 @@ pub fn addNullByte(allocator: *mem.Allocator, slice: []const u8) ![]u8 {
return result;
}
pub const NullTerminated2DArray = struct {
pub const NullTerminated2DArray = struct.{
allocator: *mem.Allocator,
byte_count: usize,
ptr: ?[*]?[*]u8,
@ -95,7 +95,7 @@ pub const NullTerminated2DArray = struct {
}
index_buf[i] = null;
return NullTerminated2DArray{
return NullTerminated2DArray.{
.allocator = allocator,
.byte_count = byte_count,
.ptr = @ptrCast(?[*]?[*]u8, buf.ptr),

View File

@ -3,7 +3,7 @@ const mem = std.mem;
/// Allocator that fails after N allocations, useful for making sure out of
/// memory conditions are handled correctly.
pub const FailingAllocator = struct {
pub const FailingAllocator = struct.{
allocator: mem.Allocator,
index: usize,
fail_index: usize,
@ -13,14 +13,14 @@ pub const FailingAllocator = struct {
deallocations: usize,
pub fn init(allocator: *mem.Allocator, fail_index: usize) FailingAllocator {
return FailingAllocator{
return FailingAllocator.{
.internal_allocator = allocator,
.fail_index = fail_index,
.index = 0,
.allocated_bytes = 0,
.freed_bytes = 0,
.deallocations = 0,
.allocator = mem.Allocator{
.allocator = mem.Allocator.{
.allocFn = alloc,
.reallocFn = realloc,
.freeFn = free,

View File

@ -11,16 +11,17 @@ const pdb = std.pdb;
const windows = os.windows;
const ArrayList = std.ArrayList;
const builtin = @import("builtin");
const maxInt = std.math.maxInt;
pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
pub const failing_allocator = FailingAllocator.init(global_allocator, 0);
pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;
pub const runtime_safety = switch (builtin.mode) {
builtin.Mode.Debug, builtin.Mode.ReleaseSafe => true,
builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => false,
};
const Module = struct {
const Module = struct.{
mod_info: pdb.ModInfo,
module_name: []u8,
obj_file_name: []u8,
@ -34,10 +35,10 @@ const Module = struct {
/// Tries to write to stderr, unbuffered, and ignores any error returned.
/// Does not append a newline.
var stderr_file: os.File = undefined;
var stderr_file_out_stream: io.FileOutStream = undefined;
var stderr_file_out_stream: os.File.OutStream = undefined;
/// TODO multithreaded awareness
var stderr_stream: ?*io.OutStream(io.FileOutStream.Error) = null;
var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
var stderr_mutex = std.Mutex.init();
pub fn warn(comptime fmt: []const u8, args: ...) void {
const held = stderr_mutex.acquire();
@ -46,12 +47,12 @@ pub fn warn(comptime fmt: []const u8, args: ...) void {
stderr.print(fmt, args) catch return;
}
pub fn getStderrStream() !*io.OutStream(io.FileOutStream.Error) {
pub fn getStderrStream() !*io.OutStream(os.File.WriteError) {
if (stderr_stream) |st| {
return st;
} else {
stderr_file = try io.getStdErr();
stderr_file_out_stream = io.FileOutStream.init(stderr_file);
stderr_file_out_stream = stderr_file.outStream();
const st = &stderr_file_out_stream.stream;
stderr_stream = st;
return st;
@ -210,7 +211,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
else => {},
}
const AddressState = union(enum) {
const AddressState = union(enum).{
NotLookingForStartAddress,
LookingForStartAddress: usize,
};
@ -219,7 +220,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
// else AddressState.NotLookingForStartAddress;
var addr_state: AddressState = undefined;
if (start_addr) |addr| {
addr_state = AddressState{ .LookingForStartAddress = addr };
addr_state = AddressState.{ .LookingForStartAddress = addr };
} else {
addr_state = AddressState.NotLookingForStartAddress;
}
@ -374,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]);
break :blk col_num_entry.StartColumn;
} else 0;
break :subsections LineInfo{
break :subsections LineInfo.{
.allocator = allocator,
.file_name = source_file_name,
.line = line,
@ -441,7 +442,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
}
}
const TtyColor = enum {
const TtyColor = enum.{
Red,
Green,
Cyan,
@ -453,7 +454,7 @@ const TtyColor = enum {
/// TODO this is a special case hack right now. clean it up and maybe make it part of std.fmt
fn setTtyColor(tty_color: TtyColor) void {
const S = struct {
const S = struct.{
var attrs: windows.WORD = undefined;
var init_attrs = false;
};
@ -659,7 +660,7 @@ fn printLineInfo(
}
// TODO use this
pub const OpenSelfDebugInfoError = error{
pub const OpenSelfDebugInfoError = error.{
MissingDebugInfo,
OutOfMemory,
UnsupportedOperatingSystem,
@ -679,7 +680,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
defer self_file.close();
const coff_obj = try allocator.createOne(coff.Coff);
coff_obj.* = coff.Coff{
coff_obj.* = coff.Coff.{
.in_file = self_file,
.allocator = allocator,
.coff_header = undefined,
@ -689,7 +690,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
.age = undefined,
};
var di = DebugInfo{
var di = DebugInfo.{
.coff = coff_obj,
.pdb = undefined,
.sect_contribs = undefined,
@ -721,7 +722,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
const name_bytes = try allocator.alloc(u8, name_bytes_len);
try pdb_stream.stream.readNoEof(name_bytes);
const HashTableHeader = packed struct {
const HashTableHeader = packed struct.{
Size: u32,
Capacity: u32,
@ -742,7 +743,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
return error.InvalidDebugInfo;
const deleted = try readSparseBitVector(&pdb_stream.stream, allocator);
const Bucket = struct {
const Bucket = struct.{
first: u32,
second: u32,
};
@ -790,7 +791,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
this_record_len += march_forward_bytes;
}
try modules.append(Module{
try modules.append(Module.{
.mod_info = mod_info,
.module_name = module_name,
.obj_file_name = obj_file_name,
@ -842,14 +843,14 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
if (word & (u32(1) << bit_i) != 0) {
try list.append(word_i * 32 + bit_i);
}
if (bit_i == @maxValue(u5)) break;
if (bit_i == maxInt(u5)) break;
}
}
return list.toOwnedSlice();
}
fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
var di = DebugInfo{
var di = DebugInfo.{
.self_exe_file = undefined,
.elf = undefined,
.debug_info = undefined,
@ -876,7 +877,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
}
pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr {
var file_stream = io.FileInStream.init(elf.in_file);
var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
section_loop: for (elf.section_headers) |*elf_section| {
@ -936,7 +937,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
if (sym.n_sect == 0) {
last_len = sym.n_value;
} else {
symbols_buf[symbol_index] = MachoSymbol{
symbols_buf[symbol_index] = MachoSymbol.{
.nlist = sym,
.ofile = ofile,
.reloc = reloc,
@ -954,7 +955,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
}
}
const sentinel = try allocator.createOne(macho.nlist_64);
sentinel.* = macho.nlist_64{
sentinel.* = macho.nlist_64.{
.n_strx = 0,
.n_type = 36,
.n_sect = 0,
@ -969,14 +970,14 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
// This sort is so that we can binary search later.
std.sort.sort(MachoSymbol, symbols, MachoSymbol.addressLessThan);
return DebugInfo{
return DebugInfo.{
.ofiles = DebugInfo.OFileTable.init(allocator),
.symbols = symbols,
.strings = strings,
};
}
fn printLineFromFile(out_stream: var, line_info: *const LineInfo) !void {
fn printLineFromFile(out_stream: var, line_info: LineInfo) !void {
var f = try os.File.openRead(line_info.file_name);
defer f.close();
// TODO fstat and make sure that the file has the correct size
@ -1008,7 +1009,7 @@ fn printLineFromFile(out_stream: var, line_info: *const LineInfo) !void {
}
}
const MachoSymbol = struct {
const MachoSymbol = struct.{
nlist: *macho.nlist_64,
ofile: ?*macho.nlist_64,
reloc: u64,
@ -1023,14 +1024,14 @@ const MachoSymbol = struct {
}
};
const MachOFile = struct {
const MachOFile = struct.{
bytes: []align(@alignOf(macho.mach_header_64)) const u8,
sect_debug_info: ?*const macho.section_64,
sect_debug_line: ?*const macho.section_64,
};
pub const DebugInfo = switch (builtin.os) {
builtin.Os.macosx => struct {
builtin.Os.macosx => struct.{
symbols: []const MachoSymbol,
strings: []const u8,
ofiles: OFileTable,
@ -1046,13 +1047,13 @@ pub const DebugInfo = switch (builtin.os) {
return self.ofiles.allocator;
}
},
builtin.Os.windows => struct {
builtin.Os.windows => struct.{
pdb: pdb.Pdb,
coff: *coff.Coff,
sect_contribs: []pdb.SectionContribEntry,
modules: []Module,
},
builtin.Os.linux => struct {
builtin.Os.linux => struct.{
self_exe_file: os.File,
elf: elf.Elf,
debug_info: *elf.SectionHeader,
@ -1068,7 +1069,7 @@ pub const DebugInfo = switch (builtin.os) {
}
pub fn readString(self: *DebugInfo) ![]u8 {
var in_file_stream = io.FileInStream.init(self.self_exe_file);
var in_file_stream = self.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
return readStringRaw(self.allocator(), in_stream);
}
@ -1081,12 +1082,12 @@ pub const DebugInfo = switch (builtin.os) {
else => @compileError("Unsupported OS"),
};
const PcRange = struct {
const PcRange = struct.{
start: u64,
end: u64,
};
const CompileUnit = struct {
const CompileUnit = struct.{
version: u16,
is_64: bool,
die: *Die,
@ -1096,25 +1097,25 @@ const CompileUnit = struct {
const AbbrevTable = ArrayList(AbbrevTableEntry);
const AbbrevTableHeader = struct {
const AbbrevTableHeader = struct.{
// offset from .debug_abbrev
offset: u64,
table: AbbrevTable,
};
const AbbrevTableEntry = struct {
const AbbrevTableEntry = struct.{
has_children: bool,
abbrev_code: u64,
tag_id: u64,
attrs: ArrayList(AbbrevAttr),
};
const AbbrevAttr = struct {
const AbbrevAttr = struct.{
attr_id: u64,
form_id: u64,
};
const FormValue = union(enum) {
const FormValue = union(enum).{
Address: u64,
Block: []u8,
Const: Constant,
@ -1128,7 +1129,7 @@ const FormValue = union(enum) {
StrPtr: u64,
};
const Constant = struct {
const Constant = struct.{
payload: []u8,
signed: bool,
@ -1139,12 +1140,12 @@ const Constant = struct {
}
};
const Die = struct {
const Die = struct.{
tag_id: u64,
has_children: bool,
attrs: ArrayList(Attr),
const Attr = struct {
const Attr = struct.{
id: u64,
value: FormValue,
};
@ -1191,14 +1192,14 @@ const Die = struct {
}
};
const FileEntry = struct {
const FileEntry = struct.{
file_name: []const u8,
dir_index: usize,
mtime: usize,
len_bytes: usize,
};
const LineInfo = struct {
const LineInfo = struct.{
line: usize,
column: usize,
file_name: []u8,
@ -1209,7 +1210,7 @@ const LineInfo = struct {
}
};
const LineNumberProgram = struct {
const LineNumberProgram = struct.{
address: usize,
file: usize,
line: isize,
@ -1231,7 +1232,7 @@ const LineNumberProgram = struct {
prev_end_sequence: bool,
pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram {
return LineNumberProgram{
return LineNumberProgram.{
.address = 0,
.file = 1,
.line = 1,
@ -1267,7 +1268,7 @@ const LineNumberProgram = struct {
self.include_dirs[file_entry.dir_index];
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
errdefer self.file_entries.allocator.free(file_name);
return LineInfo{
return LineInfo.{
.line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,
.column = self.prev_column,
.file_name = file_name,
@ -1311,7 +1312,7 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8
fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue{ .Block = buf };
return FormValue.{ .Block = buf };
}
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
@ -1320,8 +1321,8 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !
}
fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
return FormValue{
.Const = Constant{
return FormValue.{
.Const = Constant.{
.signed = signed,
.payload = try readAllocBytes(allocator, in_stream, size),
},
@ -1338,7 +1339,7 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue{ .Ref = buf };
return FormValue.{ .Ref = buf };
}
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
@ -1346,7 +1347,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type
return parseFormValueRefLen(allocator, in_stream, block_len);
}
const ParseFormValueError = error{
const ParseFormValueError = error.{
EndOfStream,
InvalidDebugInfo,
EndOfFile,
@ -1355,7 +1356,7 @@ const ParseFormValueError = error{
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
return switch (form_id) {
DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
DW.FORM_addr => FormValue.{ .Address = try parseFormValueTargetAddrSize(in_stream) },
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
@ -1375,11 +1376,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_exprloc => {
const size = try readULeb128(in_stream);
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue{ .ExprLoc = buf };
return FormValue.{ .ExprLoc = buf };
},
DW.FORM_flag => FormValue{ .Flag = (try in_stream.readByte()) != 0 },
DW.FORM_flag_present => FormValue{ .Flag = true },
DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_flag => FormValue.{ .Flag = (try in_stream.readByte()) != 0 },
DW.FORM_flag_present => FormValue.{ .Flag = true },
DW.FORM_sec_offset => FormValue.{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
@ -1390,11 +1391,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
return parseFormValueRefLen(allocator, in_stream, ref_len);
},
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_addr => FormValue.{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref_sig8 => FormValue.{ .RefSig8 = try in_stream.readIntLe(u64) },
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_string => FormValue.{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue.{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_indirect => {
const child_form_id = try readULeb128(in_stream);
return parseFormValue(allocator, in_stream, child_form_id, is_64);
@ -1405,13 +1406,13 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
const in_file = st.self_exe_file;
var in_file_stream = io.FileInStream.init(in_file);
var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
var result = AbbrevTable.init(st.allocator());
while (true) {
const abbrev_code = try readULeb128(in_stream);
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
try result.append(AbbrevTableEntry.{
.abbrev_code = abbrev_code,
.tag_id = try readULeb128(in_stream),
.has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,
@ -1423,7 +1424,7 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
const attr_id = try readULeb128(in_stream);
const form_id = try readULeb128(in_stream);
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
try attrs.append(AbbrevAttr.{
.attr_id = attr_id,
.form_id = form_id,
});
@ -1440,7 +1441,7 @@ fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable {
}
}
try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);
try st.abbrev_table_list.append(AbbrevTableHeader{
try st.abbrev_table_list.append(AbbrevTableHeader.{
.offset = abbrev_offset,
.table = try parseAbbrevTable(st),
});
@ -1456,19 +1457,19 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
const in_file = st.self_exe_file;
var in_file_stream = io.FileInStream.init(in_file);
var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
const abbrev_code = try readULeb128(in_stream);
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
var result = Die{
var result = Die.{
.tag_id = table_entry.tag_id,
.has_children = table_entry.has_children,
.attrs = ArrayList(Die.Attr).init(st.allocator()),
};
try result.attrs.resize(table_entry.attrs.len);
for (table_entry.attrs.toSliceConst()) |attr, i| {
result.attrs.items[i] = Die.Attr{
result.attrs.items[i] = Die.Attr.{
.id = attr.attr_id,
.value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
};
@ -1483,7 +1484,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
errdefer _ = di.ofiles.remove(ofile);
const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
gop.kv.value = MachOFile{
gop.kv.value = MachOFile.{
.bytes = try std.io.readFileAllocAligned(di.ofiles.allocator, ofile_path, @alignOf(macho.mach_header_64)),
.sect_debug_info = null,
.sect_debug_line = null,
@ -1574,7 +1575,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const dir_index = try readULeb128Mem(&ptr);
const mtime = try readULeb128Mem(&ptr);
const len_bytes = try readULeb128Mem(&ptr);
try file_entries.append(FileEntry{
try file_entries.append(FileEntry.{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -1605,7 +1606,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const dir_index = try readULeb128Mem(&ptr);
const mtime = try readULeb128Mem(&ptr);
const len_bytes = try readULeb128Mem(&ptr);
try file_entries.append(FileEntry{
try file_entries.append(FileEntry.{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -1682,7 +1683,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
var this_offset = di.debug_line.offset;
var this_index: usize = 0;
var in_file_stream = io.FileInStream.init(in_file);
var in_file_stream = in_file.inStream();
const in_stream = &in_file_stream.stream;
while (this_offset < debug_line_end) : (this_index += 1) {
@ -1747,7 +1748,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
const dir_index = try readULeb128(in_stream);
const mtime = try readULeb128(in_stream);
const len_bytes = try readULeb128(in_stream);
try file_entries.append(FileEntry{
try file_entries.append(FileEntry.{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -1779,7 +1780,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
const dir_index = try readULeb128(in_stream);
const mtime = try readULeb128(in_stream);
const len_bytes = try readULeb128(in_stream);
try file_entries.append(FileEntry{
try file_entries.append(FileEntry.{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -1857,7 +1858,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
var this_unit_offset = st.debug_info.offset;
var cu_index: usize = 0;
var in_file_stream = io.FileInStream.init(st.self_exe_file);
var in_file_stream = st.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
while (this_unit_offset < debug_info_end) {
@ -1896,7 +1897,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
},
else => return error.InvalidDebugInfo,
};
break :x PcRange{
break :x PcRange.{
.start = low_pc,
.end = pc_end,
};
@ -1909,7 +1910,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
}
};
try st.compile_unit_list.append(CompileUnit{
try st.compile_unit_list.append(CompileUnit.{
.version = version,
.is_64 = is_64,
.pc_range = pc_range,
@ -1923,7 +1924,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
}
fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
var in_file_stream = io.FileInStream.init(st.self_exe_file);
var in_file_stream = st.self_exe_file.inStream();
const in_stream = &in_file_stream.stream;
for (st.compile_unit_list.toSlice()) |*compile_unit| {
if (compile_unit.pc_range) |range| {
@ -1939,7 +1940,7 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
if (begin_addr == 0 and end_addr == 0) {
break;
}
if (begin_addr == @maxValue(usize)) {
if (begin_addr == maxInt(usize)) {
base_address = begin_addr;
continue;
}

View File

@ -1,10 +1,24 @@
const builtin = @import("builtin");
const Os = builtin.Os;
const std = @import("index.zig");
const mem = std.mem;
const elf = std.elf;
const cstr = std.cstr;
const linux = std.os.linux;
const os = std.os;
const assert = std.debug.assert;
const elf = std.elf;
const linux = os.linux;
const windows = os.windows;
const win_util = @import("os/windows/util.zig");
const maxInt = std.math.maxInt;
pub const DynLib = struct {
pub const DynLib = switch (builtin.os) {
Os.linux => LinuxDynLib,
Os.windows => WindowsDynLib,
else => void,
};
pub const LinuxDynLib = struct.{
allocator: *mem.Allocator,
elf_lib: ElfLib,
fd: i32,
@ -30,7 +44,7 @@ pub const DynLib = struct {
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
return DynLib{
return DynLib.{
.allocator = allocator,
.elf_lib = try ElfLib.init(bytes),
.fd = fd,
@ -50,7 +64,7 @@ pub const DynLib = struct {
}
};
pub const ElfLib = struct {
pub const ElfLib = struct.{
strings: [*]u8,
syms: [*]elf.Sym,
hashtab: [*]linux.Elf_Symndx,
@ -67,7 +81,7 @@ pub const ElfLib = struct {
const elf_addr = @ptrToInt(bytes.ptr);
var ph_addr: usize = elf_addr + eh.e_phoff;
var base: usize = @maxValue(usize);
var base: usize = maxInt(usize);
var maybe_dynv: ?[*]usize = null;
{
var i: usize = 0;
@ -84,7 +98,7 @@ pub const ElfLib = struct {
}
}
const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
if (base == @maxValue(usize)) return error.BaseNotFound;
if (base == maxInt(usize)) return error.BaseNotFound;
var maybe_strings: ?[*]u8 = null;
var maybe_syms: ?[*]elf.Sym = null;
@ -107,7 +121,7 @@ pub const ElfLib = struct {
}
}
return ElfLib{
return ElfLib.{
.base = base,
.strings = maybe_strings orelse return error.ElfStringSectionNotFound,
.syms = maybe_syms orelse return error.ElfSymSectionNotFound,
@ -154,3 +168,48 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
return mem.eql(u8, vername, cstr.toSliceConst(strings + aux.vda_name));
}
pub const WindowsDynLib = struct.{
allocator: *mem.Allocator,
dll: windows.HMODULE,
pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
const wpath = try win_util.sliceToPrefixedFileW(path);
return WindowsDynLib.{
.allocator = allocator,
.dll = windows.LoadLibraryW(&wpath) orelse {
const err = windows.GetLastError();
switch (err) {
windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound,
windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound,
windows.ERROR.MOD_NOT_FOUND => return error.FileNotFound,
else => return os.unexpectedErrorWindows(err),
}
},
};
}
pub fn close(self: *WindowsDynLib) void {
assert(windows.FreeLibrary(self.dll) != 0);
self.* = undefined;
}
pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {
return @ptrToInt(windows.GetProcAddress(self.dll, name.ptr));
}
};
test "dynamic_library" {
const libname = switch (builtin.os) {
Os.linux => "invalid_so.so",
Os.windows => "invalid_dll.dll",
else => return,
};
const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
assert(err == error.FileNotFound);
return;
};
@panic("Expected error from function");
}

View File

@ -320,14 +320,14 @@ pub const ET_DYN = 3;
/// A core file.
pub const ET_CORE = 4;
pub const FileType = enum {
pub const FileType = enum.{
Relocatable,
Executable,
Shared,
Core,
};
pub const Arch = enum {
pub const Arch = enum.{
Sparc,
x86,
Mips,
@ -339,7 +339,7 @@ pub const Arch = enum {
AArch64,
};
pub const SectionHeader = struct {
pub const SectionHeader = struct.{
name: u32,
sh_type: u32,
flags: u64,
@ -352,7 +352,7 @@ pub const SectionHeader = struct {
ent_size: u64,
};
pub const Elf = struct {
pub const Elf = struct.{
in_file: os.File,
auto_close_stream: bool,
is_64: bool,
@ -381,7 +381,7 @@ pub const Elf = struct {
elf.in_file = file;
elf.auto_close_stream = false;
var file_stream = io.FileInStream.init(elf.in_file);
var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
var magic: [4]u8 = undefined;
@ -525,7 +525,7 @@ pub const Elf = struct {
}
pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
var file_stream = io.FileInStream.init(elf.in_file);
var file_stream = elf.in_file.inStream();
const in = &file_stream.stream;
section_loop: for (elf.section_headers) |*elf_section| {
@ -572,7 +572,7 @@ pub const Elf32_Section = u16;
pub const Elf64_Section = u16;
pub const Elf32_Versym = Elf32_Half;
pub const Elf64_Versym = Elf64_Half;
pub const Elf32_Ehdr = extern struct {
pub const Elf32_Ehdr = extern struct.{
e_ident: [EI_NIDENT]u8,
e_type: Elf32_Half,
e_machine: Elf32_Half,
@ -588,7 +588,7 @@ pub const Elf32_Ehdr = extern struct {
e_shnum: Elf32_Half,
e_shstrndx: Elf32_Half,
};
pub const Elf64_Ehdr = extern struct {
pub const Elf64_Ehdr = extern struct.{
e_ident: [EI_NIDENT]u8,
e_type: Elf64_Half,
e_machine: Elf64_Half,
@ -604,7 +604,7 @@ pub const Elf64_Ehdr = extern struct {
e_shnum: Elf64_Half,
e_shstrndx: Elf64_Half,
};
pub const Elf32_Shdr = extern struct {
pub const Elf32_Shdr = extern struct.{
sh_name: Elf32_Word,
sh_type: Elf32_Word,
sh_flags: Elf32_Word,
@ -616,7 +616,7 @@ pub const Elf32_Shdr = extern struct {
sh_addralign: Elf32_Word,
sh_entsize: Elf32_Word,
};
pub const Elf64_Shdr = extern struct {
pub const Elf64_Shdr = extern struct.{
sh_name: Elf64_Word,
sh_type: Elf64_Word,
sh_flags: Elf64_Xword,
@ -628,18 +628,18 @@ pub const Elf64_Shdr = extern struct {
sh_addralign: Elf64_Xword,
sh_entsize: Elf64_Xword,
};
pub const Elf32_Chdr = extern struct {
pub const Elf32_Chdr = extern struct.{
ch_type: Elf32_Word,
ch_size: Elf32_Word,
ch_addralign: Elf32_Word,
};
pub const Elf64_Chdr = extern struct {
pub const Elf64_Chdr = extern struct.{
ch_type: Elf64_Word,
ch_reserved: Elf64_Word,
ch_size: Elf64_Xword,
ch_addralign: Elf64_Xword,
};
pub const Elf32_Sym = extern struct {
pub const Elf32_Sym = extern struct.{
st_name: Elf32_Word,
st_value: Elf32_Addr,
st_size: Elf32_Word,
@ -647,7 +647,7 @@ pub const Elf32_Sym = extern struct {
st_other: u8,
st_shndx: Elf32_Section,
};
pub const Elf64_Sym = extern struct {
pub const Elf64_Sym = extern struct.{
st_name: Elf64_Word,
st_info: u8,
st_other: u8,
@ -655,33 +655,33 @@ pub const Elf64_Sym = extern struct {
st_value: Elf64_Addr,
st_size: Elf64_Xword,
};
pub const Elf32_Syminfo = extern struct {
pub const Elf32_Syminfo = extern struct.{
si_boundto: Elf32_Half,
si_flags: Elf32_Half,
};
pub const Elf64_Syminfo = extern struct {
pub const Elf64_Syminfo = extern struct.{
si_boundto: Elf64_Half,
si_flags: Elf64_Half,
};
pub const Elf32_Rel = extern struct {
pub const Elf32_Rel = extern struct.{
r_offset: Elf32_Addr,
r_info: Elf32_Word,
};
pub const Elf64_Rel = extern struct {
pub const Elf64_Rel = extern struct.{
r_offset: Elf64_Addr,
r_info: Elf64_Xword,
};
pub const Elf32_Rela = extern struct {
pub const Elf32_Rela = extern struct.{
r_offset: Elf32_Addr,
r_info: Elf32_Word,
r_addend: Elf32_Sword,
};
pub const Elf64_Rela = extern struct {
pub const Elf64_Rela = extern struct.{
r_offset: Elf64_Addr,
r_info: Elf64_Xword,
r_addend: Elf64_Sxword,
};
pub const Elf32_Phdr = extern struct {
pub const Elf32_Phdr = extern struct.{
p_type: Elf32_Word,
p_offset: Elf32_Off,
p_vaddr: Elf32_Addr,
@ -691,7 +691,7 @@ pub const Elf32_Phdr = extern struct {
p_flags: Elf32_Word,
p_align: Elf32_Word,
};
pub const Elf64_Phdr = extern struct {
pub const Elf64_Phdr = extern struct.{
p_type: Elf64_Word,
p_flags: Elf64_Word,
p_offset: Elf64_Off,
@ -701,21 +701,21 @@ pub const Elf64_Phdr = extern struct {
p_memsz: Elf64_Xword,
p_align: Elf64_Xword,
};
pub const Elf32_Dyn = extern struct {
pub const Elf32_Dyn = extern struct.{
d_tag: Elf32_Sword,
d_un: extern union {
d_un: extern union.{
d_val: Elf32_Word,
d_ptr: Elf32_Addr,
},
};
pub const Elf64_Dyn = extern struct {
pub const Elf64_Dyn = extern struct.{
d_tag: Elf64_Sxword,
d_un: extern union {
d_un: extern union.{
d_val: Elf64_Xword,
d_ptr: Elf64_Addr,
},
};
pub const Elf32_Verdef = extern struct {
pub const Elf32_Verdef = extern struct.{
vd_version: Elf32_Half,
vd_flags: Elf32_Half,
vd_ndx: Elf32_Half,
@ -724,7 +724,7 @@ pub const Elf32_Verdef = extern struct {
vd_aux: Elf32_Word,
vd_next: Elf32_Word,
};
pub const Elf64_Verdef = extern struct {
pub const Elf64_Verdef = extern struct.{
vd_version: Elf64_Half,
vd_flags: Elf64_Half,
vd_ndx: Elf64_Half,
@ -733,111 +733,111 @@ pub const Elf64_Verdef = extern struct {
vd_aux: Elf64_Word,
vd_next: Elf64_Word,
};
pub const Elf32_Verdaux = extern struct {
pub const Elf32_Verdaux = extern struct.{
vda_name: Elf32_Word,
vda_next: Elf32_Word,
};
pub const Elf64_Verdaux = extern struct {
pub const Elf64_Verdaux = extern struct.{
vda_name: Elf64_Word,
vda_next: Elf64_Word,
};
pub const Elf32_Verneed = extern struct {
pub const Elf32_Verneed = extern struct.{
vn_version: Elf32_Half,
vn_cnt: Elf32_Half,
vn_file: Elf32_Word,
vn_aux: Elf32_Word,
vn_next: Elf32_Word,
};
pub const Elf64_Verneed = extern struct {
pub const Elf64_Verneed = extern struct.{
vn_version: Elf64_Half,
vn_cnt: Elf64_Half,
vn_file: Elf64_Word,
vn_aux: Elf64_Word,
vn_next: Elf64_Word,
};
pub const Elf32_Vernaux = extern struct {
pub const Elf32_Vernaux = extern struct.{
vna_hash: Elf32_Word,
vna_flags: Elf32_Half,
vna_other: Elf32_Half,
vna_name: Elf32_Word,
vna_next: Elf32_Word,
};
pub const Elf64_Vernaux = extern struct {
pub const Elf64_Vernaux = extern struct.{
vna_hash: Elf64_Word,
vna_flags: Elf64_Half,
vna_other: Elf64_Half,
vna_name: Elf64_Word,
vna_next: Elf64_Word,
};
pub const Elf32_auxv_t = extern struct {
pub const Elf32_auxv_t = extern struct.{
a_type: u32,
a_un: extern union {
a_un: extern union.{
a_val: u32,
},
};
pub const Elf64_auxv_t = extern struct {
pub const Elf64_auxv_t = extern struct.{
a_type: u64,
a_un: extern union {
a_un: extern union.{
a_val: u64,
},
};
pub const Elf32_Nhdr = extern struct {
pub const Elf32_Nhdr = extern struct.{
n_namesz: Elf32_Word,
n_descsz: Elf32_Word,
n_type: Elf32_Word,
};
pub const Elf64_Nhdr = extern struct {
pub const Elf64_Nhdr = extern struct.{
n_namesz: Elf64_Word,
n_descsz: Elf64_Word,
n_type: Elf64_Word,
};
pub const Elf32_Move = extern struct {
pub const Elf32_Move = extern struct.{
m_value: Elf32_Xword,
m_info: Elf32_Word,
m_poffset: Elf32_Word,
m_repeat: Elf32_Half,
m_stride: Elf32_Half,
};
pub const Elf64_Move = extern struct {
pub const Elf64_Move = extern struct.{
m_value: Elf64_Xword,
m_info: Elf64_Xword,
m_poffset: Elf64_Xword,
m_repeat: Elf64_Half,
m_stride: Elf64_Half,
};
pub const Elf32_gptab = extern union {
gt_header: extern struct {
pub const Elf32_gptab = extern union.{
gt_header: extern struct.{
gt_current_g_value: Elf32_Word,
gt_unused: Elf32_Word,
},
gt_entry: extern struct {
gt_entry: extern struct.{
gt_g_value: Elf32_Word,
gt_bytes: Elf32_Word,
},
};
pub const Elf32_RegInfo = extern struct {
pub const Elf32_RegInfo = extern struct.{
ri_gprmask: Elf32_Word,
ri_cprmask: [4]Elf32_Word,
ri_gp_value: Elf32_Sword,
};
pub const Elf_Options = extern struct {
pub const Elf_Options = extern struct.{
kind: u8,
size: u8,
@"section": Elf32_Section,
info: Elf32_Word,
};
pub const Elf_Options_Hw = extern struct {
pub const Elf_Options_Hw = extern struct.{
hwp_flags1: Elf32_Word,
hwp_flags2: Elf32_Word,
};
pub const Elf32_Lib = extern struct {
pub const Elf32_Lib = extern struct.{
l_name: Elf32_Word,
l_time_stamp: Elf32_Word,
l_checksum: Elf32_Word,
l_version: Elf32_Word,
l_flags: Elf32_Word,
};
pub const Elf64_Lib = extern struct {
pub const Elf64_Lib = extern struct.{
l_name: Elf64_Word,
l_time_stamp: Elf64_Word,
l_checksum: Elf64_Word,
@ -845,7 +845,7 @@ pub const Elf64_Lib = extern struct {
l_flags: Elf64_Word,
};
pub const Elf32_Conflict = Elf32_Addr;
pub const Elf_MIPS_ABIFlags_v0 = extern struct {
pub const Elf_MIPS_ABIFlags_v0 = extern struct.{
version: Elf32_Half,
isa_level: u8,
isa_rev: u8,
@ -859,6 +859,11 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct {
flags2: Elf32_Word,
};
pub const Auxv = switch (@sizeOf(usize)) {
4 => Elf32_auxv_t,
8 => Elf64_auxv_t,
else => @compileError("expected pointer size of 32 or 64"),
};
pub const Ehdr = switch (@sizeOf(usize)) {
4 => Elf32_Ehdr,
8 => Elf64_Ehdr,

View File

@ -6,18 +6,20 @@ pub const Locked = @import("event/locked.zig").Locked;
pub const RwLock = @import("event/rwlock.zig").RwLock;
pub const RwLocked = @import("event/rwlocked.zig").RwLocked;
pub const Loop = @import("event/loop.zig").Loop;
pub const io = @import("event/io.zig");
pub const fs = @import("event/fs.zig");
pub const tcp = @import("event/tcp.zig");
pub const net = @import("event/net.zig");
test "import event tests" {
_ = @import("event/channel.zig");
_ = @import("event/fs.zig");
_ = @import("event/future.zig");
_ = @import("event/group.zig");
_ = @import("event/io.zig");
_ = @import("event/lock.zig");
_ = @import("event/locked.zig");
_ = @import("event/rwlock.zig");
_ = @import("event/rwlocked.zig");
_ = @import("event/loop.zig");
_ = @import("event/tcp.zig");
_ = @import("event/net.zig");
}

View File

@ -9,7 +9,7 @@ const Loop = std.event.Loop;
/// when buffer is empty, consumers suspend and are resumed by producers
/// when buffer is full, producers suspend and are resumed by consumers
pub fn Channel(comptime T: type) type {
return struct {
return struct.{
loop: *Loop,
getters: std.atomic.Queue(GetNode),
@ -26,25 +26,25 @@ pub fn Channel(comptime T: type) type {
buffer_len: usize,
const SelfChannel = @This();
const GetNode = struct {
const GetNode = struct.{
tick_node: *Loop.NextTickNode,
data: Data,
const Data = union(enum) {
const Data = union(enum).{
Normal: Normal,
OrNull: OrNull,
};
const Normal = struct {
const Normal = struct.{
ptr: *T,
};
const OrNull = struct {
const OrNull = struct.{
ptr: *?T,
or_null: *std.atomic.Queue(*std.atomic.Queue(GetNode).Node).Node,
};
};
const PutNode = struct {
const PutNode = struct.{
data: T,
tick_node: *Loop.NextTickNode,
};
@ -54,7 +54,7 @@ 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.{
.loop = loop,
.buffer_len = 0,
.buffer_nodes = buffer_nodes,
@ -93,7 +93,7 @@ pub fn Channel(comptime T: type) type {
}
var my_tick_node = Loop.NextTickNode.init(@handle());
var queue_node = std.atomic.Queue(PutNode).Node.init(PutNode{
var queue_node = std.atomic.Queue(PutNode).Node.init(PutNode.{
.tick_node = &my_tick_node,
.data = data,
});
@ -129,10 +129,10 @@ pub fn Channel(comptime T: type) type {
// so we can get rid of this extra result copy
var result: T = undefined;
var my_tick_node = Loop.NextTickNode.init(@handle());
var queue_node = std.atomic.Queue(GetNode).Node.init(GetNode{
var queue_node = std.atomic.Queue(GetNode).Node.init(GetNode.{
.tick_node = &my_tick_node,
.data = GetNode.Data{
.Normal = GetNode.Normal{ .ptr = &result },
.data = GetNode.Data.{
.Normal = GetNode.Normal.{ .ptr = &result },
},
});
@ -181,10 +181,10 @@ pub fn Channel(comptime T: type) type {
var result: ?T = null;
var my_tick_node = Loop.NextTickNode.init(@handle());
var or_null_node = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).Node.init(undefined);
var queue_node = std.atomic.Queue(GetNode).Node.init(GetNode{
var queue_node = std.atomic.Queue(GetNode).Node.init(GetNode.{
.tick_node = &my_tick_node,
.data = GetNode.Data{
.OrNull = GetNode.OrNull{
.data = GetNode.Data.{
.OrNull = GetNode.OrNull.{
.ptr = &result,
.or_null = &or_null_node,
},

View File

@ -10,17 +10,17 @@ const Loop = event.Loop;
pub const RequestNode = std.atomic.Queue(Request).Node;
pub const Request = struct {
pub const Request = struct.{
msg: Msg,
finish: Finish,
pub const Finish = union(enum) {
pub const Finish = union(enum).{
TickNode: Loop.NextTickNode,
DeallocCloseOperation: *CloseOperation,
NoAction,
};
pub const Msg = union(enum) {
pub const Msg = union(enum).{
PWriteV: PWriteV,
PReadV: PReadV,
Open: Open,
@ -28,25 +28,25 @@ pub const Request = struct {
WriteFile: WriteFile,
End, // special - means the fs thread should exit
pub const PWriteV = struct {
pub const PWriteV = struct.{
fd: os.FileHandle,
iov: []os.posix.iovec_const,
iov: []const os.posix.iovec_const,
offset: usize,
result: Error!void,
pub const Error = os.File.WriteError;
pub const Error = os.PosixWriteError;
};
pub const PReadV = struct {
pub const PReadV = struct.{
fd: os.FileHandle,
iov: []os.posix.iovec,
iov: []const os.posix.iovec,
offset: usize,
result: Error!usize,
pub const Error = os.File.ReadError;
pub const Error = os.PosixReadError;
};
pub const Open = struct {
pub const Open = struct.{
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
flags: u32,
@ -56,7 +56,7 @@ pub const Request = struct {
pub const Error = os.File.OpenError;
};
pub const WriteFile = struct {
pub const WriteFile = struct.{
/// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
path: []const u8,
contents: []const u8,
@ -66,34 +66,53 @@ pub const Request = struct {
pub const Error = os.File.OpenError || os.File.WriteError;
};
pub const Close = struct {
pub const Close = struct.{
fd: os.FileHandle,
};
};
};
pub const PWriteVError = error.{OutOfMemory} || os.File.WriteError;
/// data - just the inner references - must live until pwritev promise completes.
pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) PWriteVError!void {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
=> return await (async pwritevPosix(loop, fd, data, offset) catch unreachable),
builtin.Os.windows => return await (async pwritevWindows(loop, fd, data, offset) catch unreachable),
=> {
const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
defer loop.allocator.free(iovecs);
for (data) |buf, i| {
iovecs[i] = os.posix.iovec_const.{
.iov_base = buf.ptr,
.iov_len = buf.len,
};
}
return await (async pwritevPosix(loop, fd, iovecs, offset) catch unreachable);
},
builtin.Os.windows => {
const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
defer loop.allocator.free(data_copy);
return await (async pwritevWindows(loop, fd, data, offset) catch unreachable);
},
else => @compileError("Unsupported OS"),
}
}
/// data - just the inner references - must live until pwritev promise completes.
pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
/// data must outlive the returned promise
pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) os.WindowsWriteError!void {
if (data.len == 0) return;
if (data.len == 1) return await (async pwriteWindows(loop, fd, data[0], offset) catch unreachable);
const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
defer loop.allocator.free(data_copy);
// TODO do these in parallel
var off = offset;
for (data_copy) |buf| {
for (data) |buf| {
try await (async pwriteWindows(loop, fd, buf, off) catch unreachable);
off += buf.len;
}
@ -105,11 +124,11 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off
resume @handle();
}
var resume_node = Loop.ResumeNode.Basic{
.base = Loop.ResumeNode{
var resume_node = Loop.ResumeNode.Basic.{
.base = Loop.ResumeNode.{
.id = Loop.ResumeNode.Id.Basic,
.handle = @handle(),
.overlapped = windows.OVERLAPPED{
.overlapped = windows.OVERLAPPED.{
.Internal = 0,
.InternalHigh = 0,
.Offset = @truncate(u32, offset),
@ -144,37 +163,32 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off
}
}
/// data - just the inner references - must live until pwritev promise completes.
pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {
/// iovecs must live until pwritev promise completes.
pub async fn pwritevPosix(
loop: *Loop,
fd: os.FileHandle,
iovecs: []const posix.iovec_const,
offset: usize,
) os.PosixWriteError!void {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
defer loop.allocator.free(iovecs);
for (data) |buf, i| {
iovecs[i] = os.posix.iovec_const{
.iov_base = buf.ptr,
.iov_len = buf.len,
};
}
var req_node = RequestNode{
var req_node = RequestNode.{
.prev = null,
.next = null,
.data = Request{
.msg = Request.Msg{
.PWriteV = Request.Msg.PWriteV{
.data = Request.{
.msg = Request.Msg.{
.PWriteV = Request.Msg.PWriteV.{
.fd = fd,
.iov = iovecs,
.offset = offset,
.result = undefined,
},
},
.finish = Request.Finish{
.TickNode = Loop.NextTickNode{
.finish = Request.Finish.{
.TickNode = Loop.NextTickNode.{
.prev = null,
.next = null,
.data = @handle(),
@ -192,38 +206,59 @@ pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const
return req_node.data.msg.PWriteV.result;
}
pub const PReadVError = error.{OutOfMemory} || os.File.ReadError;
/// data - just the inner references - must live until preadv promise completes.
pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {
pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) PReadVError!usize {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
assert(data.len != 0);
switch (builtin.os) {
builtin.Os.macosx,
builtin.Os.linux,
=> return await (async preadvPosix(loop, fd, data, offset) catch unreachable),
builtin.Os.windows => return await (async preadvWindows(loop, fd, data, offset) catch unreachable),
=> {
const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
defer loop.allocator.free(iovecs);
for (data) |buf, i| {
iovecs[i] = os.posix.iovec.{
.iov_base = buf.ptr,
.iov_len = buf.len,
};
}
return await (async preadvPosix(loop, fd, iovecs, offset) catch unreachable);
},
builtin.Os.windows => {
const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
defer loop.allocator.free(data_copy);
return await (async preadvWindows(loop, fd, data_copy, offset) catch unreachable);
},
else => @compileError("Unsupported OS"),
}
}
pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) !usize {
/// data must outlive the returned promise
pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) os.WindowsReadError!usize {
assert(data.len != 0);
if (data.len == 1) return await (async preadWindows(loop, fd, data[0], offset) catch unreachable);
const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
defer loop.allocator.free(data_copy);
// TODO do these in parallel?
var off: usize = 0;
var iov_i: usize = 0;
var inner_off: usize = 0;
while (true) {
const v = data_copy[iov_i];
const v = data[iov_i];
const amt_read = try await (async preadWindows(loop, fd, v[inner_off .. v.len - inner_off], offset + off) catch unreachable);
off += amt_read;
inner_off += amt_read;
if (inner_off == v.len) {
iov_i += 1;
inner_off = 0;
if (iov_i == data_copy.len) {
if (iov_i == data.len) {
return off;
}
}
@ -237,11 +272,11 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
resume @handle();
}
var resume_node = Loop.ResumeNode.Basic{
.base = Loop.ResumeNode{
var resume_node = Loop.ResumeNode.Basic.{
.base = Loop.ResumeNode.{
.id = Loop.ResumeNode.Id.Basic,
.handle = @handle(),
.overlapped = windows.OVERLAPPED{
.overlapped = windows.OVERLAPPED.{
.Internal = 0,
.InternalHigh = 0,
.Offset = @truncate(u32, offset),
@ -275,37 +310,32 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
return usize(bytes_transferred);
}
/// data - just the inner references - must live until preadv promise completes.
pub async fn preadvPosix(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {
/// iovecs must live until preadv promise completes
pub async fn preadvPosix(
loop: *Loop,
fd: os.FileHandle,
iovecs: []const posix.iovec,
offset: usize,
) os.PosixReadError!usize {
// workaround for https://github.com/ziglang/zig/issues/1194
suspend {
resume @handle();
}
const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
defer loop.allocator.free(iovecs);
for (data) |buf, i| {
iovecs[i] = os.posix.iovec{
.iov_base = buf.ptr,
.iov_len = buf.len,
};
}
var req_node = RequestNode{
var req_node = RequestNode.{
.prev = null,
.next = null,
.data = Request{
.msg = Request.Msg{
.PReadV = Request.Msg.PReadV{
.data = Request.{
.msg = Request.Msg.{
.PReadV = Request.Msg.PReadV.{
.fd = fd,
.iov = iovecs,
.offset = offset,
.result = undefined,
},
},
.finish = Request.Finish{
.TickNode = Loop.NextTickNode{
.finish = Request.Finish.{
.TickNode = Loop.NextTickNode.{
.prev = null,
.next = null,
.data = @handle(),
@ -336,20 +366,20 @@ pub async fn openPosix(
const path_c = try std.os.toPosixPath(path);
var req_node = RequestNode{
var req_node = RequestNode.{
.prev = null,
.next = null,
.data = Request{
.msg = Request.Msg{
.Open = Request.Msg.Open{
.data = Request.{
.msg = Request.Msg.{
.Open = Request.Msg.Open.{
.path = path_c[0..path.len],
.flags = flags,
.mode = mode,
.result = undefined,
},
},
.finish = Request.Finish{
.TickNode = Loop.NextTickNode{
.finish = Request.Finish.{
.TickNode = Loop.NextTickNode.{
.prev = null,
.next = null,
.data = @handle(),
@ -442,32 +472,32 @@ pub async fn openReadWrite(
/// `CloseOperation.finish`.
/// If you call `setHandle` then finishing will close the fd; otherwise finishing
/// will deallocate the `CloseOperation`.
pub const CloseOperation = struct {
pub const CloseOperation = struct.{
loop: *Loop,
os_data: OsData,
const OsData = switch (builtin.os) {
builtin.Os.linux, builtin.Os.macosx => OsDataPosix,
builtin.Os.windows => struct {
builtin.Os.windows => struct.{
handle: ?os.FileHandle,
},
else => @compileError("Unsupported OS"),
};
const OsDataPosix = struct {
const OsDataPosix = struct.{
have_fd: bool,
close_req_node: RequestNode,
};
pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
pub fn start(loop: *Loop) (error.{OutOfMemory}!*CloseOperation) {
const self = try loop.allocator.createOne(CloseOperation);
self.* = CloseOperation{
self.* = CloseOperation.{
.loop = loop,
.os_data = switch (builtin.os) {
builtin.Os.linux, builtin.Os.macosx => initOsDataPosix(self),
builtin.Os.windows => OsData{ .handle = null },
builtin.Os.windows => OsData.{ .handle = null },
else => @compileError("Unsupported OS"),
},
};
@ -475,16 +505,16 @@ pub const CloseOperation = struct {
}
fn initOsDataPosix(self: *CloseOperation) OsData {
return OsData{
return OsData.{
.have_fd = false,
.close_req_node = RequestNode{
.close_req_node = RequestNode.{
.prev = null,
.next = null,
.data = Request{
.msg = Request.Msg{
.Close = Request.Msg.Close{ .fd = undefined },
.data = Request.{
.msg = Request.Msg.{
.Close = Request.Msg.Close.{ .fd = undefined },
},
.finish = Request.Finish{ .DeallocCloseOperation = self },
.finish = Request.Finish.{ .DeallocCloseOperation = self },
},
},
};
@ -597,20 +627,20 @@ async fn writeFileModeThread(loop: *Loop, path: []const u8, contents: []const u8
const path_with_null = try std.cstr.addNullByte(loop.allocator, path);
defer loop.allocator.free(path_with_null);
var req_node = RequestNode{
var req_node = RequestNode.{
.prev = null,
.next = null,
.data = Request{
.msg = Request.Msg{
.WriteFile = Request.Msg.WriteFile{
.data = Request.{
.msg = Request.Msg.{
.WriteFile = Request.Msg.WriteFile.{
.path = path_with_null[0..path.len],
.contents = contents,
.mode = mode,
.result = undefined,
},
},
.finish = Request.Finish{
.TickNode = Loop.NextTickNode{
.finish = Request.Finish.{
.TickNode = Loop.NextTickNode.{
.prev = null,
.next = null,
.data = @handle(),
@ -644,7 +674,7 @@ pub async fn readFile(loop: *Loop, file_path: []const u8, max_size: usize) ![]u8
while (true) {
try list.ensureCapacity(list.len + os.page_size);
const buf = list.items[list.len..];
const buf_array = [][]u8{buf};
const buf_array = [][]u8.{buf};
const amt = try await (async preadv(loop, fd, buf_array, list.len) catch unreachable);
list.len += amt;
if (list.len > max_size) {
@ -656,12 +686,12 @@ pub async fn readFile(loop: *Loop, file_path: []const u8, max_size: usize) ![]u8
}
}
pub const WatchEventId = enum {
pub const WatchEventId = enum.{
CloseWrite,
Delete,
};
pub const WatchEventError = error{
pub const WatchEventError = error.{
UserResourceLimitReached,
SystemResources,
AccessDenied,
@ -669,17 +699,17 @@ pub const WatchEventError = error{
};
pub fn Watch(comptime V: type) type {
return struct {
return struct.{
channel: *event.Channel(Event.Error!Event),
os_data: OsData,
const OsData = switch (builtin.os) {
builtin.Os.macosx => struct {
builtin.Os.macosx => struct.{
file_table: FileTable,
table_lock: event.Lock,
const FileTable = std.AutoHashMap([]const u8, *Put);
const Put = struct {
const Put = struct.{
putter: promise,
value_ptr: *V,
};
@ -691,7 +721,7 @@ pub fn Watch(comptime V: type) type {
else => @compileError("Unsupported OS"),
};
const WindowsOsData = struct {
const WindowsOsData = struct.{
table_lock: event.Lock,
dir_table: DirTable,
all_putters: std.atomic.Queue(promise),
@ -700,14 +730,14 @@ pub fn Watch(comptime V: type) type {
const DirTable = std.AutoHashMap([]const u8, *Dir);
const FileTable = std.AutoHashMap([]const u16, V);
const Dir = struct {
const Dir = struct.{
putter: promise,
file_table: FileTable,
table_lock: event.Lock,
};
};
const LinuxOsData = struct {
const LinuxOsData = struct.{
putter: promise,
inotify_fd: i32,
wd_table: WdTable,
@ -716,7 +746,7 @@ pub fn Watch(comptime V: type) type {
const WdTable = std.AutoHashMap(i32, Dir);
const FileTable = std.AutoHashMap([]const u8, V);
const Dir = struct {
const Dir = struct.{
dirname: []const u8,
file_table: FileTable,
};
@ -726,7 +756,7 @@ pub fn Watch(comptime V: type) type {
const Self = @This();
pub const Event = struct {
pub const Event = struct.{
id: Id,
data: V,
@ -751,9 +781,9 @@ pub fn Watch(comptime V: type) type {
builtin.Os.windows => {
const self = try loop.allocator.createOne(Self);
errdefer loop.allocator.destroy(self);
self.* = Self{
self.* = Self.{
.channel = channel,
.os_data = OsData{
.os_data = OsData.{
.table_lock = event.Lock.init(loop),
.dir_table = OsData.DirTable.init(loop.allocator),
.ref_count = std.atomic.Int(usize).init(1),
@ -767,9 +797,9 @@ pub fn Watch(comptime V: type) type {
const self = try loop.allocator.createOne(Self);
errdefer loop.allocator.destroy(self);
self.* = Self{
self.* = Self.{
.channel = channel,
.os_data = OsData{
.os_data = OsData.{
.table_lock = event.Lock.init(loop),
.file_table = OsData.FileTable.init(loop.allocator),
},
@ -878,7 +908,7 @@ pub fn Watch(comptime V: type) type {
}
var value_copy = value;
var put = OsData.Put{
var put = OsData.Put.{
.putter = @handle(),
.value_ptr = &value_copy,
};
@ -898,12 +928,12 @@ pub fn Watch(comptime V: type) type {
) catch unreachable)) |kev| {
// TODO handle EV_ERROR
if (kev.fflags & posix.NOTE_DELETE != 0) {
await (async self.channel.put(Self.Event{
await (async self.channel.put(Self.Event.{
.id = Event.Id.Delete,
.data = value_copy,
}) catch unreachable);
} else if (kev.fflags & posix.NOTE_WRITE != 0) {
await (async self.channel.put(Self.Event{
await (async self.channel.put(Self.Event.{
.id = Event.Id.CloseWrite,
.data = value_copy,
}) catch unreachable);
@ -913,7 +943,7 @@ pub fn Watch(comptime V: type) type {
error.ProcessNotFound => unreachable,
error.AccessDenied, error.SystemResources => {
// TODO https://github.com/ziglang/zig/issues/769
const casted_err = @errSetCast(error{
const casted_err = @errSetCast(error.{
AccessDenied,
SystemResources,
}, err);
@ -948,7 +978,7 @@ pub fn Watch(comptime V: type) type {
const gop = try self.os_data.wd_table.getOrPut(wd);
if (!gop.found_existing) {
gop.kv.value = OsData.Dir{
gop.kv.value = OsData.Dir.{
.dirname = dirname_with_null,
.file_table = OsData.FileTable.init(self.channel.loop.allocator),
};
@ -1030,7 +1060,7 @@ pub fn Watch(comptime V: type) type {
const dir = try self.channel.loop.allocator.createOne(OsData.Dir);
errdefer self.channel.loop.allocator.destroy(dir);
dir.* = OsData.Dir{
dir.* = OsData.Dir.{
.file_table = OsData.FileTable.init(self.channel.loop.allocator),
.table_lock = event.Lock.init(self.channel.loop),
.putter = undefined,
@ -1059,7 +1089,7 @@ pub fn Watch(comptime V: type) type {
defer os.close(dir_handle);
var putter_node = std.atomic.Queue(promise).Node{
var putter_node = std.atomic.Queue(promise).Node.{
.data = @handle(),
.prev = null,
.next = null,
@ -1067,11 +1097,11 @@ pub fn Watch(comptime V: type) type {
self.os_data.all_putters.put(&putter_node);
defer _ = self.os_data.all_putters.remove(&putter_node);
var resume_node = Loop.ResumeNode.Basic{
.base = Loop.ResumeNode{
var resume_node = Loop.ResumeNode.Basic.{
.base = Loop.ResumeNode.{
.id = Loop.ResumeNode.Id.Basic,
.handle = @handle(),
.overlapped = windows.OVERLAPPED{
.overlapped = windows.OVERLAPPED.{
.Internal = 0,
.InternalHigh = 0,
.Offset = 0,
@ -1149,7 +1179,7 @@ pub fn Watch(comptime V: type) type {
}
};
if (user_value) |v| {
await (async self.channel.put(Event{
await (async self.channel.put(Event.{
.id = id,
.data = v,
}) catch unreachable);
@ -1173,9 +1203,9 @@ pub fn Watch(comptime V: type) type {
const loop = channel.loop;
var watch = Self{
var watch = Self.{
.channel = channel,
.os_data = OsData{
.os_data = OsData.{
.putter = @handle(),
.inotify_fd = inotify_fd,
.wd_table = OsData.WdTable.init(loop.allocator),
@ -1229,7 +1259,7 @@ pub fn Watch(comptime V: type) type {
}
};
if (user_value) |v| {
await (async channel.put(Event{
await (async channel.put(Event.{
.id = WatchEventId.CloseWrite,
.data = v,
}) catch unreachable);
@ -1246,9 +1276,7 @@ pub fn Watch(comptime V: type) type {
os.linux.EPOLLET | os.linux.EPOLLIN,
) catch unreachable)) catch |err| {
const transformed_err = switch (err) {
error.InvalidFileDescriptor => unreachable,
error.FileDescriptorAlreadyPresentInSet => unreachable,
error.InvalidSyscall => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorNotRegistered => unreachable,
error.SystemResources => error.SystemResources,
@ -1325,7 +1353,7 @@ async fn testFsWatch(loop: *Loop) !void {
{
defer os.close(fd);
try await try async pwritev(loop, fd, []const []const u8{"lorem ipsum"}, line2_offset);
try await try async pwritev(loop, fd, []const []const u8.{"lorem ipsum"}, line2_offset);
}
ev_consumed = true;
@ -1341,3 +1369,55 @@ async fn testFsWatch(loop: *Loop) !void {
// TODO test deleting the file and then re-adding it. we should get events for both
}
pub const OutStream = struct.{
fd: os.FileHandle,
stream: Stream,
loop: *Loop,
offset: usize,
pub const Error = os.File.WriteError;
pub const Stream = event.io.OutStream(Error);
pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) OutStream {
return OutStream.{
.fd = fd,
.loop = loop,
.offset = offset,
.stream = Stream.{ .writeFn = writeFn },
};
}
async<*mem.Allocator> fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
const self = @fieldParentPtr(OutStream, "stream", out_stream);
const offset = self.offset;
self.offset += bytes.len;
return await (async pwritev(self.loop, self.fd, [][]const u8.{bytes}, offset) catch unreachable);
}
};
pub const InStream = struct.{
fd: os.FileHandle,
stream: Stream,
loop: *Loop,
offset: usize,
pub const Error = PReadVError; // TODO make this not have OutOfMemory
pub const Stream = event.io.InStream(Error);
pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) InStream {
return InStream.{
.fd = fd,
.loop = loop,
.offset = offset,
.stream = Stream.{ .readFn = readFn },
};
}
async<*mem.Allocator> fn readFn(in_stream: *Stream, bytes: []u8) Error!usize {
const self = @fieldParentPtr(InStream, "stream", in_stream);
const amt = try await (async preadv(self.loop, self.fd, [][]u8.{bytes}, self.offset) catch unreachable);
self.offset += amt;
return amt;
}
};

View File

@ -11,7 +11,7 @@ const Loop = std.event.Loop;
/// and then are resumed when resolve() is called.
/// At this point the value remains forever available, and another resolve() is not allowed.
pub fn Future(comptime T: type) type {
return struct {
return struct.{
lock: Lock,
data: T,
@ -25,7 +25,7 @@ pub fn Future(comptime T: type) type {
const Queue = std.atomic.Queue(promise);
pub fn init(loop: *Loop) Self {
return Self{
return Self.{
.lock = Lock.initLocked(loop),
.available = 0,
.data = undefined,
@ -78,7 +78,7 @@ pub fn Future(comptime T: type) type {
pub fn resolve(self: *Self) void {
const prev = @atomicRmw(u8, &self.available, AtomicRmwOp.Xchg, 2, AtomicOrder.SeqCst);
assert(prev == 0 or prev == 1); // resolve() called twice
Lock.Held.release(Lock.Held{ .lock = &self.lock });
Lock.Held.release(Lock.Held.{ .lock = &self.lock });
}
};
}

View File

@ -8,7 +8,7 @@ const assert = std.debug.assert;
/// ReturnType must be `void` or `E!void`
pub fn Group(comptime ReturnType: type) type {
return struct {
return struct.{
coro_stack: Stack,
alloc_stack: Stack,
lock: Lock,
@ -22,7 +22,7 @@ pub fn Group(comptime ReturnType: type) type {
const Stack = std.atomic.Stack(promise->ReturnType);
pub fn init(loop: *Loop) Self {
return Self{
return Self.{
.coro_stack = Stack.init(),
.alloc_stack = Stack.init(),
.lock = Lock.init(loop),
@ -41,8 +41,8 @@ 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{
pub fn add(self: *Self, handle: promise->ReturnType) (error.{OutOfMemory}!void) {
const node = try self.lock.loop.allocator.create(Stack.Node.{
.next = undefined,
.data = handle,
});
@ -61,8 +61,8 @@ pub fn Group(comptime ReturnType: type) type {
/// This is equivalent to an async call, but the async function is added to the group, instead
/// of returning a promise. func must be async and have return type ReturnType.
/// Thread-safe.
pub fn call(self: *Self, comptime func: var, args: ...) (error{OutOfMemory}!void) {
const S = struct {
pub fn call(self: *Self, comptime func: var, args: ...) (error.{OutOfMemory}!void) {
const S = struct.{
async fn asyncFunc(node: **Stack.Node, args2: ...) ReturnType {
// TODO this is a hack to make the memory following be inside the coro frame
suspend {
@ -78,7 +78,7 @@ pub fn Group(comptime ReturnType: type) type {
};
var node: *Stack.Node = undefined;
const handle = try async<self.lock.loop.allocator> S.asyncFunc(&node, args);
node.* = Stack.Node{
node.* = Stack.Node.{
.next = undefined,
.data = handle,
};
@ -151,7 +151,7 @@ async fn testGroup(loop: *Loop) void {
}
async fn sleepALittle(count: *usize) void {
std.os.time.sleep(0, 1000000);
std.os.time.sleep(1 * std.os.time.millisecond);
_ = @atomicRmw(usize, count, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
}

71
std/event/io.zig Normal file
View File

@ -0,0 +1,71 @@
const std = @import("../index.zig");
const builtin = @import("builtin");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const mem = std.mem;
pub fn InStream(comptime ReadError: type) type {
return struct.{
const Self = @This();
pub const Error = ReadError;
/// Return the number of bytes read. It may be less than buffer.len.
/// If the number of bytes read is 0, it means end of stream.
/// End of stream is not an error condition.
readFn: async<*Allocator> fn (self: *Self, buffer: []u8) Error!usize,
/// Return the number of bytes read. It may be less than buffer.len.
/// If the number of bytes read is 0, it means end of stream.
/// End of stream is not an error condition.
pub async fn read(self: *Self, buffer: []u8) !usize {
return await (async self.readFn(self, buffer) catch unreachable);
}
/// Return the number of bytes read. If it is less than buffer.len
/// it means end of stream.
pub async fn readFull(self: *Self, buffer: []u8) !usize {
var index: usize = 0;
while (index != buf.len) {
const amt_read = try await (async self.read(buf[index..]) catch unreachable);
if (amt_read == 0) return index;
index += amt_read;
}
return index;
}
/// Same as `readFull` but end of stream returns `error.EndOfStream`.
pub async fn readNoEof(self: *Self, buf: []u8) !void {
const amt_read = try await (async self.readFull(buf[index..]) catch unreachable);
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 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);
}
pub async fn readStruct(self: *Self, comptime T: type, ptr: *T) !void {
// Only extern and packed structs have defined in-memory layout.
comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
return await (async self.readNoEof(@sliceToBytes((*[1]T)(ptr)[0..])) catch unreachable);
}
};
}
pub fn OutStream(comptime WriteError: type) type {
return struct.{
const Self = @This();
pub const Error = WriteError;
writeFn: async<*Allocator> fn (self: *Self, buffer: []u8) Error!void,
};
}

View File

@ -10,7 +10,7 @@ const Loop = std.event.Loop;
/// coroutines which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order.
/// Allows only one actor to hold the lock.
pub const Lock = struct {
pub const Lock = struct.{
loop: *Loop,
shared_bit: u8, // TODO make this a bool
queue: Queue,
@ -18,7 +18,7 @@ pub const Lock = struct {
const Queue = std.atomic.Queue(promise);
pub const Held = struct {
pub const Held = struct.{
lock: *Lock,
pub fn release(self: Held) void {
@ -66,7 +66,7 @@ pub const Lock = struct {
};
pub fn init(loop: *Loop) Lock {
return Lock{
return Lock.{
.loop = loop,
.shared_bit = 0,
.queue = Queue.init(),
@ -75,7 +75,7 @@ pub const Lock = struct {
}
pub fn initLocked(loop: *Loop) Lock {
return Lock{
return Lock.{
.loop = loop,
.shared_bit = 1,
.queue = Queue.init(),
@ -117,7 +117,7 @@ pub const Lock = struct {
}
}
return Held{ .lock = self };
return Held.{ .lock = self };
}
};
@ -138,7 +138,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));
assert(mem.eql(i32, shared_test_data, [1]i32.{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len));
}
async fn testLock(loop: *Loop, lock: *Lock) void {
@ -147,7 +147,7 @@ async fn testLock(loop: *Loop, lock: *Lock) void {
resume @handle();
}
const handle1 = async lockRunner(lock) catch @panic("out of memory");
var tick_node1 = Loop.NextTickNode{
var tick_node1 = Loop.NextTickNode.{
.prev = undefined,
.next = undefined,
.data = handle1,
@ -155,7 +155,7 @@ async fn testLock(loop: *Loop, lock: *Lock) void {
loop.onNextTick(&tick_node1);
const handle2 = async lockRunner(lock) catch @panic("out of memory");
var tick_node2 = Loop.NextTickNode{
var tick_node2 = Loop.NextTickNode.{
.prev = undefined,
.next = undefined,
.data = handle2,
@ -163,7 +163,7 @@ async fn testLock(loop: *Loop, lock: *Lock) void {
loop.onNextTick(&tick_node2);
const handle3 = async lockRunner(lock) catch @panic("out of memory");
var tick_node3 = Loop.NextTickNode{
var tick_node3 = Loop.NextTickNode.{
.prev = undefined,
.next = undefined,
.data = handle3,
@ -175,7 +175,7 @@ async fn testLock(loop: *Loop, lock: *Lock) void {
await handle3;
}
var shared_test_data = [1]i32{0} ** 10;
var shared_test_data = [1]i32.{0} ** 10;
var shared_test_index: usize = 0;
async fn lockRunner(lock: *Lock) void {

View File

@ -6,13 +6,13 @@ const Loop = std.event.Loop;
/// coroutines which are waiting for the lock are suspended, and
/// are resumed when the lock is released, in order.
pub fn Locked(comptime T: type) type {
return struct {
return struct.{
lock: Lock,
private_data: T,
const Self = @This();
pub const HeldLock = struct {
pub const HeldLock = struct.{
value: *T,
held: Lock.Held,
@ -22,7 +22,7 @@ pub fn Locked(comptime T: type) type {
};
pub fn init(loop: *Loop, data: T) Self {
return Self{
return Self.{
.lock = Lock.init(loop),
.private_data = data,
};
@ -33,7 +33,7 @@ pub fn Locked(comptime T: type) type {
}
pub async fn acquire(self: *Self) HeldLock {
return HeldLock{
return HeldLock.{
// TODO guaranteed allocation elision
.held = await (async self.lock.acquire() catch unreachable),
.value = &self.private_data,

Some files were not shown because too many files have changed in this diff Show More