mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge remote-tracking branch 'origin/master' into llvm8
This commit is contained in:
commit
f8d6f5daff
22
.travis.yml
22
.travis.yml
@ -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=
|
||||
@ -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()
|
||||
|
||||
@ -79,6 +79,9 @@ that counts as "freestanding" for the purposes of this table.
|
||||
[](https://travis-ci.org/ziglang/zig)
|
||||
[](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
116
build.zig
@ -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,
|
||||
|
||||
@ -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%"
|
||||
@ -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'
|
||||
@ -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
40
ci/azure/linux_script
Executable 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
104
ci/azure/macos_script
Executable 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
72
ci/azure/pipelines.yml
Normal 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
33
ci/azure/update_download_page
Executable 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
9
ci/azure/windows_install
Executable 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
|
||||
27
ci/azure/windows_script.bat
Normal file
27
ci/azure/windows_script.bat
Normal 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
30
ci/azure/windows_upload
Executable 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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
brew update
|
||||
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
brew install llvm@8
|
||||
brew outdated llvm@8 || brew upgrade llvm@8
|
||||
|
||||
@ -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
|
||||
@ -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"
|
||||
|
||||
128
doc/docgen.zig
128
doc/docgen.zig
@ -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
@ -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");
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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],
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pub const Visib = enum {
|
||||
pub const Visib = enum.{
|
||||
Private,
|
||||
Pub,
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
319
src/analyze.cpp
319
src/analyze.cpp
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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};
|
||||
|
||||
211
src/codegen.cpp
211
src/codegen.cpp
@ -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
4582
src/ir.cpp
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
||||
92
src/link.cpp
92
src/link.cpp
@ -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);
|
||||
}
|
||||
|
||||
101
src/main.cpp
101
src/main.cpp
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
28
src/os.cpp
28
src/os.cpp
@ -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;
|
||||
|
||||
@ -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 (;;) {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -92,10 +92,9 @@
|
||||
case 'c'
|
||||
|
||||
#define SYMBOL_CHAR \
|
||||
ALPHA_EXCEPT_C: \
|
||||
ALPHA: \
|
||||
case DIGIT: \
|
||||
case '_': \
|
||||
case 'c'
|
||||
case '_'
|
||||
|
||||
#define SYMBOL_START \
|
||||
ALPHA: \
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
@ -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)®_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] == '\\') {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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"));
|
||||
|
||||
151
std/build.zig
151
std/build.zig
@ -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),
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
36
std/coff.zig
36
std/coff.zig
@ -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,
|
||||
};
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
107
std/elf.zig
107
std/elf.zig
@ -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,
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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,
|
||||
},
|
||||
|
||||
336
std/event/fs.zig
336
std/event/fs.zig
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@ -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 });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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
71
std/event/io.zig
Normal 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,
|
||||
};
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user