commit f33bf48af7d9c99d532864f8a6c3f695ad5bbd21 (tree)
parent 64365bc5d7b1e2c507806ee8976acc3479ad7862
Author: Andrew Kelley <andrew@ziglang.org>
Date: Tue, 25 Feb 2020 16:30:40 -0500
Merge remote-tracking branch 'origin/master' into llvm10
Diffstat:
173 files changed, 8079 insertions(+), 8445 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -240,8 +240,8 @@ find_package(Threads)
# CMake doesn't let us create an empty executable, so we hang on to this one separately.
set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
-# This is our shim which will be replaced by libuserland written in Zig.
-set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
+# This is our shim which will be replaced by libstage2 written in Zig.
+set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp")
if(ZIG_ENABLE_MEM_PROFILE)
set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp")
@@ -263,7 +263,6 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/heap.cpp"
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
- "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
"${CMAKE_SOURCE_DIR}/src/link.cpp"
"${CMAKE_SOURCE_DIR}/src/mem.cpp"
"${CMAKE_SOURCE_DIR}/src/os.cpp"
@@ -377,27 +376,27 @@ set_target_properties(opt_c_util PROPERTIES
COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
)
-add_library(compiler STATIC ${ZIG_SOURCES})
-set_target_properties(compiler PROPERTIES
+add_library(zigcompiler STATIC ${ZIG_SOURCES})
+set_target_properties(zigcompiler PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
-target_link_libraries(compiler LINK_PUBLIC
+target_link_libraries(zigcompiler LINK_PUBLIC
zig_cpp
opt_c_util
${SOFTFLOAT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
if(NOT MSVC)
- target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
+ target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2})
endif()
if(ZIG_DIA_GUIDS_LIB)
- target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
+ target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
endif()
if(MSVC OR MINGW)
- target_link_libraries(compiler LINK_PUBLIC version)
+ target_link_libraries(zigcompiler LINK_PUBLIC version)
endif()
add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}")
@@ -405,40 +404,43 @@ set_target_properties(zig0 PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
-target_link_libraries(zig0 compiler)
+target_link_libraries(zig0 zigcompiler)
if(MSVC)
- set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib")
+ set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/zigstage2.lib")
else()
- set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
+ set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libzigstage2.a")
endif()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
- set(LIBUSERLAND_RELEASE_MODE "false")
+ set(LIBSTAGE2_RELEASE_ARG "")
else()
- set(LIBUSERLAND_RELEASE_MODE "true")
+ set(LIBSTAGE2_RELEASE_ARG --release-fast --strip)
+endif()
+if(WIN32)
+ set(LIBSTAGE2_WINDOWS_ARGS "-lntdll")
+else()
+ set(LIBSTAGE2_WINDOWS_ARGS "")
endif()
-set(BUILD_LIBUSERLAND_ARGS "build"
+set(BUILD_LIBSTAGE2_ARGS "build-lib"
+ "src-self-hosted/stage2.zig"
+ -mcpu=baseline
+ --name zigstage2
--override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
- "-Doutput-dir=${CMAKE_BINARY_DIR}"
- "-Drelease=${LIBUSERLAND_RELEASE_MODE}"
- "-Dlib-files-only"
- --prefix "${CMAKE_INSTALL_PREFIX}"
- libuserland
+ --cache on
+ --output-dir "${CMAKE_BINARY_DIR}"
+ ${LIBSTAGE2_RELEASE_ARG}
+ --disable-gen-h
+ --bundle-compiler-rt
+ -fPIC
+ -lc
+ ${LIBSTAGE2_WINDOWS_ARGS}
)
-# When using Visual Studio build system generator we default to libuserland install.
-if(MSVC)
- set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
- if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
- set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install)
- endif()
-endif()
-
-add_custom_target(zig_build_libuserland ALL
- COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS}
+add_custom_target(zig_build_libstage2 ALL
+ COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS}
DEPENDS zig0
- BYPRODUCTS "${LIBUSERLAND}"
+ BYPRODUCTS "${LIBSTAGE2}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
add_executable(zig "${ZIG_MAIN_SRC}")
@@ -447,22 +449,40 @@ set_target_properties(zig PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
-target_link_libraries(zig compiler "${LIBUSERLAND}")
+target_link_libraries(zig zigcompiler "${LIBSTAGE2}")
if(MSVC)
target_link_libraries(zig ntdll.lib)
elseif(MINGW)
target_link_libraries(zig ntdll)
endif()
-add_dependencies(zig zig_build_libuserland)
+add_dependencies(zig zig_build_libstage2)
install(TARGETS zig DESTINATION bin)
-# CODE has no effect with Visual Studio build system generator.
-if(NOT MSVC)
- get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR)
- install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")")
- install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)")
- install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")")
+set(ZIG_INSTALL_ARGS "build"
+ --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
+ "-Dlib-files-only"
+ --prefix "${CMAKE_INSTALL_PREFIX}"
+ install
+)
+
+# CODE has no effect with Visual Studio build system generator, therefore
+# when using Visual Studio build system generator we resort to running
+# `zig build install` during the build phase.
+if(MSVC)
+ set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL
+ "Windows-only: Disable copying lib/ files to install prefix during the build phase")
+ if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
+ add_custom_target(zig_install_lib_files ALL
+ COMMAND zig ${ZIG_INSTALL_ARGS}
+ DEPENDS zig
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+ )
+ endif()
+else()
+ get_target_property(zig_BINARY_DIR zig BINARY_DIR)
+ install(CODE "set(zig_EXE \"${zig_BINARY_DIR}/zig\")")
+ install(CODE "set(ZIG_INSTALL_ARGS \"${ZIG_INSTALL_ARGS}\")")
install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")")
install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake)
endif()
diff --git a/build.zig b/build.zig
@@ -65,8 +65,6 @@ pub fn build(b: *Builder) !void {
try configureStage2(b, test_stage2, ctx);
try configureStage2(b, exe, ctx);
- addLibUserlandStep(b, mode);
-
const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
@@ -176,7 +174,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
}
fn fileExists(filename: []const u8) !bool {
- fs.File.access(filename) catch |err| switch (err) {
+ fs.cwd().access(filename, .{}) catch |err| switch (err) {
error.FileNotFound => return false,
else => return err,
};
@@ -379,28 +377,3 @@ const Context = struct {
dia_guids_lib: []const u8,
llvm: LibraryDep,
};
-
-fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void {
- const artifact = b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
- artifact.disable_gen_h = true;
- artifact.bundle_compiler_rt = true;
- artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
- artifact.setBuildMode(mode);
- artifact.force_pic = true;
- if (mode != .Debug) {
- artifact.strip = true;
- }
- artifact.linkSystemLibrary("c");
- if (builtin.os == .windows) {
- artifact.linkSystemLibrary("ntdll");
- }
- const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");
- libuserland_step.dependOn(&artifact.step);
-
- const output_dir = b.option(
- []const u8,
- "output-dir",
- "For libuserland step, where to put the output",
- ) orelse return;
- artifact.setOutputDir(output_dir);
-}
diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script
@@ -34,38 +34,21 @@ release/bin/zig build test-behavior
# release/bin/zig build test-std
release/bin/zig build test-compiler-rt
-
-# This test is disabled because it triggers "out of memory" on the sr.ht CI service.
-# See https://github.com/ziglang/zig/issues/3210
-# release/bin/zig build test-compare-output
-
-# This test is disabled because it triggers "out of memory" on the sr.ht CI service.
-# See https://github.com/ziglang/zig/issues/3210
-# release/bin/zig build test-standalone
-
+release/bin/zig build test-compare-output
+release/bin/zig build test-standalone
release/bin/zig build test-stack-traces
release/bin/zig build test-cli
release/bin/zig build test-asm-link
release/bin/zig build test-runtime-safety
-
-# This test is disabled because it triggers "out of memory" on the sr.ht CI service.
-# See https://github.com/ziglang/zig/issues/3210
-# release/bin/zig build test-translate-c
-
+release/bin/zig build test-translate-c
+release/bin/zig build test-run-translated-c
release/bin/zig build test-gen-h
-
-# This test is disabled because it triggers "out of memory" on the sr.ht CI service.
-# See https://github.com/ziglang/zig/issues/3210
-# release/bin/zig build test-compile-errors
-
-# This test is disabled because it triggers "out of memory" on the sr.ht CI service.
-# See https://github.com/ziglang/zig/issues/3210
-# release/bin/zig build docs
+release/bin/zig build test-compile-errors
+release/bin/zig build docs
if [ -f ~/.s3cfg ]; then
mv ../LICENSE release/
- # Enable when `release/bin/zig build docs` passes without "out of memory" or failures
- #mv ../zig-cache/langref.html release/
+ mv ../zig-cache/langref.html release/
mv release/bin/zig release/
rmdir release/bin
diff --git a/cmake/install.cmake b/cmake/install.cmake
@@ -1,16 +1,16 @@
message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib")
-if(NOT EXISTS ${zig0_EXE})
+if(NOT EXISTS ${zig_EXE})
message("::")
message(":: ERROR: Executable not found")
message(":: (execute_process)")
message("::")
- message(":: executable: ${zig0_EXE}")
+ message(":: executable: ${zig_EXE}")
message("::")
message(FATAL_ERROR)
endif()
-execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}
+execute_process(COMMAND ${zig_EXE} ${ZIG_INSTALL_ARGS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE _result
)
@@ -19,11 +19,11 @@ if(_result)
message(":: ERROR: ${_result}")
message(":: (execute_process)")
- string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}")
+ string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}")
message("::")
- message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install")
+ message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}")
- set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS})
+ set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS})
list(LENGTH _args _len)
math(EXPR _len "${_len} - 1")
message("::")
diff --git a/doc/langref.html.in b/doc/langref.html.in
@@ -550,7 +550,7 @@ pub fn main() void {
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
integer type is {#syntax#}65535{#endsyntax#}.
</p>
- {#see_also|Integers|Floats|void|Errors|@IntType#}
+ {#see_also|Integers|Floats|void|Errors|@Type#}
{#header_close#}
{#header_open|Primitive Values#}
<div class="table-wrapper">
@@ -2025,7 +2025,8 @@ test "volatile" {
conversions are not possible.
</p>
{#code_begin|test#}
-const assert = @import("std").debug.assert;
+const std = @import("std");
+const assert = std.debug.assert;
test "pointer casting" {
const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 };
@@ -2034,7 +2035,7 @@ test "pointer casting" {
// Even this example is contrived - there are better ways to do the above than
// pointer casting. For example, using a slice narrowing cast:
- const u32_value = @bytesToSlice(u32, bytes[0..])[0];
+ const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0];
assert(u32_value == 0x12121212);
// And even another way, the most straightforward way to do it:
@@ -2114,16 +2115,16 @@ test "function alignment" {
{#link|safety check|Incorrect Pointer Alignment#}:
</p>
{#code_begin|test_safety|incorrect alignment#}
-const assert = @import("std").debug.assert;
+const std = @import("std");
test "pointer alignment safety" {
var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
- const bytes = @sliceToBytes(array[0..]);
- assert(foo(bytes) == 0x11111111);
+ const bytes = std.mem.sliceAsBytes(array[0..]);
+ std.debug.assert(foo(bytes) == 0x11111111);
}
fn foo(bytes: []u8) u32 {
const slice4 = bytes[1..5];
- const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
+ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
return int_slice[0];
}
{#code_end#}
@@ -2249,7 +2250,7 @@ test "slice widening" {
// Zig supports slice widening and slice narrowing. Cast a slice of u8
// to a slice of anything else, and Zig will perform the length conversion.
const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
- const slice = @bytesToSlice(u32, array[0..]);
+ const slice = mem.bytesAsSlice(u32, array[0..]);
assert(slice.len == 2);
assert(slice[0] == 0x12121212);
assert(slice[1] == 0x13131313);
@@ -2809,14 +2810,10 @@ test "@TagType" {
assert(@TagType(Small) == u2);
}
-// @memberCount tells how many fields an enum has:
-test "@memberCount" {
- assert(@memberCount(Small) == 4);
-}
-
-// @memberName tells the name of a field in an enum:
-test "@memberName" {
- assert(mem.eql(u8, @memberName(Small, 1), "Two"));
+// @typeInfo tells us the field count and the fields names:
+test "@typeInfo" {
+ assert(@typeInfo(Small).Enum.fields.len == 4);
+ assert(mem.eql(u8, @typeInfo(Small).Enum.fields[1].name, "Two"));
}
// @tagName gives a []const u8 representation of an enum value:
@@ -2824,7 +2821,7 @@ test "@tagName" {
assert(mem.eql(u8, @tagName(Small.Three), "Three"));
}
{#code_end#}
- {#see_also|@memberName|@memberCount|@tagName|@sizeOf#}
+ {#see_also|@typeInfo|@tagName|@sizeOf#}
{#header_open|extern enum#}
<p>
@@ -5186,7 +5183,6 @@ test "coercion of zero bit types" {
<li>{#link|@bitCast#} - change type but maintain bit representation</li>
<li>{#link|@alignCast#} - make a pointer have more alignment</li>
<li>{#link|@boolToInt#} - convert true to 1 and false to 0</li>
- <li>{#link|@bytesToSlice#} - convert a slice of bytes to a slice of another type</li>
<li>{#link|@enumToInt#} - obtain the integer tag value of an enum or tagged union</li>
<li>{#link|@errSetCast#} - convert to a smaller error set</li>
<li>{#link|@errorToInt#} - obtain the integer value of an error code</li>
@@ -5199,7 +5195,6 @@ test "coercion of zero bit types" {
<li>{#link|@intToPtr#} - convert an address to a pointer</li>
<li>{#link|@ptrCast#} - convert between pointer types</li>
<li>{#link|@ptrToInt#} - obtain the address of a pointer</li>
- <li>{#link|@sliceToBytes#} - convert a slice of anything to a slice of bytes</li>
<li>{#link|@truncate#} - convert between integer types, chopping off bits</li>
</ul>
{#header_close#}
@@ -6672,18 +6667,6 @@ comptime {
</p>
{#see_also|Alignment#}
{#header_close#}
- {#header_open|@ArgType#}
- <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
- <p>
- This builtin function takes a function type and returns the type of the parameter at index {#syntax#}n{#endsyntax#}.
- </p>
- <p>
- {#syntax#}T{#endsyntax#} must be a function type.
- </p>
- <p>
- Note: This function is deprecated. Use {#link|@typeInfo#} instead.
- </p>
- {#header_close#}
{#header_open|@as#}
<pre>{#syntax#}@as(comptime T: type, expression) T{#endsyntax#}</pre>
@@ -6817,7 +6800,7 @@ async fn func(y: *i32) void {
Asserts that {#syntax#}@sizeOf(@TypeOf(value)) == @sizeOf(DestType){#endsyntax#}.
</p>
<p>
- Asserts that {#syntax#}@typeId(DestType) != @import("builtin").TypeId.Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this.
+ Asserts that {#syntax#}@typeInfo(DestType) != .Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this.
</p>
<p>
Can be used for these things for example:
@@ -6929,18 +6912,6 @@ async fn func(y: *i32) void {
{#see_also|@bitOffsetOf#}
{#header_close#}
- {#header_open|@bytesToSlice#}
- <pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
- <p>
- Converts a slice of bytes or array of bytes into a slice of {#syntax#}Element{#endsyntax#}.
- The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.
- </p>
- <p>
- Attempting to convert a number of bytes with a length that does not evenly divide into a slice of
- elements results in safety-protected {#link|Undefined Behavior#}.
- </p>
- {#header_close#}
-
{#header_open|@call#}
<pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre>
<p>
@@ -7248,7 +7219,7 @@ test "main" {
<p>
Floored division. Rounds toward negative infinity. For unsigned integers it is
the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
- {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.
+ {#syntax#}!(@typeInfo(T) == .Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.
</p>
<ul>
<li>{#syntax#}@divFloor(-5, 3) == -2{#endsyntax#}</li>
@@ -7262,7 +7233,7 @@ test "main" {
<p>
Truncated division. Rounds toward zero. For unsigned integers it is
the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
- {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.
+ {#syntax#}!(@typeInfo(T) == .Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1){#endsyntax#}.
</p>
<ul>
<li>{#syntax#}@divTrunc(-5, 3) == -1{#endsyntax#}</li>
@@ -7320,7 +7291,7 @@ test "main" {
{#header_close#}
{#header_open|@errorToInt#}
- <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
+ <pre>{#syntax#}@errorToInt(err: var) std.meta.IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
<p>
Supports the following types:
</p>
@@ -7365,7 +7336,7 @@ comptime {
@export(internalName, .{ .name = "foo", .linkage = .Strong });
}
-extern fn internalName() void {}
+fn internalName() callconv(.C) void {}
{#code_end#}
<p>This is equivalent to:</p>
{#code_begin|obj#}
@@ -7614,7 +7585,7 @@ test "@hasDecl" {
{#header_close#}
{#header_open|@intToError#}
- <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
+ <pre>{#syntax#}@intToError(value: std.meta.IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
<p>
Converts from the integer representation of an error into {#link|The Global Error Set#} type.
</p>
@@ -7647,44 +7618,6 @@ test "@hasDecl" {
</p>
{#header_close#}
- {#header_open|@IntType#}
- <pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u16) type{#endsyntax#}</pre>
- <p>
- This function returns an integer type with the given signness and bit count. The maximum
- bit count for an integer type is {#syntax#}65535{#endsyntax#}.
- </p>
- <p>
- Deprecated. Use {#link|@Type#}.
- </p>
- {#header_close#}
-
- {#header_open|@memberCount#}
- <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
- <p>
- This function returns the number of members in a struct, enum, or union type.
- </p>
- <p>
- The result is a compile time constant.
- </p>
- <p>
- It does not include functions, variables, or constants.
- </p>
- {#header_close#}
- {#header_open|@memberName#}
- <pre>{#syntax#}@memberName(comptime T: type, comptime index: usize) [N]u8{#endsyntax#}</pre>
- <p>Returns the field name of a struct, union, or enum.</p>
- <p>
- The result is a compile time constant.
- </p>
- <p>
- It does not include functions, variables, or constants.
- </p>
- {#header_close#}
- {#header_open|@memberType#}
- <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
- <p>Returns the field type of a struct or union.</p>
- {#header_close#}
-
{#header_open|@memcpy#}
<pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
<p>
@@ -8067,14 +8000,6 @@ test "@setRuntimeSafety" {
{#see_also|@bitSizeOf|@typeInfo#}
{#header_close#}
- {#header_open|@sliceToBytes#}
- <pre>{#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}</pre>
- <p>
- Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same
- {#link|pointer|Pointers#} properties as the parameter.
- </p>
- {#header_close#}
-
{#header_open|@splat#}
<pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @TypeOf(scalar)){#endsyntax#}</pre>
<p>
@@ -8388,43 +8313,6 @@ test "integer truncation" {
<li>{#link|struct#}</li>
</ul>
{#header_close#}
-
- {#header_open|@typeId#}
- <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
- <p>
- Returns which kind of type something is. Possible values:
- </p>
- {#code_begin|syntax#}
-pub const TypeId = enum {
- Type,
- Void,
- Bool,
- NoReturn,
- Int,
- Float,
- Pointer,
- Array,
- Struct,
- ComptimeFloat,
- ComptimeInt,
- Undefined,
- Null,
- Optional,
- ErrorUnion,
- ErrorSet,
- Enum,
- Union,
- Fn,
- BoundFn,
- Opaque,
- Frame,
- AnyFrame,
- Vector,
- EnumLiteral,
-};
- {#code_end#}
- {#header_close#}
-
{#header_open|@typeInfo#}
<pre>{#syntax#}@typeInfo(comptime T: type) @import("std").builtin.TypeInfo{#endsyntax#}</pre>
<p>
@@ -8888,25 +8776,6 @@ pub fn main() void {
}
{#code_end#}
{#header_close#}
- {#header_open|Slice Widen Remainder#}
- <p>At compile-time:</p>
- {#code_begin|test_err|unable to convert#}
-comptime {
- var bytes = [5]u8{ 1, 2, 3, 4, 5 };
- var slice = @bytesToSlice(u32, bytes[0..]);
-}
- {#code_end#}
- <p>At runtime:</p>
- {#code_begin|exe_err#}
-const std = @import("std");
-
-pub fn main() void {
- var bytes = [5]u8{ 1, 2, 3, 4, 5 };
- var slice = @bytesToSlice(u32, bytes[0..]);
- std.debug.warn("value: {}\n", .{slice[0]});
-}
- {#code_end#}
- {#header_close#}
{#header_open|Attempt to Unwrap Null#}
<p>At compile-time:</p>
{#code_begin|test_err|unable to unwrap null#}
@@ -9085,14 +8954,15 @@ comptime {
{#code_end#}
<p>At runtime:</p>
{#code_begin|exe_err#}
+const mem = @import("std").mem;
pub fn main() !void {
var array align(4) = [_]u32{ 0x11111111, 0x11111111 };
- const bytes = @sliceToBytes(array[0..]);
+ const bytes = mem.sliceAsBytes(array[0..]);
if (foo(bytes) != 0x11111111) return error.Wrong;
}
fn foo(bytes: []u8) u32 {
const slice4 = bytes[1..5];
- const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
+ const int_slice = mem.bytesAsSlice(u32, @alignCast(4, slice4));
return int_slice[0];
}
{#code_end#}
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
@@ -188,6 +188,14 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
self.len += items.len;
}
+ /// Append a value to the list `n` times. Allocates more memory
+ /// as necessary.
+ pub fn appendNTimes(self: *Self, value: T, n: usize) !void {
+ const old_len = self.len;
+ try self.resize(self.len + n);
+ mem.set(T, self.items[old_len..self.len], value);
+ }
+
/// Adjust the list's length to `new_len`. Doesn't initialize
/// added items if any.
pub fn resize(self: *Self, new_len: usize) !void {
@@ -311,6 +319,23 @@ test "std.ArrayList.basic" {
testing.expect(list.pop() == 33);
}
+test "std.ArrayList.appendNTimes" {
+ var list = ArrayList(i32).init(testing.allocator);
+ defer list.deinit();
+
+ try list.appendNTimes(2, 10);
+ testing.expectEqual(@as(usize, 10), list.len);
+ for (list.toSlice()) |element| {
+ testing.expectEqual(@as(i32, 2), element);
+ }
+}
+
+test "std.ArrayList.appendNTimes with failing allocator" {
+ var list = ArrayList(i32).init(testing.failing_allocator);
+ defer list.deinit();
+ testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
+}
+
test "std.ArrayList.orderedRemove" {
var list = ArrayList(i32).init(testing.allocator);
defer list.deinit();
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
@@ -147,6 +147,10 @@ pub const Buffer = struct {
try self.resize(m.len);
mem.copy(u8, self.list.toSlice(), m);
}
+
+ pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
+ return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
+ }
};
test "simple Buffer" {
@@ -190,3 +194,11 @@ test "Buffer.initCapacity" {
testing.expect(buf.capacity() == old_cap);
testing.expect(mem.eql(u8, buf.toSliceConst(), "hello"));
}
+
+test "Buffer.print" {
+ var buf = try Buffer.init(testing.allocator, "");
+ defer buf.deinit();
+
+ try buf.print("Hello {} the {}", .{ 2, "world" });
+ testing.expect(buf.eql("Hello 2 the world"));
+}
diff --git a/lib/std/build.zig b/lib/std/build.zig
@@ -27,9 +27,6 @@ pub const Builder = struct {
install_tls: TopLevelStep,
uninstall_tls: TopLevelStep,
allocator: *Allocator,
- native_system_lib_paths: ArrayList([]const u8),
- native_system_include_dirs: ArrayList([]const u8),
- native_system_rpaths: ArrayList([]const u8),
user_input_options: UserInputOptionsMap,
available_options_map: AvailableOptionsMap,
available_options_list: ArrayList(AvailableOption),
@@ -41,6 +38,7 @@ pub const Builder = struct {
verbose_ir: bool,
verbose_llvm_ir: bool,
verbose_cimport: bool,
+ verbose_llvm_cpu_features: bool,
invalid_user_input: bool,
zig_exe: []const u8,
default_step: *Step,
@@ -137,11 +135,9 @@ pub const Builder = struct {
.verbose_ir = false,
.verbose_llvm_ir = false,
.verbose_cimport = false,
+ .verbose_llvm_cpu_features = false,
.invalid_user_input = false,
.allocator = allocator,
- .native_system_lib_paths = ArrayList([]const u8).init(allocator),
- .native_system_include_dirs = ArrayList([]const u8).init(allocator),
- .native_system_rpaths = ArrayList([]const u8).init(allocator),
.user_input_options = UserInputOptionsMap.init(allocator),
.available_options_map = AvailableOptionsMap.init(allocator),
.available_options_list = ArrayList(AvailableOption).init(allocator),
@@ -172,15 +168,11 @@ pub const Builder = struct {
};
try self.top_level_steps.append(&self.install_tls);
try self.top_level_steps.append(&self.uninstall_tls);
- self.detectNativeSystemPaths();
self.default_step = &self.install_tls.step;
return self;
}
pub fn destroy(self: *Builder) void {
- self.native_system_lib_paths.deinit();
- self.native_system_include_dirs.deinit();
- self.native_system_rpaths.deinit();
self.env_map.deinit();
self.top_level_steps.deinit();
self.allocator.destroy(self);
@@ -347,18 +339,6 @@ pub const Builder = struct {
};
}
- pub fn addNativeSystemIncludeDir(self: *Builder, path: []const u8) void {
- self.native_system_include_dirs.append(path) catch unreachable;
- }
-
- pub fn addNativeSystemRPath(self: *Builder, path: []const u8) void {
- self.native_system_rpaths.append(path) catch unreachable;
- }
-
- pub fn addNativeSystemLibPath(self: *Builder, path: []const u8) void {
- self.native_system_lib_paths.append(path) catch unreachable;
- }
-
pub fn make(self: *Builder, step_names: []const []const u8) !void {
try self.makePath(self.cache_root);
@@ -433,87 +413,6 @@ pub const Builder = struct {
return error.InvalidStepName;
}
- fn detectNativeSystemPaths(self: *Builder) void {
- var is_nixos = false;
- if (process.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
- is_nixos = true;
- var it = mem.tokenize(nix_cflags_compile, " ");
- while (true) {
- const word = it.next() orelse break;
- if (mem.eql(u8, word, "-isystem")) {
- const include_path = it.next() orelse {
- warn("Expected argument after -isystem in NIX_CFLAGS_COMPILE\n", .{});
- break;
- };
- self.addNativeSystemIncludeDir(include_path);
- } else {
- warn("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}\n", .{word});
- break;
- }
- }
- } else |err| {
- assert(err == error.EnvironmentVariableNotFound);
- }
- if (process.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
- is_nixos = true;
- var it = mem.tokenize(nix_ldflags, " ");
- while (true) {
- const word = it.next() orelse break;
- if (mem.eql(u8, word, "-rpath")) {
- const rpath = it.next() orelse {
- warn("Expected argument after -rpath in NIX_LDFLAGS\n", .{});
- break;
- };
- self.addNativeSystemRPath(rpath);
- } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') {
- const lib_path = word[2..];
- self.addNativeSystemLibPath(lib_path);
- } else {
- warn("Unrecognized C flag from NIX_LDFLAGS: {}\n", .{word});
- break;
- }
- }
- } else |err| {
- assert(err == error.EnvironmentVariableNotFound);
- }
- if (is_nixos) return;
- switch (builtin.os) {
- .windows => {},
- else => {
- const triple = (Target{
- .Cross = CrossTarget{
- .arch = builtin.arch,
- .os = builtin.os,
- .abi = builtin.abi,
- .cpu_features = builtin.cpu_features,
- },
- }).linuxTriple(self.allocator);
-
- // TODO: $ ld --verbose | grep SEARCH_DIR
- // the output contains some paths that end with lib64, maybe include them too?
- // also, what is the best possible order of things?
-
- self.addNativeSystemIncludeDir("/usr/local/include");
- self.addNativeSystemLibPath("/usr/local/lib");
- self.addNativeSystemLibPath("/usr/local/lib64");
-
- self.addNativeSystemIncludeDir(self.fmt("/usr/include/{}", .{triple}));
- self.addNativeSystemLibPath(self.fmt("/usr/lib/{}", .{triple}));
-
- self.addNativeSystemIncludeDir("/usr/include");
- self.addNativeSystemLibPath("/lib");
- self.addNativeSystemLibPath("/lib64");
- self.addNativeSystemLibPath("/usr/lib");
- self.addNativeSystemLibPath("/usr/lib64");
-
- // example: on a 64-bit debian-based linux distro, with zlib installed from apt:
- // zlib.h is in /usr/include (added above)
- // libz.so.1 is in /lib/x86_64-linux-gnu (added here)
- self.addNativeSystemLibPath(self.fmt("/lib/{}", .{triple}));
- },
- }
- }
-
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{
@@ -638,7 +537,7 @@ pub const Builder = struct {
return Target.Native;
} else {
const target_str = self.option([]const u8, "target", "the target to build for") orelse return Target.Native;
- return Target.parse(target_str) catch unreachable; // TODO better error message for bad target
+ return Target.parse(.{ .arch_os_abi = target_str }) catch unreachable; // TODO better error message for bad target
}
}
@@ -710,13 +609,13 @@ pub const Builder = struct {
}
fn typeToEnum(comptime T: type) TypeId {
- return switch (@typeId(T)) {
- builtin.TypeId.Int => TypeId.Int,
- builtin.TypeId.Float => TypeId.Float,
- builtin.TypeId.Bool => TypeId.Bool,
+ return switch (@typeInfo(T)) {
+ .Int => .Int,
+ .Float => .Float,
+ .Bool => .Bool,
else => switch (T) {
- []const u8 => TypeId.String,
- []const []const u8 => TypeId.List,
+ []const u8 => .String,
+ []const []const u8 => .List,
else => @compileError("Unsupported type: " ++ @typeName(T)),
},
};
@@ -728,11 +627,11 @@ pub const Builder = struct {
pub fn typeIdName(id: TypeId) []const u8 {
return switch (id) {
- TypeId.Bool => "bool",
- TypeId.Int => "int",
- TypeId.Float => "float",
- TypeId.String => "string",
- TypeId.List => "list",
+ .Bool => "bool",
+ .Int => "int",
+ .Float => "float",
+ .String => "string",
+ .List => "list",
};
}
@@ -1155,6 +1054,9 @@ pub const LibExeObjStep = struct {
frameworks: BufSet,
verbose_link: bool,
verbose_cc: bool,
+ emit_llvm_ir: bool = false,
+ emit_asm: bool = false,
+ emit_bin: bool = true,
disable_gen_h: bool,
bundle_compiler_rt: bool,
disable_stack_probing: bool,
@@ -1182,7 +1084,6 @@ pub const LibExeObjStep = struct {
include_dirs: ArrayList(IncludeDir),
c_macros: ArrayList([]const u8),
output_dir: ?[]const u8,
- need_system_paths: bool,
is_linking_libc: bool = false,
vcpkg_bin_path: ?[]const u8 = null,
@@ -1320,7 +1221,6 @@ pub const LibExeObjStep = struct {
.disable_stack_probing = false,
.disable_sanitize_c = false,
.output_dir = null,
- .need_system_paths = false,
.single_threaded = false,
.installed_path = null,
.install_step = null,
@@ -1496,7 +1396,6 @@ pub const LibExeObjStep = struct {
/// Prefer to use `linkSystemLibrary` instead.
pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void {
self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable;
- self.need_system_paths = true;
}
/// This links against a system library, exclusively using pkg-config to find the library.
@@ -1940,6 +1839,11 @@ pub const LibExeObjStep = struct {
if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
+ if (builder.verbose_llvm_cpu_features) zig_args.append("--verbose-llvm-cpu-features") catch unreachable;
+
+ if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
+ if (self.emit_asm) try zig_args.append("-femit-asm");
+ if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
if (self.strip) {
try zig_args.append("--strip");
@@ -2008,43 +1912,33 @@ pub const LibExeObjStep = struct {
try zig_args.append(self.target.zigTriple(builder.allocator) catch unreachable);
const all_features = self.target.getArch().allFeaturesList();
- var populated_cpu_features = cross.cpu_features.cpu.features;
- if (self.target.getArch().subArchFeature()) |sub_arch_index| {
- populated_cpu_features.addFeature(sub_arch_index);
- }
+ var populated_cpu_features = cross.cpu.model.features;
populated_cpu_features.populateDependencies(all_features);
- if (populated_cpu_features.eql(cross.cpu_features.features)) {
+ if (populated_cpu_features.eql(cross.cpu.features)) {
// The CPU name alone is sufficient.
// If it is the baseline CPU, no command line args are required.
- if (cross.cpu_features.cpu != self.target.getArch().getBaselineCpuFeatures().cpu) {
- try zig_args.append("-target-cpu");
- try zig_args.append(cross.cpu_features.cpu.name);
+ if (cross.cpu.model != Target.Cpu.baseline(self.target.getArch()).model) {
+ try zig_args.append("-mcpu");
+ try zig_args.append(cross.cpu.model.name);
}
} else {
- try zig_args.append("-target-cpu");
- try zig_args.append(cross.cpu_features.cpu.name);
+ var mcpu_buffer = try std.Buffer.init(builder.allocator, "-mcpu=");
+ try mcpu_buffer.append(cross.cpu.model.name);
- try zig_args.append("-target-feature");
- var feature_str_buffer = try std.Buffer.initSize(builder.allocator, 0);
for (all_features) |feature, i_usize| {
const i = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
const in_cpu_set = populated_cpu_features.isEnabled(i);
- const in_actual_set = cross.cpu_features.features.isEnabled(i);
+ const in_actual_set = cross.cpu.features.isEnabled(i);
if (in_cpu_set and !in_actual_set) {
- try feature_str_buffer.appendByte('-');
- try feature_str_buffer.append(feature.name);
- try feature_str_buffer.appendByte(',');
+ try mcpu_buffer.appendByte('-');
+ try mcpu_buffer.append(feature.name);
} else if (!in_cpu_set and in_actual_set) {
- try feature_str_buffer.appendByte('+');
- try feature_str_buffer.append(feature.name);
- try feature_str_buffer.appendByte(',');
+ try mcpu_buffer.appendByte('+');
+ try mcpu_buffer.append(feature.name);
}
}
- if (mem.endsWith(u8, feature_str_buffer.toSliceConst(), ",")) {
- feature_str_buffer.shrink(feature_str_buffer.len() - 1);
- }
- try zig_args.append(feature_str_buffer.toSliceConst());
+ try zig_args.append(mcpu_buffer.toSliceConst());
}
},
}
@@ -2152,23 +2046,6 @@ pub const LibExeObjStep = struct {
try zig_args.append(lib_path);
}
- if (self.need_system_paths and self.target == Target.Native) {
- for (builder.native_system_include_dirs.toSliceConst()) |include_path| {
- zig_args.append("-isystem") catch unreachable;
- zig_args.append(builder.pathFromRoot(include_path)) catch unreachable;
- }
-
- for (builder.native_system_rpaths.toSliceConst()) |rpath| {
- zig_args.append("-rpath") catch unreachable;
- zig_args.append(rpath) catch unreachable;
- }
-
- for (builder.native_system_lib_paths.toSliceConst()) |lib_path| {
- zig_args.append("--library-path") catch unreachable;
- zig_args.append(lib_path) catch unreachable;
- }
- }
-
for (self.c_macros.toSliceConst()) |c_macro| {
try zig_args.append("-D");
try zig_args.append(c_macro);
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
@@ -6,8 +6,8 @@ pub const Target = std.Target;
/// Deprecated: use `std.Target.Os`.
pub const Os = std.Target.Os;
-/// Deprecated: use `std.Target.Arch`.
-pub const Arch = std.Target.Arch;
+/// Deprecated: use `std.Target.Cpu.Arch`.
+pub const Arch = std.Target.Cpu.Arch;
/// Deprecated: use `std.Target.Abi`.
pub const Abi = std.Target.Abi;
@@ -18,9 +18,6 @@ pub const ObjectFormat = std.Target.ObjectFormat;
/// Deprecated: use `std.Target.SubSystem`.
pub const SubSystem = std.Target.SubSystem;
-/// Deprecated: use `std.Target.CpuFeatures`.
-pub const CpuFeatures = std.Target.CpuFeatures;
-
/// Deprecated: use `std.Target.Cpu`.
pub const Cpu = std.Target.Cpu;
diff --git a/lib/std/c.zig b/lib/std/c.zig
@@ -62,6 +62,8 @@ pub fn versionCheck(glibc_version: builtin.Version) type {
};
}
+pub extern "c" var environ: [*:null]?[*:0]u8;
+
pub extern "c" fn fopen(filename: [*:0]const u8, modes: [*:0]const u8) ?*FILE;
pub extern "c" fn fclose(stream: *FILE) c_int;
pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
@@ -96,6 +98,7 @@ pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int;
pub extern "c" fn fork() c_int;
pub extern "c" fn access(path: [*:0]const u8, mode: c_uint) c_int;
+pub extern "c" fn faccessat(dirfd: fd_t, path: [*:0]const u8, mode: c_uint, flags: c_uint) c_int;
pub extern "c" fn pipe(fds: *[2]fd_t) c_int;
pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int;
diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig
@@ -616,6 +616,7 @@ pub const Tokenizer = struct {
},
.BackSlash => switch (c) {
'\n' => {
+ result.start = self.index + 1;
state = .Start;
},
'\r' => {
@@ -631,6 +632,7 @@ pub const Tokenizer = struct {
},
.BackSlashCr => switch (c) {
'\n' => {
+ result.start = self.index + 1;
state = .Start;
},
else => {
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
@@ -48,7 +48,10 @@ pub const ChildProcess = struct {
cwd: ?[]const u8,
err_pipe: if (builtin.os == .windows) void else [2]os.fd_t,
- llnode: if (builtin.os == .windows) void else TailQueue(*ChildProcess).Node,
+
+ expand_arg0: Arg0Expand,
+
+ pub const Arg0Expand = os.Arg0Expand;
pub const SpawnError = error{
OutOfMemory,
@@ -90,7 +93,6 @@ pub const ChildProcess = struct {
.handle = undefined,
.thread_handle = undefined,
.err_pipe = undefined,
- .llnode = undefined,
.term = null,
.env_map = null,
.cwd = null,
@@ -102,6 +104,7 @@ pub const ChildProcess = struct {
.stdin_behavior = StdIo.Inherit,
.stdout_behavior = StdIo.Inherit,
.stderr_behavior = StdIo.Inherit,
+ .expand_arg0 = .no_expand,
};
errdefer allocator.destroy(child);
return child;
@@ -174,34 +177,56 @@ pub const ChildProcess = struct {
/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
+ /// TODO deprecate in favor of exec2
pub fn exec(
allocator: *mem.Allocator,
argv: []const []const u8,
cwd: ?[]const u8,
env_map: ?*const BufMap,
- max_output_size: usize,
+ max_output_bytes: usize,
) !ExecResult {
- const child = try ChildProcess.init(argv, allocator);
+ return exec2(.{
+ .allocator = allocator,
+ .argv = argv,
+ .cwd = cwd,
+ .env_map = env_map,
+ .max_output_bytes = max_output_bytes,
+ });
+ }
+
+ /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
+ /// If it succeeds, the caller owns result.stdout and result.stderr memory.
+ /// TODO rename to exec
+ pub fn exec2(args: struct {
+ allocator: *mem.Allocator,
+ argv: []const []const u8,
+ cwd: ?[]const u8 = null,
+ env_map: ?*const BufMap = null,
+ max_output_bytes: usize = 50 * 1024,
+ expand_arg0: Arg0Expand = .no_expand,
+ }) !ExecResult {
+ const child = try ChildProcess.init(args.argv, args.allocator);
defer child.deinit();
- child.stdin_behavior = ChildProcess.StdIo.Ignore;
- child.stdout_behavior = ChildProcess.StdIo.Pipe;
- child.stderr_behavior = ChildProcess.StdIo.Pipe;
- child.cwd = cwd;
- child.env_map = env_map;
+ child.stdin_behavior = .Ignore;
+ child.stdout_behavior = .Pipe;
+ child.stderr_behavior = .Pipe;
+ child.cwd = args.cwd;
+ child.env_map = args.env_map;
+ child.expand_arg0 = args.expand_arg0;
try child.spawn();
- var stdout = Buffer.initNull(allocator);
- var stderr = Buffer.initNull(allocator);
+ var stdout = Buffer.initNull(args.allocator);
+ var stderr = Buffer.initNull(args.allocator);
defer Buffer.deinit(&stdout);
defer Buffer.deinit(&stderr);
var stdout_file_in_stream = child.stdout.?.inStream();
var stderr_file_in_stream = child.stderr.?.inStream();
- try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
- try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
+ try stdout_file_in_stream.stream.readAllBuffer(&stdout, args.max_output_bytes);
+ try stderr_file_in_stream.stream.readAllBuffer(&stderr, args.max_output_bytes);
return ExecResult{
.term = try child.wait(),
@@ -420,7 +445,7 @@ pub const ChildProcess = struct {
os.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
}
- const err = os.execvpe(self.allocator, self.argv, env_map);
+ const err = os.execvpe_expandArg0(self.allocator, self.expand_arg0, self.argv, env_map);
forkChildErrReport(err_pipe[1], err);
}
@@ -453,7 +478,6 @@ pub const ChildProcess = struct {
self.pid = pid;
self.err_pipe = err_pipe;
- self.llnode = TailQueue(*ChildProcess).Node.init(self);
self.term = null;
if (self.stdin_behavior == StdIo.Pipe) {
@@ -827,7 +851,7 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
os.exit(1);
}
-const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
+const ErrInt = std.meta.IntType(false, @sizeOf(anyerror) * 8);
fn writeIntFd(fd: i32, value: ErrInt) !void {
const file = File{
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig
@@ -57,3 +57,34 @@ test "crypto" {
_ = @import("crypto/sha3.zig");
_ = @import("crypto/x25519.zig");
}
+
+test "issue #4532: no index out of bounds" {
+ const types = [_]type{
+ Md5,
+ Sha1,
+ Sha224,
+ Sha256,
+ Sha384,
+ Sha512,
+ Blake2s224,
+ Blake2s256,
+ Blake2b384,
+ Blake2b512,
+ };
+
+ inline for (types) |Hasher| {
+ var block = [_]u8{'#'} ** Hasher.block_length;
+ var out1: [Hasher.digest_length]u8 = undefined;
+ var out2: [Hasher.digest_length]u8 = undefined;
+
+ var h = Hasher.init();
+ h.update(block[0..]);
+ h.final(out1[0..]);
+ h.reset();
+ h.update(block[0..1]);
+ h.update(block[1..]);
+ h.final(out2[0..]);
+
+ std.testing.expectEqual(out1, out2);
+ }
+}
diff --git a/lib/std/crypto/blake2.zig b/lib/std/crypto/blake2.zig
@@ -94,7 +94,7 @@ fn Blake2s(comptime out_len: usize) type {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 64) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
off += 64 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
d.t += 64;
@@ -331,7 +331,7 @@ fn Blake2b(comptime out_len: usize) type {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 128) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 128) {
off += 128 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
d.t += 128;
diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig
@@ -24,11 +24,11 @@ pub const State = struct {
const Self = @This();
pub fn toSlice(self: *Self) []u8 {
- return @sliceToBytes(self.data[0..]);
+ return mem.sliceAsBytes(self.data[0..]);
}
pub fn toSliceConst(self: *Self) []const u8 {
- return @sliceToBytes(self.data[0..]);
+ return mem.sliceAsBytes(self.data[0..]);
}
pub fn permute(self: *Self) void {
diff --git a/lib/std/crypto/md5.zig b/lib/std/crypto/md5.zig
@@ -63,7 +63,7 @@ pub const Md5 = struct {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 64) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
off += 64 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
diff --git a/lib/std/crypto/sha1.zig b/lib/std/crypto/sha1.zig
@@ -61,7 +61,7 @@ pub const Sha1 = struct {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 64) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
off += 64 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig
@@ -116,7 +116,7 @@ fn Sha2_32(comptime params: Sha2Params32) type {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 64) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 64) {
off += 64 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
@@ -458,7 +458,7 @@ fn Sha2_64(comptime params: Sha2Params64) type {
var off: usize = 0;
// Partial buffer exists from previous update. Copy into buffer then hash.
- if (d.buf_len != 0 and d.buf_len + b.len > 128) {
+ if (d.buf_len != 0 and d.buf_len + b.len >= 128) {
off += 128 - d.buf_len;
mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig
@@ -72,7 +72,7 @@ pub const NullTerminated2DArray = struct {
errdefer allocator.free(buf);
var write_index = index_size;
- const index_buf = @bytesToSlice(?[*]u8, buf);
+ const index_buf = mem.bytesAsSlice(?[*]u8, buf);
var i: usize = 0;
for (slices) |slice| {
diff --git a/lib/std/debug/leb128.zig b/lib/std/debug/leb128.zig
@@ -2,7 +2,7 @@ const std = @import("std");
const testing = std.testing;
pub fn readULEB128(comptime T: type, in_stream: var) !T {
- const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+ const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count));
var result: T = 0;
var shift: usize = 0;
@@ -27,7 +27,7 @@ pub fn readULEB128(comptime T: type, in_stream: var) !T {
}
pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
- const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+ const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count));
var result: T = 0;
var shift: usize = 0;
@@ -55,8 +55,8 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
}
pub fn readILEB128(comptime T: type, in_stream: var) !T {
- const UT = @IntType(false, T.bit_count);
- const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+ const UT = std.meta.IntType(false, T.bit_count);
+ const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count));
var result: UT = 0;
var shift: usize = 0;
@@ -87,8 +87,8 @@ pub fn readILEB128(comptime T: type, in_stream: var) !T {
}
pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T {
- const UT = @IntType(false, T.bit_count);
- const ShiftT = @IntType(false, std.math.log2(T.bit_count));
+ const UT = std.meta.IntType(false, T.bit_count);
+ const ShiftT = std.meta.IntType(false, std.math.log2(T.bit_count));
var result: UT = 0;
var shift: usize = 0;
diff --git a/lib/std/event.zig b/lib/std/event.zig
@@ -1,6 +1,7 @@
pub const Channel = @import("event/channel.zig").Channel;
pub const Future = @import("event/future.zig").Future;
pub const Group = @import("event/group.zig").Group;
+pub const Batch = @import("event/batch.zig").Batch;
pub const Lock = @import("event/lock.zig").Lock;
pub const Locked = @import("event/locked.zig").Locked;
pub const RwLock = @import("event/rwlock.zig").RwLock;
@@ -11,6 +12,7 @@ test "import event tests" {
_ = @import("event/channel.zig");
_ = @import("event/future.zig");
_ = @import("event/group.zig");
+ _ = @import("event/batch.zig");
_ = @import("event/lock.zig");
_ = @import("event/locked.zig");
_ = @import("event/rwlock.zig");
diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig
@@ -0,0 +1,139 @@
+const std = @import("../std.zig");
+const testing = std.testing;
+
+/// Performs multiple async functions in parallel, without heap allocation.
+/// Async function frames are managed externally to this abstraction, and
+/// passed in via the `add` function. Once all the jobs are added, call `wait`.
+/// This API is *not* thread-safe. The object must be accessed from one thread at
+/// a time, however, it need not be the same thread.
+pub fn Batch(
+ /// The return value for each job.
+ /// If a job slot was re-used due to maxed out concurrency, then its result
+ /// value will be overwritten. The values can be accessed with the `results` field.
+ comptime Result: type,
+ /// How many jobs to run in parallel.
+ comptime max_jobs: comptime_int,
+ /// Controls whether the `add` and `wait` functions will be async functions.
+ comptime async_behavior: enum {
+ /// Observe the value of `std.io.is_async` to decide whether `add`
+ /// and `wait` will be async functions. Asserts that the jobs do not suspend when
+ /// `std.io.mode == .blocking`. This is a generally safe assumption, and the
+ /// usual recommended option for this parameter.
+ auto_async,
+
+ /// Always uses the `noasync` keyword when using `await` on the jobs,
+ /// making `add` and `wait` non-async functions. Asserts that the jobs do not suspend.
+ never_async,
+
+ /// `add` and `wait` use regular `await` keyword, making them async functions.
+ always_async,
+ },
+) type {
+ return struct {
+ jobs: [max_jobs]Job,
+ next_job_index: usize,
+ collected_result: CollectedResult,
+
+ const Job = struct {
+ frame: ?anyframe->Result,
+ result: Result,
+ };
+
+ const Self = @This();
+
+ const CollectedResult = switch (@typeInfo(Result)) {
+ .ErrorUnion => Result,
+ else => void,
+ };
+
+ const async_ok = switch (async_behavior) {
+ .auto_async => std.io.is_async,
+ .never_async => false,
+ .always_async => true,
+ };
+
+ pub fn init() Self {
+ return Self{
+ .jobs = [1]Job{
+ .{
+ .frame = null,
+ .result = undefined,
+ },
+ } ** max_jobs,
+ .next_job_index = 0,
+ .collected_result = {},
+ };
+ }
+
+ /// Add a frame to the Batch. If all jobs are in-flight, then this function
+ /// waits until one completes.
+ /// This function is *not* thread-safe. It must be called from one thread at
+ /// a time, however, it need not be the same thread.
+ /// TODO: "select" language feature to use the next available slot, rather than
+ /// awaiting the next index.
+ pub fn add(self: *Self, frame: anyframe->Result) void {
+ const job = &self.jobs[self.next_job_index];
+ self.next_job_index = (self.next_job_index + 1) % max_jobs;
+ if (job.frame) |existing| {
+ job.result = if (async_ok) await existing else noasync await existing;
+ if (CollectedResult != void) {
+ job.result catch |err| {
+ self.collected_result = err;
+ };
+ }
+ }
+ job.frame = frame;
+ }
+
+ /// Wait for all the jobs to complete.
+ /// Safe to call any number of times.
+ /// If `Result` is an error union, this function returns the last error that occurred, if any.
+ /// Unlike the `results` field, the return value of `wait` will report any error that occurred;
+ /// hitting max parallelism will not compromise the result.
+ /// This function is *not* thread-safe. It must be called from one thread at
+ /// a time, however, it need not be the same thread.
+ pub fn wait(self: *Self) CollectedResult {
+ for (self.jobs) |*job| if (job.frame) |f| {
+ job.result = if (async_ok) await f else noasync await f;
+ if (CollectedResult != void) {
+ job.result catch |err| {
+ self.collected_result = err;
+ };
+ }
+ job.frame = null;
+ };
+ return self.collected_result;
+ }
+ };
+}
+
+test "std.event.Batch" {
+ var count: usize = 0;
+ var batch = Batch(void, 2, .auto_async).init();
+ batch.add(&async sleepALittle(&count));
+ batch.add(&async increaseByTen(&count));
+ batch.wait();
+ testing.expect(count == 11);
+
+ var another = Batch(anyerror!void, 2, .auto_async).init();
+ another.add(&async somethingElse());
+ another.add(&async doSomethingThatFails());
+ testing.expectError(error.ItBroke, another.wait());
+}
+
+fn sleepALittle(count: *usize) void {
+ std.time.sleep(1 * std.time.millisecond);
+ _ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
+}
+
+fn increaseByTen(count: *usize) void {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ _ = @atomicRmw(usize, count, .Add, 1, .SeqCst);
+ }
+}
+
+fn doSomethingThatFails() anyerror!void {}
+fn somethingElse() anyerror!void {
+ return error.ItBroke;
+}
diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig
@@ -5,6 +5,11 @@ const testing = std.testing;
const Allocator = std.mem.Allocator;
/// ReturnType must be `void` or `E!void`
+/// TODO This API was created back with the old design of async/await, when calling any
+/// async function required an allocator. There is an ongoing experiment to transition
+/// all uses of this API to the simpler and more resource-aware `std.event.Batch` API.
+/// If the transition goes well, all usages of `Group` will be gone, and this API
+/// will be deleted.
pub fn Group(comptime ReturnType: type) type {
return struct {
frame_stack: Stack,
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig
@@ -12,15 +12,18 @@ const maxInt = std.math.maxInt;
const Thread = std.Thread;
pub const Loop = struct {
- allocator: *mem.Allocator,
next_tick_queue: std.atomic.Queue(anyframe),
os_data: OsData,
final_resume_node: ResumeNode,
pending_event_count: usize,
extra_threads: []*Thread,
- // pre-allocated eventfds. all permanently active.
- // this is how we send promises to be resumed on other threads.
+ /// For resources that have the same lifetime as the `Loop`.
+ /// This is only used by `Loop` for the thread pool and associated resources.
+ arena: std.heap.ArenaAllocator,
+
+ /// Pre-allocated eventfds. All permanently active.
+ /// This is how `Loop` sends promises to be resumed on other threads.
available_eventfd_resume_nodes: std.atomic.Stack(ResumeNode.EventFd),
eventfd_resume_nodes: []std.atomic.Stack(ResumeNode.EventFd).Node,
@@ -127,11 +130,9 @@ pub const Loop = struct {
/// Thread count is the total thread count. The thread pool size will be
/// max(thread_count - 1, 0)
pub fn initThreadPool(self: *Loop, thread_count: usize) !void {
- // TODO: https://github.com/ziglang/zig/issues/3539
- const allocator = std.heap.page_allocator;
self.* = Loop{
+ .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator),
.pending_event_count = 1,
- .allocator = allocator,
.os_data = undefined,
.next_tick_queue = std.atomic.Queue(anyframe).init(),
.extra_threads = undefined,
@@ -143,17 +144,17 @@ pub const Loop = struct {
.overlapped = ResumeNode.overlapped_init,
},
};
+ errdefer self.arena.deinit();
+
// We need at least one of these in case the fs thread wants to use onNextTick
const extra_thread_count = thread_count - 1;
const resume_node_count = std.math.max(extra_thread_count, 1);
- self.eventfd_resume_nodes = try self.allocator.alloc(
+ self.eventfd_resume_nodes = try self.arena.allocator.alloc(
std.atomic.Stack(ResumeNode.EventFd).Node,
resume_node_count,
);
- errdefer self.allocator.free(self.eventfd_resume_nodes);
- self.extra_threads = try self.allocator.alloc(*Thread, extra_thread_count);
- errdefer self.allocator.free(self.extra_threads);
+ self.extra_threads = try self.arena.allocator.alloc(*Thread, extra_thread_count);
try self.initOsData(extra_thread_count);
errdefer self.deinitOsData();
@@ -161,7 +162,8 @@ pub const Loop = struct {
pub fn deinit(self: *Loop) void {
self.deinitOsData();
- self.allocator.free(self.extra_threads);
+ self.arena.deinit();
+ self.* = undefined;
}
const InitOsDataError = os.EpollCreateError || mem.Allocator.Error || os.EventFdError ||
@@ -407,7 +409,6 @@ pub const Loop = struct {
noasync os.close(self.os_data.final_eventfd);
while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
noasync os.close(self.os_data.epollfd);
- self.allocator.free(self.eventfd_resume_nodes);
},
.macosx, .freebsd, .netbsd, .dragonfly => {
noasync os.close(self.os_data.kqfd);
diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig
@@ -101,7 +101,7 @@ pub fn LinearFifo(
}
}
{ // set unused area to undefined
- const unused = @sliceToBytes(self.buf[self.count..]);
+ const unused = mem.sliceAsBytes(self.buf[self.count..]);
@memset(unused.ptr, undefined, unused.len);
}
}
@@ -166,12 +166,12 @@ pub fn LinearFifo(
{ // set old range to undefined. Note: may be wrapped around
const slice = self.readableSliceMut(0);
if (slice.len >= count) {
- const unused = @sliceToBytes(slice[0..count]);
+ const unused = mem.sliceAsBytes(slice[0..count]);
@memset(unused.ptr, undefined, unused.len);
} else {
- const unused = @sliceToBytes(slice[0..]);
+ const unused = mem.sliceAsBytes(slice[0..]);
@memset(unused.ptr, undefined, unused.len);
- const unused2 = @sliceToBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]);
+ const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]);
@memset(unused2.ptr, undefined, unused2.len);
}
}
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
@@ -82,7 +82,7 @@ pub fn format(
comptime fmt: []const u8,
args: var,
) Errors!void {
- const ArgSetType = @IntType(false, 32);
+ const ArgSetType = u32;
if (@typeInfo(@TypeOf(args)) != .Struct) {
@compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
}
@@ -405,7 +405,7 @@ pub fn formatType(
try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
}
},
- .Struct => {
+ .Struct => |StructT| {
if (comptime std.meta.trait.hasFn("format")(T)) {
return value.format(fmt, options, context, Errors, output);
}
@@ -416,27 +416,28 @@ pub fn formatType(
}
comptime var field_i = 0;
try output(context, "{");
- inline while (field_i < @memberCount(T)) : (field_i += 1) {
+ inline for (StructT.fields) |f| {
if (field_i == 0) {
try output(context, " .");
} else {
try output(context, ", .");
}
- try output(context, @memberName(T, field_i));
+ try output(context, f.name);
try output(context, " = ");
- try formatType(@field(value, @memberName(T, field_i)), fmt, options, context, Errors, output, max_depth - 1);
+ try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
+ field_i += 1;
}
try output(context, " }");
},
.Pointer => |ptr_info| switch (ptr_info.size) {
.One => switch (@typeInfo(ptr_info.child)) {
- builtin.TypeId.Array => |info| {
+ .Array => |info| {
if (info.child == u8) {
return formatText(value, fmt, options, context, Errors, output);
}
return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
},
- builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
+ .Enum, .Union, .Struct => {
return formatType(value.*, fmt, options, context, Errors, output, max_depth);
},
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
@@ -509,7 +510,7 @@ fn formatValue(
}
const T = @TypeOf(value);
- switch (@typeId(T)) {
+ switch (@typeInfo(T)) {
.Float => return formatFloatValue(value, fmt, options, context, Errors, output),
.Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
.Bool => return output(context, if (value) "true" else "false"),
@@ -757,8 +758,6 @@ pub fn formatFloatDecimal(
} else {
try output(context, ".0");
}
- } else {
- try output(context, "0");
}
return;
@@ -945,7 +944,7 @@ fn formatIntSigned(
.fill = options.fill,
};
- const uint = @IntType(false, @TypeOf(value).bit_count);
+ const uint = std.meta.IntType(false, @TypeOf(value).bit_count);
if (value < 0) {
const minus_sign: u8 = '-';
try output(context, @as(*const [1]u8, &minus_sign)[0..]);
@@ -973,7 +972,7 @@ fn formatIntUnsigned(
assert(base >= 2);
var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
- const MinInt = @IntType(@TypeOf(value).is_signed, min_int_bits);
+ const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits);
var a: MinInt = value;
var index: usize = buf.len;
@@ -1399,6 +1398,7 @@ test "float.special" {
test "float.decimal" {
try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
+ try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
// -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
diff --git a/lib/std/fmt/parse_float.zig b/lib/std/fmt/parse_float.zig
@@ -389,7 +389,7 @@ test "fmt.parseFloat" {
const epsilon = 1e-7;
inline for ([_]type{ f16, f32, f64, f128 }) |T| {
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
@@ -96,7 +96,6 @@ pub fn updateFile(source_path: []const u8, dest_path: []const u8) !PrevStatus {
/// atime, and mode of the source file so that the next call to `updateFile` will not need a copy.
/// Returns the previous status of the file before updating.
/// If any of the directories do not exist for dest_path, they are created.
-/// TODO https://github.com/ziglang/zig/issues/2885
pub fn updateFileMode(source_path: []const u8, dest_path: []const u8, mode: ?File.Mode) !PrevStatus {
const my_cwd = cwd();
@@ -818,6 +817,13 @@ pub const Dir = struct {
) File.OpenError!File {
const w = os.windows;
+ if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
+ return error.IsDir;
+ }
+ if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
+ return error.IsDir;
+ }
+
var result = File{
.handle = undefined,
.io_mode = .blocking,
@@ -839,12 +845,6 @@ pub const Dir = struct {
.SecurityDescriptor = null,
.SecurityQualityOfService = null,
};
- if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
- return error.IsDir;
- }
- if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
- return error.IsDir;
- }
var io: w.IO_STATUS_BLOCK = undefined;
const rc = w.ntdll.NtCreateFile(
&result.handle,
@@ -864,6 +864,7 @@ pub const Dir = struct {
.OBJECT_NAME_INVALID => unreachable,
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NO_MEDIA_IN_DEVICE => return error.NoDevice,
.INVALID_PARAMETER => unreachable,
.SHARING_VIOLATION => return error.SharingViolation,
.ACCESS_DENIED => return error.AccessDenied,
@@ -1323,6 +1324,50 @@ pub const Dir = struct {
defer file.close();
try file.write(data);
}
+
+ pub const AccessError = os.AccessError;
+
+ /// Test accessing `path`.
+ /// `path` is UTF8-encoded.
+ /// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
+ /// For example, instead of testing if a file exists and then opening it, just
+ /// open it and handle the error for file not found.
+ pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {
+ if (builtin.os == .windows) {
+ const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
+ return self.accessW(&sub_path_w, flags);
+ }
+ const path_c = try os.toPosixPath(sub_path);
+ return self.accessZ(&path_c, flags);
+ }
+
+ /// Same as `access` except the path parameter is null-terminated.
+ pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {
+ if (builtin.os == .windows) {
+ const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
+ return self.accessW(&sub_path_w, flags);
+ }
+ const os_mode = if (flags.write and flags.read)
+ @as(u32, os.R_OK | os.W_OK)
+ else if (flags.write)
+ @as(u32, os.W_OK)
+ else
+ @as(u32, os.F_OK);
+ const result = if (need_async_thread)
+ std.event.Loop.instance.?.faccessatZ(self.fd, sub_path, os_mode)
+ else
+ os.faccessatZ(self.fd, sub_path, os_mode, 0);
+ return result;
+ }
+
+ /// Same as `access` except asserts the target OS is Windows and the path parameter is
+ /// * WTF-16 encoded
+ /// * null-terminated
+ /// * NtDll prefixed
+ /// TODO currently this ignores `flags`.
+ pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
+ return os.faccessatW(self.fd, sub_path_w, 0, 0);
+ }
};
/// Returns an handle to the current working directory that is open for traversal.
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
@@ -60,31 +60,6 @@ pub const File = struct {
mode: Mode = default_mode,
};
- /// Test for the existence of `path`.
- /// `path` is UTF8-encoded.
- /// In general it is recommended to avoid this function. For example,
- /// instead of testing if a file exists and then opening it, just
- /// open it and handle the error for file not found.
- /// TODO: deprecate this and move it to `std.fs.Dir`.
- /// TODO: integrate with async I/O
- pub fn access(path: []const u8) !void {
- return os.access(path, os.F_OK);
- }
-
- /// Same as `access` except the parameter is null-terminated.
- /// TODO: deprecate this and move it to `std.fs.Dir`.
- /// TODO: integrate with async I/O
- pub fn accessC(path: [*:0]const u8) !void {
- return os.accessC(path, os.F_OK);
- }
-
- /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
- /// TODO: deprecate this and move it to `std.fs.Dir`.
- /// TODO: integrate with async I/O
- pub fn accessW(path: [*:0]const u16) !void {
- return os.accessW(path, os.F_OK);
- }
-
/// Upon success, the stream is in an uninitialized state. To continue using it,
/// you must use the open() function.
pub fn close(self: File) void {
diff --git a/lib/std/fs/watch.zig b/lib/std/fs/watch.zig
@@ -26,7 +26,7 @@ fn eqlString(a: []const u16, b: []const u16) bool {
}
fn hashString(s: []const u16) u32 {
- return @truncate(u32, std.hash.Wyhash.hash(0, @sliceToBytes(s)));
+ return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceAsBytes(s)));
}
const WatchEventError = error{
diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig
@@ -93,7 +93,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
// TODO Check if the situation is better after #561 is resolved.
.Int => @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)}),
- .Float => |info| hash(hasher, @bitCast(@IntType(false, info.bits), key), strat),
+ .Float => |info| hash(hasher, @bitCast(std.meta.IntType(false, info.bits), key), strat),
.Bool => hash(hasher, @boolToInt(key), strat),
.Enum => hash(hasher, @enumToInt(key), strat),
diff --git a/lib/std/hash/wyhash.zig b/lib/std/hash/wyhash.zig
@@ -10,7 +10,7 @@ const primes = [_]u64{
};
fn read_bytes(comptime bytes: u8, data: []const u8) u64 {
- const T = @IntType(false, 8 * bytes);
+ const T = std.meta.IntType(false, 8 * bytes);
return mem.readIntSliceLittle(T, data[0..bytes]);
}
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
@@ -283,14 +283,14 @@ const WasmPageAllocator = struct {
fn getBit(self: FreeBlock, idx: usize) PageStatus {
const bit_offset = 0;
- return @intToEnum(PageStatus, Io.get(@sliceToBytes(self.data), idx, bit_offset));
+ return @intToEnum(PageStatus, Io.get(mem.sliceAsBytes(self.data), idx, bit_offset));
}
fn setBits(self: FreeBlock, start_idx: usize, len: usize, val: PageStatus) void {
const bit_offset = 0;
var i: usize = 0;
while (i < len) : (i += 1) {
- Io.set(@sliceToBytes(self.data), start_idx + i, bit_offset, @enumToInt(val));
+ Io.set(mem.sliceAsBytes(self.data), start_idx + i, bit_offset, @enumToInt(val));
}
}
@@ -552,7 +552,7 @@ pub const ArenaAllocator = struct {
if (len >= actual_min_size) break;
}
const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);
- const buf_node_slice = @bytesToSlice(BufNode, buf[0..@sizeOf(BufNode)]);
+ const buf_node_slice = mem.bytesAsSlice(BufNode, buf[0..@sizeOf(BufNode)]);
const buf_node = &buf_node_slice[0];
buf_node.* = BufNode{
.data = buf,
@@ -1015,7 +1015,7 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
// very near usize?
if (mem.page_size << 2 > maxInt(usize)) return;
- const USizeShift = @IntType(false, std.math.log2(usize.bit_count));
+ const USizeShift = std.meta.IntType(false, std.math.log2(usize.bit_count));
const large_align = @as(u29, mem.page_size << 2);
var align_mask: usize = undefined;
diff --git a/lib/std/io.zig b/lib/std/io.zig
@@ -121,76 +121,37 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
unbuffered_in_stream: *Stream,
- buffer: [buffer_size]u8,
- start_index: usize,
- end_index: usize,
+ const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
+ fifo: FifoType,
pub fn init(unbuffered_in_stream: *Stream) Self {
return Self{
.unbuffered_in_stream = unbuffered_in_stream,
- .buffer = undefined,
-
- // Initialize these two fields to buffer_size so that
- // in `readFn` we treat the state as being able to read
- // more from the unbuffered stream. If we set them to 0
- // and 0, the code would think we already hit EOF.
- .start_index = buffer_size,
- .end_index = buffer_size,
-
+ .fifo = FifoType.init(),
.stream = Stream{ .readFn = readFn },
};
}
fn readFn(in_stream: *Stream, dest: []u8) !usize {
const self = @fieldParentPtr(Self, "stream", in_stream);
-
- // Hot path for one byte reads
- if (dest.len == 1 and self.end_index > self.start_index) {
- dest[0] = self.buffer[self.start_index];
- self.start_index += 1;
- return 1;
- }
-
var dest_index: usize = 0;
- while (true) {
- const dest_space = dest.len - dest_index;
- if (dest_space == 0) {
- return dest_index;
- }
- const amt_buffered = self.end_index - self.start_index;
- if (amt_buffered == 0) {
- assert(self.end_index <= buffer_size);
- // Make sure the last read actually gave us some data
- if (self.end_index == 0) {
+ while (dest_index < dest.len) {
+ const written = self.fifo.read(dest[dest_index..]);
+ if (written == 0) {
+ // fifo empty, fill it
+ const writable = self.fifo.writableSlice(0);
+ assert(writable.len > 0);
+ const n = try self.unbuffered_in_stream.read(writable);
+ if (n == 0) {
// reading from the unbuffered stream returned nothing
// so we have nothing left to read.
return dest_index;
}
- // we can read more data from the unbuffered stream
- if (dest_space < buffer_size) {
- self.start_index = 0;
- self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
-
- // Shortcut
- if (self.end_index >= dest_space) {
- mem.copy(u8, dest[dest_index..], self.buffer[0..dest_space]);
- self.start_index = dest_space;
- return dest.len;
- }
- } else {
- // asking for so much data that buffering is actually less efficient.
- // forward the request directly to the unbuffered stream
- const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
- return dest_index + amt_read;
- }
+ self.fifo.update(n);
}
-
- const copy_amount = math.min(dest_space, amt_buffered);
- const copy_end_index = self.start_index + copy_amount;
- mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
- self.start_index = copy_end_index;
- dest_index += copy_amount;
+ dest_index += written;
}
+ return dest.len;
}
};
}
@@ -235,7 +196,7 @@ test "io.BufferedInStream" {
/// Creates a stream which supports 'un-reading' data, so that it can be read again.
/// This makes look-ahead style parsing much easier.
-pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
+pub fn PeekStream(comptime buffer_type: std.fifo.LinearFifoBufferType, comptime InStreamError: type) type {
return struct {
const Self = @This();
pub const Error = InStreamError;
@@ -244,57 +205,57 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ
stream: Stream,
base: *Stream,
- // Right now the look-ahead space is statically allocated, but a version with dynamic allocation
- // is not too difficult to derive from this.
- buffer: [buffer_size]u8,
- index: usize,
- at_end: bool,
-
- pub fn init(base: *Stream) Self {
- return Self{
- .base = base,
- .buffer = undefined,
- .index = 0,
- .at_end = false,
- .stream = Stream{ .readFn = readFn },
- };
- }
+ const FifoType = std.fifo.LinearFifo(u8, buffer_type);
+ fifo: FifoType,
+
+ pub usingnamespace switch (buffer_type) {
+ .Static => struct {
+ pub fn init(base: *Stream) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(),
+ .stream = Stream{ .readFn = readFn },
+ };
+ }
+ },
+ .Slice => struct {
+ pub fn init(base: *Stream, buf: []u8) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(buf),
+ .stream = Stream{ .readFn = readFn },
+ };
+ }
+ },
+ .Dynamic => struct {
+ pub fn init(base: *Stream, allocator: *mem.Allocator) Self {
+ return .{
+ .base = base,
+ .fifo = FifoType.init(allocator),
+ .stream = Stream{ .readFn = readFn },
+ };
+ }
+ },
+ };
- pub fn putBackByte(self: *Self, byte: u8) void {
- self.buffer[self.index] = byte;
- self.index += 1;
+ pub fn putBackByte(self: *Self, byte: u8) !void {
+ try self.putBack(&[_]u8{byte});
}
- pub fn putBack(self: *Self, bytes: []const u8) void {
- var pos = bytes.len;
- while (pos != 0) {
- pos -= 1;
- self.putBackByte(bytes[pos]);
- }
+ pub fn putBack(self: *Self, bytes: []const u8) !void {
+ try self.fifo.unget(bytes);
}
fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
const self = @fieldParentPtr(Self, "stream", in_stream);
// copy over anything putBack()'d
- var pos: usize = 0;
- while (pos < dest.len and self.index != 0) {
- dest[pos] = self.buffer[self.index - 1];
- self.index -= 1;
- pos += 1;
- }
-
- if (pos == dest.len or self.at_end) {
- return pos;
- }
+ var dest_index = self.fifo.read(dest);
+ if (dest_index == dest.len) return dest_index;
// ask the backing stream for more
- const left = dest.len - pos;
- const read = try self.base.read(dest[pos..]);
- assert(read <= left);
-
- self.at_end = (read < left);
- return pos + read;
+ dest_index += try self.base.read(dest[dest_index..]);
+ return dest_index;
}
};
}
@@ -376,7 +337,7 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
assert(u_bit_count >= bits);
break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
};
- const Buf = @IntType(false, buf_bit_count);
+ const Buf = std.meta.IntType(false, buf_bit_count);
const BufShift = math.Log2Int(Buf);
out_bits.* = @as(usize, 0);
@@ -607,52 +568,33 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr
unbuffered_out_stream: *Stream,
- buffer: [buffer_size]u8,
- index: usize,
+ const FifoType = std.fifo.LinearFifo(u8, std.fifo.LinearFifoBufferType{ .Static = buffer_size });
+ fifo: FifoType,
pub fn init(unbuffered_out_stream: *Stream) Self {
return Self{
.unbuffered_out_stream = unbuffered_out_stream,
- .buffer = undefined,
- .index = 0,
+ .fifo = FifoType.init(),
.stream = Stream{ .writeFn = writeFn },
};
}
pub fn flush(self: *Self) !void {
- try self.unbuffered_out_stream.write(self.buffer[0..self.index]);
- self.index = 0;
+ while (true) {
+ const slice = self.fifo.readableSlice(0);
+ if (slice.len == 0) break;
+ try self.unbuffered_out_stream.write(slice);
+ self.fifo.discard(slice.len);
+ }
}
fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
const self = @fieldParentPtr(Self, "stream", out_stream);
-
- if (bytes.len == 1) {
- // This is not required logic but a shorter path
- // for single byte writes
- self.buffer[self.index] = bytes[0];
- self.index += 1;
- if (self.index == buffer_size) {
- try self.flush();
- }
- return;
- } else if (bytes.len >= self.buffer.len) {
+ if (bytes.len >= self.fifo.writableLength()) {
try self.flush();
return self.unbuffered_out_stream.write(bytes);
}
- var src_index: usize = 0;
-
- while (src_index < bytes.len) {
- const dest_space_left = self.buffer.len - self.index;
- const copy_amt = math.min(dest_space_left, bytes.len - src_index);
- mem.copy(u8, self.buffer[self.index..], bytes[src_index .. src_index + copy_amt]);
- self.index += copy_amt;
- assert(self.index <= self.buffer.len);
- if (self.index == self.buffer.len) {
- try self.flush();
- }
- src_index += copy_amt;
- }
+ self.fifo.writeAssumeCapacity(bytes);
}
};
}
@@ -717,7 +659,7 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
assert(u_bit_count >= bits);
break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
};
- const Buf = @IntType(false, buf_bit_count);
+ const Buf = std.meta.IntType(false, buf_bit_count);
const BufShift = math.Log2Int(Buf);
const buf_value = @intCast(Buf, value);
@@ -848,73 +790,6 @@ pub const BufferedAtomicFile = struct {
}
};
-pub fn readLine(buf: *std.Buffer) ![]u8 {
- var stdin_stream = getStdIn().inStream();
- return readLineFrom(&stdin_stream.stream, buf);
-}
-
-/// Reads all characters until the next newline into buf, and returns
-/// a slice of the characters read (excluding the newline character(s)).
-pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
- const start = buf.len();
- while (true) {
- const byte = try stream.readByte();
- switch (byte) {
- '\r' => {
- // trash the following \n
- _ = try stream.readByte();
- return buf.toSlice()[start..];
- },
- '\n' => return buf.toSlice()[start..],
- else => try buf.appendByte(byte),
- }
- }
-}
-
-test "io.readLineFrom" {
- var buf = try std.Buffer.initSize(testing.allocator, 0);
- defer buf.deinit();
- var mem_stream = SliceInStream.init(
- \\Line 1
- \\Line 22
- \\Line 333
- );
- const stream = &mem_stream.stream;
-
- testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf));
- testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf));
- testing.expectError(error.EndOfStream, readLineFrom(stream, &buf));
- testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice());
-}
-
-pub fn readLineSlice(slice: []u8) ![]u8 {
- var stdin_stream = getStdIn().inStream();
- return readLineSliceFrom(&stdin_stream.stream, slice);
-}
-
-/// Reads all characters until the next newline into slice, and returns
-/// a slice of the characters read (excluding the newline character(s)).
-pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
- // We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
- // after taking ownership, which would always require an allocation.
- var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(testing.failing_allocator, slice) };
- try buf.resize(0);
- return try readLineFrom(stream, &buf);
-}
-
-test "io.readLineSliceFrom" {
- var buf: [7]u8 = undefined;
- var mem_stream = SliceInStream.init(
- \\Line 1
- \\Line 22
- \\Line 333
- );
- const stream = &mem_stream.stream;
-
- testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]));
- testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..]));
-}
-
pub const Packing = enum {
/// Pack data to byte alignment
Byte,
@@ -956,12 +831,12 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
//@BUG: inferred error issue. See: #1386
fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
- comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
+ comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
const u8_bit_count = 8;
const t_bit_count = comptime meta.bitCount(T);
- const U = @IntType(false, t_bit_count);
+ const U = std.meta.IntType(false, t_bit_count);
const Log2U = math.Log2Int(U);
const int_size = (U.bit_count + 7) / 8;
@@ -976,7 +851,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
if (int_size == 1) {
if (t_bit_count == 8) return @bitCast(T, buffer[0]);
- const PossiblySignedByte = @IntType(T.is_signed, 8);
+ const PossiblySignedByte = std.meta.IntType(T.is_signed, 8);
return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
}
@@ -1005,9 +880,9 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
/// Deserializes data into the type pointed to by `ptr`
pub fn deserializeInto(self: *Self, ptr: var) !void {
const T = @TypeOf(ptr);
- comptime assert(trait.is(builtin.TypeId.Pointer)(T));
+ comptime assert(trait.is(.Pointer)(T));
- if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) {
+ if (comptime trait.isSlice(T) or comptime trait.isPtrTo(.Array)(T)) {
for (ptr) |*v|
try self.deserializeInto(v);
return;
@@ -1016,7 +891,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
comptime assert(trait.isSingleItemPtr(T));
const C = comptime meta.Child(T);
- const child_type_id = @typeId(C);
+ const child_type_id = @typeInfo(C);
//custom deserializer: fn(self: *Self, deserializer: var) !void
if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
@@ -1027,10 +902,10 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
}
switch (child_type_id) {
- builtin.TypeId.Void => return,
- builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
- builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C),
- builtin.TypeId.Struct => {
+ .Void => return,
+ .Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
+ .Float, .Int => ptr.* = try self.deserializeInt(C),
+ .Struct => {
const info = @typeInfo(C).Struct;
inline for (info.fields) |*field_info| {
@@ -1040,7 +915,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
if (FieldType == void or FieldType == u0) continue;
//it doesn't make any sense to read pointers
- if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
+ if (comptime trait.is(.Pointer)(FieldType)) {
@compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
@typeName(C) ++ " because it " ++ "is of pointer-type " ++
@typeName(FieldType) ++ ".");
@@ -1049,7 +924,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
try self.deserializeInto(&@field(ptr, name));
}
},
- builtin.TypeId.Union => {
+ .Union => {
const info = @typeInfo(C).Union;
if (info.tag_type) |TagType| {
//we avoid duplicate iteration over the enum tags
@@ -1073,7 +948,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
@compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
" because it is an untagged union. Use a custom deserialize().");
},
- builtin.TypeId.Optional => {
+ .Optional => {
const OC = comptime meta.Child(C);
const exists = (try self.deserializeInt(u1)) > 0;
if (!exists) {
@@ -1085,7 +960,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
const val_ptr = &ptr.*.?;
try self.deserializeInto(val_ptr);
},
- builtin.TypeId.Enum => {
+ .Enum => {
var value = try self.deserializeInt(@TagType(C));
ptr.* = try meta.intToEnum(C, value);
},
@@ -1134,12 +1009,12 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
fn serializeInt(self: *Self, value: var) Error!void {
const T = @TypeOf(value);
- comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
+ comptime assert(trait.is(.Int)(T) or trait.is(.Float)(T));
const t_bit_count = comptime meta.bitCount(T);
const u8_bit_count = comptime meta.bitCount(u8);
- const U = @IntType(false, t_bit_count);
+ const U = std.meta.IntType(false, t_bit_count);
const Log2U = math.Log2Int(U);
const int_size = (U.bit_count + 7) / 8;
@@ -1183,11 +1058,11 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
return;
}
- switch (@typeId(T)) {
- builtin.TypeId.Void => return,
- builtin.TypeId.Bool => try self.serializeInt(@as(u1, @boolToInt(value))),
- builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value),
- builtin.TypeId.Struct => {
+ switch (@typeInfo(T)) {
+ .Void => return,
+ .Bool => try self.serializeInt(@as(u1, @boolToInt(value))),
+ .Float, .Int => try self.serializeInt(value),
+ .Struct => {
const info = @typeInfo(T);
inline for (info.Struct.fields) |*field_info| {
@@ -1197,7 +1072,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
if (FieldType == void or FieldType == u0) continue;
//It doesn't make sense to write pointers
- if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
+ if (comptime trait.is(.Pointer)(FieldType)) {
@compileError("Will not " ++ "serialize field " ++ name ++
" of struct " ++ @typeName(T) ++ " because it " ++
"is of pointer-type " ++ @typeName(FieldType) ++ ".");
@@ -1205,7 +1080,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
try self.serialize(@field(value, name));
}
},
- builtin.TypeId.Union => {
+ .Union => {
const info = @typeInfo(T).Union;
if (info.tag_type) |TagType| {
const active_tag = meta.activeTag(value);
@@ -1226,7 +1101,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
@compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
" because it is an untagged union. Use a custom serialize().");
},
- builtin.TypeId.Optional => {
+ .Optional => {
if (value == null) {
try self.serializeInt(@as(u1, @boolToInt(false)));
return;
@@ -1237,10 +1112,10 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
const val_ptr = &value.?;
try self.serialize(val_ptr.*);
},
- builtin.TypeId.Enum => {
+ .Enum => {
try self.serializeInt(@enumToInt(value));
},
- else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."),
+ else => @compileError("Cannot serialize " ++ @tagName(@typeInfo(T)) ++ " types (unimplemented)."),
}
}
};
diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig
@@ -235,7 +235,7 @@ pub fn InStream(comptime ReadError: type) type {
// Only extern and packed structs have defined in-memory layout.
comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto);
var res: [1]T = undefined;
- try self.readNoEof(@sliceToBytes(res[0..]));
+ try self.readNoEof(mem.sliceAsBytes(res[0..]));
return res[0];
}
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
@@ -5,6 +5,7 @@ const meta = std.meta;
const trait = std.trait;
const DefaultPrng = std.rand.DefaultPrng;
const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
const expectError = std.testing.expectError;
const mem = std.mem;
const fs = std.fs;
@@ -44,8 +45,8 @@ test "write a file, read it, then delete it" {
defer file.close();
const file_size = try file.getEndPos();
- const expected_file_size = "begin".len + data.len + "end".len;
- expect(file_size == expected_file_size);
+ const expected_file_size: u64 = "begin".len + data.len + "end".len;
+ expectEqual(expected_file_size, file_size);
var file_in_stream = file.inStream();
var buf_stream = io.BufferedInStream(File.ReadError).init(&file_in_stream.stream);
@@ -93,12 +94,12 @@ test "SliceInStream" {
test "PeekStream" {
const bytes = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
var ss = io.SliceInStream.init(&bytes);
- var ps = io.PeekStream(2, io.SliceInStream.Error).init(&ss.stream);
+ var ps = io.PeekStream(.{ .Static = 2 }, io.SliceInStream.Error).init(&ss.stream);
var dest: [4]u8 = undefined;
- ps.putBackByte(9);
- ps.putBackByte(10);
+ try ps.putBackByte(9);
+ try ps.putBackByte(10);
var read = try ps.stream.read(dest[0..4]);
expect(read == 4);
@@ -114,8 +115,8 @@ test "PeekStream" {
expect(read == 2);
expect(mem.eql(u8, dest[0..2], bytes[6..8]));
- ps.putBackByte(11);
- ps.putBackByte(12);
+ try ps.putBackByte(11);
+ try ps.putBackByte(12);
read = try ps.stream.read(dest[0..4]);
expect(read == 2);
@@ -317,6 +318,7 @@ test "BitStreams with File Stream" {
}
fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packing: io.Packing) !void {
+ @setEvalBranchQuota(1500);
//@NOTE: if this test is taking too long, reduce the maximum tested bitsize
const max_test_bitsize = 128;
@@ -340,8 +342,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi
comptime var i = 0;
inline while (i <= max_test_bitsize) : (i += 1) {
- const U = @IntType(false, i);
- const S = @IntType(true, i);
+ const U = std.meta.IntType(false, i);
+ const S = std.meta.IntType(true, i);
try serializer.serializeInt(@as(U, i));
if (i != 0) try serializer.serializeInt(@as(S, -1)) else try serializer.serialize(@as(S, 0));
}
@@ -349,8 +351,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi
i = 0;
inline while (i <= max_test_bitsize) : (i += 1) {
- const U = @IntType(false, i);
- const S = @IntType(true, i);
+ const U = std.meta.IntType(false, i);
+ const S = std.meta.IntType(true, i);
const x = try deserializer.deserializeInt(U);
const y = try deserializer.deserializeInt(S);
expect(x == @as(U, i));
diff --git a/lib/std/json.zig b/lib/std/json.zig
@@ -19,6 +19,74 @@ const StringEscapes = union(enum) {
},
};
+/// Checks to see if a string matches what it would be as a json-encoded string
+/// Assumes that `encoded` is a well-formed json string
+fn encodesTo(decoded: []const u8, encoded: []const u8) bool {
+ var i: usize = 0;
+ var j: usize = 0;
+ while (i < decoded.len) {
+ if (j >= encoded.len) return false;
+ if (encoded[j] != '\\') {
+ if (decoded[i] != encoded[j]) return false;
+ j += 1;
+ i += 1;
+ } else {
+ const escape_type = encoded[j + 1];
+ if (escape_type != 'u') {
+ const t: u8 = switch (escape_type) {
+ '\\' => '\\',
+ '/' => '/',
+ 'n' => '\n',
+ 'r' => '\r',
+ 't' => '\t',
+ 'f' => 12,
+ 'b' => 8,
+ '"' => '"',
+ else => unreachable,
+ };
+ if (decoded[i] != t) return false;
+ j += 2;
+ i += 1;
+ } else {
+ var codepoint = std.fmt.parseInt(u21, encoded[j + 2 .. j + 6], 16) catch unreachable;
+ j += 6;
+ if (codepoint >= 0xD800 and codepoint < 0xDC00) {
+ // surrogate pair
+ assert(encoded[j] == '\\');
+ assert(encoded[j + 1] == 'u');
+ const low_surrogate = std.fmt.parseInt(u21, encoded[j + 2 .. j + 6], 16) catch unreachable;
+ codepoint = 0x10000 + (((codepoint & 0x03ff) << 10) | (low_surrogate & 0x03ff));
+ j += 6;
+ }
+ var buf: [4]u8 = undefined;
+ const len = std.unicode.utf8Encode(codepoint, &buf) catch unreachable;
+ if (i + len > decoded.len) return false;
+ if (!mem.eql(u8, decoded[i .. i + len], buf[0..len])) return false;
+ i += len;
+ }
+ }
+ }
+ assert(i == decoded.len);
+ assert(j == encoded.len);
+ return true;
+}
+
+test "encodesTo" {
+ // same
+ testing.expectEqual(true, encodesTo("false", "false"));
+ // totally different
+ testing.expectEqual(false, encodesTo("false", "true"));
+ // differnt lengths
+ testing.expectEqual(false, encodesTo("false", "other"));
+ // with escape
+ testing.expectEqual(true, encodesTo("\\", "\\\\"));
+ testing.expectEqual(true, encodesTo("with\nescape", "with\\nescape"));
+ // with unicode
+ testing.expectEqual(true, encodesTo("ą", "\\u0105"));
+ testing.expectEqual(true, encodesTo("😂", "\\ud83d\\ude02"));
+ testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02"));
+}
+
/// A single token slice into the parent string.
///
/// Use `token.slice()` on the input at the current position to get the current slice.
@@ -1026,10 +1094,8 @@ pub const TokenStream = struct {
pub fn next(self: *TokenStream) Error!?Token {
if (self.token) |token| {
- // TODO: Audit this pattern once #2915 is closed
- const copy = token;
self.token = null;
- return copy;
+ return token;
}
var t1: ?Token = undefined;
@@ -1203,6 +1269,493 @@ pub const Value = union(enum) {
}
};
+pub const ParseOptions = struct {
+ allocator: ?*Allocator = null,
+
+ /// Behaviour when a duplicate field is encountered.
+ duplicate_field_behavior: enum {
+ UseFirst,
+ Error,
+ UseLast,
+ } = .Error,
+};
+
+fn parseInternal(comptime T: type, token: Token, tokens: *TokenStream, options: ParseOptions) !T {
+ switch (@typeInfo(T)) {
+ .Bool => {
+ return switch (token) {
+ .True => true,
+ .False => false,
+ else => error.UnexpectedToken,
+ };
+ },
+ .Float, .ComptimeFloat => {
+ const numberToken = switch (token) {
+ .Number => |n| n,
+ else => return error.UnexpectedToken,
+ };
+ return try std.fmt.parseFloat(T, numberToken.slice(tokens.slice, tokens.i - 1));
+ },
+ .Int, .ComptimeInt => {
+ const numberToken = switch (token) {
+ .Number => |n| n,
+ else => return error.UnexpectedToken,
+ };
+ if (!numberToken.is_integer) return error.UnexpectedToken;
+ return try std.fmt.parseInt(T, numberToken.slice(tokens.slice, tokens.i - 1), 10);
+ },
+ .Optional => |optionalInfo| {
+ if (token == .Null) {
+ return null;
+ } else {
+ return try parseInternal(optionalInfo.child, token, tokens, options);
+ }
+ },
+ .Enum => |enumInfo| {
+ switch (token) {
+ .Number => |numberToken| {
+ if (!numberToken.is_integer) return error.UnexpectedToken;
+ const n = try std.fmt.parseInt(enumInfo.tag_type, numberToken.slice(tokens.slice, tokens.i - 1), 10);
+ return try std.meta.intToEnum(T, n);
+ },
+ .String => |stringToken| {
+ const source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
+ switch (stringToken.escapes) {
+ .None => return std.meta.stringToEnum(T, source_slice) orelse return error.InvalidEnumTag,
+ .Some => {
+ inline for (enumInfo.fields) |field| {
+ if (field.name.len == stringToken.decodedLength() and encodesTo(field.name, source_slice)) {
+ return @field(T, field.name);
+ }
+ }
+ return error.InvalidEnumTag;
+ },
+ }
+ },
+ else => return error.UnexpectedToken,
+ }
+ },
+ .Union => |unionInfo| {
+ if (unionInfo.tag_type) |_| {
+ // try each of the union fields until we find one that matches
+ inline for (unionInfo.fields) |u_field| {
+ if (parseInternal(u_field.field_type, token, tokens, options)) |value| {
+ return @unionInit(T, u_field.name, value);
+ } else |err| {
+ // Bubble up error.OutOfMemory
+ // Parsing some types won't have OutOfMemory in their
+ // error-sets, for the condition to be valid, merge it in.
+ if (@as(@TypeOf(err) || error{OutOfMemory}, err) == error.OutOfMemory) return err;
+ // otherwise continue through the `inline for`
+ }
+ }
+ return error.NoUnionMembersMatched;
+ } else {
+ @compileError("Unable to parse into untagged union '" ++ @typeName(T) ++ "'");
+ }
+ },
+ .Struct => |structInfo| {
+ switch (token) {
+ .ObjectBegin => {},
+ else => return error.UnexpectedToken,
+ }
+ var r: T = undefined;
+ var fields_seen = [_]bool{false} ** structInfo.fields.len;
+ errdefer {
+ inline for (structInfo.fields) |field, i| {
+ if (fields_seen[i]) {
+ parseFree(field.field_type, @field(r, field.name), options);
+ }
+ }
+ }
+
+ while (true) {
+ switch ((try tokens.next()) orelse return error.UnexpectedEndOfJson) {
+ .ObjectEnd => break,
+ .String => |stringToken| {
+ const key_source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
+ var found = false;
+ inline for (structInfo.fields) |field, i| {
+ // TODO: using switches here segfault the compiler (#2727?)
+ if ((stringToken.escapes == .None and mem.eql(u8, field.name, key_source_slice)) or (stringToken.escapes == .Some and (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)))) {
+ // if (switch (stringToken.escapes) {
+ // .None => mem.eql(u8, field.name, key_source_slice),
+ // .Some => (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)),
+ // }) {
+ if (fields_seen[i]) {
+ // switch (options.duplicate_field_behavior) {
+ // .UseFirst => {},
+ // .Error => {},
+ // .UseLast => {},
+ // }
+ if (options.duplicate_field_behavior == .UseFirst) {
+ break;
+ } else if (options.duplicate_field_behavior == .Error) {
+ return error.DuplicateJSONField;
+ } else if (options.duplicate_field_behavior == .UseLast) {
+ parseFree(field.field_type, @field(r, field.name), options);
+ }
+ }
+ @field(r, field.name) = try parse(field.field_type, tokens, options);
+ fields_seen[i] = true;
+ found = true;
+ break;
+ }
+ }
+ if (!found) return error.UnknownField;
+ },
+ else => return error.UnexpectedToken,
+ }
+ }
+ inline for (structInfo.fields) |field, i| {
+ if (!fields_seen[i]) {
+ if (field.default_value) |default| {
+ @field(r, field.name) = default;
+ } else {
+ return error.MissingField;
+ }
+ }
+ }
+ return r;
+ },
+ .Array => |arrayInfo| {
+ switch (token) {
+ .ArrayBegin => {
+ var r: T = undefined;
+ var i: usize = 0;
+ errdefer {
+ while (true) : (i -= 1) {
+ parseFree(arrayInfo.child, r[i], options);
+ if (i == 0) break;
+ }
+ }
+ while (i < r.len) : (i += 1) {
+ r[i] = try parse(arrayInfo.child, tokens, options);
+ }
+ const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
+ switch (tok) {
+ .ArrayEnd => {},
+ else => return error.UnexpectedToken,
+ }
+ return r;
+ },
+ .String => |stringToken| {
+ if (arrayInfo.child != u8) return error.UnexpectedToken;
+ var r: T = undefined;
+ const source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
+ switch (stringToken.escapes) {
+ .None => mem.copy(u8, &r, source_slice),
+ .Some => try unescapeString(&r, source_slice),
+ }
+ return r;
+ },
+ else => return error.UnexpectedToken,
+ }
+ },
+ .Pointer => |ptrInfo| {
+ const allocator = options.allocator orelse return error.AllocatorRequired;
+ switch (ptrInfo.size) {
+ .One => {
+ const r: T = allocator.create(ptrInfo.child);
+ r.* = try parseInternal(ptrInfo.child, token, tokens, options);
+ return r;
+ },
+ .Slice => {
+ switch (token) {
+ .ArrayBegin => {
+ var arraylist = std.ArrayList(ptrInfo.child).init(allocator);
+ errdefer {
+ while (arraylist.popOrNull()) |v| {
+ parseFree(ptrInfo.child, v, options);
+ }
+ arraylist.deinit();
+ }
+
+ while (true) {
+ const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
+ switch (tok) {
+ .ArrayEnd => break,
+ else => {},
+ }
+
+ try arraylist.ensureCapacity(arraylist.len + 1);
+ const v = try parseInternal(ptrInfo.child, tok, tokens, options);
+ arraylist.appendAssumeCapacity(v);
+ }
+ return arraylist.toOwnedSlice();
+ },
+ .String => |stringToken| {
+ if (ptrInfo.child != u8) return error.UnexpectedToken;
+ const source_slice = stringToken.slice(tokens.slice, tokens.i - 1);
+ switch (stringToken.escapes) {
+ .None => return mem.dupe(allocator, u8, source_slice),
+ .Some => |some_escapes| {
+ const output = try allocator.alloc(u8, stringToken.decodedLength());
+ errdefer allocator.free(output);
+ try unescapeString(output, source_slice);
+ return output;
+ },
+ }
+ },
+ else => return error.UnexpectedToken,
+ }
+ },
+ else => @compileError("Unable to parse into type '" ++ @typeName(T) ++ "'"),
+ }
+ },
+ else => @compileError("Unable to parse into type '" ++ @typeName(T) ++ "'"),
+ }
+ unreachable;
+}
+
+pub fn parse(comptime T: type, tokens: *TokenStream, options: ParseOptions) !T {
+ const token = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
+ return parseInternal(T, token, tokens, options);
+}
+
+/// Releases resources created by `parse`.
+/// Should be called with the same type and `ParseOptions` that were passed to `parse`
+pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
+ switch (@typeInfo(T)) {
+ .Bool, .Float, .ComptimeFloat, .Int, .ComptimeInt, .Enum => {},
+ .Optional => {
+ if (value) |v| {
+ return parseFree(@TypeOf(v), v, options);
+ }
+ },
+ .Union => |unionInfo| {
+ if (unionInfo.tag_type) |UnionTagType| {
+ inline for (unionInfo.fields) |u_field| {
+ if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
+ parseFree(u_field.field_type, @field(value, u_field.name), options);
+ break;
+ }
+ }
+ } else {
+ unreachable;
+ }
+ },
+ .Struct => |structInfo| {
+ inline for (structInfo.fields) |field| {
+ parseFree(field.field_type, @field(value, field.name), options);
+ }
+ },
+ .Array => |arrayInfo| {
+ for (value) |v| {
+ parseFree(arrayInfo.child, v, options);
+ }
+ },
+ .Pointer => |ptrInfo| {
+ const allocator = options.allocator orelse unreachable;
+ switch (ptrInfo.size) {
+ .One => {
+ parseFree(ptrInfo.child, value.*, options);
+ allocator.destroy(v);
+ },
+ .Slice => {
+ for (value) |v| {
+ parseFree(ptrInfo.child, v, options);
+ }
+ allocator.free(value);
+ },
+ else => unreachable,
+ }
+ },
+ else => unreachable,
+ }
+}
+
+test "parse" {
+ testing.expectEqual(false, try parse(bool, &TokenStream.init("false"), ParseOptions{}));
+ testing.expectEqual(true, try parse(bool, &TokenStream.init("true"), ParseOptions{}));
+ testing.expectEqual(@as(u1, 1), try parse(u1, &TokenStream.init("1"), ParseOptions{}));
+ testing.expectError(error.Overflow, parse(u1, &TokenStream.init("50"), ParseOptions{}));
+ testing.expectEqual(@as(u64, 42), try parse(u64, &TokenStream.init("42"), ParseOptions{}));
+ testing.expectEqual(@as(f64, 42), try parse(f64, &TokenStream.init("42.0"), ParseOptions{}));
+ testing.expectEqual(@as(?bool, null), try parse(?bool, &TokenStream.init("null"), ParseOptions{}));
+ testing.expectEqual(@as(?bool, true), try parse(?bool, &TokenStream.init("true"), ParseOptions{}));
+
+ testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("\"foo\""), ParseOptions{}));
+ testing.expectEqual(@as([3]u8, "foo".*), try parse([3]u8, &TokenStream.init("[102, 111, 111]"), ParseOptions{}));
+}
+
+test "parse into enum" {
+ const T = extern enum {
+ Foo = 42,
+ Bar,
+ @"with\\escape",
+ };
+ testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("\"Foo\""), ParseOptions{}));
+ testing.expectEqual(@as(T, .Foo), try parse(T, &TokenStream.init("42"), ParseOptions{}));
+ testing.expectEqual(@as(T, .@"with\\escape"), try parse(T, &TokenStream.init("\"with\\\\escape\""), ParseOptions{}));
+ testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("5"), ParseOptions{}));
+ testing.expectError(error.InvalidEnumTag, parse(T, &TokenStream.init("\"Qux\""), ParseOptions{}));
+}
+
+test "parse into that allocates a slice" {
+ testing.expectError(error.AllocatorRequired, parse([]u8, &TokenStream.init("\"foo\""), ParseOptions{}));
+
+ const options = ParseOptions{ .allocator = testing.allocator };
+ {
+ const r = try parse([]u8, &TokenStream.init("\"foo\""), options);
+ defer parseFree([]u8, r, options);
+ testing.expectEqualSlices(u8, "foo", r);
+ }
+ {
+ const r = try parse([]u8, &TokenStream.init("[102, 111, 111]"), options);
+ defer parseFree([]u8, r, options);
+ testing.expectEqualSlices(u8, "foo", r);
+ }
+ {
+ const r = try parse([]u8, &TokenStream.init("\"with\\\\escape\""), options);
+ defer parseFree([]u8, r, options);
+ testing.expectEqualSlices(u8, "with\\escape", r);
+ }
+}
+
+test "parse into tagged union" {
+ {
+ const T = union(enum) {
+ int: i32,
+ float: f64,
+ string: []const u8,
+ };
+ testing.expectEqual(T{ .float = 1.5 }, try parse(T, &TokenStream.init("1.5"), ParseOptions{}));
+ }
+
+ { // if union matches string member, fails with NoUnionMembersMatched rather than AllocatorRequired
+ // Note that this behaviour wasn't necessarily by design, but was
+ // what fell out of the implementation and may result in interesting
+ // API breakage if changed
+ const T = union(enum) {
+ int: i32,
+ float: f64,
+ string: []const u8,
+ };
+ testing.expectError(error.NoUnionMembersMatched, parse(T, &TokenStream.init("\"foo\""), ParseOptions{}));
+ }
+
+ { // failing allocations should be bubbled up instantly without trying next member
+ var fail_alloc = testing.FailingAllocator.init(testing.allocator, 0);
+ const options = ParseOptions{ .allocator = &fail_alloc.allocator };
+ const T = union(enum) {
+ // both fields here match the input
+ string: []const u8,
+ array: [3]u8,
+ };
+ testing.expectError(error.OutOfMemory, parse(T, &TokenStream.init("[1,2,3]"), options));
+ }
+
+ {
+ // if multiple matches possible, takes first option
+ const T = union(enum) {
+ x: u8,
+ y: u8,
+ };
+ testing.expectEqual(T{ .x = 42 }, try parse(T, &TokenStream.init("42"), ParseOptions{}));
+ }
+}
+
+test "parseFree descends into tagged union" {
+ // tagged unions are broken on arm64: https://github.com/ziglang/zig/issues/4492
+ if (std.builtin.arch == .aarch64) return error.SkipZigTest;
+
+ var fail_alloc = testing.FailingAllocator.init(testing.allocator, 1);
+ const options = ParseOptions{ .allocator = &fail_alloc.allocator };
+ const T = union(enum) {
+ int: i32,
+ float: f64,
+ string: []const u8,
+ };
+ // use a string with unicode escape so we know result can't be a reference to global constant
+ const r = try parse(T, &TokenStream.init("\"with\\u0105unicode\""), options);
+ testing.expectEqual(@TagType(T).string, @as(@TagType(T), r));
+ testing.expectEqualSlices(u8, "withąunicode", r.string);
+ testing.expectEqual(@as(usize, 0), fail_alloc.deallocations);
+ parseFree(T, r, options);
+ testing.expectEqual(@as(usize, 1), fail_alloc.deallocations);
+}
+
+test "parse into struct with no fields" {
+ const T = struct {};
+ testing.expectEqual(T{}, try parse(T, &TokenStream.init("{}"), ParseOptions{}));
+}
+
+test "parse into struct with misc fields" {
+ @setEvalBranchQuota(10000);
+ const options = ParseOptions{ .allocator = testing.allocator };
+ const T = struct {
+ int: i64,
+ float: f64,
+ @"with\\escape": bool,
+ @"withąunicode😂": bool,
+ language: []const u8,
+ optional: ?bool,
+ default_field: i32 = 42,
+ static_array: [3]f64,
+ dynamic_array: []f64,
+
+ const Bar = struct {
+ nested: []const u8,
+ };
+ complex: Bar,
+
+ const Baz = struct {
+ foo: []const u8,
+ };
+ veryComplex: []Baz,
+
+ const Union = union(enum) {
+ x: u8,
+ float: f64,
+ string: []const u8,
+ };
+ a_union: Union,
+ };
+ const r = try parse(T, &TokenStream.init(
+ \\{
+ \\ "int": 420,
+ \\ "float": 3.14,
+ \\ "with\\escape": true,
+ \\ "with\u0105unicode\ud83d\ude02": false,
+ \\ "language": "zig",
+ \\ "optional": null,
+ \\ "static_array": [66.6, 420.420, 69.69],
+ \\ "dynamic_array": [66.6, 420.420, 69.69],
+ \\ "complex": {
+ \\ "nested": "zig"
+ \\ },
+ \\ "veryComplex": [
+ \\ {
+ \\ "foo": "zig"
+ \\ }, {
+ \\ "foo": "rocks"
+ \\ }
+ \\ ],
+ \\ "a_union": 100000
+ \\}
+ ), options);
+ defer parseFree(T, r, options);
+ testing.expectEqual(@as(i64, 420), r.int);
+ testing.expectEqual(@as(f64, 3.14), r.float);
+ testing.expectEqual(true, r.@"with\\escape");
+ testing.expectEqual(false, r.@"withąunicode😂");
+ testing.expectEqualSlices(u8, "zig", r.language);
+ testing.expectEqual(@as(?bool, null), r.optional);
+ testing.expectEqual(@as(i32, 42), r.default_field);
+ testing.expectEqual(@as(f64, 66.6), r.static_array[0]);
+ testing.expectEqual(@as(f64, 420.420), r.static_array[1]);
+ testing.expectEqual(@as(f64, 69.69), r.static_array[2]);
+ testing.expectEqual(@as(usize, 3), r.dynamic_array.len);
+ testing.expectEqual(@as(f64, 66.6), r.dynamic_array[0]);
+ testing.expectEqual(@as(f64, 420.420), r.dynamic_array[1]);
+ testing.expectEqual(@as(f64, 69.69), r.dynamic_array[2]);
+ testing.expectEqualSlices(u8, r.complex.nested, "zig");
+ testing.expectEqualSlices(u8, "zig", r.veryComplex[0].foo);
+ testing.expectEqualSlices(u8, "rocks", r.veryComplex[1].foo);
+ testing.expectEqual(T.Union{ .float = 100000 }, r.a_union);
+}
+
/// A non-stream JSON parser which constructs a tree of Value's.
pub const Parser = struct {
allocator: *Allocator,
@@ -1688,3 +2241,269 @@ test "string copy option" {
}
testing.expect(found_nocopy);
}
+
+pub const StringifyOptions = struct {
+ // TODO: indentation options?
+ // TODO: make escaping '/' in strings optional?
+ // TODO: allow picking if []u8 is string or array?
+};
+
+pub fn stringify(
+ value: var,
+ options: StringifyOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+) Errors!void {
+ const T = @TypeOf(value);
+ switch (@typeInfo(T)) {
+ .Float, .ComptimeFloat => {
+ return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output);
+ },
+ .Int, .ComptimeInt => {
+ return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output);
+ },
+ .Bool => {
+ return output(context, if (value) "true" else "false");
+ },
+ .Optional => {
+ if (value) |payload| {
+ return try stringify(payload, options, context, Errors, output);
+ } else {
+ return output(context, "null");
+ }
+ },
+ .Enum => {
+ if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
+ return value.jsonStringify(options, context, Errors, output);
+ }
+
+ @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
+ },
+ .Union => {
+ if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
+ return value.jsonStringify(options, context, Errors, output);
+ }
+
+ const info = @typeInfo(T).Union;
+ if (info.tag_type) |UnionTagType| {
+ inline for (info.fields) |u_field| {
+ if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
+ return try stringify(@field(value, u_field.name), options, context, Errors, output);
+ }
+ }
+ } else {
+ @compileError("Unable to stringify untagged union '" ++ @typeName(T) ++ "'");
+ }
+ },
+ .Struct => |S| {
+ if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
+ return value.jsonStringify(options, context, Errors, output);
+ }
+
+ try output(context, "{");
+ comptime var field_output = false;
+ inline for (S.fields) |Field, field_i| {
+ // don't include void fields
+ if (Field.field_type == void) continue;
+
+ if (!field_output) {
+ field_output = true;
+ } else {
+ try output(context, ",");
+ }
+
+ try stringify(Field.name, options, context, Errors, output);
+ try output(context, ":");
+ try stringify(@field(value, Field.name), options, context, Errors, output);
+ }
+ try output(context, "}");
+ return;
+ },
+ .Pointer => |ptr_info| switch (ptr_info.size) {
+ .One => {
+ // TODO: avoid loops?
+ return try stringify(value.*, options, context, Errors, output);
+ },
+ // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
+ .Slice => {
+ if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
+ try output(context, "\"");
+ var i: usize = 0;
+ while (i < value.len) : (i += 1) {
+ switch (value[i]) {
+ // normal ascii characters
+ 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]),
+ // control characters with short escapes
+ '\\' => try output(context, "\\\\"),
+ '\"' => try output(context, "\\\""),
+ '/' => try output(context, "\\/"),
+ 0x8 => try output(context, "\\b"),
+ 0xC => try output(context, "\\f"),
+ '\n' => try output(context, "\\n"),
+ '\r' => try output(context, "\\r"),
+ '\t' => try output(context, "\\t"),
+ else => {
+ const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
+ const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
+ if (codepoint <= 0xFFFF) {
+ // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
+ // then it may be represented as a six-character sequence: a reverse solidus, followed
+ // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
+ try output(context, "\\u");
+ try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
+ } else {
+ // To escape an extended character that is not in the Basic Multilingual Plane,
+ // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
+ const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
+ const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
+ try output(context, "\\u");
+ try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
+ try output(context, "\\u");
+ try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
+ }
+ i += ulen - 1;
+ },
+ }
+ }
+ try output(context, "\"");
+ return;
+ }
+
+ try output(context, "[");
+ for (value) |x, i| {
+ if (i != 0) {
+ try output(context, ",");
+ }
+ try stringify(x, options, context, Errors, output);
+ }
+ try output(context, "]");
+ return;
+ },
+ else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
+ },
+ .Array => |info| {
+ return try stringify(value[0..], options, context, Errors, output);
+ },
+ else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
+ }
+ unreachable;
+}
+
+fn teststringify(expected: []const u8, value: var) !void {
+ const TestStringifyContext = struct {
+ expected_remaining: []const u8,
+ fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {
+ if (context.expected_remaining.len < bytes.len) {
+ std.debug.warn(
+ \\====== expected this output: =========
+ \\{}
+ \\======== instead found this: =========
+ \\{}
+ \\======================================
+ , .{
+ context.expected_remaining,
+ bytes,
+ });
+ return error.TooMuchData;
+ }
+ if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) {
+ std.debug.warn(
+ \\====== expected this output: =========
+ \\{}
+ \\======== instead found this: =========
+ \\{}
+ \\======================================
+ , .{
+ context.expected_remaining[0..bytes.len],
+ bytes,
+ });
+ return error.DifferentData;
+ }
+ context.expected_remaining = context.expected_remaining[bytes.len..];
+ }
+ };
+ var buf: [100]u8 = undefined;
+ var context = TestStringifyContext{ .expected_remaining = expected };
+ try stringify(value, StringifyOptions{}, &context, error{
+ TooMuchData,
+ DifferentData,
+ }, TestStringifyContext.testStringifyWrite);
+ if (context.expected_remaining.len > 0) return error.NotEnoughData;
+}
+
+test "stringify basic types" {
+ try teststringify("false", false);
+ try teststringify("true", true);
+ try teststringify("null", @as(?u8, null));
+ try teststringify("null", @as(?*u32, null));
+ try teststringify("42", 42);
+ try teststringify("4.2e+01", 42.0);
+ try teststringify("42", @as(u8, 42));
+ try teststringify("42", @as(u128, 42));
+ try teststringify("4.2e+01", @as(f32, 42));
+ try teststringify("4.2e+01", @as(f64, 42));
+}
+
+test "stringify string" {
+ try teststringify("\"hello\"", "hello");
+ try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r");
+ try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}");
+ try teststringify("\"with unicode\\u0080\"", "with unicode\u{80}");
+ try teststringify("\"with unicode\\u00ff\"", "with unicode\u{FF}");
+ try teststringify("\"with unicode\\u0100\"", "with unicode\u{100}");
+ try teststringify("\"with unicode\\u0800\"", "with unicode\u{800}");
+ try teststringify("\"with unicode\\u8000\"", "with unicode\u{8000}");
+ try teststringify("\"with unicode\\ud799\"", "with unicode\u{D799}");
+ try teststringify("\"with unicode\\ud800\\udc00\"", "with unicode\u{10000}");
+ try teststringify("\"with unicode\\udbff\\udfff\"", "with unicode\u{10FFFF}");
+}
+
+test "stringify tagged unions" {
+ try teststringify("42", union(enum) {
+ Foo: u32,
+ Bar: bool,
+ }{ .Foo = 42 });
+}
+
+test "stringify struct" {
+ try teststringify("{\"foo\":42}", struct {
+ foo: u32,
+ }{ .foo = 42 });
+}
+
+test "stringify struct with void field" {
+ try teststringify("{\"foo\":42}", struct {
+ foo: u32,
+ bar: void = {},
+ }{ .foo = 42 });
+}
+
+test "stringify array of structs" {
+ const MyStruct = struct {
+ foo: u32,
+ };
+ try teststringify("[{\"foo\":42},{\"foo\":100},{\"foo\":1000}]", [_]MyStruct{
+ MyStruct{ .foo = 42 },
+ MyStruct{ .foo = 100 },
+ MyStruct{ .foo = 1000 },
+ });
+}
+
+test "stringify struct with custom stringifier" {
+ try teststringify("[\"something special\",42]", struct {
+ foo: u32,
+ const Self = @This();
+ pub fn jsonStringify(
+ value: Self,
+ options: StringifyOptions,
+ context: var,
+ comptime Errors: type,
+ comptime output: fn (@TypeOf(context), []const u8) Errors!void,
+ ) !void {
+ try output(context, "[\"something special\",");
+ try stringify(42, options, context, Errors, output);
+ try output(context, "]");
+ }
+ }{ .foo = 42 });
+}
diff --git a/lib/std/math.zig b/lib/std/math.zig
@@ -1,6 +1,4 @@
-const builtin = @import("builtin");
const std = @import("std.zig");
-const TypeId = builtin.TypeId;
const assert = std.debug.assert;
const testing = std.testing;
@@ -89,7 +87,7 @@ pub const snan = @import("math/nan.zig").snan;
pub const inf = @import("math/inf.zig").inf;
pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool {
- assert(@typeId(T) == TypeId.Float);
+ assert(@typeInfo(T) == .Float);
return fabs(x - y) < epsilon;
}
@@ -198,7 +196,7 @@ test "" {
}
pub fn floatMantissaBits(comptime T: type) comptime_int {
- assert(@typeId(T) == builtin.TypeId.Float);
+ assert(@typeInfo(T) == .Float);
return switch (T.bit_count) {
16 => 10,
@@ -211,7 +209,7 @@ pub fn floatMantissaBits(comptime T: type) comptime_int {
}
pub fn floatExponentBits(comptime T: type) comptime_int {
- assert(@typeId(T) == builtin.TypeId.Float);
+ assert(@typeInfo(T) == .Float);
return switch (T.bit_count) {
16 => 5,
@@ -446,7 +444,7 @@ pub fn Log2Int(comptime T: type) type {
count += 1;
}
- return @IntType(false, count);
+ return std.meta.IntType(false, count);
}
pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {
@@ -462,7 +460,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
if (is_signed) {
magnitude_bits += 1;
}
- return @IntType(is_signed, magnitude_bits);
+ return std.meta.IntType(is_signed, magnitude_bits);
}
test "math.IntFittingRange" {
@@ -526,7 +524,7 @@ fn testOverflow() void {
pub fn absInt(x: var) !@TypeOf(x) {
const T = @TypeOf(x);
- comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
+ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
comptime assert(T.is_signed); // must pass a signed integer to absInt
if (x == minInt(@TypeOf(x))) {
@@ -560,7 +558,7 @@ fn testAbsFloat() void {
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0) return error.DivisionByZero;
- if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
+ if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
return @divTrunc(numerator, denominator);
}
@@ -581,7 +579,7 @@ fn testDivTrunc() void {
pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0) return error.DivisionByZero;
- if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
+ if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
return @divFloor(numerator, denominator);
}
@@ -602,7 +600,7 @@ fn testDivFloor() void {
pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0) return error.DivisionByZero;
- if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
+ if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
const result = @divTrunc(numerator, denominator);
if (result * denominator != numerator) return error.UnexpectedRemainder;
return result;
@@ -676,13 +674,13 @@ pub fn absCast(x: var) t: {
if (@TypeOf(x) == comptime_int) {
break :t comptime_int;
} else {
- break :t @IntType(false, @TypeOf(x).bit_count);
+ break :t std.meta.IntType(false, @TypeOf(x).bit_count);
}
} {
if (@TypeOf(x) == comptime_int) {
return if (x < 0) -x else x;
}
- const uint = @IntType(false, @TypeOf(x).bit_count);
+ const uint = std.meta.IntType(false, @TypeOf(x).bit_count);
if (x >= 0) return @intCast(uint, x);
return @intCast(uint, -(x + 1)) + 1;
@@ -703,10 +701,10 @@ test "math.absCast" {
/// Returns the negation of the integer parameter.
/// Result is a signed integer.
-pub fn negateCast(x: var) !@IntType(true, @TypeOf(x).bit_count) {
+pub fn negateCast(x: var) !std.meta.IntType(true, @TypeOf(x).bit_count) {
if (@TypeOf(x).is_signed) return negate(x);
- const int = @IntType(true, @TypeOf(x).bit_count);
+ const int = std.meta.IntType(true, @TypeOf(x).bit_count);
if (x > -minInt(int)) return error.Overflow;
if (x == -minInt(int)) return minInt(int);
@@ -727,8 +725,8 @@ test "math.negateCast" {
/// Cast an integer to a different integer type. If the value doesn't fit,
/// return an error.
pub fn cast(comptime T: type, x: var) (error{Overflow}!T) {
- comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer
- comptime assert(@typeId(@TypeOf(x)) == builtin.TypeId.Int); // must pass an integer
+ comptime assert(@typeInfo(T) == .Int); // must pass an integer
+ comptime assert(@typeInfo(@TypeOf(x)) == .Int); // must pass an integer
if (maxInt(@TypeOf(x)) > maxInt(T) and x > maxInt(T)) {
return error.Overflow;
} else if (minInt(@TypeOf(x)) < minInt(T) and x < minInt(T)) {
@@ -792,11 +790,11 @@ fn testFloorPowerOfTwo() void {
/// Returns the next power of two (if the value is not already a power of two).
/// Only unsigned integers can be used. Zero is not an allowed input.
/// Result is a type with 1 more bit than the input type.
-pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T.bit_count + 1) {
- comptime assert(@typeId(T) == builtin.TypeId.Int);
+pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.IntType(T.is_signed, T.bit_count + 1) {
+ comptime assert(@typeInfo(T) == .Int);
comptime assert(!T.is_signed);
assert(value != 0);
- comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1);
+ comptime const PromotedType = std.meta.IntType(T.is_signed, T.bit_count + 1);
comptime const shiftType = std.math.Log2Int(PromotedType);
return @as(PromotedType, 1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1));
}
@@ -805,9 +803,9 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T
/// Only unsigned integers can be used. Zero is not an allowed input.
/// If the value doesn't fit, returns an error.
pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {
- comptime assert(@typeId(T) == builtin.TypeId.Int);
+ comptime assert(@typeInfo(T) == .Int);
comptime assert(!T.is_signed);
- comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1);
+ comptime const PromotedType = std.meta.IntType(T.is_signed, T.bit_count + 1);
comptime const overflowBit = @as(PromotedType, 1) << T.bit_count;
var x = ceilPowerOfTwoPromote(T, value);
if (overflowBit & x != 0) {
@@ -878,10 +876,10 @@ test "std.math.log2_int_ceil" {
pub fn lossyCast(comptime T: type, value: var) T {
switch (@typeInfo(@TypeOf(value))) {
- builtin.TypeId.Int => return @intToFloat(T, value),
- builtin.TypeId.Float => return @floatCast(T, value),
- builtin.TypeId.ComptimeInt => return @as(T, value),
- builtin.TypeId.ComptimeFloat => return @as(T, value),
+ .Int => return @intToFloat(T, value),
+ .Float => return @floatCast(T, value),
+ .ComptimeInt => return @as(T, value),
+ .ComptimeFloat => return @as(T, value),
else => @compileError("bad type"),
}
}
@@ -949,8 +947,8 @@ test "max value type" {
testing.expect(x == 2147483647);
}
-pub fn mulWide(comptime T: type, a: T, b: T) @IntType(T.is_signed, T.bit_count * 2) {
- const ResultInt = @IntType(T.is_signed, T.bit_count * 2);
+pub fn mulWide(comptime T: type, a: T, b: T) std.meta.IntType(T.is_signed, T.bit_count * 2) {
+ const ResultInt = std.meta.IntType(T.is_signed, T.bit_count * 2);
return @as(ResultInt, a) * @as(ResultInt, b);
}
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
@@ -1,5 +1,4 @@
const std = @import("../../std.zig");
-const builtin = @import("builtin");
const debug = std.debug;
const testing = std.testing;
const math = std.math;
@@ -9,10 +8,8 @@ const ArrayList = std.ArrayList;
const maxInt = std.math.maxInt;
const minInt = std.math.minInt;
-const TypeId = builtin.TypeId;
-
pub const Limb = usize;
-pub const DoubleLimb = @IntType(false, 2 * Limb.bit_count);
+pub const DoubleLimb = std.meta.IntType(false, 2 * Limb.bit_count);
pub const Log2Limb = math.Log2Int(Limb);
comptime {
@@ -270,8 +267,8 @@ pub const Int = struct {
const T = @TypeOf(value);
switch (@typeInfo(T)) {
- TypeId.Int => |info| {
- const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T;
+ .Int => |info| {
+ const UT = if (T.is_signed) std.meta.IntType(false, T.bit_count - 1) else T;
try self.ensureCapacity(@sizeOf(UT) / @sizeOf(Limb));
self.metadata = 0;
@@ -294,7 +291,7 @@ pub const Int = struct {
}
}
},
- TypeId.ComptimeInt => {
+ .ComptimeInt => {
comptime var w_value = if (value < 0) -value else value;
const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;
@@ -332,9 +329,9 @@ pub const Int = struct {
///
/// Returns an error if self cannot be narrowed into the requested type without truncation.
pub fn to(self: Int, comptime T: type) ConvertError!T {
- switch (@typeId(T)) {
- TypeId.Int => {
- const UT = @IntType(false, T.bit_count);
+ switch (@typeInfo(T)) {
+ .Int => {
+ const UT = std.meta.IntType(false, T.bit_count);
if (self.bitCountTwosComp() > T.bit_count) {
return error.TargetTooSmall;
diff --git a/lib/std/math/big/rational.zig b/lib/std/math/big/rational.zig
@@ -1,5 +1,4 @@
const std = @import("../../std.zig");
-const builtin = @import("builtin");
const debug = std.debug;
const math = std.math;
const mem = std.mem;
@@ -7,8 +6,6 @@ const testing = std.testing;
const Allocator = mem.Allocator;
const ArrayList = std.ArrayList;
-const TypeId = builtin.TypeId;
-
const bn = @import("int.zig");
const Limb = bn.Limb;
const DoubleLimb = bn.DoubleLimb;
@@ -129,9 +126,9 @@ pub const Rational = struct {
/// completely represent the provided float.
pub fn setFloat(self: *Rational, comptime T: type, f: T) !void {
// Translated from golang.go/src/math/big/rat.go.
- debug.assert(@typeId(T) == builtin.TypeId.Float);
+ debug.assert(@typeInfo(T) == .Float);
- const UnsignedIntType = @IntType(false, T.bit_count);
+ const UnsignedIntType = std.meta.IntType(false, T.bit_count);
const f_bits = @bitCast(UnsignedIntType, f);
const exponent_bits = math.floatExponentBits(T);
@@ -187,10 +184,10 @@ pub const Rational = struct {
pub fn toFloat(self: Rational, comptime T: type) !T {
// Translated from golang.go/src/math/big/rat.go.
// TODO: Indicate whether the result is not exact.
- debug.assert(@typeId(T) == builtin.TypeId.Float);
+ debug.assert(@typeInfo(T) == .Float);
const fsize = T.bit_count;
- const BitReprType = @IntType(false, T.bit_count);
+ const BitReprType = std.meta.IntType(false, T.bit_count);
const msize = math.floatMantissaBits(T);
const msize1 = msize + 1;
@@ -465,7 +462,7 @@ pub const Rational = struct {
}
};
-const SignedDoubleLimb = @IntType(true, DoubleLimb.bit_count);
+const SignedDoubleLimb = std.meta.IntType(true, DoubleLimb.bit_count);
fn gcd(rma: *Int, x: Int, y: Int) !void {
rma.assertWritable();
@@ -653,7 +650,7 @@ test "big.rational gcd one large" {
}
fn extractLowBits(a: Int, comptime T: type) T {
- testing.expect(@typeId(T) == builtin.TypeId.Int);
+ testing.expect(@typeInfo(T) == .Int);
if (T.bit_count <= Limb.bit_count) {
return @truncate(T, a.limbs[0]);
diff --git a/lib/std/math/cos.zig b/lib/std/math/cos.zig
@@ -44,7 +44,7 @@ const pi4c = 2.69515142907905952645E-15;
const m4pi = 1.273239544735162542821171882678754627704620361328125;
fn cos_(comptime T: type, x_: T) T {
- const I = @IntType(true, T.bit_count);
+ const I = std.meta.IntType(true, T.bit_count);
var x = x_;
if (math.isNan(x) or math.isInf(x)) {
diff --git a/lib/std/math/ln.zig b/lib/std/math/ln.zig
@@ -7,8 +7,6 @@
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
-const builtin = @import("builtin");
-const TypeId = builtin.TypeId;
/// Returns the natural logarithm of x.
///
@@ -19,21 +17,21 @@ const TypeId = builtin.TypeId;
/// - ln(nan) = nan
pub fn ln(x: var) @TypeOf(x) {
const T = @TypeOf(x);
- switch (@typeId(T)) {
- TypeId.ComptimeFloat => {
+ switch (@typeInfo(T)) {
+ .ComptimeFloat => {
return @as(comptime_float, ln_64(x));
},
- TypeId.Float => {
+ .Float => {
return switch (T) {
f32 => ln_32(x),
f64 => ln_64(x),
else => @compileError("ln not implemented for " ++ @typeName(T)),
};
},
- TypeId.ComptimeInt => {
+ .ComptimeInt => {
return @as(comptime_int, math.floor(ln_64(@as(f64, x))));
},
- TypeId.Int => {
+ .Int => {
return @as(T, math.floor(ln_64(@as(f64, x))));
},
else => @compileError("ln not implemented for " ++ @typeName(T)),
diff --git a/lib/std/math/log.zig b/lib/std/math/log.zig
@@ -6,8 +6,6 @@
const std = @import("../std.zig");
const math = std.math;
-const builtin = @import("builtin");
-const TypeId = builtin.TypeId;
const expect = std.testing.expect;
/// Returns the logarithm of x for the provided base.
@@ -16,24 +14,24 @@ pub fn log(comptime T: type, base: T, x: T) T {
return math.log2(x);
} else if (base == 10) {
return math.log10(x);
- } else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.ComptimeFloat) and base == math.e) {
+ } else if ((@typeInfo(T) == .Float or @typeInfo(T) == .ComptimeFloat) and base == math.e) {
return math.ln(x);
}
const float_base = math.lossyCast(f64, base);
- switch (@typeId(T)) {
- TypeId.ComptimeFloat => {
+ switch (@typeInfo(T)) {
+ .ComptimeFloat => {
return @as(comptime_float, math.ln(@as(f64, x)) / math.ln(float_base));
},
- TypeId.ComptimeInt => {
+ .ComptimeInt => {
return @as(comptime_int, math.floor(math.ln(@as(f64, x)) / math.ln(float_base)));
},
- builtin.TypeId.Int => {
+ .Int => {
// TODO implement integer log without using float math
return @floatToInt(T, math.floor(math.ln(@intToFloat(f64, x)) / math.ln(float_base)));
},
- builtin.TypeId.Float => {
+ .Float => {
switch (T) {
f32 => return @floatCast(f32, math.ln(@as(f64, x)) / math.ln(float_base)),
f64 => return math.ln(x) / math.ln(float_base),
diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig
@@ -7,8 +7,6 @@
const std = @import("../std.zig");
const math = std.math;
const testing = std.testing;
-const builtin = @import("builtin");
-const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
/// Returns the base-10 logarithm of x.
@@ -20,21 +18,21 @@ const maxInt = std.math.maxInt;
/// - log10(nan) = nan
pub fn log10(x: var) @TypeOf(x) {
const T = @TypeOf(x);
- switch (@typeId(T)) {
- TypeId.ComptimeFloat => {
+ switch (@typeInfo(T)) {
+ .ComptimeFloat => {
return @as(comptime_float, log10_64(x));
},
- TypeId.Float => {
+ .Float => {
return switch (T) {
f32 => log10_32(x),
f64 => log10_64(x),
else => @compileError("log10 not implemented for " ++ @typeName(T)),
};
},
- TypeId.ComptimeInt => {
+ .ComptimeInt => {
return @as(comptime_int, math.floor(log10_64(@as(f64, x))));
},
- TypeId.Int => {
+ .Int => {
return @floatToInt(T, math.floor(log10_64(@intToFloat(f64, x))));
},
else => @compileError("log10 not implemented for " ++ @typeName(T)),
diff --git a/lib/std/math/log2.zig b/lib/std/math/log2.zig
@@ -7,8 +7,6 @@
const std = @import("../std.zig");
const math = std.math;
const expect = std.testing.expect;
-const builtin = @import("builtin");
-const TypeId = builtin.TypeId;
const maxInt = std.math.maxInt;
/// Returns the base-2 logarithm of x.
@@ -20,18 +18,18 @@ const maxInt = std.math.maxInt;
/// - log2(nan) = nan
pub fn log2(x: var) @TypeOf(x) {
const T = @TypeOf(x);
- switch (@typeId(T)) {
- TypeId.ComptimeFloat => {
+ switch (@typeInfo(T)) {
+ .ComptimeFloat => {
return @as(comptime_float, log2_64(x));
},
- TypeId.Float => {
+ .Float => {
return switch (T) {
f32 => log2_32(x),
f64 => log2_64(x),
else => @compileError("log2 not implemented for " ++ @typeName(T)),
};
},
- TypeId.ComptimeInt => comptime {
+ .ComptimeInt => comptime {
var result = 0;
var x_shifted = x;
while (b: {
@@ -40,7 +38,7 @@ pub fn log2(x: var) @TypeOf(x) {
}) : (result += 1) {}
return result;
},
- TypeId.Int => {
+ .Int => {
return math.log2_int(T, x);
},
else => @compileError("log2 not implemented for " ++ @typeName(T)),
diff --git a/lib/std/math/pow.zig b/lib/std/math/pow.zig
@@ -145,7 +145,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
var xe = r2.exponent;
var x1 = r2.significand;
- var i = @floatToInt(@IntType(true, T.bit_count), yi);
+ var i = @floatToInt(std.meta.IntType(true, T.bit_count), yi);
while (i != 0) : (i >>= 1) {
const overflow_shift = math.floatExponentBits(T) + 1;
if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) {
diff --git a/lib/std/math/sin.zig b/lib/std/math/sin.zig
@@ -45,7 +45,7 @@ const pi4c = 2.69515142907905952645E-15;
const m4pi = 1.273239544735162542821171882678754627704620361328125;
fn sin_(comptime T: type, x_: T) T {
- const I = @IntType(true, T.bit_count);
+ const I = std.meta.IntType(true, T.bit_count);
var x = x_;
if (x == 0 or math.isNan(x)) {
diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig
@@ -31,7 +31,7 @@ pub fn sqrt(x: var) Sqrt(@TypeOf(x)) {
}
}
-fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
+fn sqrt_int(comptime T: type, value: T) std.meta.IntType(false, T.bit_count / 2) {
var op = value;
var res: T = 0;
var one: T = 1 << (T.bit_count - 2);
@@ -50,7 +50,7 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
one >>= 2;
}
- const ResultType = @IntType(false, T.bit_count / 2);
+ const ResultType = std.meta.IntType(false, T.bit_count / 2);
return @intCast(ResultType, res);
}
@@ -66,7 +66,7 @@ test "math.sqrt_int" {
/// Returns the return type `sqrt` will return given an operand of type `T`.
pub fn Sqrt(comptime T: type) type {
return switch (@typeInfo(T)) {
- .Int => |int| @IntType(false, int.bits / 2),
+ .Int => |int| std.meta.IntType(false, int.bits / 2),
else => T,
};
}
diff --git a/lib/std/math/tan.zig b/lib/std/math/tan.zig
@@ -38,7 +38,7 @@ const pi4c = 2.69515142907905952645E-15;
const m4pi = 1.273239544735162542821171882678754627704620361328125;
fn tan_(comptime T: type, x_: T) T {
- const I = @IntType(true, T.bit_count);
+ const I = std.meta.IntType(true, T.bit_count);
var x = x_;
if (x == 0 or math.isNan(x)) {
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
@@ -132,7 +132,7 @@ pub const Allocator = struct {
// their own frame with @Frame(func).
return @intToPtr([*]T, @ptrToInt(byte_slice.ptr))[0..n];
} else {
- return @bytesToSlice(T, @alignCast(a, byte_slice));
+ return mem.bytesAsSlice(T, @alignCast(a, byte_slice));
}
}
@@ -173,7 +173,7 @@ pub const Allocator = struct {
return @as([*]align(new_alignment) T, undefined)[0..0];
}
- const old_byte_slice = @sliceToBytes(old_mem);
+ const old_byte_slice = mem.sliceAsBytes(old_mem);
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
@@ -181,7 +181,7 @@ pub const Allocator = struct {
if (new_n > old_mem.len) {
@memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len);
}
- return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
+ return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice));
}
/// Prefer calling realloc to shrink if you can tolerate failure, such as
@@ -221,18 +221,18 @@ pub const Allocator = struct {
// new_n <= old_mem.len and the multiplication didn't overflow for that operation.
const byte_count = @sizeOf(T) * new_n;
- const old_byte_slice = @sliceToBytes(old_mem);
+ const old_byte_slice = mem.sliceAsBytes(old_mem);
@memset(old_byte_slice.ptr + byte_count, undefined, old_byte_slice.len - byte_count);
const byte_slice = self.shrinkFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment);
assert(byte_slice.len == byte_count);
- return @bytesToSlice(T, @alignCast(new_alignment, byte_slice));
+ return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice));
}
/// Free an array allocated with `alloc`. To free a single item,
/// see `destroy`.
pub fn free(self: *Allocator, memory: var) void {
const Slice = @typeInfo(@TypeOf(memory)).Pointer;
- const bytes = @sliceToBytes(memory);
+ const bytes = mem.sliceAsBytes(memory);
const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0;
if (bytes_len == 0) return;
const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
@@ -276,18 +276,67 @@ pub fn set(comptime T: type, dest: []T, value: T) void {
d.* = value;
}
+/// Generally, Zig users are encouraged to explicitly initialize all fields of a struct explicitly rather than using this function.
+/// However, it is recognized that there are sometimes use cases for initializing all fields to a "zero" value. For example, when
+/// interfacing with a C API where this practice is more common and relied upon. If you are performing code review and see this
+/// function used, examine closely - it may be a code smell.
/// Zero initializes the type.
-/// This can be used to zero initialize a C-struct.
+/// This can be used to zero initialize a any type for which it makes sense. Structs will be initialized recursively.
pub fn zeroes(comptime T: type) T {
- if (@sizeOf(T) == 0) return T{};
-
- if (comptime meta.containerLayout(T) != .Extern) {
- @compileError("TODO: Currently this only works for extern types");
+ switch (@typeInfo(T)) {
+ .ComptimeInt, .Int, .ComptimeFloat, .Float => {
+ return @as(T, 0);
+ },
+ .Enum, .EnumLiteral => {
+ return @intToEnum(T, 0);
+ },
+ .Void => {
+ return {};
+ },
+ .Bool => {
+ return false;
+ },
+ .Optional, .Null => {
+ return null;
+ },
+ .Struct => |struct_info| {
+ if (@sizeOf(T) == 0) return T{};
+ if (comptime meta.containerLayout(T) == .Extern) {
+ var item: T = undefined;
+ @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
+ return item;
+ } else {
+ var structure: T = undefined;
+ inline for (struct_info.fields) |field| {
+ @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
+ }
+ return structure;
+ }
+ },
+ .Pointer => |ptr_info| {
+ switch (ptr_info.size) {
+ .Slice => {
+ return &[_]ptr_info.child{};
+ },
+ .C => {
+ return null;
+ },
+ .One, .Many => {
+ @compileError("Can't set a non nullable pointer to zero.");
+ },
+ }
+ },
+ .Array => |info| {
+ var array: T = undefined;
+ for (array) |*element| {
+ element.* = zeroes(info.child);
+ }
+ return array;
+ },
+ .Vector, .ErrorUnion, .ErrorSet, .Union, .Fn, .BoundFn, .Type, .NoReturn, .Undefined, .Opaque, .Frame, .AnyFrame, => {
+ @compileError("Can't set a "++ @typeName(T) ++" to zero.");
+ },
}
-
- var item: T = undefined;
- @memset(@ptrCast([*]u8, &item), 0, @sizeOf(T));
- return item;
}
test "mem.zeroes" {
@@ -301,6 +350,62 @@ test "mem.zeroes" {
testing.expect(a.x == 0);
testing.expect(a.y == 10);
+
+ const ZigStruct = struct {
+ const IntegralTypes = struct {
+ integer_0: i0,
+ integer_8: i8,
+ integer_16: i16,
+ integer_32: i32,
+ integer_64: i64,
+ integer_128: i128,
+ unsigned_0: u0,
+ unsigned_8: u8,
+ unsigned_16: u16,
+ unsigned_32: u32,
+ unsigned_64: u64,
+ unsigned_128: u128,
+
+ float_32: f32,
+ float_64: f64,
+ };
+
+ integral_types: IntegralTypes,
+
+ const Pointers = struct {
+ optional: ?*u8,
+ c_pointer: [*c]u8,
+ slice: []u8,
+ };
+ pointers: Pointers,
+
+ array: [2]u32,
+ optional_int: ?u8,
+ empty: void,
+ };
+
+ const b = zeroes(ZigStruct);
+ testing.expectEqual(@as(i8, 0), b.integral_types.integer_0);
+ testing.expectEqual(@as(i8, 0), b.integral_types.integer_8);
+ testing.expectEqual(@as(i16, 0), b.integral_types.integer_16);
+ testing.expectEqual(@as(i32, 0), b.integral_types.integer_32);
+ testing.expectEqual(@as(i64, 0), b.integral_types.integer_64);
+ testing.expectEqual(@as(i128, 0), b.integral_types.integer_128);
+ testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_0);
+ testing.expectEqual(@as(u8, 0), b.integral_types.unsigned_8);
+ testing.expectEqual(@as(u16, 0), b.integral_types.unsigned_16);
+ testing.expectEqual(@as(u32, 0), b.integral_types.unsigned_32);
+ testing.expectEqual(@as(u64, 0), b.integral_types.unsigned_64);
+ testing.expectEqual(@as(u128, 0), b.integral_types.unsigned_128);
+ testing.expectEqual(@as(f32, 0), b.integral_types.float_32);
+ testing.expectEqual(@as(f64, 0), b.integral_types.float_64);
+ testing.expectEqual(@as(?*u8, null), b.pointers.optional);
+ testing.expectEqual(@as([*c]u8, null), b.pointers.c_pointer);
+ testing.expectEqual(@as([]u8, &[_]u8{}), b.pointers.slice);
+ for (b.array) |e| {
+ testing.expectEqual(@as(u32, 0), e);
+ }
+ testing.expectEqual(@as(?u8, null), b.optional_int);
}
pub fn secureZero(comptime T: type, s: []T) void {
@@ -387,13 +492,21 @@ pub fn allEqual(comptime T: type, slice: []const T, scalar: T) bool {
return true;
}
-/// Copies ::m to newly allocated memory. Caller is responsible to free it.
+/// Copies `m` to newly allocated memory. Caller owns the memory.
pub fn dupe(allocator: *Allocator, comptime T: type, m: []const T) ![]T {
const new_buf = try allocator.alloc(T, m.len);
copy(T, new_buf, m);
return new_buf;
}
+/// Copies `m` to newly allocated memory, with a null-terminated element. Caller owns the memory.
+pub fn dupeZ(allocator: *Allocator, comptime T: type, m: []const T) ![:0]T {
+ const new_buf = try allocator.alloc(T, m.len + 1);
+ copy(T, new_buf, m);
+ new_buf[m.len] = 0;
+ return new_buf[0..m.len :0];
+}
+
/// Remove values from the beginning of a slice.
pub fn trimLeft(comptime T: type, slice: []const T, values_to_strip: []const T) []const T {
var begin: usize = 0;
@@ -700,7 +813,7 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
assert(buffer.len >= @divExact(T.bit_count, 8));
// TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
- const uint = @IntType(false, T.bit_count);
+ const uint = std.meta.IntType(false, T.bit_count);
var bits = @truncate(uint, value);
for (buffer) |*b| {
b.* = @truncate(u8, bits);
@@ -717,7 +830,7 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
assert(buffer.len >= @divExact(T.bit_count, 8));
// TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
- const uint = @IntType(false, T.bit_count);
+ const uint = std.meta.IntType(false, T.bit_count);
var bits = @truncate(uint, value);
var index: usize = buffer.len;
while (index != 0) {
@@ -1478,6 +1591,162 @@ test "bytesToValue" {
testing.expect(deadbeef == @as(u32, 0xDEADBEEF));
}
+//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues.
+fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type {
+ if (!(trait.isSlice(bytesType) and meta.Child(bytesType) == u8) and !(trait.isPtrTo(.Array)(bytesType) and meta.Child(meta.Child(bytesType)) == u8)) {
+ @compileError("expected []u8 or *[_]u8, passed " ++ @typeName(bytesType));
+ }
+
+ if (trait.isPtrTo(.Array)(bytesType) and @typeInfo(meta.Child(bytesType)).Array.len % @sizeOf(T) != 0) {
+ @compileError("number of bytes in " ++ @typeName(bytesType) ++ " is not divisible by size of " ++ @typeName(T));
+ }
+
+ const alignment = meta.alignment(bytesType);
+
+ return if (trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T;
+}
+
+pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) {
+ const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes;
+
+ // let's not give an undefined pointer to @ptrCast
+ // it may be equal to zero and fail a null check
+ if (bytesSlice.len == 0) {
+ return &[0]T{};
+ }
+
+ const bytesType = @TypeOf(bytesSlice);
+ const alignment = comptime meta.alignment(bytesType);
+
+ const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T;
+
+ return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))];
+}
+
+test "bytesAsSlice" {
+ const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
+ const slice = bytesAsSlice(u16, bytes[0..]);
+ testing.expect(slice.len == 2);
+ testing.expect(bigToNative(u16, slice[0]) == 0xDEAD);
+ testing.expect(bigToNative(u16, slice[1]) == 0xBEEF);
+}
+
+test "bytesAsSlice keeps pointer alignment" {
+ var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
+ const numbers = bytesAsSlice(u32, bytes[0..]);
+ comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
+}
+
+test "bytesAsSlice on a packed struct" {
+ const F = packed struct {
+ a: u8,
+ };
+
+ var b = [1]u8{9};
+ var f = bytesAsSlice(F, &b);
+ testing.expect(f[0].a == 9);
+}
+
+test "bytesAsSlice with specified alignment" {
+ var bytes align(4) = [_]u8{
+ 0x33,
+ 0x33,
+ 0x33,
+ 0x33,
+ };
+ const slice: []u32 = std.mem.bytesAsSlice(u32, bytes[0..]);
+ testing.expect(slice[0] == 0x33333333);
+}
+
+//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues.
+fn SliceAsBytesReturnType(comptime sliceType: type) type {
+ if (!trait.isSlice(sliceType) and !trait.isPtrTo(.Array)(sliceType)) {
+ @compileError("expected []T or *[_]T, passed " ++ @typeName(sliceType));
+ }
+
+ const alignment = meta.alignment(sliceType);
+
+ return if (trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8;
+}
+
+pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) {
+ const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice;
+
+ // let's not give an undefined pointer to @ptrCast
+ // it may be equal to zero and fail a null check
+ if (actualSlice.len == 0) {
+ return &[0]u8{};
+ }
+
+ const sliceType = @TypeOf(actualSlice);
+ const alignment = comptime meta.alignment(sliceType);
+
+ const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8;
+
+ return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))];
+}
+
+test "sliceAsBytes" {
+ const bytes = [_]u16{ 0xDEAD, 0xBEEF };
+ const slice = sliceAsBytes(bytes[0..]);
+ testing.expect(slice.len == 4);
+ testing.expect(eql(u8, slice, switch (builtin.endian) {
+ .Big => "\xDE\xAD\xBE\xEF",
+ .Little => "\xAD\xDE\xEF\xBE",
+ }));
+}
+
+test "sliceAsBytes packed struct at runtime and comptime" {
+ const Foo = packed struct {
+ a: u4,
+ b: u4,
+ };
+ const S = struct {
+ fn doTheTest() void {
+ var foo: Foo = undefined;
+ var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]);
+ slice[0] = 0x13;
+ switch (builtin.endian) {
+ .Big => {
+ testing.expect(foo.a == 0x1);
+ testing.expect(foo.b == 0x3);
+ },
+ .Little => {
+ testing.expect(foo.a == 0x3);
+ testing.expect(foo.b == 0x1);
+ },
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
+test "sliceAsBytes and bytesAsSlice back" {
+ testing.expect(@sizeOf(i32) == 4);
+
+ var big_thing_array = [_]i32{ 1, 2, 3, 4 };
+ const big_thing_slice: []i32 = big_thing_array[0..];
+
+ const bytes = sliceAsBytes(big_thing_slice);
+ testing.expect(bytes.len == 4 * 4);
+
+ bytes[4] = 0;
+ bytes[5] = 0;
+ bytes[6] = 0;
+ bytes[7] = 0;
+ testing.expect(big_thing_slice[1] == 0);
+
+ const big_thing_again = bytesAsSlice(i32, bytes);
+ testing.expect(big_thing_again[2] == 3);
+
+ big_thing_again[2] = -1;
+ testing.expect(bytes[8] == math.maxInt(u8));
+ testing.expect(bytes[9] == math.maxInt(u8));
+ testing.expect(bytes[10] == math.maxInt(u8));
+ testing.expect(bytes[11] == math.maxInt(u8));
+}
+
fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
if (trait.isConstPtr(T))
return *const [length]meta.Child(meta.Child(T));
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
@@ -437,7 +437,7 @@ pub fn eql(a: var, b: @TypeOf(a)) bool {
},
.Pointer => |info| {
return switch (info.size) {
- .One, .Many, .C, => a == b,
+ .One, .Many, .C => a == b,
.Slice => a.ptr == b.ptr and a.len == b.len,
};
},
@@ -536,9 +536,8 @@ test "intToEnum with error return" {
pub const IntToEnumError = error{InvalidEnumTag};
pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
- comptime var i = 0;
- inline while (i != @memberCount(Tag)) : (i += 1) {
- const this_tag_value = @field(Tag, @memberName(Tag, i));
+ inline for (@typeInfo(Tag).Enum.fields) |f| {
+ const this_tag_value = @field(Tag, f.name);
if (tag_int == @enumToInt(this_tag_value)) {
return this_tag_value;
}
@@ -559,7 +558,9 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int {
/// Given a type, reference all the declarations inside, so that the semantic analyzer sees them.
pub fn refAllDecls(comptime T: type) void {
if (!builtin.is_test) return;
- _ = declarations(T);
+ inline for (declarations(T)) |decl| {
+ _ = decl;
+ }
}
/// Returns a slice of pointers to public declarations of a namespace.
@@ -579,3 +580,12 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De
return &array;
}
}
+
+pub fn IntType(comptime is_signed: bool, comptime bit_count: u16) type {
+ return @Type(TypeInfo{
+ .Int = .{
+ .is_signed = is_signed,
+ .bits = bit_count,
+ },
+ });
+}
diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig
@@ -1,5 +1,5 @@
const std = @import("../std.zig");
-const builtin = @import("builtin");
+const builtin = std.builtin;
const mem = std.mem;
const debug = std.debug;
const testing = std.testing;
@@ -54,7 +54,7 @@ pub fn hasFn(comptime name: []const u8) TraitFn {
if (!comptime isContainer(T)) return false;
if (!comptime @hasDecl(T, name)) return false;
const DeclType = @TypeOf(@field(T, name));
- return @typeId(DeclType) == .Fn;
+ return @typeInfo(DeclType) == .Fn;
}
};
return Closure.trait;
@@ -105,7 +105,7 @@ test "std.meta.trait.hasField" {
pub fn is(comptime id: builtin.TypeId) TraitFn {
const Closure = struct {
pub fn trait(comptime T: type) bool {
- return id == @typeId(T);
+ return id == @typeInfo(T);
}
};
return Closure.trait;
@@ -123,7 +123,7 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
const Closure = struct {
pub fn trait(comptime T: type) bool {
if (!comptime isSingleItemPtr(T)) return false;
- return id == @typeId(meta.Child(T));
+ return id == @typeInfo(meta.Child(T));
}
};
return Closure.trait;
@@ -135,6 +135,22 @@ test "std.meta.trait.isPtrTo" {
testing.expect(!isPtrTo(.Struct)(**struct {}));
}
+pub fn isSliceOf(comptime id: builtin.TypeId) TraitFn {
+ const Closure = struct {
+ pub fn trait(comptime T: type) bool {
+ if (!comptime isSlice(T)) return false;
+ return id == @typeInfo(meta.Child(T));
+ }
+ };
+ return Closure.trait;
+}
+
+test "std.meta.trait.isSliceOf" {
+ testing.expect(!isSliceOf(.Struct)(struct {}));
+ testing.expect(isSliceOf(.Struct)([]struct {}));
+ testing.expect(!isSliceOf(.Struct)([][]struct {}));
+}
+
///////////Strait trait Fns
//@TODO:
@@ -269,7 +285,7 @@ test "std.meta.trait.isIndexable" {
}
pub fn isNumber(comptime T: type) bool {
- return switch (@typeId(T)) {
+ return switch (@typeInfo(T)) {
.Int, .Float, .ComptimeInt, .ComptimeFloat => true,
else => false,
};
@@ -304,7 +320,7 @@ test "std.meta.trait.isConstPtr" {
}
pub fn isContainer(comptime T: type) bool {
- return switch (@typeId(T)) {
+ return switch (@typeInfo(T)) {
.Struct, .Union, .Enum => true,
else => false,
};
diff --git a/lib/std/net.zig b/lib/std/net.zig
@@ -18,7 +18,7 @@ pub const Address = extern union {
in6: os.sockaddr_in6,
un: if (has_unix_sockets) os.sockaddr_un else void,
- // TODO this crashed the compiler
+ // TODO this crashed the compiler. https://github.com/ziglang/zig/issues/3512
//pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);
pub fn parseIp(name: []const u8, port: u16) !Address {
@@ -120,7 +120,7 @@ pub const Address = extern union {
ip_slice[10] = 0xff;
ip_slice[11] = 0xff;
- const ptr = @sliceToBytes(@as(*const [1]u32, &addr)[0..]);
+ const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]);
ip_slice[12] = ptr[0];
ip_slice[13] = ptr[1];
@@ -164,7 +164,7 @@ pub const Address = extern union {
.addr = undefined,
},
};
- const out_ptr = @sliceToBytes(@as(*[1]u32, &result.in.addr)[0..]);
+ const out_ptr = mem.sliceAsBytes(@as(*[1]u32, &result.in.addr)[0..]);
var x: u8 = 0;
var index: u8 = 0;
diff --git a/lib/std/os.zig b/lib/std/os.zig
@@ -70,6 +70,8 @@ else switch (builtin.os) {
pub usingnamespace @import("os/bits.zig");
/// See also `getenv`. Populated by startup code before main().
+/// TODO this is a footgun because the value will be undefined when using `zig build-lib`.
+/// https://github.com/ziglang/zig/issues/4524
pub var environ: [][*:0]u8 = undefined;
/// Populated by startup code before main().
@@ -916,10 +918,17 @@ pub const ExecveError = error{
NameTooLong,
} || UnexpectedError;
+/// Deprecated in favor of `execveZ`.
+pub const execveC = execveZ;
+
/// Like `execve` except the parameters are null-terminated,
/// matching the syscall API on all targets. This removes the need for an allocator.
-/// This function ignores PATH environment variable. See `execvpeC` for that.
-pub fn execveC(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError {
+/// This function ignores PATH environment variable. See `execvpeZ` for that.
+pub fn execveZ(
+ path: [*:0]const u8,
+ child_argv: [*:null]const ?[*:0]const u8,
+ envp: [*:null]const ?[*:0]const u8,
+) ExecveError {
switch (errno(system.execve(path, child_argv, envp))) {
0 => unreachable,
EFAULT => unreachable,
@@ -942,19 +951,42 @@ pub fn execveC(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, en
}
}
-/// Like `execvpe` except the parameters are null-terminated,
-/// matching the syscall API on all targets. This removes the need for an allocator.
-/// This function also uses the PATH environment variable to get the full path to the executable.
-/// If `file` is an absolute path, this is the same as `execveC`.
-pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError {
+/// Deprecated in favor of `execvpeZ`.
+pub const execvpeC = execvpeZ;
+
+pub const Arg0Expand = enum {
+ expand,
+ no_expand,
+};
+
+/// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable,
+/// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall.
+/// If this function returns with an error, `argv[0]` will be restored to the value it was when it was passed in.
+pub fn execvpeZ_expandArg0(
+ comptime arg0_expand: Arg0Expand,
+ file: [*:0]const u8,
+ child_argv: switch (arg0_expand) {
+ .expand => [*:null]?[*:0]const u8,
+ .no_expand => [*:null]const ?[*:0]const u8,
+ },
+ envp: [*:null]const ?[*:0]const u8,
+) ExecveError {
const file_slice = mem.toSliceConst(u8, file);
- if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp);
+ if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveZ(file, child_argv, envp);
- const PATH = getenv("PATH") orelse "/usr/local/bin:/bin/:/usr/bin";
+ const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin";
var path_buf: [MAX_PATH_BYTES]u8 = undefined;
var it = mem.tokenize(PATH, ":");
var seen_eacces = false;
var err: ExecveError = undefined;
+
+ // In case of expanding arg0 we must put it back if we return with an error.
+ const prev_arg0 = child_argv[0];
+ defer switch (arg0_expand) {
+ .expand => child_argv[0] = prev_arg0,
+ .no_expand => {},
+ };
+
while (it.next()) |search_path| {
if (path_buf.len < search_path.len + file_slice.len + 1) return error.NameTooLong;
mem.copy(u8, &path_buf, search_path);
@@ -962,7 +994,12 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e
mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice);
const path_len = search_path.len + file_slice.len + 1;
path_buf[path_len] = 0;
- err = execveC(path_buf[0..path_len :0].ptr, child_argv, envp);
+ const full_path = path_buf[0..path_len :0].ptr;
+ switch (arg0_expand) {
+ .expand => child_argv[0] = full_path,
+ .no_expand => {},
+ }
+ err = execveZ(full_path, child_argv, envp);
switch (err) {
error.AccessDenied => seen_eacces = true,
error.FileNotFound, error.NotDir => {},
@@ -973,13 +1010,24 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e
return err;
}
-/// This function must allocate memory to add a null terminating bytes on path and each arg.
-/// It must also convert to KEY=VALUE\0 format for environment variables, and include null
-/// pointers after the args and after the environment variables.
-/// `argv_slice[0]` is the executable path.
+/// Like `execvpe` except the parameters are null-terminated,
+/// matching the syscall API on all targets. This removes the need for an allocator.
/// This function also uses the PATH environment variable to get the full path to the executable.
-pub fn execvpe(
+/// If `file` is an absolute path, this is the same as `execveZ`.
+pub fn execvpeZ(
+ file: [*:0]const u8,
+ argv: [*:null]const ?[*:0]const u8,
+ envp: [*:null]const ?[*:0]const u8,
+) ExecveError {
+ return execvpeZ_expandArg0(.no_expand, file, argv, envp);
+}
+
+/// This is the same as `execvpe` except if the `arg0_expand` parameter is set to `.expand`,
+/// then argv[0] will be replaced with the expanded version of it, after resolving in accordance
+/// with the PATH environment variable.
+pub fn execvpe_expandArg0(
allocator: *mem.Allocator,
+ arg0_expand: Arg0Expand,
argv_slice: []const []const u8,
env_map: *const std.BufMap,
) (ExecveError || error{OutOfMemory}) {
@@ -1004,7 +1052,23 @@ pub fn execvpe(
const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);
defer freeNullDelimitedEnvMap(allocator, envp_buf);
- return execvpeC(argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr);
+ switch (arg0_expand) {
+ .expand => return execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr),
+ .no_expand => return execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr),
+ }
+}
+
+/// This function must allocate memory to add a null terminating bytes on path and each arg.
+/// It must also convert to KEY=VALUE\0 format for environment variables, and include null
+/// pointers after the args and after the environment variables.
+/// `argv_slice[0]` is the executable path.
+/// This function also uses the PATH environment variable to get the full path to the executable.
+pub fn execvpe(
+ allocator: *mem.Allocator,
+ argv_slice: []const []const u8,
+ env_map: *const std.BufMap,
+) (ExecveError || error{OutOfMemory}) {
+ return execvpe_expandArg0(allocator, .no_expand, argv_slice, env_map);
}
pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![:null]?[*:0]u8 {
@@ -1038,9 +1102,37 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8)
}
/// Get an environment variable.
-/// See also `getenvC`.
-/// TODO make this go through libc when we have it
+/// See also `getenvZ`.
pub fn getenv(key: []const u8) ?[]const u8 {
+ if (builtin.link_libc) {
+ var small_key_buf: [64]u8 = undefined;
+ if (key.len < small_key_buf.len) {
+ mem.copy(u8, &small_key_buf, key);
+ small_key_buf[key.len] = 0;
+ const key0 = small_key_buf[0..key.len :0];
+ return getenvZ(key0);
+ }
+ // Search the entire `environ` because we don't have a null terminated pointer.
+ var ptr = std.c.environ;
+ while (ptr.*) |line| : (ptr += 1) {
+ var line_i: usize = 0;
+ while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {}
+ const this_key = line[0..line_i];
+
+ if (!mem.eql(u8, this_key, key)) continue;
+
+ var end_i: usize = line_i;
+ while (line[end_i] != 0) : (end_i += 1) {}
+ const value = line[line_i + 1 .. end_i];
+
+ return value;
+ }
+ return null;
+ }
+ if (builtin.os == .windows) {
+ @compileError("std.os.getenv is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");
+ }
+ // TODO see https://github.com/ziglang/zig/issues/4524
for (environ) |ptr| {
var line_i: usize = 0;
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
@@ -1056,16 +1148,50 @@ pub fn getenv(key: []const u8) ?[]const u8 {
return null;
}
+/// Deprecated in favor of `getenvZ`.
+pub const getenvC = getenvZ;
+
/// Get an environment variable with a null-terminated name.
/// See also `getenv`.
-pub fn getenvC(key: [*:0]const u8) ?[]const u8 {
+pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
if (builtin.link_libc) {
const value = system.getenv(key) orelse return null;
return mem.toSliceConst(u8, value);
}
+ if (builtin.os == .windows) {
+ @compileError("std.os.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");
+ }
return getenv(mem.toSliceConst(u8, key));
}
+/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.
+/// See also `getenv`.
+pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
+ if (builtin.os != .windows) {
+ @compileError("std.os.getenvW is a Windows-only API");
+ }
+ const key_slice = mem.toSliceConst(u16, key);
+ const ptr = windows.peb().ProcessParameters.Environment;
+ var i: usize = 0;
+ while (ptr[i] != 0) {
+ const key_start = i;
+
+ while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
+ const this_key = ptr[key_start..i];
+
+ if (ptr[i] == '=') i += 1;
+
+ const value_start = i;
+ while (ptr[i] != 0) : (i += 1) {}
+ const this_value = ptr[value_start..i :0];
+
+ if (mem.eql(u16, key_slice, this_key)) return this_value;
+
+ i += 1; // skip over null byte
+ }
+ return null;
+}
+
pub const GetCwdError = error{
NameTooLong,
CurrentWorkingDirectoryUnlinked,
@@ -1726,7 +1852,7 @@ pub fn isCygwinPty(handle: fd_t) bool {
const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]);
const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)];
- const name_wide = @bytesToSlice(u16, name_bytes);
+ const name_wide = mem.bytesAsSlice(u16, name_bytes);
return mem.indexOf(u16, name_wide, &[_]u16{ 'm', 's', 'y', 's', '-' }) != null or
mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
}
@@ -2452,6 +2578,9 @@ pub const AccessError = error{
InputOutput,
SystemResources,
BadPathName,
+ FileBusy,
+ SymLinkLoop,
+ ReadOnlyFileSystem,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -2469,8 +2598,11 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
return accessC(&path_c, mode);
}
+/// Deprecated in favor of `accessZ`.
+pub const accessC = accessZ;
+
/// Same as `access` except `path` is null-terminated.
-pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
+pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
@@ -2479,12 +2611,11 @@ pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
switch (errno(system.access(path, mode))) {
0 => return,
EACCES => return error.PermissionDenied,
- EROFS => return error.PermissionDenied,
- ELOOP => return error.PermissionDenied,
- ETXTBSY => return error.PermissionDenied,
+ EROFS => return error.ReadOnlyFileSystem,
+ ELOOP => return error.SymLinkLoop,
+ ETXTBSY => return error.FileBusy,
ENOTDIR => return error.FileNotFound,
ENOENT => return error.FileNotFound,
-
ENAMETOOLONG => return error.NameTooLong,
EINVAL => unreachable,
EFAULT => unreachable,
@@ -2510,6 +2641,79 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v
}
}
+/// Check user's permissions for a file, based on an open directory handle.
+/// TODO currently this ignores `mode` and `flags` on Windows.
+pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void {
+ if (builtin.os == .windows) {
+ const path_w = try windows.sliceToPrefixedFileW(path);
+ return faccessatW(dirfd, &path_w, mode, flags);
+ }
+ const path_c = try toPosixPath(path);
+ return faccessatZ(dirfd, &path_c, mode, flags);
+}
+
+/// Same as `faccessat` except the path parameter is null-terminated.
+pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void {
+ if (builtin.os == .windows) {
+ const path_w = try windows.cStrToPrefixedFileW(path);
+ return faccessatW(dirfd, &path_w, mode, flags);
+ }
+ switch (errno(system.faccessat(dirfd, path, mode, flags))) {
+ 0 => return,
+ EACCES => return error.PermissionDenied,
+ EROFS => return error.ReadOnlyFileSystem,
+ ELOOP => return error.SymLinkLoop,
+ ETXTBSY => return error.FileBusy,
+ ENOTDIR => return error.FileNotFound,
+ ENOENT => return error.FileNotFound,
+ ENAMETOOLONG => return error.NameTooLong,
+ EINVAL => unreachable,
+ EFAULT => unreachable,
+ EIO => return error.InputOutput,
+ ENOMEM => return error.SystemResources,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+/// Same as `faccessat` except asserts the target is Windows and the path parameter
+/// is NtDll-prefixed, null-terminated, WTF-16 encoded.
+/// TODO currently this ignores `mode` and `flags`
+pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
+ if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
+ return;
+ }
+ if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
+ return;
+ }
+
+ const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
+ error.Overflow => return error.NameTooLong,
+ };
+ var nt_name = windows.UNICODE_STRING{
+ .Length = path_len_bytes,
+ .MaximumLength = path_len_bytes,
+ .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
+ };
+ var attr = windows.OBJECT_ATTRIBUTES{
+ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
+ .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dirfd,
+ .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
+ .ObjectName = &nt_name,
+ .SecurityDescriptor = null,
+ .SecurityQualityOfService = null,
+ };
+ var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
+ switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
+ .SUCCESS => return,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .INVALID_PARAMETER => unreachable,
+ .ACCESS_DENIED => return error.PermissionDenied,
+ .OBJECT_PATH_SYNTAX_BAD => unreachable,
+ else => |rc| return windows.unexpectedStatus(rc),
+ }
+}
+
pub const PipeError = error{
SystemFdQuotaExceeded,
ProcessFdQuotaExceeded,
@@ -2844,18 +3048,26 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
}
pub fn dl_iterate_phdr(
- comptime T: type,
- callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32,
- data: ?*T,
-) isize {
+ context: var,
+ comptime Error: type,
+ comptime callback: fn (info: *dl_phdr_info, size: usize, context: @TypeOf(context)) Error!void,
+) Error!void {
+ const Context = @TypeOf(context);
+
if (builtin.object_format != .elf)
@compileError("dl_iterate_phdr is not available for this target");
if (builtin.link_libc) {
- return system.dl_iterate_phdr(
- @ptrCast(std.c.dl_iterate_phdr_callback, callback),
- @ptrCast(?*c_void, data),
- );
+ switch (system.dl_iterate_phdr(struct {
+ fn callbackC(info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int {
+ const context_ptr = @ptrCast(*const Context, @alignCast(@alignOf(*const Context), data));
+ callback(info, size, context_ptr.*) catch |err| return @errorToInt(err);
+ return 0;
+ }
+ }.callbackC, @intToPtr(?*c_void, @ptrToInt(&context)))) {
+ 0 => return,
+ else => |err| return @errSetCast(Error, @intToError(@intCast(u16, err))), // TODO don't hardcode u16
+ }
}
const elf_base = std.process.getBaseAddress();
@@ -2877,11 +3089,10 @@ pub fn dl_iterate_phdr(
.dlpi_phnum = ehdr.e_phnum,
};
- return callback(&info, @sizeOf(dl_phdr_info), data);
+ return callback(&info, @sizeOf(dl_phdr_info), context);
}
// Last return value from the callback function
- var last_r: isize = 0;
while (it.next()) |entry| {
var dlpi_phdr: [*]elf.Phdr = undefined;
var dlpi_phnum: u16 = undefined;
@@ -2903,11 +3114,8 @@ pub fn dl_iterate_phdr(
.dlpi_phnum = dlpi_phnum,
};
- last_r = callback(&info, @sizeOf(dl_phdr_info), data);
- if (last_r != 0) break;
+ try callback(&info, @sizeOf(dl_phdr_info), context);
}
-
- return last_r;
}
pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
@@ -3141,7 +3349,7 @@ pub fn res_mkquery(
// Make a reasonably unpredictable id
var ts: timespec = undefined;
clock_gettime(CLOCK_REALTIME, &ts) catch {};
- const UInt = @IntType(false, @TypeOf(ts.tv_nsec).bit_count);
+ const UInt = std.meta.IntType(false, @TypeOf(ts.tv_nsec).bit_count);
const unsec = @bitCast(UInt, ts.tv_nsec);
const id = @truncate(u32, unsec + unsec / 65536);
q[0] = @truncate(u8, id / 256);
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
@@ -1004,7 +1004,7 @@ pub const dl_phdr_info = extern struct {
pub const CPU_SETSIZE = 128;
pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
-pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8));
+pub const cpu_count_t = std.meta.IntType(false, std.math.log2(CPU_SETSIZE * 8));
pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
var sum: cpu_count_t = 0;
diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
@@ -152,7 +152,7 @@ pub fn setThreadPointer(addr: usize) void {
: [addr] "r" (addr)
);
},
- .arm => |arm| {
+ .arm => {
const rc = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr);
assert(rc == 0);
},
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
@@ -29,7 +29,7 @@ test "makePath, put some files in it, deleteTree" {
test "access file" {
try fs.makePath(a, "os_test_tmp");
- if (File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt")) |ok| {
+ if (fs.cwd().access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", .{})) |ok| {
@panic("expected error");
} else |err| {
expect(err == error.FileNotFound);
@@ -165,16 +165,19 @@ test "sigaltstack" {
// analyzed
const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
-fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) callconv(.C) i32 {
- if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
- return 0;
+const IterFnError = error{
+ MissingPtLoadSegment,
+ MissingLoad,
+ BadElfMagic,
+ FailedConsistencyCheck,
+};
- var counter = data.?;
+fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
// Count how many libraries are loaded
counter.* += @as(usize, 1);
// The image should contain at least a PT_LOAD segment
- if (info.dlpi_phnum < 1) return -1;
+ if (info.dlpi_phnum < 1) return error.MissingPtLoadSegment;
// Quick & dirty validation of the phdr pointers, make sure we're not
// pointing to some random gibberish
@@ -189,17 +192,15 @@ fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) callconv(.C) i32 {
// Find the ELF header
const elf_header = @intToPtr(*elf.Ehdr, reloc_addr - phdr.p_offset);
// Validate the magic
- if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1;
+ if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return error.BadElfMagic;
// Consistency check
- if (elf_header.e_phnum != info.dlpi_phnum) return -1;
+ if (elf_header.e_phnum != info.dlpi_phnum) return error.FailedConsistencyCheck;
found_load = true;
break;
}
- if (!found_load) return -1;
-
- return 42;
+ if (!found_load) return error.MissingLoad;
}
test "dl_iterate_phdr" {
@@ -207,7 +208,7 @@ test "dl_iterate_phdr" {
return error.SkipZigTest;
var counter: usize = 0;
- expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
+ try os.dl_iterate_phdr(&counter, IterFnError, iter_fn);
expect(counter != 0);
}
@@ -350,3 +351,11 @@ test "mmap" {
try fs.cwd().deleteFile(test_out_file);
}
+
+test "getenv" {
+ if (builtin.os == .windows) {
+ expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);
+ } else {
+ expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
+ }
+}
diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig
@@ -1187,7 +1187,7 @@ pub const RTL_USER_PROCESS_PARAMETERS = extern struct {
DllPath: UNICODE_STRING,
ImagePathName: UNICODE_STRING,
CommandLine: UNICODE_STRING,
- Environment: [*]WCHAR,
+ Environment: [*:0]WCHAR,
dwX: ULONG,
dwY: ULONG,
dwXSize: ULONG,
diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig
@@ -8,6 +8,12 @@ pub extern "NtDll" fn NtQueryInformationFile(
Length: ULONG,
FileInformationClass: FILE_INFORMATION_CLASS,
) callconv(.Stdcall) NTSTATUS;
+
+pub extern "NtDll" fn NtQueryAttributesFile(
+ ObjectAttributes: *OBJECT_ATTRIBUTES,
+ FileAttributes: *FILE_BASIC_INFORMATION,
+) callconv(.Stdcall) NTSTATUS;
+
pub extern "NtDll" fn NtCreateFile(
FileHandle: *HANDLE,
DesiredAccess: ACCESS_MASK,
diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig
@@ -34,13 +34,13 @@ pub fn PackedIntIo(comptime Int: type, comptime endian: builtin.Endian) type {
//we bitcast the desired Int type to an unsigned version of itself
// to avoid issues with shifting signed ints.
- const UnInt = @IntType(false, int_bits);
+ const UnInt = std.meta.IntType(false, int_bits);
//The maximum container int type
- const MinIo = @IntType(false, min_io_bits);
+ const MinIo = std.meta.IntType(false, min_io_bits);
//The minimum container int type
- const MaxIo = @IntType(false, max_io_bits);
+ const MaxIo = std.meta.IntType(false, max_io_bits);
return struct {
pub fn get(bytes: []const u8, index: usize, bit_offset: u7) Int {
@@ -322,7 +322,7 @@ test "PackedIntArray" {
inline while (bits <= 256) : (bits += 1) {
//alternate unsigned and signed
const even = bits % 2 == 0;
- const I = @IntType(even, bits);
+ const I = std.meta.IntType(even, bits);
const PackedArray = PackedIntArray(I, int_count);
const expected_bytes = ((bits * int_count) + 7) / 8;
@@ -369,7 +369,7 @@ test "PackedIntSlice" {
inline while (bits <= 256) : (bits += 1) {
//alternate unsigned and signed
const even = bits % 2 == 0;
- const I = @IntType(even, bits);
+ const I = std.meta.IntType(even, bits);
const P = PackedIntSlice(I);
var data = P.init(&buffer, int_count);
@@ -399,7 +399,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {
comptime var bits = 0;
inline while (bits <= max_bits) : (bits += 1) {
- const Int = @IntType(false, bits);
+ const Int = std.meta.IntType(false, bits);
const PackedArray = PackedIntArray(Int, int_count);
var packed_array = @as(PackedArray, undefined);
diff --git a/lib/std/process.zig b/lib/std/process.zig
@@ -1,5 +1,5 @@
-const builtin = @import("builtin");
const std = @import("std.zig");
+const builtin = std.builtin;
const os = std.os;
const fs = std.fs;
const BufMap = std.BufMap;
@@ -31,20 +31,16 @@ test "getCwdAlloc" {
testing.allocator.free(cwd);
}
-/// Caller must free result when done.
-/// TODO make this go through libc when we have it
+/// Caller owns resulting `BufMap`.
pub fn getEnvMap(allocator: *Allocator) !BufMap {
var result = BufMap.init(allocator);
errdefer result.deinit();
if (builtin.os == .windows) {
- const ptr = try os.windows.GetEnvironmentStringsW();
- defer os.windows.FreeEnvironmentStringsW(ptr);
+ const ptr = os.windows.peb().ProcessParameters.Environment;
var i: usize = 0;
- while (true) {
- if (ptr[i] == 0) return result;
-
+ while (ptr[i] != 0) {
const key_start = i;
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
@@ -64,6 +60,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
try result.setMove(key, value);
}
+ return result;
} else if (builtin.os == .wasi) {
var environ_count: usize = undefined;
var environ_buf_size: usize = undefined;
@@ -95,15 +92,29 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
}
}
return result;
+ } else if (builtin.link_libc) {
+ var ptr = std.c.environ;
+ while (ptr.*) |line| : (ptr += 1) {
+ var line_i: usize = 0;
+ while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {}
+ const key = line[0..line_i];
+
+ var end_i: usize = line_i;
+ while (line[end_i] != 0) : (end_i += 1) {}
+ const value = line[line_i + 1 .. end_i];
+
+ try result.set(key, value);
+ }
+ return result;
} else {
- for (os.environ) |ptr| {
+ for (os.environ) |line| {
var line_i: usize = 0;
- while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
- const key = ptr[0..line_i];
+ while (line[line_i] != 0 and line[line_i] != '=') : (line_i += 1) {}
+ const key = line[0..line_i];
var end_i: usize = line_i;
- while (ptr[end_i] != 0) : (end_i += 1) {}
- const value = ptr[line_i + 1 .. end_i];
+ while (line[end_i] != 0) : (end_i += 1) {}
+ const value = line[line_i + 1 .. end_i];
try result.set(key, value);
}
@@ -125,37 +136,20 @@ pub const GetEnvVarOwnedError = error{
};
/// Caller must free returned memory.
-/// TODO make this go through libc when we have it
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
if (builtin.os == .windows) {
- const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
- defer allocator.free(key_with_null);
-
- var buf = try allocator.alloc(u16, 256);
- defer allocator.free(buf);
-
- while (true) {
- const windows_buf_len = math.cast(os.windows.DWORD, buf.len) catch return error.OutOfMemory;
- const result = os.windows.GetEnvironmentVariableW(
- key_with_null.ptr,
- buf.ptr,
- windows_buf_len,
- ) catch |err| switch (err) {
- error.Unexpected => return error.EnvironmentVariableNotFound,
- else => |e| return e,
- };
- if (result > buf.len) {
- buf = try allocator.realloc(buf, result);
- continue;
- }
+ const result_w = blk: {
+ const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
+ defer allocator.free(key_w);
- return std.unicode.utf16leToUtf8Alloc(allocator, buf[0..result]) catch |err| switch (err) {
- error.DanglingSurrogateHalf => return error.InvalidUtf8,
- error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
- error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
- else => |e| return e,
- };
- }
+ break :blk std.os.getenvW(key_w) orelse return error.EnvironmentVariableNotFound;
+ };
+ return std.unicode.utf16leToUtf8Alloc(allocator, result_w) catch |err| switch (err) {
+ error.DanglingSurrogateHalf => return error.InvalidUtf8,
+ error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
+ else => |e| return e,
+ };
} else {
const result = os.getenv(key) orelse return error.EnvironmentVariableNotFound;
return mem.dupe(allocator, u8, result);
@@ -436,7 +430,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
errdefer allocator.free(buf);
- const result_slice_list = @bytesToSlice([]u8, buf[0..slice_list_bytes]);
+ const result_slice_list = mem.bytesAsSlice([]u8, buf[0..slice_list_bytes]);
const result_contents = buf[slice_list_bytes..];
mem.copy(u8, result_contents, contents_slice);
@@ -613,3 +607,59 @@ pub fn getBaseAddress() usize {
else => @compileError("Unsupported OS"),
}
}
+
+/// Caller owns the result value and each inner slice.
+pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]u8 {
+ switch (builtin.link_mode) {
+ .Static => return &[_][:0]u8{},
+ .Dynamic => {},
+ }
+ const List = std.ArrayList([:0]u8);
+ switch (builtin.os) {
+ .linux,
+ .freebsd,
+ .netbsd,
+ .dragonfly,
+ => {
+ var paths = List.init(allocator);
+ errdefer {
+ const slice = paths.toOwnedSlice();
+ for (slice) |item| {
+ allocator.free(item);
+ }
+ allocator.free(slice);
+ }
+ try os.dl_iterate_phdr(&paths, error{OutOfMemory}, struct {
+ fn callback(info: *os.dl_phdr_info, size: usize, list: *List) !void {
+ const name = info.dlpi_name orelse return;
+ if (name[0] == '/') {
+ const item = try mem.dupeZ(list.allocator, u8, mem.toSliceConst(u8, name));
+ errdefer list.allocator.free(item);
+ try list.append(item);
+ }
+ }
+ }.callback);
+ return paths.toOwnedSlice();
+ },
+ .macosx, .ios, .watchos, .tvos => {
+ var paths = List.init(allocator);
+ errdefer {
+ const slice = paths.toOwnedSlice();
+ for (slice) |item| {
+ allocator.free(item);
+ }
+ allocator.free(slice);
+ }
+ const img_count = std.c._dyld_image_count();
+ var i: u32 = 0;
+ while (i < img_count) : (i += 1) {
+ const name = std.c._dyld_get_image_name(i);
+ const item = try mem.dupeZ(allocator, u8, mem.toSliceConst(u8, name));
+ errdefer allocator.free(item);
+ try paths.append(item);
+ }
+ return paths.toOwnedSlice();
+ },
+ else => @compileError("getSelfExeSharedLibPaths unimplemented for this target"),
+ }
+}
diff --git a/lib/std/rand.zig b/lib/std/rand.zig
@@ -45,8 +45,8 @@ pub const Random = struct {
/// Returns a random int `i` such that `0 <= i <= maxInt(T)`.
/// `i` is evenly distributed.
pub fn int(r: *Random, comptime T: type) T {
- const UnsignedT = @IntType(false, T.bit_count);
- const ByteAlignedT = @IntType(false, @divTrunc(T.bit_count + 7, 8) * 8);
+ const UnsignedT = std.meta.IntType(false, T.bit_count);
+ const ByteAlignedT = std.meta.IntType(false, @divTrunc(T.bit_count + 7, 8) * 8);
var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined;
r.bytes(rand_bytes[0..]);
@@ -85,9 +85,9 @@ pub const Random = struct {
comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
assert(0 < less_than);
// Small is typically u32
- const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32);
+ const Small = std.meta.IntType(false, @divTrunc(T.bit_count + 31, 32) * 32);
// Large is typically u64
- const Large = @IntType(false, Small.bit_count * 2);
+ const Large = std.meta.IntType(false, Small.bit_count * 2);
// adapted from:
// http://www.pcg-random.org/posts/bounded-rands.html
@@ -99,7 +99,7 @@ pub const Random = struct {
// TODO: workaround for https://github.com/ziglang/zig/issues/1770
// should be:
// var t: Small = -%less_than;
- var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), @as(Small, less_than)));
+ var t: Small = @bitCast(Small, -%@bitCast(std.meta.IntType(true, Small.bit_count), @as(Small, less_than)));
if (t >= less_than) {
t -= less_than;
@@ -145,7 +145,7 @@ pub const Random = struct {
assert(at_least < less_than);
if (T.is_signed) {
// Two's complement makes this math pretty easy.
- const UnsignedT = @IntType(false, T.bit_count);
+ const UnsignedT = std.meta.IntType(false, T.bit_count);
const lo = @bitCast(UnsignedT, at_least);
const hi = @bitCast(UnsignedT, less_than);
const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);
@@ -163,7 +163,7 @@ pub const Random = struct {
assert(at_least < less_than);
if (T.is_signed) {
// Two's complement makes this math pretty easy.
- const UnsignedT = @IntType(false, T.bit_count);
+ const UnsignedT = std.meta.IntType(false, T.bit_count);
const lo = @bitCast(UnsignedT, at_least);
const hi = @bitCast(UnsignedT, less_than);
const result = lo +% r.uintLessThan(UnsignedT, hi -% lo);
@@ -180,7 +180,7 @@ pub const Random = struct {
assert(at_least <= at_most);
if (T.is_signed) {
// Two's complement makes this math pretty easy.
- const UnsignedT = @IntType(false, T.bit_count);
+ const UnsignedT = std.meta.IntType(false, T.bit_count);
const lo = @bitCast(UnsignedT, at_least);
const hi = @bitCast(UnsignedT, at_most);
const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);
@@ -198,7 +198,7 @@ pub const Random = struct {
assert(at_least <= at_most);
if (T.is_signed) {
// Two's complement makes this math pretty easy.
- const UnsignedT = @IntType(false, T.bit_count);
+ const UnsignedT = std.meta.IntType(false, T.bit_count);
const lo = @bitCast(UnsignedT, at_least);
const hi = @bitCast(UnsignedT, at_most);
const result = lo +% r.uintAtMost(UnsignedT, hi -% lo);
@@ -281,7 +281,7 @@ pub const Random = struct {
/// This function introduces a minor bias.
pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {
comptime assert(T.is_signed == false);
- const T2 = @IntType(false, T.bit_count * 2);
+ const T2 = std.meta.IntType(false, T.bit_count * 2);
// adapted from:
// http://www.pcg-random.org/posts/bounded-rands.html
diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig
@@ -96,6 +96,8 @@ pub fn main() !void {
builder.verbose_cimport = true;
} else if (mem.eql(u8, arg, "--verbose-cc")) {
builder.verbose_cc = true;
+ } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
+ builder.verbose_llvm_cpu_features = true;
} else if (mem.eql(u8, arg, "--")) {
builder.args = argsRest(args, arg_idx);
break;
@@ -126,7 +128,7 @@ pub fn main() !void {
}
fn runBuild(builder: *Builder) anyerror!void {
- switch (@typeId(@TypeOf(root.build).ReturnType)) {
+ switch (@typeInfo(@TypeOf(root.build).ReturnType)) {
.Void => root.build(builder),
.ErrorUnion => try root.build(builder),
else => @compileError("expected return type of build to be 'void' or '!void'"),
@@ -185,16 +187,17 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
try out_stream.write(
\\
\\Advanced Options:
- \\ --build-file [file] Override path to build.zig
- \\ --cache-dir [path] Override path to zig cache directory
- \\ --override-lib-dir [arg] Override path to Zig lib directory
- \\ --verbose-tokenize Enable compiler debug output for tokenization
- \\ --verbose-ast Enable compiler debug output for parsing into an AST
- \\ --verbose-link Enable compiler debug output for linking
- \\ --verbose-ir Enable compiler debug output for Zig IR
- \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
- \\ --verbose-cimport Enable compiler debug output for C imports
- \\ --verbose-cc Enable compiler debug output for C compilation
+ \\ --build-file [file] Override path to build.zig
+ \\ --cache-dir [path] Override path to zig cache directory
+ \\ --override-lib-dir [arg] Override path to Zig lib directory
+ \\ --verbose-tokenize Enable compiler debug output for tokenization
+ \\ --verbose-ast Enable compiler debug output for parsing into an AST
+ \\ --verbose-link Enable compiler debug output for linking
+ \\ --verbose-ir Enable compiler debug output for Zig IR
+ \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
+ \\ --verbose-cimport Enable compiler debug output for C imports
+ \\ --verbose-cc Enable compiler debug output for C compilation
+ \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
\\
);
}
diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig
@@ -511,7 +511,7 @@ export fn roundf(a: f32) f32 {
fn generic_fmod(comptime T: type, x: T, y: T) T {
@setRuntimeSafety(false);
- const uint = @IntType(false, T.bit_count);
+ const uint = std.meta.IntType(false, T.bit_count);
const log2uint = math.Log2Int(uint);
const digits = if (T == f32) 23 else 52;
const exp_bits = if (T == f32) 9 else 12;
diff --git a/lib/std/special/compiler_rt/addXf3.zig b/lib/std/special/compiler_rt/addXf3.zig
@@ -54,21 +54,21 @@ pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 {
}
// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
-fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
- const Z = @IntType(false, T.bit_count);
- const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
+fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 {
+ const Z = std.meta.IntType(false, T.bit_count);
+ const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
const significandBits = std.math.floatMantissaBits(T);
const implicitBit = @as(Z, 1) << significandBits;
- const shift = @clz(@IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit);
+ const shift = @clz(std.meta.IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit);
significand.* <<= @intCast(S, shift);
return 1 - shift;
}
// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
fn addXf3(comptime T: type, a: T, b: T) T {
- const Z = @IntType(false, T.bit_count);
- const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
+ const Z = std.meta.IntType(false, T.bit_count);
+ const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
const typeWidth = T.bit_count;
const significandBits = std.math.floatMantissaBits(T);
@@ -182,7 +182,7 @@ fn addXf3(comptime T: type, a: T, b: T) T {
// If partial cancellation occured, we need to left-shift the result
// and adjust the exponent:
if (aSignificand < implicitBit << 3) {
- const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(@IntType(false, T.bit_count), implicitBit << 3));
+ const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.IntType(false, T.bit_count), implicitBit << 3));
aSignificand <<= @intCast(S, shift);
aExponent -= shift;
}
diff --git a/lib/std/special/compiler_rt/compareXf2.zig b/lib/std/special/compiler_rt/compareXf2.zig
@@ -22,8 +22,8 @@ const GE = extern enum(i32) {
pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
@setRuntimeSafety(builtin.is_test);
- const srep_t = @IntType(true, T.bit_count);
- const rep_t = @IntType(false, T.bit_count);
+ const srep_t = std.meta.IntType(true, T.bit_count);
+ const rep_t = std.meta.IntType(false, T.bit_count);
const significandBits = std.math.floatMantissaBits(T);
const exponentBits = std.math.floatExponentBits(T);
@@ -68,7 +68,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
pub fn unordcmp(comptime T: type, a: T, b: T) i32 {
@setRuntimeSafety(builtin.is_test);
- const rep_t = @IntType(false, T.bit_count);
+ const rep_t = std.meta.IntType(false, T.bit_count);
const significandBits = std.math.floatMantissaBits(T);
const exponentBits = std.math.floatExponentBits(T);
diff --git a/lib/std/special/compiler_rt/divdf3.zig b/lib/std/special/compiler_rt/divdf3.zig
@@ -7,8 +7,8 @@ const builtin = @import("builtin");
pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, f64.bit_count);
- const SignedZ = @IntType(true, f64.bit_count);
+ const Z = std.meta.IntType(false, f64.bit_count);
+ const SignedZ = std.meta.IntType(true, f64.bit_count);
const typeWidth = f64.bit_count;
const significandBits = std.math.floatMantissaBits(f64);
@@ -312,9 +312,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
}
}
-fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
+fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
const significandBits = std.math.floatMantissaBits(T);
const implicitBit = @as(Z, 1) << significandBits;
diff --git a/lib/std/special/compiler_rt/divsf3.zig b/lib/std/special/compiler_rt/divsf3.zig
@@ -7,7 +7,7 @@ const builtin = @import("builtin");
pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, f32.bit_count);
+ const Z = std.meta.IntType(false, f32.bit_count);
const typeWidth = f32.bit_count;
const significandBits = std.math.floatMantissaBits(f32);
@@ -185,9 +185,9 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
}
}
-fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
+fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
const significandBits = std.math.floatMantissaBits(T);
const implicitBit = @as(Z, 1) << significandBits;
diff --git a/lib/std/special/compiler_rt/extendXfYf2.zig b/lib/std/special/compiler_rt/extendXfYf2.zig
@@ -30,11 +30,11 @@ pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 {
const CHAR_BIT = 8;
-fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @typeInfo(src_t).Float.bits)) dst_t {
+fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.IntType(false, @typeInfo(src_t).Float.bits)) dst_t {
@setRuntimeSafety(builtin.is_test);
- const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
- const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
+ const src_rep_t = std.meta.IntType(false, @typeInfo(src_t).Float.bits);
+ const dst_rep_t = std.meta.IntType(false, @typeInfo(dst_t).Float.bits);
const srcSigBits = std.math.floatMantissaBits(src_t);
const dstSigBits = std.math.floatMantissaBits(dst_t);
const SrcShift = std.math.Log2Int(src_rep_t);
diff --git a/lib/std/special/compiler_rt/fixint.zig b/lib/std/special/compiler_rt/fixint.zig
@@ -45,7 +45,7 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
if (exponent < 0) return 0;
// The unsigned result needs to be large enough to handle an fixint_t or rep_t
- const fixuint_t = @IntType(false, fixint_t.bit_count);
+ const fixuint_t = std.meta.IntType(false, fixint_t.bit_count);
const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
var uint_result: UintResultType = undefined;
diff --git a/lib/std/special/compiler_rt/fixuint.zig b/lib/std/special/compiler_rt/fixuint.zig
@@ -10,7 +10,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
f128 => u128,
else => unreachable,
};
- const srep_t = @IntType(true, rep_t.bit_count);
+ const srep_t = @import("std").meta.IntType(true, rep_t.bit_count);
const significandBits = switch (fp_t) {
f32 => 23,
f64 => 52,
diff --git a/lib/std/special/compiler_rt/floatsiXf.zig b/lib/std/special/compiler_rt/floatsiXf.zig
@@ -5,8 +5,8 @@ const maxInt = std.math.maxInt;
fn floatsiXf(comptime T: type, a: i32) T {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, T.bit_count);
- const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
+ const Z = std.meta.IntType(false, T.bit_count);
+ const S = std.meta.IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));
if (a == 0) {
return @as(T, 0.0);
diff --git a/lib/std/special/compiler_rt/mulXf3.zig b/lib/std/special/compiler_rt/mulXf3.zig
@@ -28,7 +28,7 @@ pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {
fn mulXf3(comptime T: type, a: T, b: T) T {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
const typeWidth = T.bit_count;
const significandBits = std.math.floatMantissaBits(T);
@@ -264,9 +264,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
}
}
-fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
+fn normalize(comptime T: type, significand: *std.meta.IntType(false, T.bit_count)) i32 {
@setRuntimeSafety(builtin.is_test);
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
const significandBits = std.math.floatMantissaBits(T);
const implicitBit = @as(Z, 1) << significandBits;
diff --git a/lib/std/special/compiler_rt/negXf2.zig b/lib/std/special/compiler_rt/negXf2.zig
@@ -19,7 +19,7 @@ pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 {
}
fn negXf2(comptime T: type, a: T) T {
- const Z = @IntType(false, T.bit_count);
+ const Z = std.meta.IntType(false, T.bit_count);
const typeWidth = T.bit_count;
const significandBits = std.math.floatMantissaBits(T);
diff --git a/lib/std/special/compiler_rt/truncXfYf2.zig b/lib/std/special/compiler_rt/truncXfYf2.zig
@@ -36,8 +36,8 @@ pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 {
}
inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
- const src_rep_t = @IntType(false, @typeInfo(src_t).Float.bits);
- const dst_rep_t = @IntType(false, @typeInfo(dst_t).Float.bits);
+ const src_rep_t = std.meta.IntType(false, @typeInfo(src_t).Float.bits);
+ const dst_rep_t = std.meta.IntType(false, @typeInfo(dst_t).Float.bits);
const srcSigBits = std.math.floatMantissaBits(src_t);
const dstSigBits = std.math.floatMantissaBits(dst_t);
const SrcShift = std.math.Log2Int(src_rep_t);
diff --git a/lib/std/special/compiler_rt/udivmod.zig b/lib/std/special/compiler_rt/udivmod.zig
@@ -10,8 +10,8 @@ const high = 1 - low;
pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?*DoubleInt) DoubleInt {
@setRuntimeSafety(is_test);
- const SingleInt = @IntType(false, @divExact(DoubleInt.bit_count, 2));
- const SignedDoubleInt = @IntType(true, DoubleInt.bit_count);
+ const SingleInt = @import("std").meta.IntType(false, @divExact(DoubleInt.bit_count, 2));
+ const SignedDoubleInt = @import("std").meta.IntType(true, DoubleInt.bit_count);
const Log2SingleInt = @import("std").math.Log2Int(SingleInt);
const n = @ptrCast(*const [2]SingleInt, &a).*; // TODO issue #421
diff --git a/lib/std/start.zig b/lib/std/start.zig
@@ -21,7 +21,9 @@ comptime {
@export(main, .{ .name = "main", .linkage = .Weak });
}
} else if (builtin.os == .windows) {
- if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) {
+ if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and
+ !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))
+ {
@export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" });
}
} else if (builtin.os == .uefi) {
@@ -34,7 +36,11 @@ comptime {
}
}
-fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, lpReserved: std.os.windows.LPVOID) callconv(.Stdcall) std.os.windows.BOOL {
+fn _DllMainCRTStartup(
+ hinstDLL: std.os.windows.HINSTANCE,
+ fdwReason: std.os.windows.DWORD,
+ lpReserved: std.os.windows.LPVOID,
+) callconv(.Stdcall) std.os.windows.BOOL {
if (@hasDecl(root, "DllMain")) {
return root.DllMain(hinstDLL, fdwReason, lpReserved);
}
diff --git a/lib/std/target.zig b/lib/std/target.zig
@@ -47,6 +47,16 @@ pub const Target = union(enum) {
emscripten,
uefi,
other,
+
+ pub fn parse(text: []const u8) !Os {
+ const info = @typeInfo(Os);
+ inline for (info.Enum.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ return @field(Os, field.name);
+ }
+ }
+ return error.UnknownOperatingSystem;
+ }
};
pub const aarch64 = @import("target/aarch64.zig");
@@ -65,463 +75,6 @@ pub const Target = union(enum) {
pub const wasm = @import("target/wasm.zig");
pub const x86 = @import("target/x86.zig");
- pub const Arch = union(enum) {
- arm: Arm32,
- armeb: Arm32,
- aarch64: Arm64,
- aarch64_be: Arm64,
- aarch64_32: Arm64,
- arc,
- avr,
- bpfel,
- bpfeb,
- hexagon,
- mips,
- mipsel,
- mips64,
- mips64el,
- msp430,
- powerpc,
- powerpc64,
- powerpc64le,
- r600,
- amdgcn,
- riscv32,
- riscv64,
- sparc,
- sparcv9,
- sparcel,
- s390x,
- tce,
- tcele,
- thumb: Arm32,
- thumbeb: Arm32,
- i386,
- x86_64,
- xcore,
- nvptx,
- nvptx64,
- le32,
- le64,
- amdil,
- amdil64,
- hsail,
- hsail64,
- spir,
- spir64,
- kalimba: Kalimba,
- shave,
- lanai,
- wasm32,
- wasm64,
- renderscript32,
- renderscript64,
- ve,
-
- pub const Arm32 = enum {
- v8_5a,
- v8_4a,
- v8_3a,
- v8_2a,
- v8_1a,
- v8a,
- v8r,
- v8m_baseline,
- v8m_mainline,
- v8_1m_mainline,
- v7a,
- v7em,
- v7m,
- v7s,
- v7k,
- v7ve,
- v6,
- v6m,
- v6k,
- v6t2,
- v5,
- v5te,
- v4t,
-
- pub fn version(version: Arm32) comptime_int {
- return switch (version) {
- .v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8a, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8,
- .v7a, .v7em, .v7m, .v7s, .v7k, .v7ve => 7,
- .v6, .v6m, .v6k, .v6t2 => 6,
- .v5, .v5te => 5,
- .v4t => 4,
- };
- }
- };
- pub const Arm64 = enum {
- v8_5a,
- v8_4a,
- v8_3a,
- v8_2a,
- v8_1a,
- v8a,
- };
- pub const Kalimba = enum {
- v5,
- v4,
- v3,
- };
- pub const Mips = enum {
- r6,
- };
- pub const PPC = enum {
- spe,
- };
-
- pub fn subArchName(arch: Arch) ?[]const u8 {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => |arm32| @tagName(arm32),
- .aarch64, .aarch64_be, .aarch64_32 => |arm64| @tagName(arm64),
- .kalimba => |kalimba| @tagName(kalimba),
- else => return null,
- };
- }
-
- pub fn subArchFeature(arch: Arch) ?Cpu.Feature.Set.Index {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => |arm32| switch (arm32) {
- .v8_5a => @enumToInt(arm.Feature.armv8_5_a),
- .v8_4a => @enumToInt(arm.Feature.armv8_4_a),
- .v8_3a => @enumToInt(arm.Feature.armv8_3_a),
- .v8_2a => @enumToInt(arm.Feature.armv8_2_a),
- .v8_1a => @enumToInt(arm.Feature.armv8_1_a),
- .v8a => @enumToInt(arm.Feature.armv8_a),
- .v8r => @enumToInt(arm.Feature.armv8_r),
- .v8m_baseline => @enumToInt(arm.Feature.armv8_m_base),
- .v8m_mainline => @enumToInt(arm.Feature.armv8_m_main),
- .v8_1m_mainline => @enumToInt(arm.Feature.armv8_1_m_main),
- .v7a => @enumToInt(arm.Feature.armv7_a),
- .v7em => @enumToInt(arm.Feature.armv7e_m),
- .v7m => @enumToInt(arm.Feature.armv7_m),
- .v7s => @enumToInt(arm.Feature.armv7s),
- .v7k => @enumToInt(arm.Feature.armv7k),
- .v7ve => @enumToInt(arm.Feature.armv7ve),
- .v6 => @enumToInt(arm.Feature.armv6),
- .v6m => @enumToInt(arm.Feature.armv6_m),
- .v6k => @enumToInt(arm.Feature.armv6k),
- .v6t2 => @enumToInt(arm.Feature.armv6t2),
- .v5 => @enumToInt(arm.Feature.armv5t),
- .v5te => @enumToInt(arm.Feature.armv5te),
- .v4t => @enumToInt(arm.Feature.armv4t),
- },
- .aarch64, .aarch64_be, .aarch64_32 => |arm64| switch (arm64) {
- .v8_5a => @enumToInt(aarch64.Feature.v8_5a),
- .v8_4a => @enumToInt(aarch64.Feature.v8_4a),
- .v8_3a => @enumToInt(aarch64.Feature.v8_3a),
- .v8_2a => @enumToInt(aarch64.Feature.v8_2a),
- .v8_1a => @enumToInt(aarch64.Feature.v8_1a),
- .v8a => @enumToInt(aarch64.Feature.v8a),
- },
- else => return null,
- };
- }
-
- pub fn isARM(arch: Arch) bool {
- return switch (arch) {
- .arm, .armeb => true,
- else => false,
- };
- }
-
- pub fn isThumb(arch: Arch) bool {
- return switch (arch) {
- .thumb, .thumbeb => true,
- else => false,
- };
- }
-
- pub fn isWasm(arch: Arch) bool {
- return switch (arch) {
- .wasm32, .wasm64 => true,
- else => false,
- };
- }
-
- pub fn isRISCV(arch: Arch) bool {
- return switch (arch) {
- .riscv32, .riscv64 => true,
- else => false,
- };
- }
-
- pub fn isMIPS(arch: Arch) bool {
- return switch (arch) {
- .mips, .mipsel, .mips64, .mips64el => true,
- else => false,
- };
- }
-
- pub fn parseCpu(arch: Arch, cpu_name: []const u8) !*const Cpu {
- for (arch.allCpus()) |cpu| {
- if (mem.eql(u8, cpu_name, cpu.name)) {
- return cpu;
- }
- }
- return error.UnknownCpu;
- }
-
- /// Comma-separated list of features, with + or - in front of each feature. This
- /// form represents a deviation from baseline CPU, which is provided as a parameter.
- /// Extra commas are ignored.
- pub fn parseCpuFeatureSet(arch: Arch, cpu: *const Cpu, features_text: []const u8) !Cpu.Feature.Set {
- const all_features = arch.allFeaturesList();
- var set = cpu.features;
- var it = mem.tokenize(features_text, ",");
- while (it.next()) |item_text| {
- var feature_name: []const u8 = undefined;
- var op: enum {
- add,
- sub,
- } = undefined;
- if (mem.startsWith(u8, item_text, "+")) {
- op = .add;
- feature_name = item_text[1..];
- } else if (mem.startsWith(u8, item_text, "-")) {
- op = .sub;
- feature_name = item_text[1..];
- } else {
- return error.InvalidCpuFeatures;
- }
- for (all_features) |feature, index_usize| {
- const index = @intCast(Cpu.Feature.Set.Index, index_usize);
- if (mem.eql(u8, feature_name, feature.name)) {
- switch (op) {
- .add => set.addFeature(index),
- .sub => set.removeFeature(index),
- }
- break;
- }
- } else {
- return error.UnknownCpuFeature;
- }
- }
- return set;
- }
-
- pub fn toElfMachine(arch: Arch) std.elf.EM {
- return switch (arch) {
- .avr => ._AVR,
- .msp430 => ._MSP430,
- .arc => ._ARC,
- .arm => ._ARM,
- .armeb => ._ARM,
- .hexagon => ._HEXAGON,
- .le32 => ._NONE,
- .mips => ._MIPS,
- .mipsel => ._MIPS_RS3_LE,
- .powerpc => ._PPC,
- .r600 => ._NONE,
- .riscv32 => ._RISCV,
- .sparc => ._SPARC,
- .sparcel => ._SPARC,
- .tce => ._NONE,
- .tcele => ._NONE,
- .thumb => ._ARM,
- .thumbeb => ._ARM,
- .i386 => ._386,
- .xcore => ._XCORE,
- .nvptx => ._NONE,
- .amdil => ._NONE,
- .hsail => ._NONE,
- .spir => ._NONE,
- .kalimba => ._CSR_KALIMBA,
- .shave => ._NONE,
- .lanai => ._LANAI,
- .wasm32 => ._NONE,
- .renderscript32 => ._NONE,
- .aarch64_32 => ._AARCH64,
- .aarch64 => ._AARCH64,
- .aarch64_be => ._AARCH64,
- .mips64 => ._MIPS,
- .mips64el => ._MIPS_RS3_LE,
- .powerpc64 => ._PPC64,
- .powerpc64le => ._PPC64,
- .riscv64 => ._RISCV,
- .x86_64 => ._X86_64,
- .nvptx64 => ._NONE,
- .le64 => ._NONE,
- .amdil64 => ._NONE,
- .hsail64 => ._NONE,
- .spir64 => ._NONE,
- .wasm64 => ._NONE,
- .renderscript64 => ._NONE,
- .amdgcn => ._NONE,
- .bpfel => ._BPF,
- .bpfeb => ._BPF,
- .sparcv9 => ._SPARCV9,
- .s390x => ._S390,
- .ve => ._NONE,
- };
- }
-
- pub fn endian(arch: Arch) builtin.Endian {
- return switch (arch) {
- .avr,
- .arm,
- .aarch64_32,
- .aarch64,
- .amdgcn,
- .amdil,
- .amdil64,
- .bpfel,
- .hexagon,
- .hsail,
- .hsail64,
- .kalimba,
- .le32,
- .le64,
- .mipsel,
- .mips64el,
- .msp430,
- .nvptx,
- .nvptx64,
- .sparcel,
- .tcele,
- .powerpc64le,
- .r600,
- .riscv32,
- .riscv64,
- .i386,
- .x86_64,
- .wasm32,
- .wasm64,
- .xcore,
- .thumb,
- .spir,
- .spir64,
- .renderscript32,
- .renderscript64,
- .shave,
- .ve,
- => .Little,
-
- .arc,
- .armeb,
- .aarch64_be,
- .bpfeb,
- .mips,
- .mips64,
- .powerpc,
- .powerpc64,
- .thumbeb,
- .sparc,
- .sparcv9,
- .tce,
- .lanai,
- .s390x,
- => .Big,
- };
- }
-
- /// Returns a name that matches the lib/std/target/* directory name.
- pub fn genericName(arch: Arch) []const u8 {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => "arm",
- .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
- .avr => "avr",
- .bpfel, .bpfeb => "bpf",
- .hexagon => "hexagon",
- .mips, .mipsel, .mips64, .mips64el => "mips",
- .msp430 => "msp430",
- .powerpc, .powerpc64, .powerpc64le => "powerpc",
- .amdgcn => "amdgpu",
- .riscv32, .riscv64 => "riscv",
- .sparc, .sparcv9, .sparcel => "sparc",
- .s390x => "systemz",
- .i386, .x86_64 => "x86",
- .nvptx, .nvptx64 => "nvptx",
- .wasm32, .wasm64 => "wasm",
- else => @tagName(arch),
- };
- }
-
- /// All CPU features Zig is aware of, sorted lexicographically by name.
- pub fn allFeaturesList(arch: Arch) []const Cpu.Feature {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => &arm.all_features,
- .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features,
- .avr => &avr.all_features,
- .bpfel, .bpfeb => &bpf.all_features,
- .hexagon => &hexagon.all_features,
- .mips, .mipsel, .mips64, .mips64el => &mips.all_features,
- .msp430 => &msp430.all_features,
- .powerpc, .powerpc64, .powerpc64le => &powerpc.all_features,
- .amdgcn => &amdgpu.all_features,
- .riscv32, .riscv64 => &riscv.all_features,
- .sparc, .sparcv9, .sparcel => &sparc.all_features,
- .s390x => &systemz.all_features,
- .i386, .x86_64 => &x86.all_features,
- .nvptx, .nvptx64 => &nvptx.all_features,
- .wasm32, .wasm64 => &wasm.all_features,
-
- else => &[0]Cpu.Feature{},
- };
- }
-
- /// The "default" set of CPU features for cross-compiling. A conservative set
- /// of features that is expected to be supported on most available hardware.
- pub fn getBaselineCpuFeatures(arch: Arch) CpuFeatures {
- const S = struct {
- const generic_cpu = Cpu{
- .name = "generic",
- .llvm_name = null,
- .features = Cpu.Feature.Set.empty,
- };
- };
- const cpu = switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic,
- .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
- .avr => &avr.cpu.avr1,
- .bpfel, .bpfeb => &bpf.cpu.generic,
- .hexagon => &hexagon.cpu.generic,
- .mips, .mipsel => &mips.cpu.mips32,
- .mips64, .mips64el => &mips.cpu.mips64,
- .msp430 => &msp430.cpu.generic,
- .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
- .amdgcn => &amdgpu.cpu.generic,
- .riscv32 => &riscv.cpu.baseline_rv32,
- .riscv64 => &riscv.cpu.baseline_rv64,
- .sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
- .s390x => &systemz.cpu.generic,
- .i386 => &x86.cpu.pentium4,
- .x86_64 => &x86.cpu.x86_64,
- .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
- .wasm32, .wasm64 => &wasm.cpu.generic,
-
- else => &S.generic_cpu,
- };
- return CpuFeatures.initFromCpu(arch, cpu);
- }
-
- /// All CPUs Zig is aware of, sorted lexicographically by name.
- pub fn allCpus(arch: Arch) []const *const Cpu {
- return switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => arm.all_cpus,
- .aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus,
- .avr => avr.all_cpus,
- .bpfel, .bpfeb => bpf.all_cpus,
- .hexagon => hexagon.all_cpus,
- .mips, .mipsel, .mips64, .mips64el => mips.all_cpus,
- .msp430 => msp430.all_cpus,
- .powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus,
- .amdgcn => amdgpu.all_cpus,
- .riscv32, .riscv64 => riscv.all_cpus,
- .sparc, .sparcv9, .sparcel => sparc.all_cpus,
- .s390x => systemz.all_cpus,
- .i386, .x86_64 => x86.all_cpus,
- .nvptx, .nvptx64 => nvptx.all_cpus,
- .wasm32, .wasm64 => wasm.all_cpus,
-
- else => &[0]*const Cpu{},
- };
- }
- };
-
pub const Abi = enum {
none,
gnu,
@@ -543,11 +96,102 @@ pub const Target = union(enum) {
coreclr,
simulator,
macabi,
+
+ pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
+ switch (arch) {
+ .wasm32, .wasm64 => return .musl,
+ else => {},
+ }
+ switch (target_os) {
+ .freestanding,
+ .ananas,
+ .cloudabi,
+ .dragonfly,
+ .lv2,
+ .solaris,
+ .haiku,
+ .minix,
+ .rtems,
+ .nacl,
+ .cnk,
+ .aix,
+ .cuda,
+ .nvcl,
+ .amdhsa,
+ .ps4,
+ .elfiamcu,
+ .mesa3d,
+ .contiki,
+ .amdpal,
+ .hermit,
+ .other,
+ => return .eabi,
+ .openbsd,
+ .macosx,
+ .freebsd,
+ .ios,
+ .tvos,
+ .watchos,
+ .fuchsia,
+ .kfreebsd,
+ .netbsd,
+ .hurd,
+ => return .gnu,
+ .windows,
+ .uefi,
+ => return .msvc,
+ .linux,
+ .wasi,
+ .emscripten,
+ => return .musl,
+ }
+ }
+
+ pub fn parse(text: []const u8) !Abi {
+ const info = @typeInfo(Abi);
+ inline for (info.Enum.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ return @field(Abi, field.name);
+ }
+ }
+ return error.UnknownApplicationBinaryInterface;
+ }
+ };
+
+ pub const ObjectFormat = enum {
+ unknown,
+ coff,
+ elf,
+ macho,
+ wasm,
+ };
+
+ pub const SubSystem = enum {
+ Console,
+ Windows,
+ Posix,
+ Native,
+ EfiApplication,
+ EfiBootServiceDriver,
+ EfiRom,
+ EfiRuntimeDriver,
+ };
+
+ pub const Cross = struct {
+ cpu: Cpu,
+ os: Os,
+ abi: Abi,
};
pub const Cpu = struct {
- name: []const u8,
- llvm_name: ?[:0]const u8,
+ /// Architecture
+ arch: Arch,
+
+ /// The CPU model to target. It has a set of features
+ /// which are overridden with the `features` field.
+ model: *const Model,
+
+ /// An explicit list of the entire CPU feature set. It may differ from the specific CPU model's features.
features: Feature.Set,
pub const Feature = struct {
@@ -573,10 +217,10 @@ pub const Target = union(enum) {
pub const Set = struct {
ints: [usize_count]usize,
- pub const needed_bit_count = 175;
+ pub const needed_bit_count = 155;
pub const byte_count = (needed_bit_count + 7) / 8;
pub const usize_count = (byte_count + (@sizeOf(usize) - 1)) / @sizeOf(usize);
- pub const Index = std.math.Log2Int(@IntType(false, usize_count * @bitSizeOf(usize)));
+ pub const Index = std.math.Log2Int(std.meta.IntType(false, usize_count * @bitSizeOf(usize)));
pub const ShiftInt = std.math.Log2Int(usize);
pub const empty = Set{ .ints = [1]usize{0} ** usize_count };
@@ -597,6 +241,12 @@ pub const Target = union(enum) {
set.ints[usize_index] |= @as(usize, 1) << bit_index;
}
+ /// Adds the specified feature set but not its dependencies.
+ pub fn addFeatureSet(set: *Set, other_set: Set) void {
+ set.ints = @as(@Vector(usize_count, usize), set.ints) |
+ @as(@Vector(usize_count, usize), other_set.ints);
+ }
+
/// Removes the specified feature but not its dependents.
pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
const usize_index = arch_feature_index / @bitSizeOf(usize);
@@ -612,8 +262,7 @@ pub const Target = union(enum) {
for (all_features_list) |feature, index_usize| {
const index = @intCast(Index, index_usize);
if (set.isEnabled(index)) {
- set.ints = @as(@Vector(usize_count, usize), set.ints) |
- @as(@Vector(usize_count, usize), feature.dependencies.ints);
+ set.addFeatureSet(feature.dependencies);
}
}
const nothing_changed = mem.eql(usize, &old, &set.ints);
@@ -648,77 +297,361 @@ pub const Target = union(enum) {
};
}
};
- };
- pub const ObjectFormat = enum {
- unknown,
- coff,
- elf,
- macho,
- wasm,
- };
+ pub const Arch = enum {
+ arm,
+ armeb,
+ aarch64,
+ aarch64_be,
+ aarch64_32,
+ arc,
+ avr,
+ bpfel,
+ bpfeb,
+ hexagon,
+ mips,
+ mipsel,
+ mips64,
+ mips64el,
+ msp430,
+ powerpc,
+ powerpc64,
+ powerpc64le,
+ r600,
+ amdgcn,
+ riscv32,
+ riscv64,
+ sparc,
+ sparcv9,
+ sparcel,
+ s390x,
+ tce,
+ tcele,
+ thumb,
+ thumbeb,
+ i386,
+ x86_64,
+ xcore,
+ nvptx,
+ nvptx64,
+ le32,
+ le64,
+ amdil,
+ amdil64,
+ hsail,
+ hsail64,
+ spir,
+ spir64,
+ kalimba,
+ shave,
+ lanai,
+ wasm32,
+ wasm64,
+ renderscript32,
+ renderscript64,
+ ve,
+
+ pub fn isARM(arch: Arch) bool {
+ return switch (arch) {
+ .arm, .armeb => true,
+ else => false,
+ };
+ }
- pub const SubSystem = enum {
- Console,
- Windows,
- Posix,
- Native,
- EfiApplication,
- EfiBootServiceDriver,
- EfiRom,
- EfiRuntimeDriver,
- };
+ pub fn isThumb(arch: Arch) bool {
+ return switch (arch) {
+ .thumb, .thumbeb => true,
+ else => false,
+ };
+ }
- pub const Cross = struct {
- arch: Arch,
- os: Os,
- abi: Abi,
- cpu_features: CpuFeatures,
- };
+ pub fn isWasm(arch: Arch) bool {
+ return switch (arch) {
+ .wasm32, .wasm64 => true,
+ else => false,
+ };
+ }
- pub const CpuFeatures = struct {
- /// The CPU to target. It has a set of features
- /// which are overridden with the `features` field.
- cpu: *const Cpu,
+ pub fn isRISCV(arch: Arch) bool {
+ return switch (arch) {
+ .riscv32, .riscv64 => true,
+ else => false,
+ };
+ }
- /// Explicitly provide the entire CPU feature set.
- features: Cpu.Feature.Set,
+ pub fn isMIPS(arch: Arch) bool {
+ return switch (arch) {
+ .mips, .mipsel, .mips64, .mips64el => true,
+ else => false,
+ };
+ }
- pub fn initFromCpu(arch: Arch, cpu: *const Cpu) CpuFeatures {
- var features = cpu.features;
- if (arch.subArchFeature()) |sub_arch_index| {
- features.addFeature(sub_arch_index);
+ pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
+ for (arch.allCpuModels()) |cpu| {
+ if (mem.eql(u8, cpu_name, cpu.name)) {
+ return cpu;
+ }
+ }
+ return error.UnknownCpu;
+ }
+
+ pub fn toElfMachine(arch: Arch) std.elf.EM {
+ return switch (arch) {
+ .avr => ._AVR,
+ .msp430 => ._MSP430,
+ .arc => ._ARC,
+ .arm => ._ARM,
+ .armeb => ._ARM,
+ .hexagon => ._HEXAGON,
+ .le32 => ._NONE,
+ .mips => ._MIPS,
+ .mipsel => ._MIPS_RS3_LE,
+ .powerpc => ._PPC,
+ .r600 => ._NONE,
+ .riscv32 => ._RISCV,
+ .sparc => ._SPARC,
+ .sparcel => ._SPARC,
+ .tce => ._NONE,
+ .tcele => ._NONE,
+ .thumb => ._ARM,
+ .thumbeb => ._ARM,
+ .i386 => ._386,
+ .xcore => ._XCORE,
+ .nvptx => ._NONE,
+ .amdil => ._NONE,
+ .hsail => ._NONE,
+ .spir => ._NONE,
+ .kalimba => ._CSR_KALIMBA,
+ .shave => ._NONE,
+ .lanai => ._LANAI,
+ .wasm32 => ._NONE,
+ .renderscript32 => ._NONE,
+ .aarch64_32 => ._AARCH64,
+ .aarch64 => ._AARCH64,
+ .aarch64_be => ._AARCH64,
+ .mips64 => ._MIPS,
+ .mips64el => ._MIPS_RS3_LE,
+ .powerpc64 => ._PPC64,
+ .powerpc64le => ._PPC64,
+ .riscv64 => ._RISCV,
+ .x86_64 => ._X86_64,
+ .nvptx64 => ._NONE,
+ .le64 => ._NONE,
+ .amdil64 => ._NONE,
+ .hsail64 => ._NONE,
+ .spir64 => ._NONE,
+ .wasm64 => ._NONE,
+ .renderscript64 => ._NONE,
+ .amdgcn => ._NONE,
+ .bpfel => ._BPF,
+ .bpfeb => ._BPF,
+ .sparcv9 => ._SPARCV9,
+ .s390x => ._S390,
+ };
+ }
+
+ pub fn endian(arch: Arch) builtin.Endian {
+ return switch (arch) {
+ .avr,
+ .arm,
+ .aarch64_32,
+ .aarch64,
+ .amdgcn,
+ .amdil,
+ .amdil64,
+ .bpfel,
+ .hexagon,
+ .hsail,
+ .hsail64,
+ .kalimba,
+ .le32,
+ .le64,
+ .mipsel,
+ .mips64el,
+ .msp430,
+ .nvptx,
+ .nvptx64,
+ .sparcel,
+ .tcele,
+ .powerpc64le,
+ .r600,
+ .riscv32,
+ .riscv64,
+ .i386,
+ .x86_64,
+ .wasm32,
+ .wasm64,
+ .xcore,
+ .thumb,
+ .spir,
+ .spir64,
+ .renderscript32,
+ .renderscript64,
+ .shave,
+ => .Little,
+
+ .arc,
+ .armeb,
+ .aarch64_be,
+ .bpfeb,
+ .mips,
+ .mips64,
+ .powerpc,
+ .powerpc64,
+ .thumbeb,
+ .sparc,
+ .sparcv9,
+ .tce,
+ .lanai,
+ .s390x,
+ => .Big,
+ };
+ }
+
+ /// Returns a name that matches the lib/std/target/* directory name.
+ pub fn genericName(arch: Arch) []const u8 {
+ return switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => "arm",
+ .aarch64, .aarch64_be, .aarch64_32 => "aarch64",
+ .avr => "avr",
+ .bpfel, .bpfeb => "bpf",
+ .hexagon => "hexagon",
+ .mips, .mipsel, .mips64, .mips64el => "mips",
+ .msp430 => "msp430",
+ .powerpc, .powerpc64, .powerpc64le => "powerpc",
+ .amdgcn => "amdgpu",
+ .riscv32, .riscv64 => "riscv",
+ .sparc, .sparcv9, .sparcel => "sparc",
+ .s390x => "systemz",
+ .i386, .x86_64 => "x86",
+ .nvptx, .nvptx64 => "nvptx",
+ .wasm32, .wasm64 => "wasm",
+ else => @tagName(arch),
+ };
}
- features.populateDependencies(arch.allFeaturesList());
- return CpuFeatures{
- .cpu = cpu,
- .features = features,
+
+ /// All CPU features Zig is aware of, sorted lexicographically by name.
+ pub fn allFeaturesList(arch: Arch) []const Cpu.Feature {
+ return switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => &arm.all_features,
+ .aarch64, .aarch64_be, .aarch64_32 => &aarch64.all_features,
+ .avr => &avr.all_features,
+ .bpfel, .bpfeb => &bpf.all_features,
+ .hexagon => &hexagon.all_features,
+ .mips, .mipsel, .mips64, .mips64el => &mips.all_features,
+ .msp430 => &msp430.all_features,
+ .powerpc, .powerpc64, .powerpc64le => &powerpc.all_features,
+ .amdgcn => &amdgpu.all_features,
+ .riscv32, .riscv64 => &riscv.all_features,
+ .sparc, .sparcv9, .sparcel => &sparc.all_features,
+ .s390x => &systemz.all_features,
+ .i386, .x86_64 => &x86.all_features,
+ .nvptx, .nvptx64 => &nvptx.all_features,
+ .wasm32, .wasm64 => &wasm.all_features,
+
+ else => &[0]Cpu.Feature{},
+ };
+ }
+
+ /// All processors Zig is aware of, sorted lexicographically by name.
+ pub fn allCpuModels(arch: Arch) []const *const Cpu.Model {
+ return switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => arm.all_cpus,
+ .aarch64, .aarch64_be, .aarch64_32 => aarch64.all_cpus,
+ .avr => avr.all_cpus,
+ .bpfel, .bpfeb => bpf.all_cpus,
+ .hexagon => hexagon.all_cpus,
+ .mips, .mipsel, .mips64, .mips64el => mips.all_cpus,
+ .msp430 => msp430.all_cpus,
+ .powerpc, .powerpc64, .powerpc64le => powerpc.all_cpus,
+ .amdgcn => amdgpu.all_cpus,
+ .riscv32, .riscv64 => riscv.all_cpus,
+ .sparc, .sparcv9, .sparcel => sparc.all_cpus,
+ .s390x => systemz.all_cpus,
+ .i386, .x86_64 => x86.all_cpus,
+ .nvptx, .nvptx64 => nvptx.all_cpus,
+ .wasm32, .wasm64 => wasm.all_cpus,
+
+ else => &[0]*const Model{},
+ };
+ }
+
+ pub fn parse(text: []const u8) !Arch {
+ const info = @typeInfo(Arch);
+ inline for (info.Enum.fields) |field| {
+ if (mem.eql(u8, text, field.name)) {
+ return @as(Arch, @field(Arch, field.name));
+ }
+ }
+ return error.UnknownArchitecture;
+ }
+ };
+
+ pub const Model = struct {
+ name: []const u8,
+ llvm_name: ?[:0]const u8,
+ features: Feature.Set,
+
+ pub fn toCpu(model: *const Model, arch: Arch) Cpu {
+ var features = model.features;
+ features.populateDependencies(arch.allFeaturesList());
+ return .{
+ .arch = arch,
+ .model = model,
+ .features = features,
+ };
+ }
+ };
+
+ /// The "default" set of CPU features for cross-compiling. A conservative set
+ /// of features that is expected to be supported on most available hardware.
+ pub fn baseline(arch: Arch) Cpu {
+ const S = struct {
+ const generic_model = Model{
+ .name = "generic",
+ .llvm_name = null,
+ .features = Cpu.Feature.Set.empty,
+ };
};
+ const model = switch (arch) {
+ .arm, .armeb, .thumb, .thumbeb => &arm.cpu.baseline,
+ .aarch64, .aarch64_be, .aarch64_32 => &aarch64.cpu.generic,
+ .avr => &avr.cpu.avr1,
+ .bpfel, .bpfeb => &bpf.cpu.generic,
+ .hexagon => &hexagon.cpu.generic,
+ .mips, .mipsel => &mips.cpu.mips32,
+ .mips64, .mips64el => &mips.cpu.mips64,
+ .msp430 => &msp430.cpu.generic,
+ .powerpc, .powerpc64, .powerpc64le => &powerpc.cpu.generic,
+ .amdgcn => &amdgpu.cpu.generic,
+ .riscv32 => &riscv.cpu.baseline_rv32,
+ .riscv64 => &riscv.cpu.baseline_rv64,
+ .sparc, .sparcv9, .sparcel => &sparc.cpu.generic,
+ .s390x => &systemz.cpu.generic,
+ .i386 => &x86.cpu.pentium4,
+ .x86_64 => &x86.cpu.x86_64,
+ .nvptx, .nvptx64 => &nvptx.cpu.sm_20,
+ .wasm32, .wasm64 => &wasm.cpu.generic,
+
+ else => &S.generic_model,
+ };
+ return model.toCpu(arch);
}
};
pub const current = Target{
.Cross = Cross{
- .arch = builtin.arch,
+ .cpu = builtin.cpu,
.os = builtin.os,
.abi = builtin.abi,
- .cpu_features = builtin.cpu_features,
},
};
pub const stack_align = 16;
- pub fn getCpuFeatures(self: Target) CpuFeatures {
- return switch (self) {
- .Native => builtin.cpu_features,
- .Cross => |cross| cross.cpu_features,
- };
- }
-
pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
- return std.fmt.allocPrint(allocator, "{}{}-{}-{}", .{
+ return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
@tagName(self.getArch()),
- Target.archSubArchName(self.getArch()),
@tagName(self.getOs()),
@tagName(self.getAbi()),
});
@@ -780,139 +713,115 @@ pub const Target = union(enum) {
});
}
- /// TODO: Support CPU features here?
- /// https://github.com/ziglang/zig/issues/4261
- pub fn parse(text: []const u8) !Target {
- var it = mem.separate(text, "-");
- const arch_name = it.next() orelse return error.MissingArchitecture;
- const os_name = it.next() orelse return error.MissingOperatingSystem;
- const abi_name = it.next();
- const arch = try parseArchSub(arch_name);
+ pub const ParseOptions = struct {
+ /// This is sometimes called a "triple". It looks roughly like this:
+ /// riscv64-linux-gnu
+ /// The fields are, respectively:
+ /// * CPU Architecture
+ /// * Operating System
+ /// * C ABI (optional)
+ arch_os_abi: []const u8,
- var cross = Cross{
- .arch = arch,
- .cpu_features = arch.getBaselineCpuFeatures(),
- .os = try parseOs(os_name),
- .abi = undefined,
- };
- cross.abi = if (abi_name) |n| try parseAbi(n) else defaultAbi(cross.arch, cross.os);
- return Target{ .Cross = cross };
- }
+ /// Looks like "name+a+b-c-d+e", where "name" is a CPU Model name, "a", "b", and "e"
+ /// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features
+ /// to remove from the set.
+ cpu_features: []const u8 = "baseline",
- pub fn defaultAbi(arch: Arch, target_os: Os) Abi {
- switch (arch) {
- .wasm32, .wasm64 => return .musl,
- else => {},
- }
- switch (target_os) {
- .freestanding,
- .ananas,
- .cloudabi,
- .dragonfly,
- .lv2,
- .solaris,
- .haiku,
- .minix,
- .rtems,
- .nacl,
- .cnk,
- .aix,
- .cuda,
- .nvcl,
- .amdhsa,
- .ps4,
- .elfiamcu,
- .mesa3d,
- .contiki,
- .amdpal,
- .hermit,
- .other,
- => return .eabi,
- .openbsd,
- .macosx,
- .freebsd,
- .ios,
- .tvos,
- .watchos,
- .fuchsia,
- .kfreebsd,
- .netbsd,
- .hurd,
- => return .gnu,
- .windows,
- .uefi,
- => return .msvc,
- .linux,
- .wasi,
- .emscripten,
- => return .musl,
- }
- }
+ /// If this is provided, the function will populate some information about parsing failures,
+ /// so that user-friendly error messages can be delivered.
+ diagnostics: ?*Diagnostics = null,
- pub const ParseArchSubError = error{
- UnknownArchitecture,
- UnknownSubArchitecture,
- };
+ pub const Diagnostics = struct {
+ /// If the architecture was determined, this will be populated.
+ arch: ?Cpu.Arch = null,
- pub fn parseArchSub(text: []const u8) ParseArchSubError!Arch {
- const info = @typeInfo(Arch);
- inline for (info.Union.fields) |field| {
- if (mem.startsWith(u8, text, field.name)) {
- if (field.field_type == void) {
- return @as(Arch, @field(Arch, field.name));
- } else {
- const sub_info = @typeInfo(field.field_type);
- inline for (sub_info.Enum.fields) |sub_field| {
- const combined = field.name ++ sub_field.name;
- if (mem.eql(u8, text, combined)) {
- return @unionInit(Arch, field.name, @field(field.field_type, sub_field.name));
- }
- }
- return error.UnknownSubArchitecture;
- }
- }
- }
- return error.UnknownArchitecture;
- }
+ /// If the OS was determined, this will be populated.
+ os: ?Os = null,
- pub fn parseOs(text: []const u8) !Os {
- const info = @typeInfo(Os);
- inline for (info.Enum.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- return @field(Os, field.name);
- }
- }
- return error.UnknownOperatingSystem;
- }
+ /// If the ABI was determined, this will be populated.
+ abi: ?Abi = null,
- pub fn parseAbi(text: []const u8) !Abi {
- const info = @typeInfo(Abi);
- inline for (info.Enum.fields) |field| {
- if (mem.eql(u8, text, field.name)) {
- return @field(Abi, field.name);
- }
- }
- return error.UnknownApplicationBinaryInterface;
- }
+ /// If the CPU name was determined, this will be populated.
+ cpu_name: ?[]const u8 = null,
- fn archSubArchName(arch: Arch) []const u8 {
- return switch (arch) {
- .arm => |sub| @tagName(sub),
- .armeb => |sub| @tagName(sub),
- .thumb => |sub| @tagName(sub),
- .thumbeb => |sub| @tagName(sub),
- .aarch64 => |sub| @tagName(sub),
- .aarch64_be => |sub| @tagName(sub),
- .kalimba => |sub| @tagName(sub),
- else => "",
+ /// If error.UnknownCpuFeature is returned, this will be populated.
+ unknown_feature_name: ?[]const u8 = null,
};
- }
+ };
- pub fn subArchName(self: Target) []const u8 {
- switch (self) {
- .Native => return archSubArchName(builtin.arch),
- .Cross => |cross| return archSubArchName(cross.arch),
+ pub fn parse(args: ParseOptions) !Target {
+ var dummy_diags: ParseOptions.Diagnostics = undefined;
+ var diags = args.diagnostics orelse &dummy_diags;
+
+ var it = mem.separate(args.arch_os_abi, "-");
+ const arch_name = it.next() orelse return error.MissingArchitecture;
+ const arch = try Cpu.Arch.parse(arch_name);
+ diags.arch = arch;
+
+ const os_name = it.next() orelse return error.MissingOperatingSystem;
+ const os = try Os.parse(os_name);
+ diags.os = os;
+
+ const abi_name = it.next();
+ const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os);
+ diags.abi = abi;
+
+ if (it.next() != null) return error.UnexpectedExtraField;
+
+ const all_features = arch.allFeaturesList();
+ var index: usize = 0;
+ while (index < args.cpu_features.len and
+ args.cpu_features[index] != '+' and
+ args.cpu_features[index] != '-')
+ {
+ index += 1;
}
+ const cpu_name = args.cpu_features[0..index];
+ diags.cpu_name = cpu_name;
+
+ const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: {
+ const cpu_model = try arch.parseCpuModel(cpu_name);
+
+ var set = cpu_model.features;
+ while (index < args.cpu_features.len) {
+ const op = args.cpu_features[index];
+ index += 1;
+ const start = index;
+ while (index < args.cpu_features.len and
+ args.cpu_features[index] != '+' and
+ args.cpu_features[index] != '-')
+ {
+ index += 1;
+ }
+ const feature_name = args.cpu_features[start..index];
+ for (all_features) |feature, feat_index_usize| {
+ const feat_index = @intCast(Cpu.Feature.Set.Index, feat_index_usize);
+ if (mem.eql(u8, feature_name, feature.name)) {
+ switch (op) {
+ '+' => set.addFeature(feat_index),
+ '-' => set.removeFeature(feat_index),
+ else => unreachable,
+ }
+ break;
+ }
+ } else {
+ diags.unknown_feature_name = feature_name;
+ return error.UnknownCpuFeature;
+ }
+ }
+ set.populateDependencies(all_features);
+ break :blk .{
+ .arch = arch,
+ .model = cpu_model,
+ .features = set,
+ };
+ };
+ var cross = Cross{
+ .cpu = cpu,
+ .os = os,
+ .abi = abi,
+ };
+ return Target{ .Cross = cross };
}
pub fn oFileExt(self: Target) []const u8 {
@@ -971,11 +880,15 @@ pub const Target = union(enum) {
};
}
- pub fn getArch(self: Target) Arch {
- switch (self) {
- .Native => return builtin.arch,
- .Cross => |t| return t.arch,
- }
+ pub fn getCpu(self: Target) Cpu {
+ return switch (self) {
+ .Native => builtin.cpu,
+ .Cross => |cross| cross.cpu,
+ };
+ }
+
+ pub fn getArch(self: Target) Cpu.Arch {
+ return self.getCpu().arch;
}
pub fn getAbi(self: Target) Abi {
@@ -1041,6 +954,20 @@ pub const Target = union(enum) {
};
}
+ pub fn isAndroid(self: Target) bool {
+ return switch (self.getAbi()) {
+ .android => true,
+ else => false,
+ };
+ }
+
+ pub fn isDragonFlyBSD(self: Target) bool {
+ return switch (self.getOs()) {
+ .dragonfly => true,
+ else => false,
+ };
+ }
+
pub fn isUefi(self: Target) bool {
return switch (self.getOs()) {
.uefi => true,
@@ -1194,16 +1121,202 @@ pub const Target = union(enum) {
return .unavailable;
}
+
+ pub const FloatAbi = enum {
+ hard,
+ soft,
+ soft_fp,
+ };
+
+ pub fn getFloatAbi(self: Target) FloatAbi {
+ return switch (self.getAbi()) {
+ .gnueabihf,
+ .eabihf,
+ .musleabihf,
+ => .hard,
+ else => .soft,
+ };
+ }
+
+ pub fn hasDynamicLinker(self: Target) bool {
+ switch (self.getArch()) {
+ .wasm32,
+ .wasm64,
+ => return false,
+ else => {},
+ }
+ switch (self.getOs()) {
+ .freestanding,
+ .ios,
+ .tvos,
+ .watchos,
+ .macosx,
+ .uefi,
+ .windows,
+ .emscripten,
+ .other,
+ => return false,
+ else => return true,
+ }
+ }
+
+ /// Caller owns returned memory.
+ pub fn getStandardDynamicLinkerPath(
+ self: Target,
+ allocator: *mem.Allocator,
+ ) error{
+ OutOfMemory,
+ UnknownDynamicLinkerPath,
+ TargetHasNoDynamicLinker,
+ }![:0]u8 {
+ const a = allocator;
+ if (self.isAndroid()) {
+ return mem.dupeZ(a, u8, if (self.getArchPtrBitWidth() == 64)
+ "/system/bin/linker64"
+ else
+ "/system/bin/linker");
+ }
+
+ if (self.isMusl()) {
+ var result = try std.Buffer.init(allocator, "/lib/ld-musl-");
+ defer result.deinit();
+
+ var is_arm = false;
+ switch (self.getArch()) {
+ .arm, .thumb => {
+ try result.append("arm");
+ is_arm = true;
+ },
+ .armeb, .thumbeb => {
+ try result.append("armeb");
+ is_arm = true;
+ },
+ else => |arch| try result.append(@tagName(arch)),
+ }
+ if (is_arm and self.getFloatAbi() == .hard) {
+ try result.append("hf");
+ }
+ try result.append(".so.1");
+ return result.toOwnedSlice();
+ }
+
+ switch (self.getOs()) {
+ .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"),
+ .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"),
+ .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"),
+ .linux => switch (self.getArch()) {
+ .i386,
+ .sparc,
+ .sparcel,
+ => return mem.dupeZ(a, u8, "/lib/ld-linux.so.2"),
+
+ .aarch64 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64.so.1"),
+ .aarch64_be => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_be.so.1"),
+ .aarch64_32 => return mem.dupeZ(a, u8, "/lib/ld-linux-aarch64_32.so.1"),
+
+ .arm,
+ .armeb,
+ .thumb,
+ .thumbeb,
+ => return mem.dupeZ(a, u8, switch (self.getFloatAbi()) {
+ .hard => "/lib/ld-linux-armhf.so.3",
+ else => "/lib/ld-linux.so.3",
+ }),
+
+ .mips,
+ .mipsel,
+ .mips64,
+ .mips64el,
+ => return error.UnknownDynamicLinkerPath,
+
+ .powerpc => return mem.dupeZ(a, u8, "/lib/ld.so.1"),
+ .powerpc64, .powerpc64le => return mem.dupeZ(a, u8, "/lib64/ld64.so.2"),
+ .s390x => return mem.dupeZ(a, u8, "/lib64/ld64.so.1"),
+ .sparcv9 => return mem.dupeZ(a, u8, "/lib64/ld-linux.so.2"),
+ .x86_64 => return mem.dupeZ(a, u8, switch (self.getAbi()) {
+ .gnux32 => "/libx32/ld-linux-x32.so.2",
+ else => "/lib64/ld-linux-x86-64.so.2",
+ }),
+
+ .riscv32 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv32-ilp32.so.1"),
+ .riscv64 => return mem.dupeZ(a, u8, "/lib/ld-linux-riscv64-lp64.so.1"),
+
+ .wasm32,
+ .wasm64,
+ => return error.TargetHasNoDynamicLinker,
+
+ .arc,
+ .avr,
+ .bpfel,
+ .bpfeb,
+ .hexagon,
+ .msp430,
+ .r600,
+ .amdgcn,
+ .tce,
+ .tcele,
+ .xcore,
+ .nvptx,
+ .nvptx64,
+ .le32,
+ .le64,
+ .amdil,
+ .amdil64,
+ .hsail,
+ .hsail64,
+ .spir,
+ .spir64,
+ .kalimba,
+ .shave,
+ .lanai,
+ .renderscript32,
+ .renderscript64,
+ .ve,
+ => return error.UnknownDynamicLinkerPath,
+ },
+
+ .freestanding,
+ .ios,
+ .tvos,
+ .watchos,
+ .macosx,
+ .uefi,
+ .windows,
+ .emscripten,
+ .other,
+ => return error.TargetHasNoDynamicLinker,
+
+ else => return error.UnknownDynamicLinkerPath,
+ }
+ }
};
-test "parseCpuFeatureSet" {
- const arch: Target.Arch = .x86_64;
- const baseline = arch.getBaselineCpuFeatures();
- const set = try arch.parseCpuFeatureSet(baseline.cpu, "-sse,-avx,-cx8");
- std.testing.expect(!Target.x86.featureSetHas(set, .sse));
- std.testing.expect(!Target.x86.featureSetHas(set, .avx));
- std.testing.expect(!Target.x86.featureSetHas(set, .cx8));
- // These are expected because they are part of the baseline
- std.testing.expect(Target.x86.featureSetHas(set, .cmov));
- std.testing.expect(Target.x86.featureSetHas(set, .fxsr));
+test "Target.parse" {
+ {
+ const target = (try Target.parse(.{
+ .arch_os_abi = "x86_64-linux-gnu",
+ .cpu_features = "x86_64-sse-sse2-avx-cx8",
+ })).Cross;
+
+ std.testing.expect(target.os == .linux);
+ std.testing.expect(target.abi == .gnu);
+ std.testing.expect(target.cpu.arch == .x86_64);
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .avx));
+ std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .cx8));
+ std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .cmov));
+ std.testing.expect(Target.x86.featureSetHas(target.cpu.features, .fxsr));
+ }
+ {
+ const target = (try Target.parse(.{
+ .arch_os_abi = "arm-linux-musleabihf",
+ .cpu_features = "generic+v8a",
+ })).Cross;
+
+ std.testing.expect(target.os == .linux);
+ std.testing.expect(target.abi == .musleabihf);
+ std.testing.expect(target.cpu.arch == .arm);
+ std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
+ std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));
+ }
}
diff --git a/lib/std/target/aarch64.zig b/lib/std/target/aarch64.zig
@@ -1,15 +1,9 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
- a35,
- a53,
- a55,
- a57,
a65,
- a72,
- a73,
- a75,
a76,
aes,
aggressive_fma,
@@ -46,11 +40,7 @@ pub const Feature = enum {
dotprod,
ete,
exynos_cheap_as_move,
- exynosm1,
- exynosm2,
- exynosm3,
exynosm4,
- falkor,
fmi,
force_32bit_jump_tables,
fp_armv8,
@@ -64,7 +54,6 @@ pub const Feature = enum {
fuse_csel,
fuse_literals,
jsconv,
- kryo,
lor,
lse,
lsl_fast,
@@ -112,7 +101,6 @@ pub const Feature = enum {
reserve_x6,
reserve_x7,
reserve_x9,
- saphira,
sb,
sel2,
sha2,
@@ -132,11 +120,6 @@ pub const Feature = enum {
sve2_sha3,
sve2_sm4,
tagged_globals,
- thunderx,
- thunderx2t99,
- thunderxt81,
- thunderxt83,
- thunderxt88,
tlb_rmi,
tme,
tpidr_el1,
@@ -144,7 +127,6 @@ pub const Feature = enum {
tpidr_el3,
tracev8_4,
trbe,
- tsv110,
uaops,
use_aa,
use_postra_scheduler,
@@ -163,72 +145,13 @@ pub const Feature = enum {
zcz_gp,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
@setEvalBranchQuota(2000);
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
- result[@enumToInt(Feature.a35)] = .{
- .llvm_name = "a35",
- .description = "Cortex-A35 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .neon,
- .perfmon,
- }),
- };
- result[@enumToInt(Feature.a53)] = .{
- .llvm_name = "a53",
- .description = "Cortex-A53 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .balance_fp_ops,
- .crc,
- .crypto,
- .custom_cheap_as_move,
- .fp_armv8,
- .fuse_aes,
- .neon,
- .perfmon,
- .use_aa,
- .use_postra_scheduler,
- }),
- };
- result[@enumToInt(Feature.a55)] = .{
- .llvm_name = "a55",
- .description = "Cortex-A55 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .crypto,
- .dotprod,
- .fp_armv8,
- .fullfp16,
- .fuse_aes,
- .neon,
- .perfmon,
- .rcpc,
- .v8_2a,
- }),
- };
- result[@enumToInt(Feature.a57)] = .{
- .llvm_name = "a57",
- .description = "Cortex-A57 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .balance_fp_ops,
- .crc,
- .crypto,
- .custom_cheap_as_move,
- .fp_armv8,
- .fuse_aes,
- .fuse_literals,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- }),
- };
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.a65)] = .{
.llvm_name = "a65",
.description = "Cortex-A65 ARM processors",
@@ -244,54 +167,13 @@ pub const all_features = blk: {
.v8_2a,
}),
};
- result[@enumToInt(Feature.a72)] = .{
- .llvm_name = "a72",
- .description = "Cortex-A72 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .fuse_aes,
- .neon,
- .perfmon,
- }),
- };
- result[@enumToInt(Feature.a73)] = .{
- .llvm_name = "a73",
- .description = "Cortex-A73 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .fuse_aes,
- .neon,
- .perfmon,
- }),
- };
- result[@enumToInt(Feature.a75)] = .{
- .llvm_name = "a75",
- .description = "Cortex-A75 ARM processors",
- .dependencies = featureSet(&[_]Feature{
- .crypto,
- .dotprod,
- .fp_armv8,
- .fullfp16,
- .fuse_aes,
- .neon,
- .perfmon,
- .rcpc,
- .v8_2a,
- }),
- };
result[@enumToInt(Feature.a76)] = .{
.llvm_name = "a76",
.description = "Cortex-A76 ARM processors",
.dependencies = featureSet(&[_]Feature{
.crypto,
.dotprod,
- .fp_armv8,
.fullfp16,
- .neon,
.rcpc,
.ssbs,
.v8_2a,
@@ -563,58 +445,6 @@ pub const all_features = blk: {
.custom_cheap_as_move,
}),
};
- result[@enumToInt(Feature.exynosm1)] = .{
- .llvm_name = null,
- .description = "Samsung Exynos-M1 processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .exynos_cheap_as_move,
- .force_32bit_jump_tables,
- .fuse_aes,
- .perfmon,
- .slow_misaligned_128store,
- .slow_paired_128,
- .use_postra_scheduler,
- .use_reciprocal_square_root,
- .zcz_fp,
- }),
- };
- result[@enumToInt(Feature.exynosm2)] = .{
- .llvm_name = null,
- .description = "Samsung Exynos-M2 processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .exynos_cheap_as_move,
- .force_32bit_jump_tables,
- .fuse_aes,
- .perfmon,
- .slow_misaligned_128store,
- .slow_paired_128,
- .use_postra_scheduler,
- .zcz_fp,
- }),
- };
- result[@enumToInt(Feature.exynosm3)] = .{
- .llvm_name = "exynosm3",
- .description = "Samsung Exynos-M3 processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .exynos_cheap_as_move,
- .force_32bit_jump_tables,
- .fuse_address,
- .fuse_aes,
- .fuse_csel,
- .fuse_literals,
- .lsl_fast,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- .zcz_fp,
- }),
- };
result[@enumToInt(Feature.exynosm4)] = .{
.llvm_name = "exynosm4",
.description = "Samsung Exynos-M4 processors",
@@ -638,24 +468,6 @@ pub const all_features = blk: {
.zcz,
}),
};
- result[@enumToInt(Feature.falkor)] = .{
- .llvm_name = "falkor",
- .description = "Qualcomm Falkor processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .custom_cheap_as_move,
- .fp_armv8,
- .lsl_fast,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .rdm,
- .slow_strqro_store,
- .use_postra_scheduler,
- .zcz,
- }),
- };
result[@enumToInt(Feature.fmi)] = .{
.llvm_name = "fmi",
.description = "Enable v8.4-A Flag Manipulation Instructions",
@@ -727,22 +539,6 @@ pub const all_features = blk: {
.fp_armv8,
}),
};
- result[@enumToInt(Feature.kryo)] = .{
- .llvm_name = "kryo",
- .description = "Qualcomm Kryo processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .custom_cheap_as_move,
- .fp_armv8,
- .lsl_fast,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- .zcz,
- }),
- };
result[@enumToInt(Feature.lor)] = .{
.llvm_name = "lor",
.description = "Enables ARM v8.1 Limited Ordering Regions extension",
@@ -1005,23 +801,6 @@ pub const all_features = blk: {
.description = "Reserve X9, making it unavailable as a GPR",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.saphira)] = .{
- .llvm_name = "saphira",
- .description = "Qualcomm Saphira processors",
- .dependencies = featureSet(&[_]Feature{
- .crypto,
- .custom_cheap_as_move,
- .fp_armv8,
- .lsl_fast,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .spe,
- .use_postra_scheduler,
- .v8_4a,
- .zcz,
- }),
- };
result[@enumToInt(Feature.sb)] = .{
.llvm_name = "sb",
.description = "Enable v8.5 Speculation Barrier",
@@ -1137,74 +916,6 @@ pub const all_features = blk: {
.description = "Use an instruction sequence for taking the address of a global that allows a memory tag in the upper address bits",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.thunderx)] = .{
- .llvm_name = "thunderx",
- .description = "Cavium ThunderX processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- }),
- };
- result[@enumToInt(Feature.thunderx2t99)] = .{
- .llvm_name = "thunderx2t99",
- .description = "Cavium ThunderX2 processors",
- .dependencies = featureSet(&[_]Feature{
- .aggressive_fma,
- .arith_bcc_fusion,
- .crc,
- .crypto,
- .fp_armv8,
- .lse,
- .neon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- .v8_1a,
- }),
- };
- result[@enumToInt(Feature.thunderxt81)] = .{
- .llvm_name = "thunderxt81",
- .description = "Cavium ThunderX processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- }),
- };
- result[@enumToInt(Feature.thunderxt83)] = .{
- .llvm_name = "thunderxt83",
- .description = "Cavium ThunderX processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- }),
- };
- result[@enumToInt(Feature.thunderxt88)] = .{
- .llvm_name = "thunderxt88",
- .description = "Cavium ThunderX processors",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .crypto,
- .fp_armv8,
- .neon,
- .perfmon,
- .predictable_select_expensive,
- .use_postra_scheduler,
- }),
- };
result[@enumToInt(Feature.tlb_rmi)] = .{
.llvm_name = "tlb-rmi",
.description = "Enable v8.4-A TLB Range and Maintenance Instructions",
@@ -1240,24 +951,6 @@ pub const all_features = blk: {
.description = "Enable Trace Buffer Extension",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.tsv110)] = .{
- .llvm_name = "tsv110",
- .description = "HiSilicon TS-V110 processors",
- .dependencies = featureSet(&[_]Feature{
- .crypto,
- .custom_cheap_as_move,
- .dotprod,
- .fp_armv8,
- .fp16fml,
- .fullfp16,
- .fuse_aes,
- .neon,
- .perfmon,
- .spe,
- .use_postra_scheduler,
- .v8_2a,
- }),
- };
result[@enumToInt(Feature.uaops)] = .{
.llvm_name = "uaops",
.description = "Enable v8.2 UAO PState",
@@ -1398,282 +1091,417 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const apple_a10 = Cpu{
+ pub const apple_a10 = CpuModel{
.name = "apple_a10",
.llvm_name = "apple-a10",
.features = featureSet(&[_]Feature{
.apple_a10,
}),
};
- pub const apple_a11 = Cpu{
+ pub const apple_a11 = CpuModel{
.name = "apple_a11",
.llvm_name = "apple-a11",
.features = featureSet(&[_]Feature{
.apple_a11,
}),
};
- pub const apple_a12 = Cpu{
+ pub const apple_a12 = CpuModel{
.name = "apple_a12",
.llvm_name = "apple-a12",
.features = featureSet(&[_]Feature{
.apple_a12,
}),
};
- pub const apple_a13 = Cpu{
+ pub const apple_a13 = CpuModel{
.name = "apple_a13",
.llvm_name = "apple-a13",
.features = featureSet(&[_]Feature{
.apple_a13,
}),
};
- pub const apple_a7 = Cpu{
+ pub const apple_a7 = CpuModel{
.name = "apple_a7",
.llvm_name = "apple-a7",
.features = featureSet(&[_]Feature{
.apple_a7,
}),
};
- pub const apple_a8 = Cpu{
+ pub const apple_a8 = CpuModel{
.name = "apple_a8",
.llvm_name = "apple-a8",
.features = featureSet(&[_]Feature{
.apple_a7,
}),
};
- pub const apple_a9 = Cpu{
+ pub const apple_a9 = CpuModel{
.name = "apple_a9",
.llvm_name = "apple-a9",
.features = featureSet(&[_]Feature{
.apple_a7,
}),
};
- pub const apple_latest = Cpu{
+ pub const apple_latest = CpuModel{
.name = "apple_latest",
.llvm_name = "apple-latest",
.features = featureSet(&[_]Feature{
.apple_a13,
}),
};
- pub const apple_s4 = Cpu{
+ pub const apple_s4 = CpuModel{
.name = "apple_s4",
.llvm_name = "apple-s4",
.features = featureSet(&[_]Feature{
.apple_a12,
}),
};
- pub const apple_s5 = Cpu{
+ pub const apple_s5 = CpuModel{
.name = "apple_s5",
.llvm_name = "apple-s5",
.features = featureSet(&[_]Feature{
.apple_a12,
}),
};
- pub const cortex_a35 = Cpu{
+ pub const cortex_a35 = CpuModel{
.name = "cortex_a35",
.llvm_name = "cortex-a35",
.features = featureSet(&[_]Feature{
- .a35,
+ .crc,
+ .crypto,
+ .perfmon,
+ .v8a,
}),
};
- pub const cortex_a53 = Cpu{
+ pub const cortex_a53 = CpuModel{
.name = "cortex_a53",
.llvm_name = "cortex-a53",
.features = featureSet(&[_]Feature{
- .a53,
+ .balance_fp_ops,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fuse_aes,
+ .perfmon,
+ .use_aa,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const cortex_a55 = Cpu{
+ pub const cortex_a55 = CpuModel{
.name = "cortex_a55",
.llvm_name = "cortex-a55",
.features = featureSet(&[_]Feature{
- .a55,
+ .crypto,
+ .dotprod,
+ .fullfp16,
+ .fuse_aes,
+ .perfmon,
+ .rcpc,
+ .v8_2a,
}),
};
- pub const cortex_a57 = Cpu{
+ pub const cortex_a57 = CpuModel{
.name = "cortex_a57",
.llvm_name = "cortex-a57",
.features = featureSet(&[_]Feature{
- .a57,
+ .balance_fp_ops,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fuse_aes,
+ .fuse_literals,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const cortex_a65 = Cpu{
+ pub const cortex_a65 = CpuModel{
.name = "cortex_a65",
.llvm_name = "cortex-a65",
.features = featureSet(&[_]Feature{
.a65,
}),
};
- pub const cortex_a65ae = Cpu{
+ pub const cortex_a65ae = CpuModel{
.name = "cortex_a65ae",
.llvm_name = "cortex-a65ae",
.features = featureSet(&[_]Feature{
.a65,
}),
};
- pub const cortex_a72 = Cpu{
+ pub const cortex_a72 = CpuModel{
.name = "cortex_a72",
.llvm_name = "cortex-a72",
.features = featureSet(&[_]Feature{
- .a72,
+ .crc,
+ .crypto,
+ .fuse_aes,
+ .perfmon,
+ .v8a,
}),
};
- pub const cortex_a73 = Cpu{
+ pub const cortex_a73 = CpuModel{
.name = "cortex_a73",
.llvm_name = "cortex-a73",
.features = featureSet(&[_]Feature{
- .a73,
+ .crc,
+ .crypto,
+ .fuse_aes,
+ .perfmon,
+ .v8a,
}),
};
- pub const cortex_a75 = Cpu{
+ pub const cortex_a75 = CpuModel{
.name = "cortex_a75",
.llvm_name = "cortex-a75",
.features = featureSet(&[_]Feature{
- .a75,
+ .crypto,
+ .dotprod,
+ .fullfp16,
+ .fuse_aes,
+ .perfmon,
+ .rcpc,
+ .v8_2a,
}),
};
- pub const cortex_a76 = Cpu{
+ pub const cortex_a76 = CpuModel{
.name = "cortex_a76",
.llvm_name = "cortex-a76",
.features = featureSet(&[_]Feature{
.a76,
}),
};
- pub const cortex_a76ae = Cpu{
+ pub const cortex_a76ae = CpuModel{
.name = "cortex_a76ae",
.llvm_name = "cortex-a76ae",
.features = featureSet(&[_]Feature{
.a76,
}),
};
- pub const cyclone = Cpu{
+ pub const cyclone = CpuModel{
.name = "cyclone",
.llvm_name = "cyclone",
.features = featureSet(&[_]Feature{
.apple_a7,
}),
};
- pub const exynos_m1 = Cpu{
+ pub const exynos_m1 = CpuModel{
.name = "exynos_m1",
.llvm_name = null,
.features = featureSet(&[_]Feature{
- .exynosm1,
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_aes,
+ .perfmon,
+ .slow_misaligned_128store,
+ .slow_paired_128,
+ .use_postra_scheduler,
+ .use_reciprocal_square_root,
+ .v8a,
+ .zcz_fp,
}),
};
- pub const exynos_m2 = Cpu{
+ pub const exynos_m2 = CpuModel{
.name = "exynos_m2",
.llvm_name = null,
.features = featureSet(&[_]Feature{
- .exynosm2,
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_aes,
+ .perfmon,
+ .slow_misaligned_128store,
+ .slow_paired_128,
+ .use_postra_scheduler,
+ .v8a,
+ .zcz_fp,
}),
};
- pub const exynos_m3 = Cpu{
+ pub const exynos_m3 = CpuModel{
.name = "exynos_m3",
.llvm_name = "exynos-m3",
.features = featureSet(&[_]Feature{
- .exynosm3,
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_address,
+ .fuse_aes,
+ .fuse_csel,
+ .fuse_literals,
+ .lsl_fast,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
+ .zcz_fp,
}),
};
- pub const exynos_m4 = Cpu{
+ pub const exynos_m4 = CpuModel{
.name = "exynos_m4",
.llvm_name = "exynos-m4",
.features = featureSet(&[_]Feature{
.exynosm4,
}),
};
- pub const exynos_m5 = Cpu{
+ pub const exynos_m5 = CpuModel{
.name = "exynos_m5",
.llvm_name = "exynos-m5",
.features = featureSet(&[_]Feature{
.exynosm4,
}),
};
- pub const falkor = Cpu{
+ pub const falkor = CpuModel{
.name = "falkor",
.llvm_name = "falkor",
.features = featureSet(&[_]Feature{
- .falkor,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .lsl_fast,
+ .perfmon,
+ .predictable_select_expensive,
+ .rdm,
+ .slow_strqro_store,
+ .use_postra_scheduler,
+ .v8a,
+ .zcz,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.ete,
- .fp_armv8,
.fuse_aes,
- .neon,
.perfmon,
.use_postra_scheduler,
+ .v8a,
}),
};
- pub const kryo = Cpu{
+ pub const kryo = CpuModel{
.name = "kryo",
.llvm_name = "kryo",
.features = featureSet(&[_]Feature{
- .kryo,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .lsl_fast,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .zcz,
+ .v8a,
}),
};
- pub const neoverse_e1 = Cpu{
+ pub const neoverse_e1 = CpuModel{
.name = "neoverse_e1",
.llvm_name = "neoverse-e1",
.features = featureSet(&[_]Feature{
.neoversee1,
}),
};
- pub const neoverse_n1 = Cpu{
+ pub const neoverse_n1 = CpuModel{
.name = "neoverse_n1",
.llvm_name = "neoverse-n1",
.features = featureSet(&[_]Feature{
.neoversen1,
}),
};
- pub const saphira = Cpu{
+ pub const saphira = CpuModel{
.name = "saphira",
.llvm_name = "saphira",
.features = featureSet(&[_]Feature{
- .saphira,
+ .crypto,
+ .custom_cheap_as_move,
+ .lsl_fast,
+ .perfmon,
+ .predictable_select_expensive,
+ .spe,
+ .use_postra_scheduler,
+ .v8_4a,
+ .zcz,
}),
};
- pub const thunderx = Cpu{
+ pub const thunderx = CpuModel{
.name = "thunderx",
.llvm_name = "thunderx",
.features = featureSet(&[_]Feature{
- .thunderx,
+ .crc,
+ .crypto,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const thunderx2t99 = Cpu{
+ pub const thunderx2t99 = CpuModel{
.name = "thunderx2t99",
.llvm_name = "thunderx2t99",
.features = featureSet(&[_]Feature{
- .thunderx2t99,
+ .aggressive_fma,
+ .arith_bcc_fusion,
+ .crc,
+ .crypto,
+ .lse,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8_1a,
}),
};
- pub const thunderxt81 = Cpu{
+ pub const thunderxt81 = CpuModel{
.name = "thunderxt81",
.llvm_name = "thunderxt81",
.features = featureSet(&[_]Feature{
- .thunderxt81,
+ .crc,
+ .crypto,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const thunderxt83 = Cpu{
+ pub const thunderxt83 = CpuModel{
.name = "thunderxt83",
.llvm_name = "thunderxt83",
.features = featureSet(&[_]Feature{
- .thunderxt83,
+ .crc,
+ .crypto,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const thunderxt88 = Cpu{
+ pub const thunderxt88 = CpuModel{
.name = "thunderxt88",
.llvm_name = "thunderxt88",
.features = featureSet(&[_]Feature{
- .thunderxt88,
+ .crc,
+ .crypto,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8a,
}),
};
- pub const tsv110 = Cpu{
+ pub const tsv110 = CpuModel{
.name = "tsv110",
.llvm_name = "tsv110",
.features = featureSet(&[_]Feature{
- .tsv110,
+ .crypto,
+ .custom_cheap_as_move,
+ .dotprod,
+ .fp16fml,
+ .fullfp16,
+ .fuse_aes,
+ .perfmon,
+ .spe,
+ .use_postra_scheduler,
+ .v8_2a,
}),
};
};
@@ -1681,7 +1509,7 @@ pub const cpu = struct {
/// All aarch64 CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.apple_a10,
&cpu.apple_a11,
&cpu.apple_a12,
diff --git a/lib/std/target/amdgpu.zig b/lib/std/target/amdgpu.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
@"16_bit_insts",
@@ -112,12 +113,12 @@ pub const Feature = enum {
xnack,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.@"16_bit_insts")] = .{
.llvm_name = "16-bit-insts",
.description = "Has i16/f16 instructions",
@@ -784,7 +785,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const bonaire = Cpu{
+ pub const bonaire = CpuModel{
.name = "bonaire",
.llvm_name = "bonaire",
.features = featureSet(&[_]Feature{
@@ -794,7 +795,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const carrizo = Cpu{
+ pub const carrizo = CpuModel{
.name = "carrizo",
.llvm_name = "carrizo",
.features = featureSet(&[_]Feature{
@@ -807,7 +808,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const fiji = Cpu{
+ pub const fiji = CpuModel{
.name = "fiji",
.llvm_name = "fiji",
.features = featureSet(&[_]Feature{
@@ -818,14 +819,14 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.wavefrontsize64,
}),
};
- pub const generic_hsa = Cpu{
+ pub const generic_hsa = CpuModel{
.name = "generic_hsa",
.llvm_name = "generic-hsa",
.features = featureSet(&[_]Feature{
@@ -833,7 +834,7 @@ pub const cpu = struct {
.wavefrontsize64,
}),
};
- pub const gfx1010 = Cpu{
+ pub const gfx1010 = CpuModel{
.name = "gfx1010",
.llvm_name = "gfx1010",
.features = featureSet(&[_]Feature{
@@ -859,7 +860,7 @@ pub const cpu = struct {
.wavefrontsize32,
}),
};
- pub const gfx1011 = Cpu{
+ pub const gfx1011 = CpuModel{
.name = "gfx1011",
.llvm_name = "gfx1011",
.features = featureSet(&[_]Feature{
@@ -888,7 +889,7 @@ pub const cpu = struct {
.wavefrontsize32,
}),
};
- pub const gfx1012 = Cpu{
+ pub const gfx1012 = CpuModel{
.name = "gfx1012",
.llvm_name = "gfx1012",
.features = featureSet(&[_]Feature{
@@ -918,7 +919,7 @@ pub const cpu = struct {
.wavefrontsize32,
}),
};
- pub const gfx600 = Cpu{
+ pub const gfx600 = CpuModel{
.name = "gfx600",
.llvm_name = "gfx600",
.features = featureSet(&[_]Feature{
@@ -930,7 +931,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const gfx601 = Cpu{
+ pub const gfx601 = CpuModel{
.name = "gfx601",
.llvm_name = "gfx601",
.features = featureSet(&[_]Feature{
@@ -940,7 +941,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const gfx700 = Cpu{
+ pub const gfx700 = CpuModel{
.name = "gfx700",
.llvm_name = "gfx700",
.features = featureSet(&[_]Feature{
@@ -950,7 +951,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const gfx701 = Cpu{
+ pub const gfx701 = CpuModel{
.name = "gfx701",
.llvm_name = "gfx701",
.features = featureSet(&[_]Feature{
@@ -962,7 +963,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const gfx702 = Cpu{
+ pub const gfx702 = CpuModel{
.name = "gfx702",
.llvm_name = "gfx702",
.features = featureSet(&[_]Feature{
@@ -973,7 +974,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const gfx703 = Cpu{
+ pub const gfx703 = CpuModel{
.name = "gfx703",
.llvm_name = "gfx703",
.features = featureSet(&[_]Feature{
@@ -983,7 +984,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const gfx704 = Cpu{
+ pub const gfx704 = CpuModel{
.name = "gfx704",
.llvm_name = "gfx704",
.features = featureSet(&[_]Feature{
@@ -993,7 +994,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const gfx801 = Cpu{
+ pub const gfx801 = CpuModel{
.name = "gfx801",
.llvm_name = "gfx801",
.features = featureSet(&[_]Feature{
@@ -1006,7 +1007,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const gfx802 = Cpu{
+ pub const gfx802 = CpuModel{
.name = "gfx802",
.llvm_name = "gfx802",
.features = featureSet(&[_]Feature{
@@ -1018,7 +1019,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const gfx803 = Cpu{
+ pub const gfx803 = CpuModel{
.name = "gfx803",
.llvm_name = "gfx803",
.features = featureSet(&[_]Feature{
@@ -1029,7 +1030,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const gfx810 = Cpu{
+ pub const gfx810 = CpuModel{
.name = "gfx810",
.llvm_name = "gfx810",
.features = featureSet(&[_]Feature{
@@ -1039,7 +1040,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const gfx900 = Cpu{
+ pub const gfx900 = CpuModel{
.name = "gfx900",
.llvm_name = "gfx900",
.features = featureSet(&[_]Feature{
@@ -1051,7 +1052,7 @@ pub const cpu = struct {
.no_xnack_support,
}),
};
- pub const gfx902 = Cpu{
+ pub const gfx902 = CpuModel{
.name = "gfx902",
.llvm_name = "gfx902",
.features = featureSet(&[_]Feature{
@@ -1063,7 +1064,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const gfx904 = Cpu{
+ pub const gfx904 = CpuModel{
.name = "gfx904",
.llvm_name = "gfx904",
.features = featureSet(&[_]Feature{
@@ -1075,7 +1076,7 @@ pub const cpu = struct {
.no_xnack_support,
}),
};
- pub const gfx906 = Cpu{
+ pub const gfx906 = CpuModel{
.name = "gfx906",
.llvm_name = "gfx906",
.features = featureSet(&[_]Feature{
@@ -1090,7 +1091,7 @@ pub const cpu = struct {
.no_xnack_support,
}),
};
- pub const gfx908 = Cpu{
+ pub const gfx908 = CpuModel{
.name = "gfx908",
.llvm_name = "gfx908",
.features = featureSet(&[_]Feature{
@@ -1113,7 +1114,7 @@ pub const cpu = struct {
.sram_ecc,
}),
};
- pub const gfx909 = Cpu{
+ pub const gfx909 = CpuModel{
.name = "gfx909",
.llvm_name = "gfx909",
.features = featureSet(&[_]Feature{
@@ -1124,7 +1125,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const hainan = Cpu{
+ pub const hainan = CpuModel{
.name = "hainan",
.llvm_name = "hainan",
.features = featureSet(&[_]Feature{
@@ -1134,7 +1135,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const hawaii = Cpu{
+ pub const hawaii = CpuModel{
.name = "hawaii",
.llvm_name = "hawaii",
.features = featureSet(&[_]Feature{
@@ -1146,7 +1147,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const iceland = Cpu{
+ pub const iceland = CpuModel{
.name = "iceland",
.llvm_name = "iceland",
.features = featureSet(&[_]Feature{
@@ -1158,7 +1159,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const kabini = Cpu{
+ pub const kabini = CpuModel{
.name = "kabini",
.llvm_name = "kabini",
.features = featureSet(&[_]Feature{
@@ -1168,7 +1169,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const kaveri = Cpu{
+ pub const kaveri = CpuModel{
.name = "kaveri",
.llvm_name = "kaveri",
.features = featureSet(&[_]Feature{
@@ -1178,7 +1179,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const mullins = Cpu{
+ pub const mullins = CpuModel{
.name = "mullins",
.llvm_name = "mullins",
.features = featureSet(&[_]Feature{
@@ -1188,7 +1189,7 @@ pub const cpu = struct {
.sea_islands,
}),
};
- pub const oland = Cpu{
+ pub const oland = CpuModel{
.name = "oland",
.llvm_name = "oland",
.features = featureSet(&[_]Feature{
@@ -1198,7 +1199,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const pitcairn = Cpu{
+ pub const pitcairn = CpuModel{
.name = "pitcairn",
.llvm_name = "pitcairn",
.features = featureSet(&[_]Feature{
@@ -1208,7 +1209,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const polaris10 = Cpu{
+ pub const polaris10 = CpuModel{
.name = "polaris10",
.llvm_name = "polaris10",
.features = featureSet(&[_]Feature{
@@ -1219,7 +1220,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const polaris11 = Cpu{
+ pub const polaris11 = CpuModel{
.name = "polaris11",
.llvm_name = "polaris11",
.features = featureSet(&[_]Feature{
@@ -1230,7 +1231,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const stoney = Cpu{
+ pub const stoney = CpuModel{
.name = "stoney",
.llvm_name = "stoney",
.features = featureSet(&[_]Feature{
@@ -1240,7 +1241,7 @@ pub const cpu = struct {
.xnack,
}),
};
- pub const tahiti = Cpu{
+ pub const tahiti = CpuModel{
.name = "tahiti",
.llvm_name = "tahiti",
.features = featureSet(&[_]Feature{
@@ -1252,7 +1253,7 @@ pub const cpu = struct {
.southern_islands,
}),
};
- pub const tonga = Cpu{
+ pub const tonga = CpuModel{
.name = "tonga",
.llvm_name = "tonga",
.features = featureSet(&[_]Feature{
@@ -1264,7 +1265,7 @@ pub const cpu = struct {
.volcanic_islands,
}),
};
- pub const verde = Cpu{
+ pub const verde = CpuModel{
.name = "verde",
.llvm_name = "verde",
.features = featureSet(&[_]Feature{
@@ -1279,7 +1280,7 @@ pub const cpu = struct {
/// All amdgpu CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.bonaire,
&cpu.carrizo,
&cpu.fiji,
diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig
@@ -1,61 +1,14 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
@"32bit",
@"8msecext",
- a12,
- a15,
- a17,
- a32,
- a35,
- a5,
- a53,
- a55,
- a57,
- a7,
- a72,
- a73,
- a75,
a76,
- a8,
- a9,
aclass,
acquire_release,
aes,
- armv2,
- armv2a,
- armv3,
- armv3m,
- armv4,
- armv4t,
- armv5t,
- armv5te,
- armv5tej,
- armv6,
- armv6_m,
- armv6j,
- armv6k,
- armv6kz,
- armv6s_m,
- armv6t2,
- armv7_a,
- armv7_m,
- armv7_r,
- armv7e_m,
- armv7k,
- armv7s,
- armv7ve,
- armv8_a,
- armv8_m_base,
- armv8_m_main,
- armv8_r,
- armv8_1_a,
- armv8_1_m_main,
- armv8_2_a,
- armv8_3_a,
- armv8_4_a,
- armv8_5_a,
avoid_movs_shop,
avoid_partial_cpsr,
cheap_predicable_cpsr,
@@ -71,13 +24,13 @@ pub const Feature = enum {
execute_only,
expand_fp_mlx,
exynos,
+ fp16,
+ fp16fml,
+ fp64,
fp_armv8,
fp_armv8d16,
fp_armv8d16sp,
fp_armv8sp,
- fp16,
- fp16fml,
- fp64,
fpao,
fpregs,
fpregs16,
@@ -85,12 +38,28 @@ pub const Feature = enum {
fullfp16,
fuse_aes,
fuse_literals,
+ has_v4t,
+ has_v5t,
+ has_v5te,
+ has_v6,
+ has_v6k,
+ has_v6m,
+ has_v6t2,
+ has_v7,
+ has_v7clrex,
+ has_v8_1a,
+ has_v8_1m_main,
+ has_v8_2a,
+ has_v8_3a,
+ has_v8_4a,
+ has_v8_5a,
+ has_v8,
+ has_v8m,
+ has_v8m_main,
hwdiv,
hwdiv_arm,
iwmmxt,
iwmmxt2,
- krait,
- kryo,
lob,
long_calls,
loop_align,
@@ -117,9 +86,6 @@ pub const Feature = enum {
prefer_vmovsr,
prof_unpr,
r4,
- r5,
- r52,
- r7,
ras,
rclass,
read_tp_hard,
@@ -138,28 +104,43 @@ pub const Feature = enum {
splat_vfp_neon,
strict_align,
swift,
- thumb_mode,
thumb2,
+ thumb_mode,
trustzone,
use_misched,
+ v2,
+ v2a,
+ v3,
+ v3m,
+ v4,
v4t,
v5t,
v5te,
+ v5tej,
v6,
+ v6j,
v6k,
+ v6kz,
v6m,
+ v6sm,
v6t2,
- v7,
- v7clrex,
- v8,
+ v7a,
+ v7em,
+ v7k,
+ v7m,
+ v7r,
+ v7s,
+ v7ve,
+ v8a,
+ v8m,
+ v8m_main,
+ v8r,
v8_1a,
v8_1m_main,
v8_2a,
v8_3a,
v8_4a,
v8_5a,
- v8m,
- v8m_main,
vfp2,
vfp2sp,
vfp3,
@@ -179,13 +160,13 @@ pub const Feature = enum {
zcz,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
@setEvalBranchQuota(10000);
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.@"32bit")] = .{
.llvm_name = "32bit",
.description = "Prefer 32-bit Thumb instrs",
@@ -196,86 +177,11 @@ pub const all_features = blk: {
.description = "Enable support for ARMv8-M Security Extensions",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.a12)] = .{
- .llvm_name = "a12",
- .description = "Cortex-A12 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a15)] = .{
- .llvm_name = "a15",
- .description = "Cortex-A15 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a17)] = .{
- .llvm_name = "a17",
- .description = "Cortex-A17 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a32)] = .{
- .llvm_name = "a32",
- .description = "Cortex-A32 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a35)] = .{
- .llvm_name = "a35",
- .description = "Cortex-A35 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a5)] = .{
- .llvm_name = "a5",
- .description = "Cortex-A5 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a53)] = .{
- .llvm_name = "a53",
- .description = "Cortex-A53 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a55)] = .{
- .llvm_name = "a55",
- .description = "Cortex-A55 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a57)] = .{
- .llvm_name = "a57",
- .description = "Cortex-A57 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a7)] = .{
- .llvm_name = "a7",
- .description = "Cortex-A7 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a72)] = .{
- .llvm_name = "a72",
- .description = "Cortex-A72 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a73)] = .{
- .llvm_name = "a73",
- .description = "Cortex-A73 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a75)] = .{
- .llvm_name = "a75",
- .description = "Cortex-A75 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
result[@enumToInt(Feature.a76)] = .{
.llvm_name = "a76",
.description = "Cortex-A76 ARM processors",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.a8)] = .{
- .llvm_name = "a8",
- .description = "Cortex-A8 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.a9)] = .{
- .llvm_name = "a9",
- .description = "Cortex-A9 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
result[@enumToInt(Feature.aclass)] = .{
.llvm_name = "aclass",
.description = "Is application profile ('A' series)",
@@ -293,368 +199,6 @@ pub const all_features = blk: {
.neon,
}),
};
- result[@enumToInt(Feature.armv2)] = .{
- .llvm_name = "armv2",
- .description = "ARMv2 architecture",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.armv2a)] = .{
- .llvm_name = "armv2a",
- .description = "ARMv2a architecture",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.armv3)] = .{
- .llvm_name = "armv3",
- .description = "ARMv3 architecture",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.armv3m)] = .{
- .llvm_name = "armv3m",
- .description = "ARMv3m architecture",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.armv4)] = .{
- .llvm_name = "armv4",
- .description = "ARMv4 architecture",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.armv4t)] = .{
- .llvm_name = "armv4t",
- .description = "ARMv4t architecture",
- .dependencies = featureSet(&[_]Feature{
- .v4t,
- }),
- };
- result[@enumToInt(Feature.armv5t)] = .{
- .llvm_name = "armv5t",
- .description = "ARMv5t architecture",
- .dependencies = featureSet(&[_]Feature{
- .v5t,
- }),
- };
- result[@enumToInt(Feature.armv5te)] = .{
- .llvm_name = "armv5te",
- .description = "ARMv5te architecture",
- .dependencies = featureSet(&[_]Feature{
- .v5te,
- }),
- };
- result[@enumToInt(Feature.armv5tej)] = .{
- .llvm_name = "armv5tej",
- .description = "ARMv5tej architecture",
- .dependencies = featureSet(&[_]Feature{
- .v5te,
- }),
- };
- result[@enumToInt(Feature.armv6)] = .{
- .llvm_name = "armv6",
- .description = "ARMv6 architecture",
- .dependencies = featureSet(&[_]Feature{
- .dsp,
- .v6,
- }),
- };
- result[@enumToInt(Feature.armv6_m)] = .{
- .llvm_name = "armv6-m",
- .description = "ARMv6m architecture",
- .dependencies = featureSet(&[_]Feature{
- .db,
- .mclass,
- .noarm,
- .strict_align,
- .thumb_mode,
- .v6m,
- }),
- };
- result[@enumToInt(Feature.armv6j)] = .{
- .llvm_name = "armv6j",
- .description = "ARMv7a architecture",
- .dependencies = featureSet(&[_]Feature{
- .armv6,
- }),
- };
- result[@enumToInt(Feature.armv6k)] = .{
- .llvm_name = "armv6k",
- .description = "ARMv6k architecture",
- .dependencies = featureSet(&[_]Feature{
- .v6k,
- }),
- };
- result[@enumToInt(Feature.armv6kz)] = .{
- .llvm_name = "armv6kz",
- .description = "ARMv6kz architecture",
- .dependencies = featureSet(&[_]Feature{
- .trustzone,
- .v6k,
- }),
- };
- result[@enumToInt(Feature.armv6s_m)] = .{
- .llvm_name = "armv6s-m",
- .description = "ARMv6sm architecture",
- .dependencies = featureSet(&[_]Feature{
- .db,
- .mclass,
- .noarm,
- .strict_align,
- .thumb_mode,
- .v6m,
- }),
- };
- result[@enumToInt(Feature.armv6t2)] = .{
- .llvm_name = "armv6t2",
- .description = "ARMv6t2 architecture",
- .dependencies = featureSet(&[_]Feature{
- .dsp,
- .v6t2,
- }),
- };
- result[@enumToInt(Feature.armv7_a)] = .{
- .llvm_name = "armv7-a",
- .description = "ARMv7a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .db,
- .dsp,
- .neon,
- .v7,
- }),
- };
- result[@enumToInt(Feature.armv7_m)] = .{
- .llvm_name = "armv7-m",
- .description = "ARMv7m architecture",
- .dependencies = featureSet(&[_]Feature{
- .db,
- .hwdiv,
- .mclass,
- .noarm,
- .thumb_mode,
- .thumb2,
- .v7,
- }),
- };
- result[@enumToInt(Feature.armv7_r)] = .{
- .llvm_name = "armv7-r",
- .description = "ARMv7r architecture",
- .dependencies = featureSet(&[_]Feature{
- .db,
- .dsp,
- .hwdiv,
- .rclass,
- .v7,
- }),
- };
- result[@enumToInt(Feature.armv7e_m)] = .{
- .llvm_name = "armv7e-m",
- .description = "ARMv7em architecture",
- .dependencies = featureSet(&[_]Feature{
- .db,
- .dsp,
- .hwdiv,
- .mclass,
- .noarm,
- .thumb_mode,
- .thumb2,
- .v7,
- }),
- };
- result[@enumToInt(Feature.armv7k)] = .{
- .llvm_name = "armv7k",
- .description = "ARMv7a architecture",
- .dependencies = featureSet(&[_]Feature{
- .armv7_a,
- }),
- };
- result[@enumToInt(Feature.armv7s)] = .{
- .llvm_name = "armv7s",
- .description = "ARMv7a architecture",
- .dependencies = featureSet(&[_]Feature{
- .armv7_a,
- }),
- };
- result[@enumToInt(Feature.armv7ve)] = .{
- .llvm_name = "armv7ve",
- .description = "ARMv7ve architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .db,
- .dsp,
- .mp,
- .neon,
- .trustzone,
- .v7,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_a)] = .{
- .llvm_name = "armv8-a",
- .description = "ARMv8a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .trustzone,
- .v8,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_m_base)] = .{
- .llvm_name = "armv8-m.base",
- .description = "ARMv8mBaseline architecture",
- .dependencies = featureSet(&[_]Feature{
- .@"8msecext",
- .acquire_release,
- .db,
- .hwdiv,
- .mclass,
- .noarm,
- .strict_align,
- .thumb_mode,
- .v7clrex,
- .v8m,
- }),
- };
- result[@enumToInt(Feature.armv8_m_main)] = .{
- .llvm_name = "armv8-m.main",
- .description = "ARMv8mMainline architecture",
- .dependencies = featureSet(&[_]Feature{
- .@"8msecext",
- .acquire_release,
- .db,
- .hwdiv,
- .mclass,
- .noarm,
- .thumb_mode,
- .v8m_main,
- }),
- };
- result[@enumToInt(Feature.armv8_r)] = .{
- .llvm_name = "armv8-r",
- .description = "ARMv8r architecture",
- .dependencies = featureSet(&[_]Feature{
- .crc,
- .db,
- .dfb,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .rclass,
- .v8,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_1_a)] = .{
- .llvm_name = "armv8.1-a",
- .description = "ARMv81a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .trustzone,
- .v8_1a,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_1_m_main)] = .{
- .llvm_name = "armv8.1-m.main",
- .description = "ARMv81mMainline architecture",
- .dependencies = featureSet(&[_]Feature{
- .@"8msecext",
- .acquire_release,
- .db,
- .hwdiv,
- .lob,
- .mclass,
- .noarm,
- .ras,
- .thumb_mode,
- .v8_1m_main,
- }),
- };
- result[@enumToInt(Feature.armv8_2_a)] = .{
- .llvm_name = "armv8.2-a",
- .description = "ARMv82a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .ras,
- .trustzone,
- .v8_2a,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_3_a)] = .{
- .llvm_name = "armv8.3-a",
- .description = "ARMv83a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .ras,
- .trustzone,
- .v8_3a,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_4_a)] = .{
- .llvm_name = "armv8.4-a",
- .description = "ARMv84a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dotprod,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .ras,
- .trustzone,
- .v8_4a,
- .virtualization,
- }),
- };
- result[@enumToInt(Feature.armv8_5_a)] = .{
- .llvm_name = "armv8.5-a",
- .description = "ARMv85a architecture",
- .dependencies = featureSet(&[_]Feature{
- .aclass,
- .crc,
- .crypto,
- .db,
- .dotprod,
- .dsp,
- .fp_armv8,
- .mp,
- .neon,
- .ras,
- .trustzone,
- .v8_5a,
- .virtualization,
- }),
- };
result[@enumToInt(Feature.avoid_movs_shop)] = .{
.llvm_name = "avoid-movs-shop",
.description = "Avoid movs instructions with shifter operand",
@@ -754,6 +298,25 @@ pub const all_features = blk: {
.zcz,
}),
};
+ result[@enumToInt(Feature.fp16)] = .{
+ .llvm_name = "fp16",
+ .description = "Enable half-precision floating point",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp16fml)] = .{
+ .llvm_name = "fp16fml",
+ .description = "Enable full half-precision floating point fml instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fullfp16,
+ }),
+ };
+ result[@enumToInt(Feature.fp64)] = .{
+ .llvm_name = "fp64",
+ .description = "Floating point unit supports double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .fpregs64,
+ }),
+ };
result[@enumToInt(Feature.fp_armv8)] = .{
.llvm_name = "fp-armv8",
.description = "Enable ARMv8 FP",
@@ -772,39 +335,20 @@ pub const all_features = blk: {
.vfp4d16,
}),
};
- result[@enumToInt(Feature.fp_armv8d16sp)] = .{
- .llvm_name = "fp-armv8d16sp",
- .description = "Enable ARMv8 FP with only 16 d-registers and no double precision",
- .dependencies = featureSet(&[_]Feature{
- .vfp4d16sp,
- }),
- };
- result[@enumToInt(Feature.fp_armv8sp)] = .{
- .llvm_name = "fp-armv8sp",
- .description = "Enable ARMv8 FP with no double precision",
- .dependencies = featureSet(&[_]Feature{
- .d32,
- .fp_armv8d16sp,
- .vfp4sp,
- }),
- };
- result[@enumToInt(Feature.fp16)] = .{
- .llvm_name = "fp16",
- .description = "Enable half-precision floating point",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.fp16fml)] = .{
- .llvm_name = "fp16fml",
- .description = "Enable full half-precision floating point fml instructions",
+ result[@enumToInt(Feature.fp_armv8d16sp)] = .{
+ .llvm_name = "fp-armv8d16sp",
+ .description = "Enable ARMv8 FP with only 16 d-registers and no double precision",
.dependencies = featureSet(&[_]Feature{
- .fullfp16,
+ .vfp4d16sp,
}),
};
- result[@enumToInt(Feature.fp64)] = .{
- .llvm_name = "fp64",
- .description = "Floating point unit supports double precision",
+ result[@enumToInt(Feature.fp_armv8sp)] = .{
+ .llvm_name = "fp-armv8sp",
+ .description = "Enable ARMv8 FP with no double precision",
.dependencies = featureSet(&[_]Feature{
- .fpregs64,
+ .d32,
+ .fp_armv8d16sp,
+ .vfp4sp,
}),
};
result[@enumToInt(Feature.fpao)] = .{
@@ -849,6 +393,135 @@ pub const all_features = blk: {
.description = "CPU fuses literal generation operations",
.dependencies = featureSet(&[_]Feature{}),
};
+ result[@enumToInt(Feature.has_v4t)] = .{
+ .llvm_name = "v4t",
+ .description = "Support ARM v4T instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.has_v5t)] = .{
+ .llvm_name = "v5t",
+ .description = "Support ARM v5T instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v4t,
+ }),
+ };
+ result[@enumToInt(Feature.has_v5te)] = .{
+ .llvm_name = "v5te",
+ .description = "Support ARM v5TE, v5TEj, and v5TExp instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v5t,
+ }),
+ };
+ result[@enumToInt(Feature.has_v6)] = .{
+ .llvm_name = "v6",
+ .description = "Support ARM v6 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v5te,
+ }),
+ };
+ result[@enumToInt(Feature.has_v6k)] = .{
+ .llvm_name = "v6k",
+ .description = "Support ARM v6k instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v6,
+ }),
+ };
+ result[@enumToInt(Feature.has_v6m)] = .{
+ .llvm_name = "v6m",
+ .description = "Support ARM v6M instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v6,
+ }),
+ };
+ result[@enumToInt(Feature.has_v6t2)] = .{
+ .llvm_name = "v6t2",
+ .description = "Support ARM v6t2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .thumb2,
+ .has_v6k,
+ .has_v8m,
+ }),
+ };
+ result[@enumToInt(Feature.has_v7)] = .{
+ .llvm_name = "v7",
+ .description = "Support ARM v7 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .perfmon,
+ .has_v6t2,
+ .has_v7clrex,
+ }),
+ };
+ result[@enumToInt(Feature.has_v7clrex)] = .{
+ .llvm_name = "v7clrex",
+ .description = "Has v7 clrex instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.has_v8)] = .{
+ .llvm_name = "v8",
+ .description = "Support ARM v8 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .acquire_release,
+ .has_v7,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_1a)] = .{
+ .llvm_name = "v8.1a",
+ .description = "Support ARM v8.1a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v8,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_1m_main)] = .{
+ .llvm_name = "v8.1m.main",
+ .description = "Support ARM v8-1M Mainline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v8m_main,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_2a)] = .{
+ .llvm_name = "v8.2a",
+ .description = "Support ARM v8.2a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v8_1a,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_3a)] = .{
+ .llvm_name = "v8.3a",
+ .description = "Support ARM v8.3a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_4a)] = .{
+ .llvm_name = "v8.4a",
+ .description = "Support ARM v8.4a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .dotprod,
+ .has_v8_3a,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8_5a)] = .{
+ .llvm_name = "v8.5a",
+ .description = "Support ARM v8.5a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sb,
+ .has_v8_4a,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8m)] = .{
+ .llvm_name = "v8m",
+ .description = "Support ARM v8M Baseline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v6m,
+ }),
+ };
+ result[@enumToInt(Feature.has_v8m_main)] = .{
+ .llvm_name = "v8m.main",
+ .description = "Support ARM v8M Mainline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v7,
+ }),
+ };
result[@enumToInt(Feature.hwdiv)] = .{
.llvm_name = "hwdiv",
.description = "Enable divide instructions in Thumb",
@@ -863,26 +536,16 @@ pub const all_features = blk: {
.llvm_name = "iwmmxt",
.description = "ARMv5te architecture",
.dependencies = featureSet(&[_]Feature{
- .armv5te,
+ .has_v5te,
}),
};
result[@enumToInt(Feature.iwmmxt2)] = .{
.llvm_name = "iwmmxt2",
.description = "ARMv5te architecture",
.dependencies = featureSet(&[_]Feature{
- .armv5te,
+ .has_v5te,
}),
};
- result[@enumToInt(Feature.krait)] = .{
- .llvm_name = "krait",
- .description = "Qualcomm Krait processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.kryo)] = .{
- .llvm_name = "kryo",
- .description = "Qualcomm Kryo processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
result[@enumToInt(Feature.lob)] = .{
.llvm_name = "lob",
.description = "Enable Low Overhead Branch extensions",
@@ -925,7 +588,7 @@ pub const all_features = blk: {
.dsp,
.fpregs16,
.fpregs64,
- .v8_1m_main,
+ .has_v8_1m_main,
}),
};
result[@enumToInt(Feature.mve_fp)] = .{
@@ -1024,21 +687,6 @@ pub const all_features = blk: {
.description = "Cortex-R4 ARM processors",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.r5)] = .{
- .llvm_name = "r5",
- .description = "Cortex-R5 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.r52)] = .{
- .llvm_name = "r52",
- .description = "Cortex-R52 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.r7)] = .{
- .llvm_name = "r7",
- .description = "Cortex-R7 ARM processors",
- .dependencies = featureSet(&[_]Feature{}),
- };
result[@enumToInt(Feature.ras)] = .{
.llvm_name = "ras",
.description = "Enable Reliability, Availability and Serviceability extensions",
@@ -1133,16 +781,16 @@ pub const all_features = blk: {
.description = "Swift ARM processors",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.thumb_mode)] = .{
- .llvm_name = "thumb-mode",
- .description = "Thumb mode",
- .dependencies = featureSet(&[_]Feature{}),
- };
result[@enumToInt(Feature.thumb2)] = .{
.llvm_name = "thumb2",
.description = "Enable Thumb2 instructions",
.dependencies = featureSet(&[_]Feature{}),
};
+ result[@enumToInt(Feature.thumb_mode)] = .{
+ .llvm_name = "thumb-mode",
+ .description = "Thumb mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
result[@enumToInt(Feature.trustzone)] = .{
.llvm_name = "trustzone",
.description = "Enable support for TrustZone security extensions",
@@ -1153,133 +801,366 @@ pub const all_features = blk: {
.description = "Use the MachineScheduler",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.v4t)] = .{
- .llvm_name = "v4t",
- .description = "Support ARM v4T instructions",
+ result[@enumToInt(Feature.v2)] = .{
+ .llvm_name = "armv2",
+ .description = "ARMv2 architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v2a)] = .{
+ .llvm_name = "armv2a",
+ .description = "ARMv2a architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v3)] = .{
+ .llvm_name = "armv3",
+ .description = "ARMv3 architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v3m)] = .{
+ .llvm_name = "armv3m",
+ .description = "ARMv3m architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v4)] = .{
+ .llvm_name = "armv4",
+ .description = "ARMv4 architecture",
.dependencies = featureSet(&[_]Feature{}),
};
- result[@enumToInt(Feature.v5t)] = .{
- .llvm_name = "v5t",
- .description = "Support ARM v5T instructions",
+ result[@enumToInt(Feature.v4t)] = .{
+ .llvm_name = "armv4t",
+ .description = "ARMv4t architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v4t,
+ }),
+ };
+ result[@enumToInt(Feature.v5t)] = .{
+ .llvm_name = "armv5t",
+ .description = "ARMv5t architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v5t,
+ }),
+ };
+ result[@enumToInt(Feature.v5te)] = .{
+ .llvm_name = "armv5te",
+ .description = "ARMv5te architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v5te,
+ }),
+ };
+ result[@enumToInt(Feature.v5tej)] = .{
+ .llvm_name = "armv5tej",
+ .description = "ARMv5tej architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v5te,
+ }),
+ };
+ result[@enumToInt(Feature.v6)] = .{
+ .llvm_name = "armv6",
+ .description = "ARMv6 architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .dsp,
+ .has_v6,
+ }),
+ };
+ result[@enumToInt(Feature.v6m)] = .{
+ .llvm_name = "armv6-m",
+ .description = "ARMv6m architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .has_v6m,
+ }),
+ };
+ result[@enumToInt(Feature.v6j)] = .{
+ .llvm_name = "armv6j",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v6,
+ }),
+ };
+ result[@enumToInt(Feature.v6k)] = .{
+ .llvm_name = "armv6k",
+ .description = "ARMv6k architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .has_v6k,
+ }),
+ };
+ result[@enumToInt(Feature.v6kz)] = .{
+ .llvm_name = "armv6kz",
+ .description = "ARMv6kz architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .trustzone,
+ .has_v6k,
+ }),
+ };
+ result[@enumToInt(Feature.v6sm)] = .{
+ .llvm_name = "armv6s-m",
+ .description = "ARMv6sm architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .has_v6m,
+ }),
+ };
+ result[@enumToInt(Feature.v6t2)] = .{
+ .llvm_name = "armv6t2",
+ .description = "ARMv6t2 architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .dsp,
+ .has_v6t2,
+ }),
+ };
+ result[@enumToInt(Feature.v7a)] = .{
+ .llvm_name = "armv7-a",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .db,
+ .dsp,
+ .neon,
+ .has_v7,
+ }),
+ };
+ result[@enumToInt(Feature.v7m)] = .{
+ .llvm_name = "armv7-m",
+ .description = "ARMv7m architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .thumb2,
+ .has_v7,
+ }),
+ };
+ result[@enumToInt(Feature.v7r)] = .{
+ .llvm_name = "armv7-r",
+ .description = "ARMv7r architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .dsp,
+ .hwdiv,
+ .rclass,
+ .has_v7,
+ }),
+ };
+ result[@enumToInt(Feature.v7em)] = .{
+ .llvm_name = "armv7e-m",
+ .description = "ARMv7em architecture",
.dependencies = featureSet(&[_]Feature{
- .v4t,
+ .db,
+ .dsp,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .thumb2,
+ .has_v7,
}),
};
- result[@enumToInt(Feature.v5te)] = .{
- .llvm_name = "v5te",
- .description = "Support ARM v5TE, v5TEj, and v5TExp instructions",
+ result[@enumToInt(Feature.v7k)] = .{
+ .llvm_name = "armv7k",
+ .description = "ARMv7a architecture",
.dependencies = featureSet(&[_]Feature{
- .v5t,
+ .v7a,
}),
};
- result[@enumToInt(Feature.v6)] = .{
- .llvm_name = "v6",
- .description = "Support ARM v6 instructions",
+ result[@enumToInt(Feature.v7s)] = .{
+ .llvm_name = "armv7s",
+ .description = "ARMv7a architecture",
.dependencies = featureSet(&[_]Feature{
- .v5te,
+ .v7a,
}),
};
- result[@enumToInt(Feature.v6k)] = .{
- .llvm_name = "v6k",
- .description = "Support ARM v6k instructions",
+ result[@enumToInt(Feature.v7ve)] = .{
+ .llvm_name = "armv7ve",
+ .description = "ARMv7ve architecture",
.dependencies = featureSet(&[_]Feature{
- .v6,
+ .aclass,
+ .db,
+ .dsp,
+ .mp,
+ .neon,
+ .trustzone,
+ .has_v7,
+ .virtualization,
}),
};
- result[@enumToInt(Feature.v6m)] = .{
- .llvm_name = "v6m",
- .description = "Support ARM v6M instructions",
+ result[@enumToInt(Feature.v8a)] = .{
+ .llvm_name = "armv8-a",
+ .description = "ARMv8a architecture",
.dependencies = featureSet(&[_]Feature{
- .v6,
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .trustzone,
+ .has_v8,
+ .virtualization,
}),
};
- result[@enumToInt(Feature.v6t2)] = .{
- .llvm_name = "v6t2",
- .description = "Support ARM v6t2 instructions",
+ result[@enumToInt(Feature.v8m)] = .{
+ .llvm_name = "armv8-m.base",
+ .description = "ARMv8mBaseline architecture",
.dependencies = featureSet(&[_]Feature{
- .thumb2,
- .v6k,
- .v8m,
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .has_v7clrex,
+ .has_v8m,
}),
};
- result[@enumToInt(Feature.v7)] = .{
- .llvm_name = "v7",
- .description = "Support ARM v7 instructions",
+ result[@enumToInt(Feature.v8m_main)] = .{
+ .llvm_name = "armv8-m.main",
+ .description = "ARMv8mMainline architecture",
.dependencies = featureSet(&[_]Feature{
- .perfmon,
- .v6t2,
- .v7clrex,
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .has_v8m_main,
}),
};
- result[@enumToInt(Feature.v7clrex)] = .{
- .llvm_name = "v7clrex",
- .description = "Has v7 clrex instruction",
- .dependencies = featureSet(&[_]Feature{}),
- };
- result[@enumToInt(Feature.v8)] = .{
- .llvm_name = "v8",
- .description = "Support ARM v8 instructions",
+ result[@enumToInt(Feature.v8r)] = .{
+ .llvm_name = "armv8-r",
+ .description = "ARMv8r architecture",
.dependencies = featureSet(&[_]Feature{
- .acquire_release,
- .v7,
+ .crc,
+ .db,
+ .dfb,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .rclass,
+ .has_v8,
+ .virtualization,
}),
};
result[@enumToInt(Feature.v8_1a)] = .{
- .llvm_name = "v8.1a",
- .description = "Support ARM v8.1a instructions",
+ .llvm_name = "armv8.1-a",
+ .description = "ARMv81a architecture",
.dependencies = featureSet(&[_]Feature{
- .v8,
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .trustzone,
+ .has_v8_1a,
+ .virtualization,
}),
};
result[@enumToInt(Feature.v8_1m_main)] = .{
- .llvm_name = "v8.1m.main",
- .description = "Support ARM v8-1M Mainline instructions",
+ .llvm_name = "armv8.1-m.main",
+ .description = "ARMv81mMainline architecture",
.dependencies = featureSet(&[_]Feature{
- .v8m_main,
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .lob,
+ .mclass,
+ .noarm,
+ .ras,
+ .thumb_mode,
+ .has_v8_1m_main,
}),
};
result[@enumToInt(Feature.v8_2a)] = .{
- .llvm_name = "v8.2a",
- .description = "Support ARM v8.2a instructions",
+ .llvm_name = "armv8.2-a",
+ .description = "ARMv82a architecture",
.dependencies = featureSet(&[_]Feature{
- .v8_1a,
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .has_v8_2a,
+ .virtualization,
}),
};
result[@enumToInt(Feature.v8_3a)] = .{
- .llvm_name = "v8.3a",
- .description = "Support ARM v8.3a instructions",
+ .llvm_name = "armv8.3-a",
+ .description = "ARMv83a architecture",
.dependencies = featureSet(&[_]Feature{
- .v8_2a,
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .has_v8_3a,
+ .virtualization,
}),
};
result[@enumToInt(Feature.v8_4a)] = .{
- .llvm_name = "v8.4a",
- .description = "Support ARM v8.4a instructions",
+ .llvm_name = "armv8.4-a",
+ .description = "ARMv84a architecture",
.dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
.dotprod,
- .v8_3a,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .has_v8_4a,
+ .virtualization,
}),
};
result[@enumToInt(Feature.v8_5a)] = .{
- .llvm_name = "v8.5a",
- .description = "Support ARM v8.5a instructions",
- .dependencies = featureSet(&[_]Feature{
- .sb,
- .v8_4a,
- }),
- };
- result[@enumToInt(Feature.v8m)] = .{
- .llvm_name = "v8m",
- .description = "Support ARM v8M Baseline instructions",
- .dependencies = featureSet(&[_]Feature{
- .v6m,
- }),
- };
- result[@enumToInt(Feature.v8m_main)] = .{
- .llvm_name = "v8m.main",
- .description = "Support ARM v8M Mainline instructions",
+ .llvm_name = "armv8.5-a",
+ .description = "ARMv85a architecture",
.dependencies = featureSet(&[_]Feature{
- .v7,
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dotprod,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .has_v8_5a,
+ .virtualization,
}),
};
result[@enumToInt(Feature.vfp2)] = .{
@@ -1399,7 +1280,7 @@ pub const all_features = blk: {
.llvm_name = "xscale",
.description = "ARMv5te architecture",
.dependencies = featureSet(&[_]Feature{
- .armv5te,
+ .has_v5te,
}),
};
result[@enumToInt(Feature.zcz)] = .{
@@ -1416,221 +1297,227 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const arm1020e = Cpu{
+ pub const arm1020e = CpuModel{
.name = "arm1020e",
.llvm_name = "arm1020e",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm1020t = Cpu{
+ pub const arm1020t = CpuModel{
.name = "arm1020t",
.llvm_name = "arm1020t",
.features = featureSet(&[_]Feature{
- .armv5t,
+ .v5t,
}),
};
- pub const arm1022e = Cpu{
+ pub const arm1022e = CpuModel{
.name = "arm1022e",
.llvm_name = "arm1022e",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm10e = Cpu{
+ pub const arm10e = CpuModel{
.name = "arm10e",
.llvm_name = "arm10e",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm10tdmi = Cpu{
+ pub const arm10tdmi = CpuModel{
.name = "arm10tdmi",
.llvm_name = "arm10tdmi",
.features = featureSet(&[_]Feature{
- .armv5t,
+ .v5t,
}),
};
- pub const arm1136j_s = Cpu{
+ pub const arm1136j_s = CpuModel{
.name = "arm1136j_s",
.llvm_name = "arm1136j-s",
.features = featureSet(&[_]Feature{
- .armv6,
+ .v6,
}),
};
- pub const arm1136jf_s = Cpu{
+ pub const arm1136jf_s = CpuModel{
.name = "arm1136jf_s",
.llvm_name = "arm1136jf-s",
.features = featureSet(&[_]Feature{
- .armv6,
+ .v6,
.slowfpvmlx,
.vfp2,
}),
};
- pub const arm1156t2_s = Cpu{
+ pub const arm1156t2_s = CpuModel{
.name = "arm1156t2_s",
.llvm_name = "arm1156t2-s",
.features = featureSet(&[_]Feature{
- .armv6t2,
+ .v6t2,
}),
};
- pub const arm1156t2f_s = Cpu{
+ pub const arm1156t2f_s = CpuModel{
.name = "arm1156t2f_s",
.llvm_name = "arm1156t2f-s",
.features = featureSet(&[_]Feature{
- .armv6t2,
+ .v6t2,
.slowfpvmlx,
.vfp2,
}),
};
- pub const arm1176j_s = Cpu{
+ pub const arm1176j_s = CpuModel{
.name = "arm1176j_s",
.llvm_name = "arm1176j-s",
.features = featureSet(&[_]Feature{
- .armv6kz,
+ .v6kz,
}),
};
- pub const arm1176jz_s = Cpu{
+ pub const arm1176jz_s = CpuModel{
.name = "arm1176jz_s",
.llvm_name = "arm1176jz-s",
.features = featureSet(&[_]Feature{
- .armv6kz,
+ .v6kz,
}),
};
- pub const arm1176jzf_s = Cpu{
+ pub const arm1176jzf_s = CpuModel{
.name = "arm1176jzf_s",
.llvm_name = "arm1176jzf-s",
.features = featureSet(&[_]Feature{
- .armv6kz,
+ .v6kz,
.slowfpvmlx,
.vfp2,
}),
};
- pub const arm710t = Cpu{
+ pub const arm710t = CpuModel{
.name = "arm710t",
.llvm_name = "arm710t",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm720t = Cpu{
+ pub const arm720t = CpuModel{
.name = "arm720t",
.llvm_name = "arm720t",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm7tdmi = Cpu{
+ pub const arm7tdmi = CpuModel{
.name = "arm7tdmi",
.llvm_name = "arm7tdmi",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm7tdmi_s = Cpu{
+ pub const arm7tdmi_s = CpuModel{
.name = "arm7tdmi_s",
.llvm_name = "arm7tdmi-s",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm8 = Cpu{
+ pub const arm8 = CpuModel{
.name = "arm8",
.llvm_name = "arm8",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const arm810 = Cpu{
+ pub const arm810 = CpuModel{
.name = "arm810",
.llvm_name = "arm810",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const arm9 = Cpu{
+ pub const arm9 = CpuModel{
.name = "arm9",
.llvm_name = "arm9",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm920 = Cpu{
+ pub const arm920 = CpuModel{
.name = "arm920",
.llvm_name = "arm920",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm920t = Cpu{
+ pub const arm920t = CpuModel{
.name = "arm920t",
.llvm_name = "arm920t",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm922t = Cpu{
+ pub const arm922t = CpuModel{
.name = "arm922t",
.llvm_name = "arm922t",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm926ej_s = Cpu{
+ pub const arm926ej_s = CpuModel{
.name = "arm926ej_s",
.llvm_name = "arm926ej-s",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm940t = Cpu{
+ pub const arm940t = CpuModel{
.name = "arm940t",
.llvm_name = "arm940t",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const arm946e_s = Cpu{
+ pub const arm946e_s = CpuModel{
.name = "arm946e_s",
.llvm_name = "arm946e-s",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm966e_s = Cpu{
+ pub const arm966e_s = CpuModel{
.name = "arm966e_s",
.llvm_name = "arm966e-s",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm968e_s = Cpu{
+ pub const arm968e_s = CpuModel{
.name = "arm968e_s",
.llvm_name = "arm968e-s",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm9e = Cpu{
+ pub const arm9e = CpuModel{
.name = "arm9e",
.llvm_name = "arm9e",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const arm9tdmi = Cpu{
+ pub const arm9tdmi = CpuModel{
.name = "arm9tdmi",
.llvm_name = "arm9tdmi",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
+ }),
+ };
+ pub const baseline = CpuModel{
+ .name = "baseline",
+ .llvm_name = "generic",
+ .features = featureSet(&[_]Feature{
+ .v6m,
}),
};
- pub const cortex_a12 = Cpu{
+ pub const cortex_a12 = CpuModel{
.name = "cortex_a12",
.llvm_name = "cortex-a12",
.features = featureSet(&[_]Feature{
- .a12,
- .armv7_a,
+ .v7a,
.avoid_partial_cpsr,
.mp,
.ret_addr_stack,
@@ -1640,12 +1527,11 @@ pub const cpu = struct {
.vmlx_forwarding,
}),
};
- pub const cortex_a15 = Cpu{
+ pub const cortex_a15 = CpuModel{
.name = "cortex_a15",
.llvm_name = "cortex-a15",
.features = featureSet(&[_]Feature{
- .a15,
- .armv7_a,
+ .v7a,
.avoid_partial_cpsr,
.dont_widen_vmovs,
.mp,
@@ -1658,12 +1544,11 @@ pub const cpu = struct {
.vldn_align,
}),
};
- pub const cortex_a17 = Cpu{
+ pub const cortex_a17 = CpuModel{
.name = "cortex_a17",
.llvm_name = "cortex-a17",
.features = featureSet(&[_]Feature{
- .a17,
- .armv7_a,
+ .v7a,
.avoid_partial_cpsr,
.mp,
.ret_addr_stack,
@@ -1673,35 +1558,33 @@ pub const cpu = struct {
.vmlx_forwarding,
}),
};
- pub const cortex_a32 = Cpu{
+ pub const cortex_a32 = CpuModel{
.name = "cortex_a32",
.llvm_name = "cortex-a32",
.features = featureSet(&[_]Feature{
- .armv8_a,
.crc,
.crypto,
.hwdiv,
.hwdiv_arm,
+ .v8a,
}),
};
- pub const cortex_a35 = Cpu{
+ pub const cortex_a35 = CpuModel{
.name = "cortex_a35",
.llvm_name = "cortex-a35",
.features = featureSet(&[_]Feature{
- .a35,
- .armv8_a,
.crc,
.crypto,
.hwdiv,
.hwdiv_arm,
+ .v8a,
}),
};
- pub const cortex_a5 = Cpu{
+ pub const cortex_a5 = CpuModel{
.name = "cortex_a5",
.llvm_name = "cortex-a5",
.features = featureSet(&[_]Feature{
- .a5,
- .armv7_a,
+ .v7a,
.mp,
.ret_addr_stack,
.slow_fp_brcc,
@@ -1712,12 +1595,11 @@ pub const cpu = struct {
.vmlx_forwarding,
}),
};
- pub const cortex_a53 = Cpu{
+ pub const cortex_a53 = CpuModel{
.name = "cortex_a53",
.llvm_name = "cortex-a53",
.features = featureSet(&[_]Feature{
- .a53,
- .armv8_a,
+ .v8a,
.crc,
.crypto,
.fpao,
@@ -1725,23 +1607,21 @@ pub const cpu = struct {
.hwdiv_arm,
}),
};
- pub const cortex_a55 = Cpu{
+ pub const cortex_a55 = CpuModel{
.name = "cortex_a55",
.llvm_name = "cortex-a55",
.features = featureSet(&[_]Feature{
- .a55,
- .armv8_2_a,
+ .v8_2a,
.dotprod,
.hwdiv,
.hwdiv_arm,
}),
};
- pub const cortex_a57 = Cpu{
+ pub const cortex_a57 = CpuModel{
.name = "cortex_a57",
.llvm_name = "cortex-a57",
.features = featureSet(&[_]Feature{
- .a57,
- .armv8_a,
+ .v8a,
.avoid_partial_cpsr,
.cheap_predicable_cpsr,
.crc,
@@ -1751,12 +1631,11 @@ pub const cpu = struct {
.hwdiv_arm,
}),
};
- pub const cortex_a7 = Cpu{
+ pub const cortex_a7 = CpuModel{
.name = "cortex_a7",
.llvm_name = "cortex-a7",
.features = featureSet(&[_]Feature{
- .a7,
- .armv7_a,
+ .v7a,
.mp,
.ret_addr_stack,
.slow_fp_brcc,
@@ -1769,47 +1648,44 @@ pub const cpu = struct {
.vmlx_hazards,
}),
};
- pub const cortex_a72 = Cpu{
+ pub const cortex_a72 = CpuModel{
.name = "cortex_a72",
.llvm_name = "cortex-a72",
.features = featureSet(&[_]Feature{
- .a72,
- .armv8_a,
+ .v8a,
.crc,
.crypto,
.hwdiv,
.hwdiv_arm,
}),
};
- pub const cortex_a73 = Cpu{
+ pub const cortex_a73 = CpuModel{
.name = "cortex_a73",
.llvm_name = "cortex-a73",
.features = featureSet(&[_]Feature{
- .a73,
- .armv8_a,
+ .v8a,
.crc,
.crypto,
.hwdiv,
.hwdiv_arm,
}),
};
- pub const cortex_a75 = Cpu{
+ pub const cortex_a75 = CpuModel{
.name = "cortex_a75",
.llvm_name = "cortex-a75",
.features = featureSet(&[_]Feature{
- .a75,
- .armv8_2_a,
+ .v8_2a,
.dotprod,
.hwdiv,
.hwdiv_arm,
}),
};
- pub const cortex_a76 = Cpu{
+ pub const cortex_a76 = CpuModel{
.name = "cortex_a76",
.llvm_name = "cortex-a76",
.features = featureSet(&[_]Feature{
.a76,
- .armv8_2_a,
+ .v8_2a,
.crc,
.crypto,
.dotprod,
@@ -1818,12 +1694,12 @@ pub const cpu = struct {
.hwdiv_arm,
}),
};
- pub const cortex_a76ae = Cpu{
+ pub const cortex_a76ae = CpuModel{
.name = "cortex_a76ae",
.llvm_name = "cortex-a76ae",
.features = featureSet(&[_]Feature{
.a76,
- .armv8_2_a,
+ .v8_2a,
.crc,
.crypto,
.dotprod,
@@ -1832,12 +1708,11 @@ pub const cpu = struct {
.hwdiv_arm,
}),
};
- pub const cortex_a8 = Cpu{
+ pub const cortex_a8 = CpuModel{
.name = "cortex_a8",
.llvm_name = "cortex-a8",
.features = featureSet(&[_]Feature{
- .a8,
- .armv7_a,
+ .v7a,
.nonpipelined_vfp,
.ret_addr_stack,
.slow_fp_brcc,
@@ -1848,12 +1723,11 @@ pub const cpu = struct {
.vmlx_hazards,
}),
};
- pub const cortex_a9 = Cpu{
+ pub const cortex_a9 = CpuModel{
.name = "cortex_a9",
.llvm_name = "cortex-a9",
.features = featureSet(&[_]Feature{
- .a9,
- .armv7_a,
+ .v7a,
.avoid_partial_cpsr,
.expand_fp_mlx,
.fp16,
@@ -1868,51 +1742,51 @@ pub const cpu = struct {
.vmlx_hazards,
}),
};
- pub const cortex_m0 = Cpu{
+ pub const cortex_m0 = CpuModel{
.name = "cortex_m0",
.llvm_name = "cortex-m0",
.features = featureSet(&[_]Feature{
- .armv6_m,
+ .v6m,
}),
};
- pub const cortex_m0plus = Cpu{
+ pub const cortex_m0plus = CpuModel{
.name = "cortex_m0plus",
.llvm_name = "cortex-m0plus",
.features = featureSet(&[_]Feature{
- .armv6_m,
+ .v6m,
}),
};
- pub const cortex_m1 = Cpu{
+ pub const cortex_m1 = CpuModel{
.name = "cortex_m1",
.llvm_name = "cortex-m1",
.features = featureSet(&[_]Feature{
- .armv6_m,
+ .v6m,
}),
};
- pub const cortex_m23 = Cpu{
+ pub const cortex_m23 = CpuModel{
.name = "cortex_m23",
.llvm_name = "cortex-m23",
.features = featureSet(&[_]Feature{
- .armv8_m_base,
+ .v8m,
.no_movt,
}),
};
- pub const cortex_m3 = Cpu{
+ pub const cortex_m3 = CpuModel{
.name = "cortex_m3",
.llvm_name = "cortex-m3",
.features = featureSet(&[_]Feature{
- .armv7_m,
+ .v7m,
.loop_align,
.m3,
.no_branch_predictor,
.use_misched,
}),
};
- pub const cortex_m33 = Cpu{
+ pub const cortex_m33 = CpuModel{
.name = "cortex_m33",
.llvm_name = "cortex-m33",
.features = featureSet(&[_]Feature{
- .armv8_m_main,
+ .v8m_main,
.dsp,
.fp_armv8d16sp,
.loop_align,
@@ -1922,11 +1796,11 @@ pub const cpu = struct {
.use_misched,
}),
};
- pub const cortex_m35p = Cpu{
+ pub const cortex_m35p = CpuModel{
.name = "cortex_m35p",
.llvm_name = "cortex-m35p",
.features = featureSet(&[_]Feature{
- .armv8_m_main,
+ .v8m_main,
.dsp,
.fp_armv8d16sp,
.loop_align,
@@ -1936,11 +1810,11 @@ pub const cpu = struct {
.use_misched,
}),
};
- pub const cortex_m4 = Cpu{
+ pub const cortex_m4 = CpuModel{
.name = "cortex_m4",
.llvm_name = "cortex-m4",
.features = featureSet(&[_]Feature{
- .armv7e_m,
+ .v7em,
.loop_align,
.no_branch_predictor,
.slowfpvfmx,
@@ -1949,29 +1823,29 @@ pub const cpu = struct {
.vfp4d16sp,
}),
};
- pub const cortex_m7 = Cpu{
+ pub const cortex_m7 = CpuModel{
.name = "cortex_m7",
.llvm_name = "cortex-m7",
.features = featureSet(&[_]Feature{
- .armv7e_m,
+ .v7em,
.fp_armv8d16,
}),
};
- pub const cortex_r4 = Cpu{
+ pub const cortex_r4 = CpuModel{
.name = "cortex_r4",
.llvm_name = "cortex-r4",
.features = featureSet(&[_]Feature{
- .armv7_r,
+ .v7r,
.avoid_partial_cpsr,
.r4,
.ret_addr_stack,
}),
};
- pub const cortex_r4f = Cpu{
+ pub const cortex_r4f = CpuModel{
.name = "cortex_r4f",
.llvm_name = "cortex-r4f",
.features = featureSet(&[_]Feature{
- .armv7_r,
+ .v7r,
.avoid_partial_cpsr,
.r4,
.ret_addr_stack,
@@ -1981,14 +1855,13 @@ pub const cpu = struct {
.vfp3d16,
}),
};
- pub const cortex_r5 = Cpu{
+ pub const cortex_r5 = CpuModel{
.name = "cortex_r5",
.llvm_name = "cortex-r5",
.features = featureSet(&[_]Feature{
- .armv7_r,
+ .v7r,
.avoid_partial_cpsr,
.hwdiv_arm,
- .r5,
.ret_addr_stack,
.slow_fp_brcc,
.slowfpvfmx,
@@ -1996,26 +1869,24 @@ pub const cpu = struct {
.vfp3d16,
}),
};
- pub const cortex_r52 = Cpu{
+ pub const cortex_r52 = CpuModel{
.name = "cortex_r52",
.llvm_name = "cortex-r52",
.features = featureSet(&[_]Feature{
- .armv8_r,
+ .v8r,
.fpao,
- .r52,
.use_misched,
}),
};
- pub const cortex_r7 = Cpu{
+ pub const cortex_r7 = CpuModel{
.name = "cortex_r7",
.llvm_name = "cortex-r7",
.features = featureSet(&[_]Feature{
- .armv7_r,
+ .v7r,
.avoid_partial_cpsr,
.fp16,
.hwdiv_arm,
.mp,
- .r7,
.ret_addr_stack,
.slow_fp_brcc,
.slowfpvfmx,
@@ -2023,11 +1894,11 @@ pub const cpu = struct {
.vfp3d16,
}),
};
- pub const cortex_r8 = Cpu{
+ pub const cortex_r8 = CpuModel{
.name = "cortex_r8",
.llvm_name = "cortex-r8",
.features = featureSet(&[_]Feature{
- .armv7_r,
+ .v7r,
.avoid_partial_cpsr,
.fp16,
.hwdiv_arm,
@@ -2039,11 +1910,11 @@ pub const cpu = struct {
.vfp3d16,
}),
};
- pub const cyclone = Cpu{
+ pub const cyclone = CpuModel{
.name = "cyclone",
.llvm_name = "cyclone",
.features = featureSet(&[_]Feature{
- .armv8_a,
+ .v8a,
.avoid_movs_shop,
.avoid_partial_cpsr,
.crypto,
@@ -2061,119 +1932,117 @@ pub const cpu = struct {
.zcz,
}),
};
- pub const ep9312 = Cpu{
+ pub const ep9312 = CpuModel{
.name = "ep9312",
.llvm_name = "ep9312",
.features = featureSet(&[_]Feature{
- .armv4t,
+ .v4t,
}),
};
- pub const exynos_m1 = Cpu{
+ pub const exynos_m1 = CpuModel{
.name = "exynos_m1",
.llvm_name = null,
.features = featureSet(&[_]Feature{
- .armv8_a,
+ .v8a,
.exynos,
}),
};
- pub const exynos_m2 = Cpu{
+ pub const exynos_m2 = CpuModel{
.name = "exynos_m2",
.llvm_name = null,
.features = featureSet(&[_]Feature{
- .armv8_a,
+ .v8a,
.exynos,
}),
};
- pub const exynos_m3 = Cpu{
+ pub const exynos_m3 = CpuModel{
.name = "exynos_m3",
.llvm_name = "exynos-m3",
.features = featureSet(&[_]Feature{
- .armv8_a,
+ .v8_2a,
.exynos,
}),
};
- pub const exynos_m4 = Cpu{
+ pub const exynos_m4 = CpuModel{
.name = "exynos_m4",
.llvm_name = "exynos-m4",
.features = featureSet(&[_]Feature{
- .armv8_2_a,
+ .v8_2a,
.dotprod,
.exynos,
.fullfp16,
}),
};
- pub const exynos_m5 = Cpu{
+ pub const exynos_m5 = CpuModel{
.name = "exynos_m5",
.llvm_name = "exynos-m5",
.features = featureSet(&[_]Feature{
- .armv8_2_a,
.dotprod,
.exynos,
.fullfp16,
+ .v8_2a,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const iwmmxt = Cpu{
+ pub const iwmmxt = CpuModel{
.name = "iwmmxt",
.llvm_name = "iwmmxt",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
- pub const krait = Cpu{
+ pub const krait = CpuModel{
.name = "krait",
.llvm_name = "krait",
.features = featureSet(&[_]Feature{
- .armv7_a,
.avoid_partial_cpsr,
.fp16,
.hwdiv,
.hwdiv_arm,
- .krait,
.muxed_units,
.ret_addr_stack,
+ .v7a,
.vfp4,
.vldn_align,
.vmlx_forwarding,
}),
};
- pub const kryo = Cpu{
+ pub const kryo = CpuModel{
.name = "kryo",
.llvm_name = "kryo",
.features = featureSet(&[_]Feature{
- .armv8_a,
.crc,
.crypto,
.hwdiv,
.hwdiv_arm,
- .kryo,
+ .v8a,
}),
};
- pub const mpcore = Cpu{
+ pub const mpcore = CpuModel{
.name = "mpcore",
.llvm_name = "mpcore",
.features = featureSet(&[_]Feature{
- .armv6k,
+ .v6k,
.slowfpvmlx,
.vfp2,
}),
};
- pub const mpcorenovfp = Cpu{
+ pub const mpcorenovfp = CpuModel{
.name = "mpcorenovfp",
.llvm_name = "mpcorenovfp",
.features = featureSet(&[_]Feature{
- .armv6k,
+ .v6k,
}),
};
- pub const neoverse_n1 = Cpu{
+ pub const neoverse_n1 = CpuModel{
.name = "neoverse_n1",
.llvm_name = "neoverse-n1",
.features = featureSet(&[_]Feature{
- .armv8_2_a,
+ .v8_2a,
.crc,
.crypto,
.dotprod,
@@ -2181,56 +2050,56 @@ pub const cpu = struct {
.hwdiv_arm,
}),
};
- pub const sc000 = Cpu{
+ pub const sc000 = CpuModel{
.name = "sc000",
.llvm_name = "sc000",
.features = featureSet(&[_]Feature{
- .armv6_m,
+ .v6m,
}),
};
- pub const sc300 = Cpu{
+ pub const sc300 = CpuModel{
.name = "sc300",
.llvm_name = "sc300",
.features = featureSet(&[_]Feature{
- .armv7_m,
+ .v7m,
.m3,
.no_branch_predictor,
.use_misched,
}),
};
- pub const strongarm = Cpu{
+ pub const strongarm = CpuModel{
.name = "strongarm",
.llvm_name = "strongarm",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const strongarm110 = Cpu{
+ pub const strongarm110 = CpuModel{
.name = "strongarm110",
.llvm_name = "strongarm110",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const strongarm1100 = Cpu{
+ pub const strongarm1100 = CpuModel{
.name = "strongarm1100",
.llvm_name = "strongarm1100",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const strongarm1110 = Cpu{
+ pub const strongarm1110 = CpuModel{
.name = "strongarm1110",
.llvm_name = "strongarm1110",
.features = featureSet(&[_]Feature{
- .armv4,
+ .v4,
}),
};
- pub const swift = Cpu{
+ pub const swift = CpuModel{
.name = "swift",
.llvm_name = "swift",
.features = featureSet(&[_]Feature{
- .armv7_a,
+ .v7a,
.avoid_movs_shop,
.avoid_partial_cpsr,
.disable_postra_scheduler,
@@ -2254,11 +2123,11 @@ pub const cpu = struct {
.wide_stride_vfp,
}),
};
- pub const xscale = Cpu{
+ pub const xscale = CpuModel{
.name = "xscale",
.llvm_name = "xscale",
.features = featureSet(&[_]Feature{
- .armv5te,
+ .v5te,
}),
};
};
@@ -2266,7 +2135,7 @@ pub const cpu = struct {
/// All arm CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.arm1020e,
&cpu.arm1020t,
&cpu.arm1022e,
diff --git a/lib/std/target/avr.zig b/lib/std/target/avr.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
addsubiw,
@@ -37,12 +38,12 @@ pub const Feature = enum {
xmegau,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.addsubiw)] = .{
.llvm_name = "addsubiw",
.description = "Enable 16-bit register-immediate addition and subtraction instructions",
@@ -293,28 +294,28 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const at43usb320 = Cpu{
+ pub const at43usb320 = CpuModel{
.name = "at43usb320",
.llvm_name = "at43usb320",
.features = featureSet(&[_]Feature{
.avr31,
}),
};
- pub const at43usb355 = Cpu{
+ pub const at43usb355 = CpuModel{
.name = "at43usb355",
.llvm_name = "at43usb355",
.features = featureSet(&[_]Feature{
.avr3,
}),
};
- pub const at76c711 = Cpu{
+ pub const at76c711 = CpuModel{
.name = "at76c711",
.llvm_name = "at76c711",
.features = featureSet(&[_]Feature{
.avr3,
}),
};
- pub const at86rf401 = Cpu{
+ pub const at86rf401 = CpuModel{
.name = "at86rf401",
.llvm_name = "at86rf401",
.features = featureSet(&[_]Feature{
@@ -323,217 +324,217 @@ pub const cpu = struct {
.movw,
}),
};
- pub const at90c8534 = Cpu{
+ pub const at90c8534 = CpuModel{
.name = "at90c8534",
.llvm_name = "at90c8534",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90can128 = Cpu{
+ pub const at90can128 = CpuModel{
.name = "at90can128",
.llvm_name = "at90can128",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const at90can32 = Cpu{
+ pub const at90can32 = CpuModel{
.name = "at90can32",
.llvm_name = "at90can32",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90can64 = Cpu{
+ pub const at90can64 = CpuModel{
.name = "at90can64",
.llvm_name = "at90can64",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90pwm1 = Cpu{
+ pub const at90pwm1 = CpuModel{
.name = "at90pwm1",
.llvm_name = "at90pwm1",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90pwm161 = Cpu{
+ pub const at90pwm161 = CpuModel{
.name = "at90pwm161",
.llvm_name = "at90pwm161",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90pwm2 = Cpu{
+ pub const at90pwm2 = CpuModel{
.name = "at90pwm2",
.llvm_name = "at90pwm2",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90pwm216 = Cpu{
+ pub const at90pwm216 = CpuModel{
.name = "at90pwm216",
.llvm_name = "at90pwm216",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90pwm2b = Cpu{
+ pub const at90pwm2b = CpuModel{
.name = "at90pwm2b",
.llvm_name = "at90pwm2b",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90pwm3 = Cpu{
+ pub const at90pwm3 = CpuModel{
.name = "at90pwm3",
.llvm_name = "at90pwm3",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90pwm316 = Cpu{
+ pub const at90pwm316 = CpuModel{
.name = "at90pwm316",
.llvm_name = "at90pwm316",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90pwm3b = Cpu{
+ pub const at90pwm3b = CpuModel{
.name = "at90pwm3b",
.llvm_name = "at90pwm3b",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90pwm81 = Cpu{
+ pub const at90pwm81 = CpuModel{
.name = "at90pwm81",
.llvm_name = "at90pwm81",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const at90s1200 = Cpu{
+ pub const at90s1200 = CpuModel{
.name = "at90s1200",
.llvm_name = "at90s1200",
.features = featureSet(&[_]Feature{
.avr0,
}),
};
- pub const at90s2313 = Cpu{
+ pub const at90s2313 = CpuModel{
.name = "at90s2313",
.llvm_name = "at90s2313",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s2323 = Cpu{
+ pub const at90s2323 = CpuModel{
.name = "at90s2323",
.llvm_name = "at90s2323",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s2333 = Cpu{
+ pub const at90s2333 = CpuModel{
.name = "at90s2333",
.llvm_name = "at90s2333",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s2343 = Cpu{
+ pub const at90s2343 = CpuModel{
.name = "at90s2343",
.llvm_name = "at90s2343",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s4414 = Cpu{
+ pub const at90s4414 = CpuModel{
.name = "at90s4414",
.llvm_name = "at90s4414",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s4433 = Cpu{
+ pub const at90s4433 = CpuModel{
.name = "at90s4433",
.llvm_name = "at90s4433",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s4434 = Cpu{
+ pub const at90s4434 = CpuModel{
.name = "at90s4434",
.llvm_name = "at90s4434",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s8515 = Cpu{
+ pub const at90s8515 = CpuModel{
.name = "at90s8515",
.llvm_name = "at90s8515",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90s8535 = Cpu{
+ pub const at90s8535 = CpuModel{
.name = "at90s8535",
.llvm_name = "at90s8535",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const at90scr100 = Cpu{
+ pub const at90scr100 = CpuModel{
.name = "at90scr100",
.llvm_name = "at90scr100",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90usb1286 = Cpu{
+ pub const at90usb1286 = CpuModel{
.name = "at90usb1286",
.llvm_name = "at90usb1286",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const at90usb1287 = Cpu{
+ pub const at90usb1287 = CpuModel{
.name = "at90usb1287",
.llvm_name = "at90usb1287",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const at90usb162 = Cpu{
+ pub const at90usb162 = CpuModel{
.name = "at90usb162",
.llvm_name = "at90usb162",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const at90usb646 = Cpu{
+ pub const at90usb646 = CpuModel{
.name = "at90usb646",
.llvm_name = "at90usb646",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90usb647 = Cpu{
+ pub const at90usb647 = CpuModel{
.name = "at90usb647",
.llvm_name = "at90usb647",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const at90usb82 = Cpu{
+ pub const at90usb82 = CpuModel{
.name = "at90usb82",
.llvm_name = "at90usb82",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const at94k = Cpu{
+ pub const at94k = CpuModel{
.name = "at94k",
.llvm_name = "at94k",
.features = featureSet(&[_]Feature{
@@ -543,133 +544,133 @@ pub const cpu = struct {
.mul,
}),
};
- pub const ata5272 = Cpu{
+ pub const ata5272 = CpuModel{
.name = "ata5272",
.llvm_name = "ata5272",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const ata5505 = Cpu{
+ pub const ata5505 = CpuModel{
.name = "ata5505",
.llvm_name = "ata5505",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const ata5790 = Cpu{
+ pub const ata5790 = CpuModel{
.name = "ata5790",
.llvm_name = "ata5790",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const ata5795 = Cpu{
+ pub const ata5795 = CpuModel{
.name = "ata5795",
.llvm_name = "ata5795",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const ata6285 = Cpu{
+ pub const ata6285 = CpuModel{
.name = "ata6285",
.llvm_name = "ata6285",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const ata6286 = Cpu{
+ pub const ata6286 = CpuModel{
.name = "ata6286",
.llvm_name = "ata6286",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const ata6289 = Cpu{
+ pub const ata6289 = CpuModel{
.name = "ata6289",
.llvm_name = "ata6289",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega103 = Cpu{
+ pub const atmega103 = CpuModel{
.name = "atmega103",
.llvm_name = "atmega103",
.features = featureSet(&[_]Feature{
.avr31,
}),
};
- pub const atmega128 = Cpu{
+ pub const atmega128 = CpuModel{
.name = "atmega128",
.llvm_name = "atmega128",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega1280 = Cpu{
+ pub const atmega1280 = CpuModel{
.name = "atmega1280",
.llvm_name = "atmega1280",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega1281 = Cpu{
+ pub const atmega1281 = CpuModel{
.name = "atmega1281",
.llvm_name = "atmega1281",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega1284 = Cpu{
+ pub const atmega1284 = CpuModel{
.name = "atmega1284",
.llvm_name = "atmega1284",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega1284p = Cpu{
+ pub const atmega1284p = CpuModel{
.name = "atmega1284p",
.llvm_name = "atmega1284p",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega1284rfr2 = Cpu{
+ pub const atmega1284rfr2 = CpuModel{
.name = "atmega1284rfr2",
.llvm_name = "atmega1284rfr2",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega128a = Cpu{
+ pub const atmega128a = CpuModel{
.name = "atmega128a",
.llvm_name = "atmega128a",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega128rfa1 = Cpu{
+ pub const atmega128rfa1 = CpuModel{
.name = "atmega128rfa1",
.llvm_name = "atmega128rfa1",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega128rfr2 = Cpu{
+ pub const atmega128rfr2 = CpuModel{
.name = "atmega128rfr2",
.llvm_name = "atmega128rfr2",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const atmega16 = Cpu{
+ pub const atmega16 = CpuModel{
.name = "atmega16",
.llvm_name = "atmega16",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega161 = Cpu{
+ pub const atmega161 = CpuModel{
.name = "atmega161",
.llvm_name = "atmega161",
.features = featureSet(&[_]Feature{
@@ -680,14 +681,14 @@ pub const cpu = struct {
.spm,
}),
};
- pub const atmega162 = Cpu{
+ pub const atmega162 = CpuModel{
.name = "atmega162",
.llvm_name = "atmega162",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega163 = Cpu{
+ pub const atmega163 = CpuModel{
.name = "atmega163",
.llvm_name = "atmega163",
.features = featureSet(&[_]Feature{
@@ -698,623 +699,623 @@ pub const cpu = struct {
.spm,
}),
};
- pub const atmega164a = Cpu{
+ pub const atmega164a = CpuModel{
.name = "atmega164a",
.llvm_name = "atmega164a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega164p = Cpu{
+ pub const atmega164p = CpuModel{
.name = "atmega164p",
.llvm_name = "atmega164p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega164pa = Cpu{
+ pub const atmega164pa = CpuModel{
.name = "atmega164pa",
.llvm_name = "atmega164pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega165 = Cpu{
+ pub const atmega165 = CpuModel{
.name = "atmega165",
.llvm_name = "atmega165",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega165a = Cpu{
+ pub const atmega165a = CpuModel{
.name = "atmega165a",
.llvm_name = "atmega165a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega165p = Cpu{
+ pub const atmega165p = CpuModel{
.name = "atmega165p",
.llvm_name = "atmega165p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega165pa = Cpu{
+ pub const atmega165pa = CpuModel{
.name = "atmega165pa",
.llvm_name = "atmega165pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega168 = Cpu{
+ pub const atmega168 = CpuModel{
.name = "atmega168",
.llvm_name = "atmega168",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega168a = Cpu{
+ pub const atmega168a = CpuModel{
.name = "atmega168a",
.llvm_name = "atmega168a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega168p = Cpu{
+ pub const atmega168p = CpuModel{
.name = "atmega168p",
.llvm_name = "atmega168p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega168pa = Cpu{
+ pub const atmega168pa = CpuModel{
.name = "atmega168pa",
.llvm_name = "atmega168pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega169 = Cpu{
+ pub const atmega169 = CpuModel{
.name = "atmega169",
.llvm_name = "atmega169",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega169a = Cpu{
+ pub const atmega169a = CpuModel{
.name = "atmega169a",
.llvm_name = "atmega169a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega169p = Cpu{
+ pub const atmega169p = CpuModel{
.name = "atmega169p",
.llvm_name = "atmega169p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega169pa = Cpu{
+ pub const atmega169pa = CpuModel{
.name = "atmega169pa",
.llvm_name = "atmega169pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16a = Cpu{
+ pub const atmega16a = CpuModel{
.name = "atmega16a",
.llvm_name = "atmega16a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16hva = Cpu{
+ pub const atmega16hva = CpuModel{
.name = "atmega16hva",
.llvm_name = "atmega16hva",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16hva2 = Cpu{
+ pub const atmega16hva2 = CpuModel{
.name = "atmega16hva2",
.llvm_name = "atmega16hva2",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16hvb = Cpu{
+ pub const atmega16hvb = CpuModel{
.name = "atmega16hvb",
.llvm_name = "atmega16hvb",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16hvbrevb = Cpu{
+ pub const atmega16hvbrevb = CpuModel{
.name = "atmega16hvbrevb",
.llvm_name = "atmega16hvbrevb",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16m1 = Cpu{
+ pub const atmega16m1 = CpuModel{
.name = "atmega16m1",
.llvm_name = "atmega16m1",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega16u2 = Cpu{
+ pub const atmega16u2 = CpuModel{
.name = "atmega16u2",
.llvm_name = "atmega16u2",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const atmega16u4 = Cpu{
+ pub const atmega16u4 = CpuModel{
.name = "atmega16u4",
.llvm_name = "atmega16u4",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega2560 = Cpu{
+ pub const atmega2560 = CpuModel{
.name = "atmega2560",
.llvm_name = "atmega2560",
.features = featureSet(&[_]Feature{
.avr6,
}),
};
- pub const atmega2561 = Cpu{
+ pub const atmega2561 = CpuModel{
.name = "atmega2561",
.llvm_name = "atmega2561",
.features = featureSet(&[_]Feature{
.avr6,
}),
};
- pub const atmega2564rfr2 = Cpu{
+ pub const atmega2564rfr2 = CpuModel{
.name = "atmega2564rfr2",
.llvm_name = "atmega2564rfr2",
.features = featureSet(&[_]Feature{
.avr6,
}),
};
- pub const atmega256rfr2 = Cpu{
+ pub const atmega256rfr2 = CpuModel{
.name = "atmega256rfr2",
.llvm_name = "atmega256rfr2",
.features = featureSet(&[_]Feature{
.avr6,
}),
};
- pub const atmega32 = Cpu{
+ pub const atmega32 = CpuModel{
.name = "atmega32",
.llvm_name = "atmega32",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega323 = Cpu{
+ pub const atmega323 = CpuModel{
.name = "atmega323",
.llvm_name = "atmega323",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega324a = Cpu{
+ pub const atmega324a = CpuModel{
.name = "atmega324a",
.llvm_name = "atmega324a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega324p = Cpu{
+ pub const atmega324p = CpuModel{
.name = "atmega324p",
.llvm_name = "atmega324p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega324pa = Cpu{
+ pub const atmega324pa = CpuModel{
.name = "atmega324pa",
.llvm_name = "atmega324pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega325 = Cpu{
+ pub const atmega325 = CpuModel{
.name = "atmega325",
.llvm_name = "atmega325",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3250 = Cpu{
+ pub const atmega3250 = CpuModel{
.name = "atmega3250",
.llvm_name = "atmega3250",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3250a = Cpu{
+ pub const atmega3250a = CpuModel{
.name = "atmega3250a",
.llvm_name = "atmega3250a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3250p = Cpu{
+ pub const atmega3250p = CpuModel{
.name = "atmega3250p",
.llvm_name = "atmega3250p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3250pa = Cpu{
+ pub const atmega3250pa = CpuModel{
.name = "atmega3250pa",
.llvm_name = "atmega3250pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega325a = Cpu{
+ pub const atmega325a = CpuModel{
.name = "atmega325a",
.llvm_name = "atmega325a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega325p = Cpu{
+ pub const atmega325p = CpuModel{
.name = "atmega325p",
.llvm_name = "atmega325p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega325pa = Cpu{
+ pub const atmega325pa = CpuModel{
.name = "atmega325pa",
.llvm_name = "atmega325pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega328 = Cpu{
+ pub const atmega328 = CpuModel{
.name = "atmega328",
.llvm_name = "atmega328",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega328p = Cpu{
+ pub const atmega328p = CpuModel{
.name = "atmega328p",
.llvm_name = "atmega328p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega329 = Cpu{
+ pub const atmega329 = CpuModel{
.name = "atmega329",
.llvm_name = "atmega329",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3290 = Cpu{
+ pub const atmega3290 = CpuModel{
.name = "atmega3290",
.llvm_name = "atmega3290",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3290a = Cpu{
+ pub const atmega3290a = CpuModel{
.name = "atmega3290a",
.llvm_name = "atmega3290a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3290p = Cpu{
+ pub const atmega3290p = CpuModel{
.name = "atmega3290p",
.llvm_name = "atmega3290p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega3290pa = Cpu{
+ pub const atmega3290pa = CpuModel{
.name = "atmega3290pa",
.llvm_name = "atmega3290pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega329a = Cpu{
+ pub const atmega329a = CpuModel{
.name = "atmega329a",
.llvm_name = "atmega329a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega329p = Cpu{
+ pub const atmega329p = CpuModel{
.name = "atmega329p",
.llvm_name = "atmega329p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega329pa = Cpu{
+ pub const atmega329pa = CpuModel{
.name = "atmega329pa",
.llvm_name = "atmega329pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32a = Cpu{
+ pub const atmega32a = CpuModel{
.name = "atmega32a",
.llvm_name = "atmega32a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32c1 = Cpu{
+ pub const atmega32c1 = CpuModel{
.name = "atmega32c1",
.llvm_name = "atmega32c1",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32hvb = Cpu{
+ pub const atmega32hvb = CpuModel{
.name = "atmega32hvb",
.llvm_name = "atmega32hvb",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32hvbrevb = Cpu{
+ pub const atmega32hvbrevb = CpuModel{
.name = "atmega32hvbrevb",
.llvm_name = "atmega32hvbrevb",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32m1 = Cpu{
+ pub const atmega32m1 = CpuModel{
.name = "atmega32m1",
.llvm_name = "atmega32m1",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32u2 = Cpu{
+ pub const atmega32u2 = CpuModel{
.name = "atmega32u2",
.llvm_name = "atmega32u2",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const atmega32u4 = Cpu{
+ pub const atmega32u4 = CpuModel{
.name = "atmega32u4",
.llvm_name = "atmega32u4",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega32u6 = Cpu{
+ pub const atmega32u6 = CpuModel{
.name = "atmega32u6",
.llvm_name = "atmega32u6",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega406 = Cpu{
+ pub const atmega406 = CpuModel{
.name = "atmega406",
.llvm_name = "atmega406",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega48 = Cpu{
+ pub const atmega48 = CpuModel{
.name = "atmega48",
.llvm_name = "atmega48",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega48a = Cpu{
+ pub const atmega48a = CpuModel{
.name = "atmega48a",
.llvm_name = "atmega48a",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega48p = Cpu{
+ pub const atmega48p = CpuModel{
.name = "atmega48p",
.llvm_name = "atmega48p",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega48pa = Cpu{
+ pub const atmega48pa = CpuModel{
.name = "atmega48pa",
.llvm_name = "atmega48pa",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega64 = Cpu{
+ pub const atmega64 = CpuModel{
.name = "atmega64",
.llvm_name = "atmega64",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega640 = Cpu{
+ pub const atmega640 = CpuModel{
.name = "atmega640",
.llvm_name = "atmega640",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega644 = Cpu{
+ pub const atmega644 = CpuModel{
.name = "atmega644",
.llvm_name = "atmega644",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega644a = Cpu{
+ pub const atmega644a = CpuModel{
.name = "atmega644a",
.llvm_name = "atmega644a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega644p = Cpu{
+ pub const atmega644p = CpuModel{
.name = "atmega644p",
.llvm_name = "atmega644p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega644pa = Cpu{
+ pub const atmega644pa = CpuModel{
.name = "atmega644pa",
.llvm_name = "atmega644pa",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega644rfr2 = Cpu{
+ pub const atmega644rfr2 = CpuModel{
.name = "atmega644rfr2",
.llvm_name = "atmega644rfr2",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega645 = Cpu{
+ pub const atmega645 = CpuModel{
.name = "atmega645",
.llvm_name = "atmega645",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6450 = Cpu{
+ pub const atmega6450 = CpuModel{
.name = "atmega6450",
.llvm_name = "atmega6450",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6450a = Cpu{
+ pub const atmega6450a = CpuModel{
.name = "atmega6450a",
.llvm_name = "atmega6450a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6450p = Cpu{
+ pub const atmega6450p = CpuModel{
.name = "atmega6450p",
.llvm_name = "atmega6450p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega645a = Cpu{
+ pub const atmega645a = CpuModel{
.name = "atmega645a",
.llvm_name = "atmega645a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega645p = Cpu{
+ pub const atmega645p = CpuModel{
.name = "atmega645p",
.llvm_name = "atmega645p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega649 = Cpu{
+ pub const atmega649 = CpuModel{
.name = "atmega649",
.llvm_name = "atmega649",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6490 = Cpu{
+ pub const atmega6490 = CpuModel{
.name = "atmega6490",
.llvm_name = "atmega6490",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6490a = Cpu{
+ pub const atmega6490a = CpuModel{
.name = "atmega6490a",
.llvm_name = "atmega6490a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega6490p = Cpu{
+ pub const atmega6490p = CpuModel{
.name = "atmega6490p",
.llvm_name = "atmega6490p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega649a = Cpu{
+ pub const atmega649a = CpuModel{
.name = "atmega649a",
.llvm_name = "atmega649a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega649p = Cpu{
+ pub const atmega649p = CpuModel{
.name = "atmega649p",
.llvm_name = "atmega649p",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega64a = Cpu{
+ pub const atmega64a = CpuModel{
.name = "atmega64a",
.llvm_name = "atmega64a",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega64c1 = Cpu{
+ pub const atmega64c1 = CpuModel{
.name = "atmega64c1",
.llvm_name = "atmega64c1",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega64hve = Cpu{
+ pub const atmega64hve = CpuModel{
.name = "atmega64hve",
.llvm_name = "atmega64hve",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega64m1 = Cpu{
+ pub const atmega64m1 = CpuModel{
.name = "atmega64m1",
.llvm_name = "atmega64m1",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega64rfr2 = Cpu{
+ pub const atmega64rfr2 = CpuModel{
.name = "atmega64rfr2",
.llvm_name = "atmega64rfr2",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const atmega8 = Cpu{
+ pub const atmega8 = CpuModel{
.name = "atmega8",
.llvm_name = "atmega8",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega8515 = Cpu{
+ pub const atmega8515 = CpuModel{
.name = "atmega8515",
.llvm_name = "atmega8515",
.features = featureSet(&[_]Feature{
@@ -1325,7 +1326,7 @@ pub const cpu = struct {
.spm,
}),
};
- pub const atmega8535 = Cpu{
+ pub const atmega8535 = CpuModel{
.name = "atmega8535",
.llvm_name = "atmega8535",
.features = featureSet(&[_]Feature{
@@ -1336,175 +1337,175 @@ pub const cpu = struct {
.spm,
}),
};
- pub const atmega88 = Cpu{
+ pub const atmega88 = CpuModel{
.name = "atmega88",
.llvm_name = "atmega88",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega88a = Cpu{
+ pub const atmega88a = CpuModel{
.name = "atmega88a",
.llvm_name = "atmega88a",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega88p = Cpu{
+ pub const atmega88p = CpuModel{
.name = "atmega88p",
.llvm_name = "atmega88p",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega88pa = Cpu{
+ pub const atmega88pa = CpuModel{
.name = "atmega88pa",
.llvm_name = "atmega88pa",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega8a = Cpu{
+ pub const atmega8a = CpuModel{
.name = "atmega8a",
.llvm_name = "atmega8a",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega8hva = Cpu{
+ pub const atmega8hva = CpuModel{
.name = "atmega8hva",
.llvm_name = "atmega8hva",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const atmega8u2 = Cpu{
+ pub const atmega8u2 = CpuModel{
.name = "atmega8u2",
.llvm_name = "atmega8u2",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const attiny10 = Cpu{
+ pub const attiny10 = CpuModel{
.name = "attiny10",
.llvm_name = "attiny10",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny102 = Cpu{
+ pub const attiny102 = CpuModel{
.name = "attiny102",
.llvm_name = "attiny102",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny104 = Cpu{
+ pub const attiny104 = CpuModel{
.name = "attiny104",
.llvm_name = "attiny104",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny11 = Cpu{
+ pub const attiny11 = CpuModel{
.name = "attiny11",
.llvm_name = "attiny11",
.features = featureSet(&[_]Feature{
.avr1,
}),
};
- pub const attiny12 = Cpu{
+ pub const attiny12 = CpuModel{
.name = "attiny12",
.llvm_name = "attiny12",
.features = featureSet(&[_]Feature{
.avr1,
}),
};
- pub const attiny13 = Cpu{
+ pub const attiny13 = CpuModel{
.name = "attiny13",
.llvm_name = "attiny13",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny13a = Cpu{
+ pub const attiny13a = CpuModel{
.name = "attiny13a",
.llvm_name = "attiny13a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny15 = Cpu{
+ pub const attiny15 = CpuModel{
.name = "attiny15",
.llvm_name = "attiny15",
.features = featureSet(&[_]Feature{
.avr1,
}),
};
- pub const attiny1634 = Cpu{
+ pub const attiny1634 = CpuModel{
.name = "attiny1634",
.llvm_name = "attiny1634",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const attiny167 = Cpu{
+ pub const attiny167 = CpuModel{
.name = "attiny167",
.llvm_name = "attiny167",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const attiny20 = Cpu{
+ pub const attiny20 = CpuModel{
.name = "attiny20",
.llvm_name = "attiny20",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny22 = Cpu{
+ pub const attiny22 = CpuModel{
.name = "attiny22",
.llvm_name = "attiny22",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const attiny2313 = Cpu{
+ pub const attiny2313 = CpuModel{
.name = "attiny2313",
.llvm_name = "attiny2313",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny2313a = Cpu{
+ pub const attiny2313a = CpuModel{
.name = "attiny2313a",
.llvm_name = "attiny2313a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny24 = Cpu{
+ pub const attiny24 = CpuModel{
.name = "attiny24",
.llvm_name = "attiny24",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny24a = Cpu{
+ pub const attiny24a = CpuModel{
.name = "attiny24a",
.llvm_name = "attiny24a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny25 = Cpu{
+ pub const attiny25 = CpuModel{
.name = "attiny25",
.llvm_name = "attiny25",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny26 = Cpu{
+ pub const attiny26 = CpuModel{
.name = "attiny26",
.llvm_name = "attiny26",
.features = featureSet(&[_]Feature{
@@ -1512,602 +1513,602 @@ pub const cpu = struct {
.lpmx,
}),
};
- pub const attiny261 = Cpu{
+ pub const attiny261 = CpuModel{
.name = "attiny261",
.llvm_name = "attiny261",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny261a = Cpu{
+ pub const attiny261a = CpuModel{
.name = "attiny261a",
.llvm_name = "attiny261a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny28 = Cpu{
+ pub const attiny28 = CpuModel{
.name = "attiny28",
.llvm_name = "attiny28",
.features = featureSet(&[_]Feature{
.avr1,
}),
};
- pub const attiny4 = Cpu{
+ pub const attiny4 = CpuModel{
.name = "attiny4",
.llvm_name = "attiny4",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny40 = Cpu{
+ pub const attiny40 = CpuModel{
.name = "attiny40",
.llvm_name = "attiny40",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny4313 = Cpu{
+ pub const attiny4313 = CpuModel{
.name = "attiny4313",
.llvm_name = "attiny4313",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny43u = Cpu{
+ pub const attiny43u = CpuModel{
.name = "attiny43u",
.llvm_name = "attiny43u",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny44 = Cpu{
+ pub const attiny44 = CpuModel{
.name = "attiny44",
.llvm_name = "attiny44",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny44a = Cpu{
+ pub const attiny44a = CpuModel{
.name = "attiny44a",
.llvm_name = "attiny44a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny45 = Cpu{
+ pub const attiny45 = CpuModel{
.name = "attiny45",
.llvm_name = "attiny45",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny461 = Cpu{
+ pub const attiny461 = CpuModel{
.name = "attiny461",
.llvm_name = "attiny461",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny461a = Cpu{
+ pub const attiny461a = CpuModel{
.name = "attiny461a",
.llvm_name = "attiny461a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny48 = Cpu{
+ pub const attiny48 = CpuModel{
.name = "attiny48",
.llvm_name = "attiny48",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny5 = Cpu{
+ pub const attiny5 = CpuModel{
.name = "attiny5",
.llvm_name = "attiny5",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const attiny828 = Cpu{
+ pub const attiny828 = CpuModel{
.name = "attiny828",
.llvm_name = "attiny828",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny84 = Cpu{
+ pub const attiny84 = CpuModel{
.name = "attiny84",
.llvm_name = "attiny84",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny84a = Cpu{
+ pub const attiny84a = CpuModel{
.name = "attiny84a",
.llvm_name = "attiny84a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny85 = Cpu{
+ pub const attiny85 = CpuModel{
.name = "attiny85",
.llvm_name = "attiny85",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny861 = Cpu{
+ pub const attiny861 = CpuModel{
.name = "attiny861",
.llvm_name = "attiny861",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny861a = Cpu{
+ pub const attiny861a = CpuModel{
.name = "attiny861a",
.llvm_name = "attiny861a",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny87 = Cpu{
+ pub const attiny87 = CpuModel{
.name = "attiny87",
.llvm_name = "attiny87",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny88 = Cpu{
+ pub const attiny88 = CpuModel{
.name = "attiny88",
.llvm_name = "attiny88",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const attiny9 = Cpu{
+ pub const attiny9 = CpuModel{
.name = "attiny9",
.llvm_name = "attiny9",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const atxmega128a1 = Cpu{
+ pub const atxmega128a1 = CpuModel{
.name = "atxmega128a1",
.llvm_name = "atxmega128a1",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega128a1u = Cpu{
+ pub const atxmega128a1u = CpuModel{
.name = "atxmega128a1u",
.llvm_name = "atxmega128a1u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128a3 = Cpu{
+ pub const atxmega128a3 = CpuModel{
.name = "atxmega128a3",
.llvm_name = "atxmega128a3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega128a3u = Cpu{
+ pub const atxmega128a3u = CpuModel{
.name = "atxmega128a3u",
.llvm_name = "atxmega128a3u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128a4u = Cpu{
+ pub const atxmega128a4u = CpuModel{
.name = "atxmega128a4u",
.llvm_name = "atxmega128a4u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128b1 = Cpu{
+ pub const atxmega128b1 = CpuModel{
.name = "atxmega128b1",
.llvm_name = "atxmega128b1",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128b3 = Cpu{
+ pub const atxmega128b3 = CpuModel{
.name = "atxmega128b3",
.llvm_name = "atxmega128b3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128c3 = Cpu{
+ pub const atxmega128c3 = CpuModel{
.name = "atxmega128c3",
.llvm_name = "atxmega128c3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega128d3 = Cpu{
+ pub const atxmega128d3 = CpuModel{
.name = "atxmega128d3",
.llvm_name = "atxmega128d3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega128d4 = Cpu{
+ pub const atxmega128d4 = CpuModel{
.name = "atxmega128d4",
.llvm_name = "atxmega128d4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega16a4 = Cpu{
+ pub const atxmega16a4 = CpuModel{
.name = "atxmega16a4",
.llvm_name = "atxmega16a4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega16a4u = Cpu{
+ pub const atxmega16a4u = CpuModel{
.name = "atxmega16a4u",
.llvm_name = "atxmega16a4u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega16c4 = Cpu{
+ pub const atxmega16c4 = CpuModel{
.name = "atxmega16c4",
.llvm_name = "atxmega16c4",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega16d4 = Cpu{
+ pub const atxmega16d4 = CpuModel{
.name = "atxmega16d4",
.llvm_name = "atxmega16d4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega16e5 = Cpu{
+ pub const atxmega16e5 = CpuModel{
.name = "atxmega16e5",
.llvm_name = "atxmega16e5",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega192a3 = Cpu{
+ pub const atxmega192a3 = CpuModel{
.name = "atxmega192a3",
.llvm_name = "atxmega192a3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega192a3u = Cpu{
+ pub const atxmega192a3u = CpuModel{
.name = "atxmega192a3u",
.llvm_name = "atxmega192a3u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega192c3 = Cpu{
+ pub const atxmega192c3 = CpuModel{
.name = "atxmega192c3",
.llvm_name = "atxmega192c3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega192d3 = Cpu{
+ pub const atxmega192d3 = CpuModel{
.name = "atxmega192d3",
.llvm_name = "atxmega192d3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega256a3 = Cpu{
+ pub const atxmega256a3 = CpuModel{
.name = "atxmega256a3",
.llvm_name = "atxmega256a3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega256a3b = Cpu{
+ pub const atxmega256a3b = CpuModel{
.name = "atxmega256a3b",
.llvm_name = "atxmega256a3b",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega256a3bu = Cpu{
+ pub const atxmega256a3bu = CpuModel{
.name = "atxmega256a3bu",
.llvm_name = "atxmega256a3bu",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega256a3u = Cpu{
+ pub const atxmega256a3u = CpuModel{
.name = "atxmega256a3u",
.llvm_name = "atxmega256a3u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega256c3 = Cpu{
+ pub const atxmega256c3 = CpuModel{
.name = "atxmega256c3",
.llvm_name = "atxmega256c3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega256d3 = Cpu{
+ pub const atxmega256d3 = CpuModel{
.name = "atxmega256d3",
.llvm_name = "atxmega256d3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega32a4 = Cpu{
+ pub const atxmega32a4 = CpuModel{
.name = "atxmega32a4",
.llvm_name = "atxmega32a4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega32a4u = Cpu{
+ pub const atxmega32a4u = CpuModel{
.name = "atxmega32a4u",
.llvm_name = "atxmega32a4u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega32c4 = Cpu{
+ pub const atxmega32c4 = CpuModel{
.name = "atxmega32c4",
.llvm_name = "atxmega32c4",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega32d4 = Cpu{
+ pub const atxmega32d4 = CpuModel{
.name = "atxmega32d4",
.llvm_name = "atxmega32d4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega32e5 = Cpu{
+ pub const atxmega32e5 = CpuModel{
.name = "atxmega32e5",
.llvm_name = "atxmega32e5",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega32x1 = Cpu{
+ pub const atxmega32x1 = CpuModel{
.name = "atxmega32x1",
.llvm_name = "atxmega32x1",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega384c3 = Cpu{
+ pub const atxmega384c3 = CpuModel{
.name = "atxmega384c3",
.llvm_name = "atxmega384c3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega384d3 = Cpu{
+ pub const atxmega384d3 = CpuModel{
.name = "atxmega384d3",
.llvm_name = "atxmega384d3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega64a1 = Cpu{
+ pub const atxmega64a1 = CpuModel{
.name = "atxmega64a1",
.llvm_name = "atxmega64a1",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega64a1u = Cpu{
+ pub const atxmega64a1u = CpuModel{
.name = "atxmega64a1u",
.llvm_name = "atxmega64a1u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64a3 = Cpu{
+ pub const atxmega64a3 = CpuModel{
.name = "atxmega64a3",
.llvm_name = "atxmega64a3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega64a3u = Cpu{
+ pub const atxmega64a3u = CpuModel{
.name = "atxmega64a3u",
.llvm_name = "atxmega64a3u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64a4u = Cpu{
+ pub const atxmega64a4u = CpuModel{
.name = "atxmega64a4u",
.llvm_name = "atxmega64a4u",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64b1 = Cpu{
+ pub const atxmega64b1 = CpuModel{
.name = "atxmega64b1",
.llvm_name = "atxmega64b1",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64b3 = Cpu{
+ pub const atxmega64b3 = CpuModel{
.name = "atxmega64b3",
.llvm_name = "atxmega64b3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64c3 = Cpu{
+ pub const atxmega64c3 = CpuModel{
.name = "atxmega64c3",
.llvm_name = "atxmega64c3",
.features = featureSet(&[_]Feature{
.xmegau,
}),
};
- pub const atxmega64d3 = Cpu{
+ pub const atxmega64d3 = CpuModel{
.name = "atxmega64d3",
.llvm_name = "atxmega64d3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega64d4 = Cpu{
+ pub const atxmega64d4 = CpuModel{
.name = "atxmega64d4",
.llvm_name = "atxmega64d4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const atxmega8e5 = Cpu{
+ pub const atxmega8e5 = CpuModel{
.name = "atxmega8e5",
.llvm_name = "atxmega8e5",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avr1 = Cpu{
+ pub const avr1 = CpuModel{
.name = "avr1",
.llvm_name = "avr1",
.features = featureSet(&[_]Feature{
.avr1,
}),
};
- pub const avr2 = Cpu{
+ pub const avr2 = CpuModel{
.name = "avr2",
.llvm_name = "avr2",
.features = featureSet(&[_]Feature{
.avr2,
}),
};
- pub const avr25 = Cpu{
+ pub const avr25 = CpuModel{
.name = "avr25",
.llvm_name = "avr25",
.features = featureSet(&[_]Feature{
.avr25,
}),
};
- pub const avr3 = Cpu{
+ pub const avr3 = CpuModel{
.name = "avr3",
.llvm_name = "avr3",
.features = featureSet(&[_]Feature{
.avr3,
}),
};
- pub const avr31 = Cpu{
+ pub const avr31 = CpuModel{
.name = "avr31",
.llvm_name = "avr31",
.features = featureSet(&[_]Feature{
.avr31,
}),
};
- pub const avr35 = Cpu{
+ pub const avr35 = CpuModel{
.name = "avr35",
.llvm_name = "avr35",
.features = featureSet(&[_]Feature{
.avr35,
}),
};
- pub const avr4 = Cpu{
+ pub const avr4 = CpuModel{
.name = "avr4",
.llvm_name = "avr4",
.features = featureSet(&[_]Feature{
.avr4,
}),
};
- pub const avr5 = Cpu{
+ pub const avr5 = CpuModel{
.name = "avr5",
.llvm_name = "avr5",
.features = featureSet(&[_]Feature{
.avr5,
}),
};
- pub const avr51 = Cpu{
+ pub const avr51 = CpuModel{
.name = "avr51",
.llvm_name = "avr51",
.features = featureSet(&[_]Feature{
.avr51,
}),
};
- pub const avr6 = Cpu{
+ pub const avr6 = CpuModel{
.name = "avr6",
.llvm_name = "avr6",
.features = featureSet(&[_]Feature{
.avr6,
}),
};
- pub const avrtiny = Cpu{
+ pub const avrtiny = CpuModel{
.name = "avrtiny",
.llvm_name = "avrtiny",
.features = featureSet(&[_]Feature{
.avrtiny,
}),
};
- pub const avrxmega1 = Cpu{
+ pub const avrxmega1 = CpuModel{
.name = "avrxmega1",
.llvm_name = "avrxmega1",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega2 = Cpu{
+ pub const avrxmega2 = CpuModel{
.name = "avrxmega2",
.llvm_name = "avrxmega2",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega3 = Cpu{
+ pub const avrxmega3 = CpuModel{
.name = "avrxmega3",
.llvm_name = "avrxmega3",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega4 = Cpu{
+ pub const avrxmega4 = CpuModel{
.name = "avrxmega4",
.llvm_name = "avrxmega4",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega5 = Cpu{
+ pub const avrxmega5 = CpuModel{
.name = "avrxmega5",
.llvm_name = "avrxmega5",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega6 = Cpu{
+ pub const avrxmega6 = CpuModel{
.name = "avrxmega6",
.llvm_name = "avrxmega6",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const avrxmega7 = Cpu{
+ pub const avrxmega7 = CpuModel{
.name = "avrxmega7",
.llvm_name = "avrxmega7",
.features = featureSet(&[_]Feature{
.xmega,
}),
};
- pub const m3000 = Cpu{
+ pub const m3000 = CpuModel{
.name = "m3000",
.llvm_name = "m3000",
.features = featureSet(&[_]Feature{
@@ -2119,7 +2120,7 @@ pub const cpu = struct {
/// All avr CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.at43usb320,
&cpu.at43usb355,
&cpu.at76c711,
diff --git a/lib/std/target/bpf.zig b/lib/std/target/bpf.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
alu32,
@@ -7,12 +8,12 @@ pub const Feature = enum {
dwarfris,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.alu32)] = .{
.llvm_name = "alu32",
.description = "Enable ALU32 instructions",
@@ -37,27 +38,27 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const probe = Cpu{
+ pub const probe = CpuModel{
.name = "probe",
.llvm_name = "probe",
.features = featureSet(&[_]Feature{}),
};
- pub const v1 = Cpu{
+ pub const v1 = CpuModel{
.name = "v1",
.llvm_name = "v1",
.features = featureSet(&[_]Feature{}),
};
- pub const v2 = Cpu{
+ pub const v2 = CpuModel{
.name = "v2",
.llvm_name = "v2",
.features = featureSet(&[_]Feature{}),
};
- pub const v3 = Cpu{
+ pub const v3 = CpuModel{
.name = "v3",
.llvm_name = "v3",
.features = featureSet(&[_]Feature{}),
@@ -67,7 +68,7 @@ pub const cpu = struct {
/// All bpf CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.generic,
&cpu.probe,
&cpu.v1,
diff --git a/lib/std/target/hexagon.zig b/lib/std/target/hexagon.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
duplex,
@@ -28,12 +29,12 @@ pub const Feature = enum {
zreg,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.duplex)] = .{
.llvm_name = "duplex",
.description = "Enable generation of duplex instruction",
@@ -186,7 +187,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
@@ -201,7 +202,7 @@ pub const cpu = struct {
.v60,
}),
};
- pub const hexagonv5 = Cpu{
+ pub const hexagonv5 = CpuModel{
.name = "hexagonv5",
.llvm_name = "hexagonv5",
.features = featureSet(&[_]Feature{
@@ -214,7 +215,7 @@ pub const cpu = struct {
.v5,
}),
};
- pub const hexagonv55 = Cpu{
+ pub const hexagonv55 = CpuModel{
.name = "hexagonv55",
.llvm_name = "hexagonv55",
.features = featureSet(&[_]Feature{
@@ -228,7 +229,7 @@ pub const cpu = struct {
.v55,
}),
};
- pub const hexagonv60 = Cpu{
+ pub const hexagonv60 = CpuModel{
.name = "hexagonv60",
.llvm_name = "hexagonv60",
.features = featureSet(&[_]Feature{
@@ -243,7 +244,7 @@ pub const cpu = struct {
.v60,
}),
};
- pub const hexagonv62 = Cpu{
+ pub const hexagonv62 = CpuModel{
.name = "hexagonv62",
.llvm_name = "hexagonv62",
.features = featureSet(&[_]Feature{
@@ -259,7 +260,7 @@ pub const cpu = struct {
.v62,
}),
};
- pub const hexagonv65 = Cpu{
+ pub const hexagonv65 = CpuModel{
.name = "hexagonv65",
.llvm_name = "hexagonv65",
.features = featureSet(&[_]Feature{
@@ -277,7 +278,7 @@ pub const cpu = struct {
.v65,
}),
};
- pub const hexagonv66 = Cpu{
+ pub const hexagonv66 = CpuModel{
.name = "hexagonv66",
.llvm_name = "hexagonv66",
.features = featureSet(&[_]Feature{
@@ -301,7 +302,7 @@ pub const cpu = struct {
/// All hexagon CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.generic,
&cpu.hexagonv5,
&cpu.hexagonv55,
diff --git a/lib/std/target/mips.zig b/lib/std/target/mips.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
abs2008,
@@ -55,12 +56,12 @@ pub const Feature = enum {
xgot,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.abs2008)] = .{
.llvm_name = "abs2008",
.description = "Disable IEEE 754-2008 abs.fmt mode",
@@ -386,119 +387,119 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.mips32,
}),
};
- pub const mips1 = Cpu{
+ pub const mips1 = CpuModel{
.name = "mips1",
.llvm_name = "mips1",
.features = featureSet(&[_]Feature{
.mips1,
}),
};
- pub const mips2 = Cpu{
+ pub const mips2 = CpuModel{
.name = "mips2",
.llvm_name = "mips2",
.features = featureSet(&[_]Feature{
.mips2,
}),
};
- pub const mips3 = Cpu{
+ pub const mips3 = CpuModel{
.name = "mips3",
.llvm_name = "mips3",
.features = featureSet(&[_]Feature{
.mips3,
}),
};
- pub const mips32 = Cpu{
+ pub const mips32 = CpuModel{
.name = "mips32",
.llvm_name = "mips32",
.features = featureSet(&[_]Feature{
.mips32,
}),
};
- pub const mips32r2 = Cpu{
+ pub const mips32r2 = CpuModel{
.name = "mips32r2",
.llvm_name = "mips32r2",
.features = featureSet(&[_]Feature{
.mips32r2,
}),
};
- pub const mips32r3 = Cpu{
+ pub const mips32r3 = CpuModel{
.name = "mips32r3",
.llvm_name = "mips32r3",
.features = featureSet(&[_]Feature{
.mips32r3,
}),
};
- pub const mips32r5 = Cpu{
+ pub const mips32r5 = CpuModel{
.name = "mips32r5",
.llvm_name = "mips32r5",
.features = featureSet(&[_]Feature{
.mips32r5,
}),
};
- pub const mips32r6 = Cpu{
+ pub const mips32r6 = CpuModel{
.name = "mips32r6",
.llvm_name = "mips32r6",
.features = featureSet(&[_]Feature{
.mips32r6,
}),
};
- pub const mips4 = Cpu{
+ pub const mips4 = CpuModel{
.name = "mips4",
.llvm_name = "mips4",
.features = featureSet(&[_]Feature{
.mips4,
}),
};
- pub const mips5 = Cpu{
+ pub const mips5 = CpuModel{
.name = "mips5",
.llvm_name = "mips5",
.features = featureSet(&[_]Feature{
.mips5,
}),
};
- pub const mips64 = Cpu{
+ pub const mips64 = CpuModel{
.name = "mips64",
.llvm_name = "mips64",
.features = featureSet(&[_]Feature{
.mips64,
}),
};
- pub const mips64r2 = Cpu{
+ pub const mips64r2 = CpuModel{
.name = "mips64r2",
.llvm_name = "mips64r2",
.features = featureSet(&[_]Feature{
.mips64r2,
}),
};
- pub const mips64r3 = Cpu{
+ pub const mips64r3 = CpuModel{
.name = "mips64r3",
.llvm_name = "mips64r3",
.features = featureSet(&[_]Feature{
.mips64r3,
}),
};
- pub const mips64r5 = Cpu{
+ pub const mips64r5 = CpuModel{
.name = "mips64r5",
.llvm_name = "mips64r5",
.features = featureSet(&[_]Feature{
.mips64r5,
}),
};
- pub const mips64r6 = Cpu{
+ pub const mips64r6 = CpuModel{
.name = "mips64r6",
.llvm_name = "mips64r6",
.features = featureSet(&[_]Feature{
.mips64r6,
}),
};
- pub const octeon = Cpu{
+ pub const octeon = CpuModel{
.name = "octeon",
.llvm_name = "octeon",
.features = featureSet(&[_]Feature{
@@ -506,7 +507,7 @@ pub const cpu = struct {
.mips64r2,
}),
};
- pub const @"octeon+" = Cpu{
+ pub const @"octeon+" = CpuModel{
.name = "octeon+",
.llvm_name = "octeon+",
.features = featureSet(&[_]Feature{
@@ -515,7 +516,7 @@ pub const cpu = struct {
.mips64r2,
}),
};
- pub const p5600 = Cpu{
+ pub const p5600 = CpuModel{
.name = "p5600",
.llvm_name = "p5600",
.features = featureSet(&[_]Feature{
@@ -527,7 +528,7 @@ pub const cpu = struct {
/// All mips CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.generic,
&cpu.mips1,
&cpu.mips2,
diff --git a/lib/std/target/msp430.zig b/lib/std/target/msp430.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
ext,
@@ -8,12 +9,12 @@ pub const Feature = enum {
hwmultf5,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.ext)] = .{
.llvm_name = "ext",
.description = "Enable MSP430-X extensions",
@@ -43,17 +44,17 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const msp430 = Cpu{
+ pub const msp430 = CpuModel{
.name = "msp430",
.llvm_name = "msp430",
.features = featureSet(&[_]Feature{}),
};
- pub const msp430x = Cpu{
+ pub const msp430x = CpuModel{
.name = "msp430x",
.llvm_name = "msp430x",
.features = featureSet(&[_]Feature{
@@ -65,7 +66,7 @@ pub const cpu = struct {
/// All msp430 CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.generic,
&cpu.msp430,
&cpu.msp430x,
diff --git a/lib/std/target/nvptx.zig b/lib/std/target/nvptx.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
ptx32,
@@ -29,12 +30,12 @@ pub const Feature = enum {
sm_75,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.ptx32)] = .{
.llvm_name = "ptx32",
.description = "Use PTX version 3.2",
@@ -169,28 +170,28 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const sm_20 = Cpu{
+ pub const sm_20 = CpuModel{
.name = "sm_20",
.llvm_name = "sm_20",
.features = featureSet(&[_]Feature{
.sm_20,
}),
};
- pub const sm_21 = Cpu{
+ pub const sm_21 = CpuModel{
.name = "sm_21",
.llvm_name = "sm_21",
.features = featureSet(&[_]Feature{
.sm_21,
}),
};
- pub const sm_30 = Cpu{
+ pub const sm_30 = CpuModel{
.name = "sm_30",
.llvm_name = "sm_30",
.features = featureSet(&[_]Feature{
.sm_30,
}),
};
- pub const sm_32 = Cpu{
+ pub const sm_32 = CpuModel{
.name = "sm_32",
.llvm_name = "sm_32",
.features = featureSet(&[_]Feature{
@@ -198,14 +199,14 @@ pub const cpu = struct {
.sm_32,
}),
};
- pub const sm_35 = Cpu{
+ pub const sm_35 = CpuModel{
.name = "sm_35",
.llvm_name = "sm_35",
.features = featureSet(&[_]Feature{
.sm_35,
}),
};
- pub const sm_37 = Cpu{
+ pub const sm_37 = CpuModel{
.name = "sm_37",
.llvm_name = "sm_37",
.features = featureSet(&[_]Feature{
@@ -213,7 +214,7 @@ pub const cpu = struct {
.sm_37,
}),
};
- pub const sm_50 = Cpu{
+ pub const sm_50 = CpuModel{
.name = "sm_50",
.llvm_name = "sm_50",
.features = featureSet(&[_]Feature{
@@ -221,7 +222,7 @@ pub const cpu = struct {
.sm_50,
}),
};
- pub const sm_52 = Cpu{
+ pub const sm_52 = CpuModel{
.name = "sm_52",
.llvm_name = "sm_52",
.features = featureSet(&[_]Feature{
@@ -229,7 +230,7 @@ pub const cpu = struct {
.sm_52,
}),
};
- pub const sm_53 = Cpu{
+ pub const sm_53 = CpuModel{
.name = "sm_53",
.llvm_name = "sm_53",
.features = featureSet(&[_]Feature{
@@ -237,7 +238,7 @@ pub const cpu = struct {
.sm_53,
}),
};
- pub const sm_60 = Cpu{
+ pub const sm_60 = CpuModel{
.name = "sm_60",
.llvm_name = "sm_60",
.features = featureSet(&[_]Feature{
@@ -245,7 +246,7 @@ pub const cpu = struct {
.sm_60,
}),
};
- pub const sm_61 = Cpu{
+ pub const sm_61 = CpuModel{
.name = "sm_61",
.llvm_name = "sm_61",
.features = featureSet(&[_]Feature{
@@ -253,7 +254,7 @@ pub const cpu = struct {
.sm_61,
}),
};
- pub const sm_62 = Cpu{
+ pub const sm_62 = CpuModel{
.name = "sm_62",
.llvm_name = "sm_62",
.features = featureSet(&[_]Feature{
@@ -261,7 +262,7 @@ pub const cpu = struct {
.sm_62,
}),
};
- pub const sm_70 = Cpu{
+ pub const sm_70 = CpuModel{
.name = "sm_70",
.llvm_name = "sm_70",
.features = featureSet(&[_]Feature{
@@ -269,7 +270,7 @@ pub const cpu = struct {
.sm_70,
}),
};
- pub const sm_72 = Cpu{
+ pub const sm_72 = CpuModel{
.name = "sm_72",
.llvm_name = "sm_72",
.features = featureSet(&[_]Feature{
@@ -277,7 +278,7 @@ pub const cpu = struct {
.sm_72,
}),
};
- pub const sm_75 = Cpu{
+ pub const sm_75 = CpuModel{
.name = "sm_75",
.llvm_name = "sm_75",
.features = featureSet(&[_]Feature{
@@ -290,7 +291,7 @@ pub const cpu = struct {
/// All nvptx CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.sm_20,
&cpu.sm_21,
&cpu.sm_30,
diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
@"64bit",
@@ -56,12 +57,12 @@ pub const Feature = enum {
vsx,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.@"64bit")] = .{
.llvm_name = "64bit",
.description = "Enable 64-bit instructions",
@@ -383,7 +384,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const @"440" = Cpu{
+ pub const @"440" = CpuModel{
.name = "440",
.llvm_name = "440",
.features = featureSet(&[_]Feature{
@@ -395,7 +396,7 @@ pub const cpu = struct {
.msync,
}),
};
- pub const @"450" = Cpu{
+ pub const @"450" = CpuModel{
.name = "450",
.llvm_name = "450",
.features = featureSet(&[_]Feature{
@@ -407,21 +408,21 @@ pub const cpu = struct {
.msync,
}),
};
- pub const @"601" = Cpu{
+ pub const @"601" = CpuModel{
.name = "601",
.llvm_name = "601",
.features = featureSet(&[_]Feature{
.fpu,
}),
};
- pub const @"602" = Cpu{
+ pub const @"602" = CpuModel{
.name = "602",
.llvm_name = "602",
.features = featureSet(&[_]Feature{
.fpu,
}),
};
- pub const @"603" = Cpu{
+ pub const @"603" = CpuModel{
.name = "603",
.llvm_name = "603",
.features = featureSet(&[_]Feature{
@@ -429,7 +430,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"603e" = Cpu{
+ pub const @"603e" = CpuModel{
.name = "603e",
.llvm_name = "603e",
.features = featureSet(&[_]Feature{
@@ -437,7 +438,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"603ev" = Cpu{
+ pub const @"603ev" = CpuModel{
.name = "603ev",
.llvm_name = "603ev",
.features = featureSet(&[_]Feature{
@@ -445,7 +446,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"604" = Cpu{
+ pub const @"604" = CpuModel{
.name = "604",
.llvm_name = "604",
.features = featureSet(&[_]Feature{
@@ -453,7 +454,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"604e" = Cpu{
+ pub const @"604e" = CpuModel{
.name = "604e",
.llvm_name = "604e",
.features = featureSet(&[_]Feature{
@@ -461,7 +462,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"620" = Cpu{
+ pub const @"620" = CpuModel{
.name = "620",
.llvm_name = "620",
.features = featureSet(&[_]Feature{
@@ -469,7 +470,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"7400" = Cpu{
+ pub const @"7400" = CpuModel{
.name = "7400",
.llvm_name = "7400",
.features = featureSet(&[_]Feature{
@@ -478,7 +479,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"7450" = Cpu{
+ pub const @"7450" = CpuModel{
.name = "7450",
.llvm_name = "7450",
.features = featureSet(&[_]Feature{
@@ -487,7 +488,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"750" = Cpu{
+ pub const @"750" = CpuModel{
.name = "750",
.llvm_name = "750",
.features = featureSet(&[_]Feature{
@@ -495,7 +496,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"970" = Cpu{
+ pub const @"970" = CpuModel{
.name = "970",
.llvm_name = "970",
.features = featureSet(&[_]Feature{
@@ -508,7 +509,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const a2 = Cpu{
+ pub const a2 = CpuModel{
.name = "a2",
.llvm_name = "a2",
.features = featureSet(&[_]Feature{
@@ -533,7 +534,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const a2q = Cpu{
+ pub const a2q = CpuModel{
.name = "a2q",
.llvm_name = "a2q",
.features = featureSet(&[_]Feature{
@@ -559,7 +560,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const e500 = Cpu{
+ pub const e500 = CpuModel{
.name = "e500",
.llvm_name = "e500",
.features = featureSet(&[_]Feature{
@@ -569,7 +570,7 @@ pub const cpu = struct {
.spe,
}),
};
- pub const e500mc = Cpu{
+ pub const e500mc = CpuModel{
.name = "e500mc",
.llvm_name = "e500mc",
.features = featureSet(&[_]Feature{
@@ -579,7 +580,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const e5500 = Cpu{
+ pub const e5500 = CpuModel{
.name = "e5500",
.llvm_name = "e5500",
.features = featureSet(&[_]Feature{
@@ -591,7 +592,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const future = Cpu{
+ pub const future = CpuModel{
.name = "future",
.llvm_name = "future",
.features = featureSet(&[_]Feature{
@@ -630,7 +631,7 @@ pub const cpu = struct {
.vsx,
}),
};
- pub const g3 = Cpu{
+ pub const g3 = CpuModel{
.name = "g3",
.llvm_name = "g3",
.features = featureSet(&[_]Feature{
@@ -638,7 +639,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const g4 = Cpu{
+ pub const g4 = CpuModel{
.name = "g4",
.llvm_name = "g4",
.features = featureSet(&[_]Feature{
@@ -647,7 +648,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const @"g4+" = Cpu{
+ pub const @"g4+" = CpuModel{
.name = "g4+",
.llvm_name = "g4+",
.features = featureSet(&[_]Feature{
@@ -656,7 +657,7 @@ pub const cpu = struct {
.frsqrte,
}),
};
- pub const g5 = Cpu{
+ pub const g5 = CpuModel{
.name = "g5",
.llvm_name = "g5",
.features = featureSet(&[_]Feature{
@@ -669,28 +670,28 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
- pub const ppc = Cpu{
+ pub const ppc = CpuModel{
.name = "ppc",
.llvm_name = "ppc",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
- pub const ppc32 = Cpu{
+ pub const ppc32 = CpuModel{
.name = "ppc32",
.llvm_name = "ppc32",
.features = featureSet(&[_]Feature{
.hard_float,
}),
};
- pub const ppc64 = Cpu{
+ pub const ppc64 = CpuModel{
.name = "ppc64",
.llvm_name = "ppc64",
.features = featureSet(&[_]Feature{
@@ -703,7 +704,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const ppc64le = Cpu{
+ pub const ppc64le = CpuModel{
.name = "ppc64le",
.llvm_name = "ppc64le",
.features = featureSet(&[_]Feature{
@@ -739,7 +740,7 @@ pub const cpu = struct {
.vsx,
}),
};
- pub const pwr3 = Cpu{
+ pub const pwr3 = CpuModel{
.name = "pwr3",
.llvm_name = "pwr3",
.features = featureSet(&[_]Feature{
@@ -751,7 +752,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr4 = Cpu{
+ pub const pwr4 = CpuModel{
.name = "pwr4",
.llvm_name = "pwr4",
.features = featureSet(&[_]Feature{
@@ -764,7 +765,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr5 = Cpu{
+ pub const pwr5 = CpuModel{
.name = "pwr5",
.llvm_name = "pwr5",
.features = featureSet(&[_]Feature{
@@ -779,7 +780,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr5x = Cpu{
+ pub const pwr5x = CpuModel{
.name = "pwr5x",
.llvm_name = "pwr5x",
.features = featureSet(&[_]Feature{
@@ -795,7 +796,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr6 = Cpu{
+ pub const pwr6 = CpuModel{
.name = "pwr6",
.llvm_name = "pwr6",
.features = featureSet(&[_]Feature{
@@ -815,7 +816,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr6x = Cpu{
+ pub const pwr6x = CpuModel{
.name = "pwr6x",
.llvm_name = "pwr6x",
.features = featureSet(&[_]Feature{
@@ -835,7 +836,7 @@ pub const cpu = struct {
.stfiwx,
}),
};
- pub const pwr7 = Cpu{
+ pub const pwr7 = CpuModel{
.name = "pwr7",
.llvm_name = "pwr7",
.features = featureSet(&[_]Feature{
@@ -864,7 +865,7 @@ pub const cpu = struct {
.vsx,
}),
};
- pub const pwr8 = Cpu{
+ pub const pwr8 = CpuModel{
.name = "pwr8",
.llvm_name = "pwr8",
.features = featureSet(&[_]Feature{
@@ -900,7 +901,7 @@ pub const cpu = struct {
.vsx,
}),
};
- pub const pwr9 = Cpu{
+ pub const pwr9 = CpuModel{
.name = "pwr9",
.llvm_name = "pwr9",
.features = featureSet(&[_]Feature{
@@ -947,7 +948,7 @@ pub const cpu = struct {
/// All powerpc CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.@"440",
&cpu.@"450",
&cpu.@"601",
diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
@"64bit",
@@ -44,12 +45,12 @@ pub const Feature = enum {
rvc_hints,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.@"64bit")] = .{
.llvm_name = "64bit",
.description = "Implements RV64",
@@ -261,7 +262,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const baseline_rv32 = Cpu{
+ pub const baseline_rv32 = CpuModel{
.name = "baseline_rv32",
.llvm_name = null,
.features = featureSet(&[_]Feature{
@@ -273,7 +274,7 @@ pub const cpu = struct {
}),
};
- pub const baseline_rv64 = Cpu{
+ pub const baseline_rv64 = CpuModel{
.name = "baseline_rv64",
.llvm_name = null,
.features = featureSet(&[_]Feature{
@@ -286,14 +287,14 @@ pub const cpu = struct {
}),
};
- pub const generic_rv32 = Cpu{
+ pub const generic_rv32 = CpuModel{
.name = "generic_rv32",
.llvm_name = null,
.features = featureSet(&[_]Feature{
.rvc_hints,
}),
};
- pub const generic_rv64 = Cpu{
+ pub const generic_rv64 = CpuModel{
.name = "generic_rv64",
.llvm_name = null,
.features = featureSet(&[_]Feature{
@@ -306,7 +307,7 @@ pub const cpu = struct {
/// All riscv CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.baseline_rv32,
&cpu.baseline_rv64,
&cpu.generic_rv32,
diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
deprecated_v8,
@@ -23,12 +24,12 @@ pub const Feature = enum {
vis3,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.deprecated_v8)] = .{
.llvm_name = "deprecated-v8",
.description = "Enable deprecated V8 instructions in V9 mode",
@@ -133,7 +134,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const at697e = Cpu{
+ pub const at697e = CpuModel{
.name = "at697e",
.llvm_name = "at697e",
.features = featureSet(&[_]Feature{
@@ -141,7 +142,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const at697f = Cpu{
+ pub const at697f = CpuModel{
.name = "at697f",
.llvm_name = "at697f",
.features = featureSet(&[_]Feature{
@@ -149,17 +150,17 @@ pub const cpu = struct {
.leon,
}),
};
- pub const f934 = Cpu{
+ pub const f934 = CpuModel{
.name = "f934",
.llvm_name = "f934",
.features = featureSet(&[_]Feature{}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const gr712rc = Cpu{
+ pub const gr712rc = CpuModel{
.name = "gr712rc",
.llvm_name = "gr712rc",
.features = featureSet(&[_]Feature{
@@ -167,7 +168,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const gr740 = Cpu{
+ pub const gr740 = CpuModel{
.name = "gr740",
.llvm_name = "gr740",
.features = featureSet(&[_]Feature{
@@ -178,19 +179,19 @@ pub const cpu = struct {
.leonpwrpsr,
}),
};
- pub const hypersparc = Cpu{
+ pub const hypersparc = CpuModel{
.name = "hypersparc",
.llvm_name = "hypersparc",
.features = featureSet(&[_]Feature{}),
};
- pub const leon2 = Cpu{
+ pub const leon2 = CpuModel{
.name = "leon2",
.llvm_name = "leon2",
.features = featureSet(&[_]Feature{
.leon,
}),
};
- pub const leon3 = Cpu{
+ pub const leon3 = CpuModel{
.name = "leon3",
.llvm_name = "leon3",
.features = featureSet(&[_]Feature{
@@ -198,7 +199,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const leon4 = Cpu{
+ pub const leon4 = CpuModel{
.name = "leon4",
.llvm_name = "leon4",
.features = featureSet(&[_]Feature{
@@ -207,7 +208,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2080 = Cpu{
+ pub const ma2080 = CpuModel{
.name = "ma2080",
.llvm_name = "ma2080",
.features = featureSet(&[_]Feature{
@@ -215,7 +216,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2085 = Cpu{
+ pub const ma2085 = CpuModel{
.name = "ma2085",
.llvm_name = "ma2085",
.features = featureSet(&[_]Feature{
@@ -223,7 +224,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2100 = Cpu{
+ pub const ma2100 = CpuModel{
.name = "ma2100",
.llvm_name = "ma2100",
.features = featureSet(&[_]Feature{
@@ -231,7 +232,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2150 = Cpu{
+ pub const ma2150 = CpuModel{
.name = "ma2150",
.llvm_name = "ma2150",
.features = featureSet(&[_]Feature{
@@ -239,7 +240,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2155 = Cpu{
+ pub const ma2155 = CpuModel{
.name = "ma2155",
.llvm_name = "ma2155",
.features = featureSet(&[_]Feature{
@@ -247,7 +248,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2450 = Cpu{
+ pub const ma2450 = CpuModel{
.name = "ma2450",
.llvm_name = "ma2450",
.features = featureSet(&[_]Feature{
@@ -255,7 +256,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2455 = Cpu{
+ pub const ma2455 = CpuModel{
.name = "ma2455",
.llvm_name = "ma2455",
.features = featureSet(&[_]Feature{
@@ -263,7 +264,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2480 = Cpu{
+ pub const ma2480 = CpuModel{
.name = "ma2480",
.llvm_name = "ma2480",
.features = featureSet(&[_]Feature{
@@ -271,7 +272,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2485 = Cpu{
+ pub const ma2485 = CpuModel{
.name = "ma2485",
.llvm_name = "ma2485",
.features = featureSet(&[_]Feature{
@@ -279,7 +280,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2x5x = Cpu{
+ pub const ma2x5x = CpuModel{
.name = "ma2x5x",
.llvm_name = "ma2x5x",
.features = featureSet(&[_]Feature{
@@ -287,7 +288,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const ma2x8x = Cpu{
+ pub const ma2x8x = CpuModel{
.name = "ma2x8x",
.llvm_name = "ma2x8x",
.features = featureSet(&[_]Feature{
@@ -295,7 +296,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const myriad2 = Cpu{
+ pub const myriad2 = CpuModel{
.name = "myriad2",
.llvm_name = "myriad2",
.features = featureSet(&[_]Feature{
@@ -303,7 +304,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const myriad2_1 = Cpu{
+ pub const myriad2_1 = CpuModel{
.name = "myriad2_1",
.llvm_name = "myriad2.1",
.features = featureSet(&[_]Feature{
@@ -311,7 +312,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const myriad2_2 = Cpu{
+ pub const myriad2_2 = CpuModel{
.name = "myriad2_2",
.llvm_name = "myriad2.2",
.features = featureSet(&[_]Feature{
@@ -319,7 +320,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const myriad2_3 = Cpu{
+ pub const myriad2_3 = CpuModel{
.name = "myriad2_3",
.llvm_name = "myriad2.3",
.features = featureSet(&[_]Feature{
@@ -327,7 +328,7 @@ pub const cpu = struct {
.leon,
}),
};
- pub const niagara = Cpu{
+ pub const niagara = CpuModel{
.name = "niagara",
.llvm_name = "niagara",
.features = featureSet(&[_]Feature{
@@ -337,7 +338,7 @@ pub const cpu = struct {
.vis2,
}),
};
- pub const niagara2 = Cpu{
+ pub const niagara2 = CpuModel{
.name = "niagara2",
.llvm_name = "niagara2",
.features = featureSet(&[_]Feature{
@@ -348,7 +349,7 @@ pub const cpu = struct {
.vis2,
}),
};
- pub const niagara3 = Cpu{
+ pub const niagara3 = CpuModel{
.name = "niagara3",
.llvm_name = "niagara3",
.features = featureSet(&[_]Feature{
@@ -359,7 +360,7 @@ pub const cpu = struct {
.vis2,
}),
};
- pub const niagara4 = Cpu{
+ pub const niagara4 = CpuModel{
.name = "niagara4",
.llvm_name = "niagara4",
.features = featureSet(&[_]Feature{
@@ -371,32 +372,32 @@ pub const cpu = struct {
.vis3,
}),
};
- pub const sparclet = Cpu{
+ pub const sparclet = CpuModel{
.name = "sparclet",
.llvm_name = "sparclet",
.features = featureSet(&[_]Feature{}),
};
- pub const sparclite = Cpu{
+ pub const sparclite = CpuModel{
.name = "sparclite",
.llvm_name = "sparclite",
.features = featureSet(&[_]Feature{}),
};
- pub const sparclite86x = Cpu{
+ pub const sparclite86x = CpuModel{
.name = "sparclite86x",
.llvm_name = "sparclite86x",
.features = featureSet(&[_]Feature{}),
};
- pub const supersparc = Cpu{
+ pub const supersparc = CpuModel{
.name = "supersparc",
.llvm_name = "supersparc",
.features = featureSet(&[_]Feature{}),
};
- pub const tsc701 = Cpu{
+ pub const tsc701 = CpuModel{
.name = "tsc701",
.llvm_name = "tsc701",
.features = featureSet(&[_]Feature{}),
};
- pub const ultrasparc = Cpu{
+ pub const ultrasparc = CpuModel{
.name = "ultrasparc",
.llvm_name = "ultrasparc",
.features = featureSet(&[_]Feature{
@@ -405,7 +406,7 @@ pub const cpu = struct {
.vis,
}),
};
- pub const ultrasparc3 = Cpu{
+ pub const ultrasparc3 = CpuModel{
.name = "ultrasparc3",
.llvm_name = "ultrasparc3",
.features = featureSet(&[_]Feature{
@@ -415,7 +416,7 @@ pub const cpu = struct {
.vis2,
}),
};
- pub const ut699 = Cpu{
+ pub const ut699 = CpuModel{
.name = "ut699",
.llvm_name = "ut699",
.features = featureSet(&[_]Feature{
@@ -426,7 +427,7 @@ pub const cpu = struct {
.no_fsmuld,
}),
};
- pub const v7 = Cpu{
+ pub const v7 = CpuModel{
.name = "v7",
.llvm_name = "v7",
.features = featureSet(&[_]Feature{
@@ -434,12 +435,12 @@ pub const cpu = struct {
.soft_mul_div,
}),
};
- pub const v8 = Cpu{
+ pub const v8 = CpuModel{
.name = "v8",
.llvm_name = "v8",
.features = featureSet(&[_]Feature{}),
};
- pub const v9 = Cpu{
+ pub const v9 = CpuModel{
.name = "v9",
.llvm_name = "v9",
.features = featureSet(&[_]Feature{
@@ -451,7 +452,7 @@ pub const cpu = struct {
/// All sparc CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.at697e,
&cpu.at697f,
&cpu.f934,
diff --git a/lib/std/target/systemz.zig b/lib/std/target/systemz.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
deflate_conversion,
@@ -39,12 +40,12 @@ pub const Feature = enum {
vector_packed_decimal_enhancement,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.deflate_conversion)] = .{
.llvm_name = "deflate-conversion",
.description = "Assume that the deflate-conversion facility is installed",
@@ -229,7 +230,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const arch10 = Cpu{
+ pub const arch10 = CpuModel{
.name = "arch10",
.llvm_name = "arch10",
.features = featureSet(&[_]Feature{
@@ -252,7 +253,7 @@ pub const cpu = struct {
.transactional_execution,
}),
};
- pub const arch11 = Cpu{
+ pub const arch11 = CpuModel{
.name = "arch11",
.llvm_name = "arch11",
.features = featureSet(&[_]Feature{
@@ -280,7 +281,7 @@ pub const cpu = struct {
.vector,
}),
};
- pub const arch12 = Cpu{
+ pub const arch12 = CpuModel{
.name = "arch12",
.llvm_name = "arch12",
.features = featureSet(&[_]Feature{
@@ -315,7 +316,7 @@ pub const cpu = struct {
.vector_packed_decimal,
}),
};
- pub const arch13 = Cpu{
+ pub const arch13 = CpuModel{
.name = "arch13",
.llvm_name = "arch13",
.features = featureSet(&[_]Feature{
@@ -356,12 +357,12 @@ pub const cpu = struct {
.vector_packed_decimal_enhancement,
}),
};
- pub const arch8 = Cpu{
+ pub const arch8 = CpuModel{
.name = "arch8",
.llvm_name = "arch8",
.features = featureSet(&[_]Feature{}),
};
- pub const arch9 = Cpu{
+ pub const arch9 = CpuModel{
.name = "arch9",
.llvm_name = "arch9",
.features = featureSet(&[_]Feature{
@@ -377,17 +378,17 @@ pub const cpu = struct {
.reset_reference_bits_multiple,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const z10 = Cpu{
+ pub const z10 = CpuModel{
.name = "z10",
.llvm_name = "z10",
.features = featureSet(&[_]Feature{}),
};
- pub const z13 = Cpu{
+ pub const z13 = CpuModel{
.name = "z13",
.llvm_name = "z13",
.features = featureSet(&[_]Feature{
@@ -415,7 +416,7 @@ pub const cpu = struct {
.vector,
}),
};
- pub const z14 = Cpu{
+ pub const z14 = CpuModel{
.name = "z14",
.llvm_name = "z14",
.features = featureSet(&[_]Feature{
@@ -450,7 +451,7 @@ pub const cpu = struct {
.vector_packed_decimal,
}),
};
- pub const z15 = Cpu{
+ pub const z15 = CpuModel{
.name = "z15",
.llvm_name = "z15",
.features = featureSet(&[_]Feature{
@@ -491,7 +492,7 @@ pub const cpu = struct {
.vector_packed_decimal_enhancement,
}),
};
- pub const z196 = Cpu{
+ pub const z196 = CpuModel{
.name = "z196",
.llvm_name = "z196",
.features = featureSet(&[_]Feature{
@@ -507,7 +508,7 @@ pub const cpu = struct {
.reset_reference_bits_multiple,
}),
};
- pub const zEC12 = Cpu{
+ pub const zEC12 = CpuModel{
.name = "zEC12",
.llvm_name = "zEC12",
.features = featureSet(&[_]Feature{
@@ -535,7 +536,7 @@ pub const cpu = struct {
/// All systemz CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.arch10,
&cpu.arch11,
&cpu.arch12,
diff --git a/lib/std/target/wasm.zig b/lib/std/target/wasm.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
atomics,
@@ -14,12 +15,12 @@ pub const Feature = enum {
unimplemented_simd128,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.atomics)] = .{
.llvm_name = "atomics",
.description = "Enable Atomics",
@@ -81,7 +82,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const bleeding_edge = Cpu{
+ pub const bleeding_edge = CpuModel{
.name = "bleeding_edge",
.llvm_name = "bleeding-edge",
.features = featureSet(&[_]Feature{
@@ -92,12 +93,12 @@ pub const cpu = struct {
.simd128,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{}),
};
- pub const mvp = Cpu{
+ pub const mvp = CpuModel{
.name = "mvp",
.llvm_name = "mvp",
.features = featureSet(&[_]Feature{}),
@@ -107,7 +108,7 @@ pub const cpu = struct {
/// All wasm CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.bleeding_edge,
&cpu.generic,
&cpu.mvp,
diff --git a/lib/std/target/x86.zig b/lib/std/target/x86.zig
@@ -1,5 +1,6 @@
const std = @import("../std.zig");
-const Cpu = std.Target.Cpu;
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
pub const Feature = enum {
@"3dnow",
@@ -129,12 +130,12 @@ pub const Feature = enum {
xsaves,
};
-pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+pub usingnamespace CpuFeature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
- std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
- var result: [len]Cpu.Feature = undefined;
+ std.debug.assert(len <= CpuFeature.Set.needed_bit_count);
+ var result: [len]CpuFeature = undefined;
result[@enumToInt(Feature.@"3dnow")] = .{
.llvm_name = "3dnow",
.description = "Enable 3DNow! instructions",
@@ -851,7 +852,7 @@ pub const all_features = blk: {
};
pub const cpu = struct {
- pub const amdfam10 = Cpu{
+ pub const amdfam10 = CpuModel{
.name = "amdfam10",
.llvm_name = "amdfam10",
.features = featureSet(&[_]Feature{
@@ -872,7 +873,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon = Cpu{
+ pub const athlon = CpuModel{
.name = "athlon",
.llvm_name = "athlon",
.features = featureSet(&[_]Feature{
@@ -886,7 +887,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon_4 = Cpu{
+ pub const athlon_4 = CpuModel{
.name = "athlon_4",
.llvm_name = "athlon-4",
.features = featureSet(&[_]Feature{
@@ -902,7 +903,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon_fx = Cpu{
+ pub const athlon_fx = CpuModel{
.name = "athlon_fx",
.llvm_name = "athlon-fx",
.features = featureSet(&[_]Feature{
@@ -920,7 +921,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon_mp = Cpu{
+ pub const athlon_mp = CpuModel{
.name = "athlon_mp",
.llvm_name = "athlon-mp",
.features = featureSet(&[_]Feature{
@@ -936,7 +937,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon_tbird = Cpu{
+ pub const athlon_tbird = CpuModel{
.name = "athlon_tbird",
.llvm_name = "athlon-tbird",
.features = featureSet(&[_]Feature{
@@ -950,7 +951,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon_xp = Cpu{
+ pub const athlon_xp = CpuModel{
.name = "athlon_xp",
.llvm_name = "athlon-xp",
.features = featureSet(&[_]Feature{
@@ -966,7 +967,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon64 = Cpu{
+ pub const athlon64 = CpuModel{
.name = "athlon64",
.llvm_name = "athlon64",
.features = featureSet(&[_]Feature{
@@ -984,7 +985,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const athlon64_sse3 = Cpu{
+ pub const athlon64_sse3 = CpuModel{
.name = "athlon64_sse3",
.llvm_name = "athlon64-sse3",
.features = featureSet(&[_]Feature{
@@ -1003,7 +1004,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const atom = Cpu{
+ pub const atom = CpuModel{
.name = "atom",
.llvm_name = "atom",
.features = featureSet(&[_]Feature{
@@ -1028,7 +1029,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const barcelona = Cpu{
+ pub const barcelona = CpuModel{
.name = "barcelona",
.llvm_name = "barcelona",
.features = featureSet(&[_]Feature{
@@ -1049,7 +1050,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const bdver1 = Cpu{
+ pub const bdver1 = CpuModel{
.name = "bdver1",
.llvm_name = "bdver1",
.features = featureSet(&[_]Feature{
@@ -1077,7 +1078,7 @@ pub const cpu = struct {
.xsave,
}),
};
- pub const bdver2 = Cpu{
+ pub const bdver2 = CpuModel{
.name = "bdver2",
.llvm_name = "bdver2",
.features = featureSet(&[_]Feature{
@@ -1110,7 +1111,7 @@ pub const cpu = struct {
.xsave,
}),
};
- pub const bdver3 = Cpu{
+ pub const bdver3 = CpuModel{
.name = "bdver3",
.llvm_name = "bdver3",
.features = featureSet(&[_]Feature{
@@ -1145,7 +1146,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const bdver4 = Cpu{
+ pub const bdver4 = CpuModel{
.name = "bdver4",
.llvm_name = "bdver4",
.features = featureSet(&[_]Feature{
@@ -1183,7 +1184,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const bonnell = Cpu{
+ pub const bonnell = CpuModel{
.name = "bonnell",
.llvm_name = "bonnell",
.features = featureSet(&[_]Feature{
@@ -1208,7 +1209,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const broadwell = Cpu{
+ pub const broadwell = CpuModel{
.name = "broadwell",
.llvm_name = "broadwell",
.features = featureSet(&[_]Feature{
@@ -1253,7 +1254,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const btver1 = Cpu{
+ pub const btver1 = CpuModel{
.name = "btver1",
.llvm_name = "btver1",
.features = featureSet(&[_]Feature{
@@ -1278,7 +1279,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const btver2 = Cpu{
+ pub const btver2 = CpuModel{
.name = "btver2",
.llvm_name = "btver2",
.features = featureSet(&[_]Feature{
@@ -1313,7 +1314,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const c3 = Cpu{
+ pub const c3 = CpuModel{
.name = "c3",
.llvm_name = "c3",
.features = featureSet(&[_]Feature{
@@ -1323,7 +1324,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const c3_2 = Cpu{
+ pub const c3_2 = CpuModel{
.name = "c3_2",
.llvm_name = "c3-2",
.features = featureSet(&[_]Feature{
@@ -1337,7 +1338,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const cannonlake = Cpu{
+ pub const cannonlake = CpuModel{
.name = "cannonlake",
.llvm_name = "cannonlake",
.features = featureSet(&[_]Feature{
@@ -1397,7 +1398,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const cascadelake = Cpu{
+ pub const cascadelake = CpuModel{
.name = "cascadelake",
.llvm_name = "cascadelake",
.features = featureSet(&[_]Feature{
@@ -1456,7 +1457,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const cooperlake = Cpu{
+ pub const cooperlake = CpuModel{
.name = "cooperlake",
.llvm_name = "cooperlake",
.features = featureSet(&[_]Feature{
@@ -1516,7 +1517,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const core_avx_i = Cpu{
+ pub const core_avx_i = CpuModel{
.name = "core_avx_i",
.llvm_name = "core-avx-i",
.features = featureSet(&[_]Feature{
@@ -1549,7 +1550,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const core_avx2 = Cpu{
+ pub const core_avx2 = CpuModel{
.name = "core_avx2",
.llvm_name = "core-avx2",
.features = featureSet(&[_]Feature{
@@ -1591,7 +1592,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const core2 = Cpu{
+ pub const core2 = CpuModel{
.name = "core2",
.llvm_name = "core2",
.features = featureSet(&[_]Feature{
@@ -1610,7 +1611,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const corei7 = Cpu{
+ pub const corei7 = CpuModel{
.name = "corei7",
.llvm_name = "corei7",
.features = featureSet(&[_]Feature{
@@ -1629,7 +1630,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const corei7_avx = Cpu{
+ pub const corei7_avx = CpuModel{
.name = "corei7_avx",
.llvm_name = "corei7-avx",
.features = featureSet(&[_]Feature{
@@ -1659,7 +1660,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const generic = Cpu{
+ pub const generic = CpuModel{
.name = "generic",
.llvm_name = "generic",
.features = featureSet(&[_]Feature{
@@ -1669,7 +1670,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const geode = Cpu{
+ pub const geode = CpuModel{
.name = "geode",
.llvm_name = "geode",
.features = featureSet(&[_]Feature{
@@ -1680,7 +1681,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const goldmont = Cpu{
+ pub const goldmont = CpuModel{
.name = "goldmont",
.llvm_name = "goldmont",
.features = featureSet(&[_]Feature{
@@ -1717,7 +1718,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const goldmont_plus = Cpu{
+ pub const goldmont_plus = CpuModel{
.name = "goldmont_plus",
.llvm_name = "goldmont-plus",
.features = featureSet(&[_]Feature{
@@ -1756,7 +1757,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const haswell = Cpu{
+ pub const haswell = CpuModel{
.name = "haswell",
.llvm_name = "haswell",
.features = featureSet(&[_]Feature{
@@ -1798,7 +1799,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const _i386 = Cpu{
+ pub const _i386 = CpuModel{
.name = "_i386",
.llvm_name = "i386",
.features = featureSet(&[_]Feature{
@@ -1807,7 +1808,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const _i486 = Cpu{
+ pub const _i486 = CpuModel{
.name = "_i486",
.llvm_name = "i486",
.features = featureSet(&[_]Feature{
@@ -1816,7 +1817,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const _i586 = Cpu{
+ pub const _i586 = CpuModel{
.name = "_i586",
.llvm_name = "i586",
.features = featureSet(&[_]Feature{
@@ -1826,7 +1827,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const _i686 = Cpu{
+ pub const _i686 = CpuModel{
.name = "_i686",
.llvm_name = "i686",
.features = featureSet(&[_]Feature{
@@ -1837,7 +1838,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const icelake_client = Cpu{
+ pub const icelake_client = CpuModel{
.name = "icelake_client",
.llvm_name = "icelake-client",
.features = featureSet(&[_]Feature{
@@ -1906,7 +1907,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const icelake_server = Cpu{
+ pub const icelake_server = CpuModel{
.name = "icelake_server",
.llvm_name = "icelake-server",
.features = featureSet(&[_]Feature{
@@ -1977,7 +1978,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const ivybridge = Cpu{
+ pub const ivybridge = CpuModel{
.name = "ivybridge",
.llvm_name = "ivybridge",
.features = featureSet(&[_]Feature{
@@ -2010,7 +2011,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const k6 = Cpu{
+ pub const k6 = CpuModel{
.name = "k6",
.llvm_name = "k6",
.features = featureSet(&[_]Feature{
@@ -2021,7 +2022,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const k6_2 = Cpu{
+ pub const k6_2 = CpuModel{
.name = "k6_2",
.llvm_name = "k6-2",
.features = featureSet(&[_]Feature{
@@ -2032,7 +2033,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const k6_3 = Cpu{
+ pub const k6_3 = CpuModel{
.name = "k6_3",
.llvm_name = "k6-3",
.features = featureSet(&[_]Feature{
@@ -2043,7 +2044,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const k8 = Cpu{
+ pub const k8 = CpuModel{
.name = "k8",
.llvm_name = "k8",
.features = featureSet(&[_]Feature{
@@ -2061,7 +2062,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const k8_sse3 = Cpu{
+ pub const k8_sse3 = CpuModel{
.name = "k8_sse3",
.llvm_name = "k8-sse3",
.features = featureSet(&[_]Feature{
@@ -2080,7 +2081,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const knl = Cpu{
+ pub const knl = CpuModel{
.name = "knl",
.llvm_name = "knl",
.features = featureSet(&[_]Feature{
@@ -2123,7 +2124,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const knm = Cpu{
+ pub const knm = CpuModel{
.name = "knm",
.llvm_name = "knm",
.features = featureSet(&[_]Feature{
@@ -2167,14 +2168,14 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const lakemont = Cpu{
+ pub const lakemont = CpuModel{
.name = "lakemont",
.llvm_name = "lakemont",
.features = featureSet(&[_]Feature{
.vzeroupper,
}),
};
- pub const nehalem = Cpu{
+ pub const nehalem = CpuModel{
.name = "nehalem",
.llvm_name = "nehalem",
.features = featureSet(&[_]Feature{
@@ -2193,7 +2194,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const nocona = Cpu{
+ pub const nocona = CpuModel{
.name = "nocona",
.llvm_name = "nocona",
.features = featureSet(&[_]Feature{
@@ -2210,7 +2211,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const opteron = Cpu{
+ pub const opteron = CpuModel{
.name = "opteron",
.llvm_name = "opteron",
.features = featureSet(&[_]Feature{
@@ -2228,7 +2229,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const opteron_sse3 = Cpu{
+ pub const opteron_sse3 = CpuModel{
.name = "opteron_sse3",
.llvm_name = "opteron-sse3",
.features = featureSet(&[_]Feature{
@@ -2247,7 +2248,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const penryn = Cpu{
+ pub const penryn = CpuModel{
.name = "penryn",
.llvm_name = "penryn",
.features = featureSet(&[_]Feature{
@@ -2266,7 +2267,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium = Cpu{
+ pub const pentium = CpuModel{
.name = "pentium",
.llvm_name = "pentium",
.features = featureSet(&[_]Feature{
@@ -2276,7 +2277,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium_m = Cpu{
+ pub const pentium_m = CpuModel{
.name = "pentium_m",
.llvm_name = "pentium-m",
.features = featureSet(&[_]Feature{
@@ -2291,7 +2292,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium_mmx = Cpu{
+ pub const pentium_mmx = CpuModel{
.name = "pentium_mmx",
.llvm_name = "pentium-mmx",
.features = featureSet(&[_]Feature{
@@ -2302,7 +2303,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium2 = Cpu{
+ pub const pentium2 = CpuModel{
.name = "pentium2",
.llvm_name = "pentium2",
.features = featureSet(&[_]Feature{
@@ -2316,7 +2317,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium3 = Cpu{
+ pub const pentium3 = CpuModel{
.name = "pentium3",
.llvm_name = "pentium3",
.features = featureSet(&[_]Feature{
@@ -2331,7 +2332,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium3m = Cpu{
+ pub const pentium3m = CpuModel{
.name = "pentium3m",
.llvm_name = "pentium3m",
.features = featureSet(&[_]Feature{
@@ -2346,7 +2347,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium4 = Cpu{
+ pub const pentium4 = CpuModel{
.name = "pentium4",
.llvm_name = "pentium4",
.features = featureSet(&[_]Feature{
@@ -2361,7 +2362,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentium4m = Cpu{
+ pub const pentium4m = CpuModel{
.name = "pentium4m",
.llvm_name = "pentium4m",
.features = featureSet(&[_]Feature{
@@ -2376,7 +2377,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const pentiumpro = Cpu{
+ pub const pentiumpro = CpuModel{
.name = "pentiumpro",
.llvm_name = "pentiumpro",
.features = featureSet(&[_]Feature{
@@ -2388,7 +2389,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const prescott = Cpu{
+ pub const prescott = CpuModel{
.name = "prescott",
.llvm_name = "prescott",
.features = featureSet(&[_]Feature{
@@ -2403,7 +2404,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const sandybridge = Cpu{
+ pub const sandybridge = CpuModel{
.name = "sandybridge",
.llvm_name = "sandybridge",
.features = featureSet(&[_]Feature{
@@ -2433,7 +2434,7 @@ pub const cpu = struct {
.xsaveopt,
}),
};
- pub const silvermont = Cpu{
+ pub const silvermont = CpuModel{
.name = "silvermont",
.llvm_name = "silvermont",
.features = featureSet(&[_]Feature{
@@ -2462,7 +2463,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const skx = Cpu{
+ pub const skx = CpuModel{
.name = "skx",
.llvm_name = "skx",
.features = featureSet(&[_]Feature{
@@ -2520,7 +2521,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const skylake = Cpu{
+ pub const skylake = CpuModel{
.name = "skylake",
.llvm_name = "skylake",
.features = featureSet(&[_]Feature{
@@ -2571,7 +2572,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const skylake_avx512 = Cpu{
+ pub const skylake_avx512 = CpuModel{
.name = "skylake_avx512",
.llvm_name = "skylake-avx512",
.features = featureSet(&[_]Feature{
@@ -2629,7 +2630,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const slm = Cpu{
+ pub const slm = CpuModel{
.name = "slm",
.llvm_name = "slm",
.features = featureSet(&[_]Feature{
@@ -2658,7 +2659,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const tigerlake = Cpu{
+ pub const tigerlake = CpuModel{
.name = "tigerlake",
.llvm_name = "tigerlake",
.features = featureSet(&[_]Feature{
@@ -2731,7 +2732,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const tremont = Cpu{
+ pub const tremont = CpuModel{
.name = "tremont",
.llvm_name = "tremont",
.features = featureSet(&[_]Feature{
@@ -2775,7 +2776,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const westmere = Cpu{
+ pub const westmere = CpuModel{
.name = "westmere",
.llvm_name = "westmere",
.features = featureSet(&[_]Feature{
@@ -2795,7 +2796,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const winchip_c6 = Cpu{
+ pub const winchip_c6 = CpuModel{
.name = "winchip_c6",
.llvm_name = "winchip-c6",
.features = featureSet(&[_]Feature{
@@ -2805,7 +2806,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const winchip2 = Cpu{
+ pub const winchip2 = CpuModel{
.name = "winchip2",
.llvm_name = "winchip2",
.features = featureSet(&[_]Feature{
@@ -2815,7 +2816,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const x86_64 = Cpu{
+ pub const x86_64 = CpuModel{
.name = "x86_64",
.llvm_name = "x86-64",
.features = featureSet(&[_]Feature{
@@ -2833,7 +2834,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const yonah = Cpu{
+ pub const yonah = CpuModel{
.name = "yonah",
.llvm_name = "yonah",
.features = featureSet(&[_]Feature{
@@ -2848,7 +2849,7 @@ pub const cpu = struct {
.x87,
}),
};
- pub const znver1 = Cpu{
+ pub const znver1 = CpuModel{
.name = "znver1",
.llvm_name = "znver1",
.features = featureSet(&[_]Feature{
@@ -2893,7 +2894,7 @@ pub const cpu = struct {
.xsaves,
}),
};
- pub const znver2 = Cpu{
+ pub const znver2 = CpuModel{
.name = "znver2",
.llvm_name = "znver2",
.features = featureSet(&[_]Feature{
@@ -2946,7 +2947,7 @@ pub const cpu = struct {
/// All x86 CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
-pub const all_cpus = &[_]*const Cpu{
+pub const all_cpus = &[_]*const CpuModel{
&cpu.amdfam10,
&cpu.athlon,
&cpu.athlon_4,
diff --git a/lib/std/thread.zig b/lib/std/thread.zig
@@ -148,7 +148,7 @@ pub const Thread = struct {
const default_stack_size = 16 * 1024 * 1024;
const Context = @TypeOf(context);
- comptime assert(@ArgType(@TypeOf(startFn), 0) == Context);
+ comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context);
if (builtin.os == builtin.Os.windows) {
const WinThread = struct {
@@ -158,7 +158,7 @@ pub const Thread = struct {
};
fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
- switch (@typeId(@TypeOf(startFn).ReturnType)) {
+ switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
.Int => {
return startFn(arg);
},
@@ -201,7 +201,7 @@ pub const Thread = struct {
fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 {
const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
- switch (@typeId(@TypeOf(startFn).ReturnType)) {
+ switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
.Int => {
return startFn(arg);
},
diff --git a/lib/std/time.zig b/lib/std/time.zig
@@ -8,6 +8,7 @@ const math = std.math;
pub const epoch = @import("time/epoch.zig");
/// Spurious wakeups are possible and no precision of timing is guaranteed.
+/// TODO integrate with evented I/O
pub fn sleep(nanoseconds: u64) void {
if (builtin.os == .windows) {
const ns_per_ms = ns_per_s / ms_per_s;
@@ -152,15 +153,9 @@ pub const Timer = struct {
}
/// Reads the timer value since start or the last reset in nanoseconds
- pub fn read(self: *Timer) u64 {
+ pub fn read(self: Timer) u64 {
var clock = clockNative() - self.start_time;
- if (builtin.os == .windows) {
- return @divFloor(clock * ns_per_s, self.frequency);
- }
- if (comptime std.Target.current.isDarwin()) {
- return @divFloor(clock * self.frequency.numer, self.frequency.denom);
- }
- return clock;
+ return self.nativeDurationToNanos(clock);
}
/// Resets the timer value to 0/now.
@@ -171,7 +166,7 @@ pub const Timer = struct {
/// Returns the current value of the timer in nanoseconds, then resets it
pub fn lap(self: *Timer) u64 {
var now = clockNative();
- var lap_time = self.read();
+ var lap_time = self.nativeDurationToNanos(now - self.start_time);
self.start_time = now;
return lap_time;
}
@@ -187,6 +182,16 @@ pub const Timer = struct {
os.clock_gettime(monotonic_clock_id, &ts) catch unreachable;
return @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec);
}
+
+ fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
+ if (builtin.os == .windows) {
+ return @divFloor(duration * ns_per_s, self.frequency);
+ }
+ if (comptime std.Target.current.isDarwin()) {
+ return @divFloor(duration * self.frequency.numer, self.frequency.denom);
+ }
+ return duration;
+ }
};
test "sleep" {
diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig
@@ -243,7 +243,7 @@ pub const Utf16LeIterator = struct {
pub fn init(s: []const u16) Utf16LeIterator {
return Utf16LeIterator{
- .bytes = @sliceToBytes(s),
+ .bytes = mem.sliceAsBytes(s),
.i = 0,
};
}
@@ -496,7 +496,7 @@ pub fn utf16leToUtf8(utf8: []u8, utf16le: []const u16) !usize {
test "utf16leToUtf8" {
var utf16le: [2]u16 = undefined;
- const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
+ const utf16le_as_bytes = mem.sliceAsBytes(utf16le[0..]);
{
mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
@@ -606,12 +606,12 @@ test "utf8ToUtf16Le" {
{
const length = try utf8ToUtf16Le(utf16le[0..], "𐐷");
testing.expectEqual(@as(usize, 2), length);
- testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16le[0..]));
+ testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16le[0..]));
}
{
const length = try utf8ToUtf16Le(utf16le[0..], "\u{10FFFF}");
testing.expectEqual(@as(usize, 2), length);
- testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16le[0..]));
+ testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16le[0..]));
}
}
@@ -619,13 +619,13 @@ test "utf8ToUtf16LeWithNull" {
{
const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "𐐷");
defer testing.allocator.free(utf16);
- testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..]));
+ testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16[0..]));
testing.expect(utf16[2] == 0);
}
{
const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "\u{10FFFF}");
defer testing.allocator.free(utf16);
- testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..]));
+ testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16[0..]));
testing.expect(utf16[2] == 0);
}
}
diff --git a/lib/std/zig.zig b/lib/std/zig.zig
@@ -5,6 +5,7 @@ pub const parse = @import("zig/parse.zig").parse;
pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStringLiteral;
pub const render = @import("zig/render.zig").render;
pub const ast = @import("zig/ast.zig");
+pub const system = @import("zig/system.zig");
test "std.zig tests" {
_ = @import("zig/ast.zig");
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
@@ -460,10 +460,9 @@ pub const Node = struct {
}
pub fn iterate(base: *Node, index: usize) ?*Node {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (base.id == @field(Id, @memberName(Id, i))) {
- const T = @field(Node, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (base.id == @field(Id, f.name)) {
+ const T = @field(Node, f.name);
return @fieldParentPtr(T, "base", base).iterate(index);
}
}
@@ -471,10 +470,9 @@ pub const Node = struct {
}
pub fn firstToken(base: *const Node) TokenIndex {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (base.id == @field(Id, @memberName(Id, i))) {
- const T = @field(Node, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (base.id == @field(Id, f.name)) {
+ const T = @field(Node, f.name);
return @fieldParentPtr(T, "base", base).firstToken();
}
}
@@ -482,10 +480,9 @@ pub const Node = struct {
}
pub fn lastToken(base: *const Node) TokenIndex {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (base.id == @field(Id, @memberName(Id, i))) {
- const T = @field(Node, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (base.id == @field(Id, f.name)) {
+ const T = @field(Node, f.name);
return @fieldParentPtr(T, "base", base).lastToken();
}
}
@@ -493,10 +490,9 @@ pub const Node = struct {
}
pub fn typeToId(comptime T: type) Id {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (T == @field(Node, @memberName(Id, i))) {
- return @field(Id, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (T == @field(Node, f.name)) {
+ return @field(Id, f.name);
}
}
unreachable;
@@ -1567,7 +1563,9 @@ pub const Node = struct {
pub const Op = union(enum) {
AddressOf,
ArrayType: ArrayInfo,
- Await,
+ Await: struct {
+ noasync_token: ?TokenIndex = null,
+ },
BitNot,
BoolNot,
Cancel,
@@ -2184,10 +2182,10 @@ pub const Node = struct {
pub fn iterate(self: *Asm, index: usize) ?*Node {
var i = index;
- if (i < self.outputs.len) return &self.outputs.at(index).*.base;
+ if (i < self.outputs.len) return &self.outputs.at(i).*.base;
i -= self.outputs.len;
- if (i < self.inputs.len) return &self.inputs.at(index).*.base;
+ if (i < self.inputs.len) return &self.inputs.at(i).*.base;
i -= self.inputs.len;
return null;
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
@@ -1129,7 +1129,7 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
/// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
- var maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);
+ const maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);
if (maybe_async) |async_token| {
const token_fn = eatToken(it, .Keyword_fn);
if (async_token.ptr.id == .Keyword_async and token_fn != null) {
@@ -2179,7 +2179,19 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
.MinusPercent => ops{ .NegationWrap = {} },
.Ampersand => ops{ .AddressOf = {} },
.Keyword_try => ops{ .Try = {} },
- .Keyword_await => ops{ .Await = {} },
+ .Keyword_await => ops{ .Await = .{} },
+ .Keyword_noasync => if (eatToken(it, .Keyword_await)) |await_tok| {
+ const node = try arena.create(Node.PrefixOp);
+ node.* = Node.PrefixOp{
+ .op_token = await_tok,
+ .op = .{ .Await = .{ .noasync_token = token.index } },
+ .rhs = undefined, // set by caller
+ };
+ return &node.base;
+ } else {
+ putBackToken(it, token.index);
+ return null;
+ },
else => {
putBackToken(it, token.index);
return null;
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
@@ -1,3 +1,12 @@
+test "zig fmt: noasync await" {
+ try testCanonical(
+ \\fn foo() void {
+ \\ x = noasync await y;
+ \\}
+ \\
+ );
+}
+
test "zig fmt: trailing comma in container declaration" {
try testCanonical(
\\const X = struct { foo: i32 };
@@ -83,10 +92,12 @@ test "zig fmt: convert extern/nakedcc/stdcallcc into callconv(...)" {
\\nakedcc fn foo1() void {}
\\stdcallcc fn foo2() void {}
\\extern fn foo3() void {}
+ \\extern "mylib" fn foo4() void {}
,
\\fn foo1() callconv(.Naked) void {}
\\fn foo2() callconv(.Stdcall) void {}
\\fn foo3() callconv(.C) void {}
+ \\fn foo4() callconv(.C) void {}
\\
);
}
@@ -1399,7 +1410,7 @@ test "zig fmt: same-line comment after non-block if expression" {
test "zig fmt: same-line comment on comptime expression" {
try testCanonical(
\\test "" {
- \\ comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
+ \\ comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
\\}
\\
);
diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig
@@ -1,5 +1,4 @@
const std = @import("../std.zig");
-const builtin = @import("builtin");
const assert = std.debug.assert;
const mem = std.mem;
const ast = std.zig.ast;
@@ -14,7 +13,7 @@ pub const Error = error{
/// Returns whether anything changed
pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Child.Error || Error)!bool {
- comptime assert(@typeId(@TypeOf(stream)) == builtin.TypeId.Pointer);
+ comptime assert(@typeInfo(@TypeOf(stream)) == .Pointer);
var anything_changed: bool = false;
@@ -584,12 +583,18 @@ fn renderExpression(
},
.Try,
- .Await,
.Cancel,
.Resume,
=> {
try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
},
+
+ .Await => |await_info| {
+ if (await_info.noasync_token) |tok| {
+ try renderToken(tree, stream, tok, indent, start_col, Space.Space);
+ }
+ try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
+ },
}
return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space);
@@ -1390,6 +1395,7 @@ fn renderExpression(
try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
} else {
cc_rewrite_str = ".C";
+ fn_proto.lib_name = null;
}
}
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
@@ -0,0 +1,163 @@
+const std = @import("../std.zig");
+const mem = std.mem;
+const Allocator = std.mem.Allocator;
+const ArrayList = std.ArrayList;
+const assert = std.debug.assert;
+const process = std.process;
+
+const is_windows = std.Target.current.isWindows();
+
+pub const NativePaths = struct {
+ include_dirs: ArrayList([:0]u8),
+ lib_dirs: ArrayList([:0]u8),
+ rpaths: ArrayList([:0]u8),
+ warnings: ArrayList([:0]u8),
+
+ pub fn detect(allocator: *Allocator) !NativePaths {
+ var self: NativePaths = .{
+ .include_dirs = ArrayList([:0]u8).init(allocator),
+ .lib_dirs = ArrayList([:0]u8).init(allocator),
+ .rpaths = ArrayList([:0]u8).init(allocator),
+ .warnings = ArrayList([:0]u8).init(allocator),
+ };
+ errdefer self.deinit();
+
+ var is_nix = false;
+ if (process.getEnvVarOwned(allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
+ defer allocator.free(nix_cflags_compile);
+
+ is_nix = true;
+ var it = mem.tokenize(nix_cflags_compile, " ");
+ while (true) {
+ const word = it.next() orelse break;
+ if (mem.eql(u8, word, "-isystem")) {
+ const include_path = it.next() orelse {
+ try self.addWarning("Expected argument after -isystem in NIX_CFLAGS_COMPILE");
+ break;
+ };
+ try self.addIncludeDir(include_path);
+ } else {
+ try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}", .{word});
+ break;
+ }
+ }
+ } else |err| switch (err) {
+ error.InvalidUtf8 => {},
+ error.EnvironmentVariableNotFound => {},
+ error.OutOfMemory => |e| return e,
+ }
+ if (process.getEnvVarOwned(allocator, "NIX_LDFLAGS")) |nix_ldflags| {
+ defer allocator.free(nix_ldflags);
+
+ is_nix = true;
+ var it = mem.tokenize(nix_ldflags, " ");
+ while (true) {
+ const word = it.next() orelse break;
+ if (mem.eql(u8, word, "-rpath")) {
+ const rpath = it.next() orelse {
+ try self.addWarning("Expected argument after -rpath in NIX_LDFLAGS");
+ break;
+ };
+ try self.addRPath(rpath);
+ } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') {
+ const lib_path = word[2..];
+ try self.addLibDir(lib_path);
+ } else {
+ try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {}", .{word});
+ break;
+ }
+ }
+ } else |err| switch (err) {
+ error.InvalidUtf8 => {},
+ error.EnvironmentVariableNotFound => {},
+ error.OutOfMemory => |e| return e,
+ }
+ if (is_nix) {
+ return self;
+ }
+
+ if (!is_windows) {
+ const triple = try std.Target.current.linuxTriple(allocator);
+
+ // TODO: $ ld --verbose | grep SEARCH_DIR
+ // the output contains some paths that end with lib64, maybe include them too?
+ // TODO: what is the best possible order of things?
+ // TODO: some of these are suspect and should only be added on some systems. audit needed.
+
+ try self.addIncludeDir("/usr/local/include");
+ try self.addLibDir("/usr/local/lib");
+ try self.addLibDir("/usr/local/lib64");
+
+ try self.addIncludeDirFmt("/usr/include/{}", .{triple});
+ try self.addLibDirFmt("/usr/lib/{}", .{triple});
+
+ try self.addIncludeDir("/usr/include");
+ try self.addLibDir("/lib");
+ try self.addLibDir("/lib64");
+ try self.addLibDir("/usr/lib");
+ try self.addLibDir("/usr/lib64");
+
+ // example: on a 64-bit debian-based linux distro, with zlib installed from apt:
+ // zlib.h is in /usr/include (added above)
+ // libz.so.1 is in /lib/x86_64-linux-gnu (added here)
+ try self.addLibDirFmt("/lib/{}", .{triple});
+ }
+
+ return self;
+ }
+
+ pub fn deinit(self: *NativePaths) void {
+ deinitArray(&self.include_dirs);
+ deinitArray(&self.lib_dirs);
+ deinitArray(&self.rpaths);
+ deinitArray(&self.warnings);
+ self.* = undefined;
+ }
+
+ fn deinitArray(array: *ArrayList([:0]u8)) void {
+ for (array.toSlice()) |item| {
+ array.allocator.free(item);
+ }
+ array.deinit();
+ }
+
+ pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void {
+ return self.appendArray(&self.include_dirs, s);
+ }
+
+ pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
+ const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args);
+ errdefer self.include_dirs.allocator.free(item);
+ try self.include_dirs.append(item);
+ }
+
+ pub fn addLibDir(self: *NativePaths, s: []const u8) !void {
+ return self.appendArray(&self.lib_dirs, s);
+ }
+
+ pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
+ const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args);
+ errdefer self.lib_dirs.allocator.free(item);
+ try self.lib_dirs.append(item);
+ }
+
+ pub fn addWarning(self: *NativePaths, s: []const u8) !void {
+ return self.appendArray(&self.warnings, s);
+ }
+
+ pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
+ const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args);
+ errdefer self.warnings.allocator.free(item);
+ try self.warnings.append(item);
+ }
+
+ pub fn addRPath(self: *NativePaths, s: []const u8) !void {
+ return self.appendArray(&self.rpaths, s);
+ }
+
+ fn appendArray(self: *NativePaths, array: *ArrayList([:0]u8), s: []const u8) !void {
+ const item = try std.mem.dupeZ(array.allocator, u8, s);
+ errdefer array.allocator.free(item);
+ try array.append(item);
+ }
+};
diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig
@@ -414,10 +414,8 @@ pub const Tokenizer = struct {
pub fn next(self: *Tokenizer) Token {
if (self.pending_invalid_token) |token| {
- // TODO: Audit this pattern once #2915 is closed
- const copy = token;
self.pending_invalid_token = null;
- return copy;
+ return token;
}
const start_index = self.index;
var state = State.Start;
@@ -1270,10 +1268,8 @@ pub const Tokenizer = struct {
if (result.id == Token.Id.Eof) {
if (self.pending_invalid_token) |token| {
- // TODO: Audit this pattern once #2915 is closed
- const copy = token;
self.pending_invalid_token = null;
- return copy;
+ return token;
}
}
diff --git a/src-self-hosted/c.zig b/src-self-hosted/c.zig
@@ -4,5 +4,4 @@ pub usingnamespace @cImport({
@cInclude("inttypes.h");
@cInclude("config.h");
@cInclude("zig_llvm.h");
- @cInclude("windows_sdk.h");
});
diff --git a/src-self-hosted/introspect.zig b/src-self-hosted/introspect.zig
@@ -6,6 +6,14 @@ const fs = std.fs;
const warn = std.debug.warn;
+pub fn detectDynamicLinker(allocator: *mem.Allocator, target: std.Target) ![:0]u8 {
+ if (target == .Native) {
+ return @import("libc_installation.zig").detectNativeDynamicLinker(allocator);
+ } else {
+ return target.getStandardDynamicLinkerPath(allocator);
+ }
+}
+
/// Caller must free result
pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
const test_zig_dir = try fs.path.join(allocator, &[_][]const u8{ test_path, "lib", "zig" });
diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig
@@ -76,20 +76,18 @@ pub const Inst = struct {
}
pub fn typeToId(comptime T: type) Id {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (T == @field(Inst, @memberName(Id, i))) {
- return @field(Id, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (T == @field(Inst, f.name)) {
+ return @field(Id, f.name);
}
}
unreachable;
}
pub fn dump(base: *const Inst) void {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (base.id == @field(Id, @memberName(Id, i))) {
- const T = @field(Inst, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (base.id == @field(Id, f.name)) {
+ const T = @field(Inst, f.name);
std.debug.warn("#{} = {}(", .{ base.debug_id, @tagName(base.id) });
@fieldParentPtr(T, "base", base).dump();
std.debug.warn(")", .{});
@@ -100,10 +98,9 @@ pub const Inst = struct {
}
pub fn hasSideEffects(base: *const Inst) bool {
- comptime var i = 0;
- inline while (i < @memberCount(Id)) : (i += 1) {
- if (base.id == @field(Id, @memberName(Id, i))) {
- const T = @field(Inst, @memberName(Id, i));
+ inline for (@typeInfo(Id).Enum.fields) |f| {
+ if (base.id == @field(Id, f.name)) {
+ const T = @field(Inst, f.name);
return @fieldParentPtr(T, "base", base).hasSideEffects();
}
}
@@ -1805,21 +1802,19 @@ pub const Builder = struct {
};
// Look at the params and ref() other instructions
- comptime var i = 0;
- inline while (i < @memberCount(I.Params)) : (i += 1) {
- const FieldType = comptime @TypeOf(@field(@as(I.Params, undefined), @memberName(I.Params, i)));
- switch (FieldType) {
- *Inst => @field(inst.params, @memberName(I.Params, i)).ref(self),
- *BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self),
- ?*Inst => if (@field(inst.params, @memberName(I.Params, i))) |other| other.ref(self),
+ inline for (@typeInfo(I.Params).Struct.fields) |f| {
+ switch (f.fiedl_type) {
+ *Inst => @field(inst.params, f.name).ref(self),
+ *BasicBlock => @field(inst.params, f.name).ref(self),
+ ?*Inst => if (@field(inst.params, f.name)) |other| other.ref(self),
[]*Inst => {
// TODO https://github.com/ziglang/zig/issues/1269
- for (@field(inst.params, @memberName(I.Params, i))) |other|
+ for (@field(inst.params, f.name)) |other|
other.ref(self);
},
[]*BasicBlock => {
// TODO https://github.com/ziglang/zig/issues/1269
- for (@field(inst.params, @memberName(I.Params, i))) |other|
+ for (@field(inst.params, f.name)) |other|
other.ref(self);
},
Type.Pointer.Mut,
@@ -1831,7 +1826,7 @@ pub const Builder = struct {
=> {},
// it's ok to add more types here, just make sure that
// any instructions and basic blocks are ref'd appropriately
- else => @compileError("unrecognized type in Params: " ++ @typeName(FieldType)),
+ else => @compileError("unrecognized type in Params: " ++ @typeName(f.field_type)),
}
}
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
@@ -1,20 +1,29 @@
const std = @import("std");
const builtin = @import("builtin");
-const event = std.event;
const util = @import("util.zig");
const Target = std.Target;
-const c = @import("c.zig");
const fs = std.fs;
const Allocator = std.mem.Allocator;
+const Batch = std.event.Batch;
+
+const is_darwin = Target.current.isDarwin();
+const is_windows = Target.current.isWindows();
+const is_freebsd = Target.current.isFreeBSD();
+const is_netbsd = Target.current.isNetBSD();
+const is_linux = Target.current.isLinux();
+const is_dragonfly = Target.current.isDragonFlyBSD();
+const is_gnu = Target.current.isGnu();
+
+usingnamespace @import("windows_sdk.zig");
/// See the render function implementation for documentation of the fields.
pub const LibCInstallation = struct {
- include_dir: []const u8,
- lib_dir: ?[]const u8,
- static_lib_dir: ?[]const u8,
- msvc_lib_dir: ?[]const u8,
- kernel32_lib_dir: ?[]const u8,
- dynamic_linker_path: ?[]const u8,
+ include_dir: ?[:0]const u8 = null,
+ sys_include_dir: ?[:0]const u8 = null,
+ crt_dir: ?[:0]const u8 = null,
+ static_crt_dir: ?[:0]const u8 = null,
+ msvc_lib_dir: ?[:0]const u8 = null,
+ kernel32_lib_dir: ?[:0]const u8 = null,
pub const FindError = error{
OutOfMemory,
@@ -27,31 +36,24 @@ pub const LibCInstallation = struct {
LibCStdLibHeaderNotFound,
LibCKernel32LibNotFound,
UnsupportedArchitecture,
+ WindowsSdkNotFound,
};
pub fn parse(
- self: *LibCInstallation,
allocator: *Allocator,
libc_file: []const u8,
stderr: *std.io.OutStream(fs.File.WriteError),
- ) !void {
- self.initEmpty();
-
- const keys = [_][]const u8{
- "include_dir",
- "lib_dir",
- "static_lib_dir",
- "msvc_lib_dir",
- "kernel32_lib_dir",
- "dynamic_linker_path",
- };
+ ) !LibCInstallation {
+ var self: LibCInstallation = .{};
+
+ const fields = std.meta.fields(LibCInstallation);
const FoundKey = struct {
found: bool,
- allocated: ?[]u8,
+ allocated: ?[:0]u8,
};
- var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** keys.len;
+ var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** fields.len;
errdefer {
- self.initEmpty();
+ self = .{};
for (found_keys) |found_key| {
if (found_key.allocated) |s| allocator.free(s);
}
@@ -69,152 +71,216 @@ pub const LibCInstallation = struct {
return error.ParseError;
};
const value = line_it.rest();
- inline for (keys) |key, i| {
- if (std.mem.eql(u8, name, key)) {
+ inline for (fields) |field, i| {
+ if (std.mem.eql(u8, name, field.name)) {
found_keys[i].found = true;
- switch (@typeInfo(@TypeOf(@field(self, key)))) {
- .Optional => {
- if (value.len == 0) {
- @field(self, key) = null;
- } else {
- found_keys[i].allocated = try std.mem.dupe(allocator, u8, value);
- @field(self, key) = found_keys[i].allocated;
- }
- },
- else => {
- if (value.len == 0) {
- try stderr.print("field cannot be empty: {}\n", .{key});
- return error.ParseError;
- }
- const dupe = try std.mem.dupe(allocator, u8, value);
- found_keys[i].allocated = dupe;
- @field(self, key) = dupe;
- },
+ if (value.len == 0) {
+ @field(self, field.name) = null;
+ } else {
+ found_keys[i].allocated = try std.mem.dupeZ(allocator, u8, value);
+ @field(self, field.name) = found_keys[i].allocated;
}
break;
}
}
}
- for (found_keys) |found_key, i| {
- if (!found_key.found) {
- try stderr.print("missing field: {}\n", .{keys[i]});
+ inline for (fields) |field, i| {
+ if (!found_keys[i].found) {
+ try stderr.print("missing field: {}\n", .{field.name});
return error.ParseError;
}
}
+ if (self.include_dir == null) {
+ try stderr.print("include_dir may not be empty\n", .{});
+ return error.ParseError;
+ }
+ if (self.sys_include_dir == null) {
+ try stderr.print("sys_include_dir may not be empty\n", .{});
+ return error.ParseError;
+ }
+ if (self.crt_dir == null and !is_darwin) {
+ try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.getOs())});
+ return error.ParseError;
+ }
+ if (self.static_crt_dir == null and is_windows and is_gnu) {
+ try stderr.print("static_crt_dir may not be empty for {}-{}\n", .{
+ @tagName(Target.current.getOs()),
+ @tagName(Target.current.getAbi()),
+ });
+ return error.ParseError;
+ }
+ if (self.msvc_lib_dir == null and is_windows and !is_gnu) {
+ try stderr.print("msvc_lib_dir may not be empty for {}-{}\n", .{
+ @tagName(Target.current.getOs()),
+ @tagName(Target.current.getAbi()),
+ });
+ return error.ParseError;
+ }
+ if (self.kernel32_lib_dir == null and is_windows and !is_gnu) {
+ try stderr.print("kernel32_lib_dir may not be empty for {}-{}\n", .{
+ @tagName(Target.current.getOs()),
+ @tagName(Target.current.getAbi()),
+ });
+ return error.ParseError;
+ }
+
+ return self;
}
- pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(fs.File.WriteError)) !void {
+ pub fn render(self: LibCInstallation, out: *std.io.OutStream(fs.File.WriteError)) !void {
@setEvalBranchQuota(4000);
- const lib_dir = self.lib_dir orelse "";
- const static_lib_dir = self.static_lib_dir orelse "";
+ const include_dir = self.include_dir orelse "";
+ const sys_include_dir = self.sys_include_dir orelse "";
+ const crt_dir = self.crt_dir orelse "";
+ const static_crt_dir = self.static_crt_dir orelse "";
const msvc_lib_dir = self.msvc_lib_dir orelse "";
const kernel32_lib_dir = self.kernel32_lib_dir orelse "";
- const dynamic_linker_path = self.dynamic_linker_path orelse util.getDynamicLinkerPath(Target{ .Native = {} });
+
try out.print(
\\# The directory that contains `stdlib.h`.
- \\# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
+ \\# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
\\include_dir={}
\\
- \\# The directory that contains `crt1.o`.
- \\# On Linux, can be found with `cc -print-file-name=crt1.o`.
+ \\# The system-specific include directory. May be the same as `include_dir`.
+ \\# On Windows it's the directory that includes `vcruntime.h`.
+ \\# On POSIX it's the directory that includes `sys/errno.h`.
+ \\sys_include_dir={}
+ \\
+ \\# The directory that contains `crt1.o` or `crt2.o`.
+ \\# On POSIX, can be found with `cc -print-file-name=crt1.o`.
\\# Not needed when targeting MacOS.
- \\lib_dir={}
+ \\crt_dir={}
\\
\\# The directory that contains `crtbegin.o`.
- \\# On Linux, can be found with `cc -print-file-name=crtbegin.o`.
- \\# Not needed when targeting MacOS or Windows.
- \\static_lib_dir={}
+ \\# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.
+ \\# Only needed when targeting MinGW-w64 on Windows.
+ \\static_crt_dir={}
\\
\\# The directory that contains `vcruntime.lib`.
- \\# Only needed when targeting Windows.
+ \\# Only needed when targeting MSVC on Windows.
\\msvc_lib_dir={}
\\
\\# The directory that contains `kernel32.lib`.
- \\# Only needed when targeting Windows.
+ \\# Only needed when targeting MSVC on Windows.
\\kernel32_lib_dir={}
\\
- \\# The full path to the dynamic linker, on the target system.
- \\# Only needed when targeting Linux.
- \\dynamic_linker_path={}
- \\
- , .{ self.include_dir, lib_dir, static_lib_dir, msvc_lib_dir, kernel32_lib_dir, dynamic_linker_path });
+ , .{
+ include_dir,
+ sys_include_dir,
+ crt_dir,
+ static_crt_dir,
+ msvc_lib_dir,
+ kernel32_lib_dir,
+ });
}
+ pub const FindNativeOptions = struct {
+ allocator: *Allocator,
+
+ /// If enabled, will print human-friendly errors to stderr.
+ verbose: bool = false,
+ };
+
/// Finds the default, native libc.
- pub fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
- self.initEmpty();
- var group = event.Group(FindError!void).init(allocator);
- errdefer group.wait() catch {};
- var windows_sdk: ?*c.ZigWindowsSDK = null;
- errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk));
-
- switch (builtin.os) {
- .windows => {
- var sdk: *c.ZigWindowsSDK = undefined;
- switch (c.zig_find_windows_sdk(@ptrCast(?[*]?[*]c.ZigWindowsSDK, &sdk))) {
- c.ZigFindWindowsSdkError.None => {
- windows_sdk = sdk;
-
- if (sdk.msvc_lib_dir_ptr != 0) {
- self.msvc_lib_dir = try std.mem.dupe(allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
- }
- try group.call(findNativeKernel32LibDir, .{ allocator, self, sdk });
- try group.call(findNativeIncludeDirWindows, .{ self, allocator, sdk });
- try group.call(findNativeLibDirWindows, .{ self, allocator, sdk });
+ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation {
+ var self: LibCInstallation = .{};
+
+ if (is_windows) {
+ if (is_gnu) {
+ var batch = Batch(FindError!void, 3, .auto_async).init();
+ batch.add(&async self.findNativeIncludeDirPosix(args));
+ batch.add(&async self.findNativeCrtDirPosix(args));
+ batch.add(&async self.findNativeStaticCrtDirPosix(args));
+ try batch.wait();
+ } else {
+ var sdk: *ZigWindowsSDK = undefined;
+ switch (zig_find_windows_sdk(&sdk)) {
+ .None => {
+ defer zig_free_windows_sdk(sdk);
+
+ var batch = Batch(FindError!void, 5, .auto_async).init();
+ batch.add(&async self.findNativeMsvcIncludeDir(args, sdk));
+ batch.add(&async self.findNativeMsvcLibDir(args, sdk));
+ batch.add(&async self.findNativeKernel32LibDir(args, sdk));
+ batch.add(&async self.findNativeIncludeDirWindows(args, sdk));
+ batch.add(&async self.findNativeCrtDirWindows(args, sdk));
+ try batch.wait();
},
- c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory,
- c.ZigFindWindowsSdkError.NotFound => return error.NotFound,
- c.ZigFindWindowsSdkError.PathTooLong => return error.NotFound,
+ .OutOfMemory => return error.OutOfMemory,
+ .NotFound => return error.WindowsSdkNotFound,
+ .PathTooLong => return error.WindowsSdkNotFound,
}
- },
- .linux => {
- try group.call(findNativeIncludeDirLinux, .{ self, allocator });
- try group.call(findNativeLibDirLinux, .{ self, allocator });
- try group.call(findNativeStaticLibDir, .{ self, allocator });
- try group.call(findNativeDynamicLinker, .{ self, allocator });
- },
- .macosx, .freebsd, .netbsd => {
- self.include_dir = try std.mem.dupe(allocator, u8, "/usr/include");
- },
- else => @compileError("unimplemented: find libc for this OS"),
+ }
+ } else {
+ try blk: {
+ var batch = Batch(FindError!void, 2, .auto_async).init();
+ errdefer batch.wait() catch {};
+ batch.add(&async self.findNativeIncludeDirPosix(args));
+ if (is_freebsd or is_netbsd) {
+ self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib");
+ } else if (is_linux or is_dragonfly) {
+ batch.add(&async self.findNativeCrtDirPosix(args));
+ }
+ break :blk batch.wait();
+ };
+ }
+ return self;
+ }
+
+ /// Must be the same allocator passed to `parse` or `findNative`.
+ pub fn deinit(self: *LibCInstallation, allocator: *Allocator) void {
+ const fields = std.meta.fields(LibCInstallation);
+ inline for (fields) |field| {
+ if (@field(self, field.name)) |payload| {
+ allocator.free(payload);
+ }
}
- return group.wait();
+ self.* = undefined;
}
- async fn findNativeIncludeDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- const cc_exe = std.os.getenv("CC") orelse "cc";
+ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ const allocator = args.allocator;
+ const dev_null = if (is_windows) "nul" else "/dev/null";
+ const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
const argv = [_][]const u8{
cc_exe,
"-E",
"-Wp,-v",
"-xc",
- "/dev/null",
+ dev_null,
};
- // TODO make this use event loop
- const errorable_result = std.ChildProcess.exec(allocator, &argv, null, null, 1024 * 1024);
- const exec_result = if (std.debug.runtime_safety) blk: {
- break :blk errorable_result catch unreachable;
- } else blk: {
- break :blk errorable_result catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- else => return error.UnableToSpawnCCompiler,
- };
+ const exec_res = std.ChildProcess.exec2(.{
+ .allocator = allocator,
+ .argv = &argv,
+ .max_output_bytes = 1024 * 1024,
+ // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
+ // to their own executable, without even bothering to resolve PATH. This results in the message:
+ // error: unable to execute command: Executable "" doesn't exist!
+ // So we use the expandArg0 variant of ChildProcess to give them a helping hand.
+ .expand_arg0 = .expand,
+ }) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => {
+ printVerboseInvocation(&argv, null, args.verbose, null);
+ return error.UnableToSpawnCCompiler;
+ },
};
defer {
- allocator.free(exec_result.stdout);
- allocator.free(exec_result.stderr);
+ allocator.free(exec_res.stdout);
+ allocator.free(exec_res.stderr);
}
-
- switch (exec_result.term) {
- .Exited => |code| {
- if (code != 0) return error.CCompilerExitCode;
+ switch (exec_res.term) {
+ .Exited => |code| if (code != 0) {
+ printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
+ return error.CCompilerExitCode;
},
else => {
+ printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
return error.CCompilerCrashed;
},
}
- var it = std.mem.tokenize(exec_result.stderr, "\n\r");
+ var it = std.mem.tokenize(exec_res.stderr, "\n\r");
var search_paths = std.ArrayList([]const u8).init(allocator);
defer search_paths.deinit();
while (it.next()) |line| {
@@ -226,16 +292,44 @@ pub const LibCInstallation = struct {
return error.CCompilerCannotFindHeaders;
}
- // search in reverse order
+ const include_dir_example_file = "stdlib.h";
+ const sys_include_dir_example_file = if (is_windows) "sys\\types.h" else "sys/errno.h";
+
var path_i: usize = 0;
while (path_i < search_paths.len) : (path_i += 1) {
+ // search in reverse order
const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
- const stdlib_path = try fs.path.join(allocator, &[_][]const u8{ search_path, "stdlib.h" });
- defer allocator.free(stdlib_path);
+ var search_dir = fs.cwd().openDirList(search_path) catch |err| switch (err) {
+ error.FileNotFound,
+ error.NotDir,
+ error.NoDevice,
+ => continue,
+
+ else => return error.FileSystem,
+ };
+ defer search_dir.close();
+
+ if (self.include_dir == null) {
+ if (search_dir.accessZ(include_dir_example_file, .{})) |_| {
+ self.include_dir = try std.mem.dupeZ(allocator, u8, search_path);
+ } else |err| switch (err) {
+ error.FileNotFound => {},
+ else => return error.FileSystem,
+ }
+ }
+
+ if (self.sys_include_dir == null) {
+ if (search_dir.accessZ(sys_include_dir_example_file, .{})) |_| {
+ self.sys_include_dir = try std.mem.dupeZ(allocator, u8, search_path);
+ } else |err| switch (err) {
+ error.FileNotFound => {},
+ else => return error.FileSystem,
+ }
+ }
- if (try fileExists(stdlib_path)) {
- self.include_dir = try std.mem.dupe(allocator, u8, search_path);
+ if (self.include_dir != null and self.sys_include_dir != null) {
+ // Success.
return;
}
}
@@ -243,7 +337,13 @@ pub const LibCInstallation = struct {
return error.LibCStdLibHeaderNotFound;
}
- async fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) !void {
+ fn findNativeIncludeDirWindows(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
@@ -255,180 +355,363 @@ pub const LibCInstallation = struct {
const stream = &std.io.BufferOutStream.init(&result_buf).stream;
try stream.print("{}\\Include\\{}\\ucrt", .{ search.path, search.version });
- const stdlib_path = try fs.path.join(
- allocator,
- [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
- );
- defer allocator.free(stdlib_path);
+ var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
+ error.FileNotFound,
+ error.NotDir,
+ error.NoDevice,
+ => continue,
- if (try fileExists(stdlib_path)) {
- self.include_dir = result_buf.toOwnedSlice();
- return;
- }
+ else => return error.FileSystem,
+ };
+ defer dir.close();
+
+ dir.accessZ("stdlib.h", .{}) catch |err| switch (err) {
+ error.FileNotFound => continue,
+ else => return error.FileSystem,
+ };
+
+ self.include_dir = result_buf.toOwnedSlice();
+ return;
}
return error.LibCStdLibHeaderNotFound;
}
- async fn findNativeLibDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void {
+ fn findNativeCrtDirWindows(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
var result_buf = try std.Buffer.initSize(allocator, 0);
defer result_buf.deinit();
+ const arch_sub_dir = switch (builtin.arch) {
+ .i386 => "x86",
+ .x86_64 => "x64",
+ .arm, .armeb => "arm",
+ else => return error.UnsupportedArchitecture,
+ };
+
for (searches) |search| {
result_buf.shrink(0);
const stream = &std.io.BufferOutStream.init(&result_buf).stream;
- try stream.print("{}\\Lib\\{}\\ucrt\\", .{ search.path, search.version });
- switch (builtin.arch) {
- .i386 => try stream.write("x86"),
- .x86_64 => try stream.write("x64"),
- .aarch64 => try stream.write("arm"),
- else => return error.UnsupportedArchitecture,
- }
- const ucrt_lib_path = try fs.path.join(
- allocator,
- [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
- );
- defer allocator.free(ucrt_lib_path);
- if (try fileExists(ucrt_lib_path)) {
- self.lib_dir = result_buf.toOwnedSlice();
- return;
- }
- }
- return error.LibCRuntimeNotFound;
- }
+ try stream.print("{}\\Lib\\{}\\ucrt\\{}", .{ search.path, search.version, arch_sub_dir });
- async fn findNativeLibDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- self.lib_dir = try ccPrintFileName(allocator, "crt1.o", true);
- }
+ var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
+ error.FileNotFound,
+ error.NotDir,
+ error.NoDevice,
+ => continue,
- async fn findNativeStaticLibDir(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- self.static_lib_dir = try ccPrintFileName(allocator, "crtbegin.o", true);
- }
+ else => return error.FileSystem,
+ };
+ defer dir.close();
- async fn findNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- var dyn_tests = [_]DynTest{
- DynTest{
- .name = "ld-linux-x86-64.so.2",
- .result = null,
- },
- DynTest{
- .name = "ld-musl-x86_64.so.1",
- .result = null,
- },
- };
- var group = event.Group(FindError!void).init(allocator);
- errdefer group.wait() catch {};
- for (dyn_tests) |*dyn_test| {
- try group.call(testNativeDynamicLinker, .{ self, allocator, dyn_test });
- }
- try group.wait();
- for (dyn_tests) |*dyn_test| {
- if (dyn_test.result) |result| {
- self.dynamic_linker_path = result;
- return;
- }
+ dir.accessZ("ucrt.lib", .{}) catch |err| switch (err) {
+ error.FileNotFound => continue,
+ else => return error.FileSystem,
+ };
+
+ self.crt_dir = result_buf.toOwnedSlice();
+ return;
}
+ return error.LibCRuntimeNotFound;
}
- const DynTest = struct {
- name: []const u8,
- result: ?[]const u8,
- };
+ fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ self.crt_dir = try ccPrintFileName(.{
+ .allocator = args.allocator,
+ .search_basename = "crt1.o",
+ .want_dirname = .only_dir,
+ .verbose = args.verbose,
+ });
+ }
- async fn testNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator, dyn_test: *DynTest) FindError!void {
- if (ccPrintFileName(allocator, dyn_test.name, false)) |result| {
- dyn_test.result = result;
- return;
- } else |err| switch (err) {
- error.LibCRuntimeNotFound => return,
- else => return err,
- }
+ fn findNativeStaticCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ self.static_crt_dir = try ccPrintFileName(.{
+ .allocator = args.allocator,
+ .search_basename = "crtbegin.o",
+ .want_dirname = .only_dir,
+ .verbose = args.verbose,
+ });
}
- async fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void {
+ fn findNativeKernel32LibDir(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
var result_buf = try std.Buffer.initSize(allocator, 0);
defer result_buf.deinit();
+ const arch_sub_dir = switch (builtin.arch) {
+ .i386 => "x86",
+ .x86_64 => "x64",
+ .arm, .armeb => "arm",
+ else => return error.UnsupportedArchitecture,
+ };
+
for (searches) |search| {
result_buf.shrink(0);
const stream = &std.io.BufferOutStream.init(&result_buf).stream;
- try stream.print("{}\\Lib\\{}\\um\\", .{ search.path, search.version });
- switch (builtin.arch) {
- .i386 => try stream.write("x86\\"),
- .x86_64 => try stream.write("x64\\"),
- .aarch64 => try stream.write("arm\\"),
- else => return error.UnsupportedArchitecture,
- }
- const kernel32_path = try fs.path.join(
- allocator,
- [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
- );
- defer allocator.free(kernel32_path);
- if (try fileExists(kernel32_path)) {
- self.kernel32_lib_dir = result_buf.toOwnedSlice();
- return;
- }
+ try stream.print("{}\\Lib\\{}\\um\\{}", .{ search.path, search.version, arch_sub_dir });
+
+ var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
+ error.FileNotFound,
+ error.NotDir,
+ error.NoDevice,
+ => continue,
+
+ else => return error.FileSystem,
+ };
+ defer dir.close();
+
+ dir.accessZ("kernel32.lib", .{}) catch |err| switch (err) {
+ error.FileNotFound => continue,
+ else => return error.FileSystem,
+ };
+
+ self.kernel32_lib_dir = result_buf.toOwnedSlice();
+ return;
}
return error.LibCKernel32LibNotFound;
}
- fn initEmpty(self: *LibCInstallation) void {
- self.* = LibCInstallation{
- .include_dir = @as([*]const u8, undefined)[0..0],
- .lib_dir = null,
- .static_lib_dir = null,
- .msvc_lib_dir = null,
- .kernel32_lib_dir = null,
- .dynamic_linker_path = null,
+ fn findNativeMsvcIncludeDir(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
+ const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCStdLibHeaderNotFound;
+ const msvc_lib_dir = msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len];
+ const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound;
+ const up2 = fs.path.dirname(up1) orelse return error.LibCStdLibHeaderNotFound;
+
+ var result_buf = try std.Buffer.init(allocator, up2);
+ defer result_buf.deinit();
+
+ try result_buf.append("\\include");
+
+ var dir = fs.cwd().openDirList(result_buf.toSliceConst()) catch |err| switch (err) {
+ error.FileNotFound,
+ error.NotDir,
+ error.NoDevice,
+ => return error.LibCStdLibHeaderNotFound,
+
+ else => return error.FileSystem,
+ };
+ defer dir.close();
+
+ dir.accessZ("vcruntime.h", .{}) catch |err| switch (err) {
+ error.FileNotFound => return error.LibCStdLibHeaderNotFound,
+ else => return error.FileSystem,
};
+
+ self.sys_include_dir = result_buf.toOwnedSlice();
+ }
+
+ fn findNativeMsvcLibDir(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+ const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCRuntimeNotFound;
+ self.msvc_lib_dir = try std.mem.dupeZ(allocator, u8, msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
}
};
+const default_cc_exe = if (is_windows) "cc.exe" else "cc";
+
+pub const CCPrintFileNameOptions = struct {
+ allocator: *Allocator,
+ search_basename: []const u8,
+ want_dirname: enum { full_path, only_dir },
+ verbose: bool = false,
+};
+
/// caller owns returned memory
-fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
- const cc_exe = std.os.getenv("CC") orelse "cc";
- const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{o_file});
+fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
+ const allocator = args.allocator;
+
+ const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
+ const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
defer allocator.free(arg1);
const argv = [_][]const u8{ cc_exe, arg1 };
- // TODO This simulates evented I/O for the child process exec
- event.Loop.startCpuBoundOperation();
- const errorable_result = std.ChildProcess.exec(allocator, &argv, null, null, 1024 * 1024);
- const exec_result = if (std.debug.runtime_safety) blk: {
- break :blk errorable_result catch unreachable;
- } else blk: {
- break :blk errorable_result catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- else => return error.UnableToSpawnCCompiler,
- };
+ const exec_res = std.ChildProcess.exec2(.{
+ .allocator = allocator,
+ .argv = &argv,
+ .max_output_bytes = 1024 * 1024,
+ // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
+ // to their own executable, without even bothering to resolve PATH. This results in the message:
+ // error: unable to execute command: Executable "" doesn't exist!
+ // So we use the expandArg0 variant of ChildProcess to give them a helping hand.
+ .expand_arg0 = .expand,
+ }) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => return error.UnableToSpawnCCompiler,
};
defer {
- allocator.free(exec_result.stdout);
- allocator.free(exec_result.stderr);
+ allocator.free(exec_res.stdout);
+ allocator.free(exec_res.stderr);
}
- switch (exec_result.term) {
- .Exited => |code| {
- if (code != 0) return error.CCompilerExitCode;
+ switch (exec_res.term) {
+ .Exited => |code| if (code != 0) {
+ printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
+ return error.CCompilerExitCode;
},
else => {
+ printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
return error.CCompilerCrashed;
},
}
- var it = std.mem.tokenize(exec_result.stdout, "\n\r");
+
+ var it = std.mem.tokenize(exec_res.stdout, "\n\r");
const line = it.next() orelse return error.LibCRuntimeNotFound;
- const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
+ // When this command fails, it returns exit code 0 and duplicates the input file name.
+ // So we detect failure by checking if the output matches exactly the input.
+ if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound;
+ switch (args.want_dirname) {
+ .full_path => return std.mem.dupeZ(allocator, u8, line),
+ .only_dir => {
+ const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
+ return std.mem.dupeZ(allocator, u8, dirname);
+ },
+ }
+}
+
+fn printVerboseInvocation(
+ argv: []const []const u8,
+ search_basename: ?[]const u8,
+ verbose: bool,
+ stderr: ?[]const u8,
+) void {
+ if (!verbose) return;
- if (want_dirname) {
- return std.mem.dupe(allocator, u8, dirname);
+ if (search_basename) |s| {
+ std.debug.warn("Zig attempted to find the file '{}' by executing this command:\n", .{s});
} else {
- return std.mem.dupe(allocator, u8, line);
+ std.debug.warn("Zig attempted to find the path to native system libc headers by executing this command:\n", .{});
+ }
+ for (argv) |arg, i| {
+ if (i != 0) std.debug.warn(" ", .{});
+ std.debug.warn("{}", .{arg});
+ }
+ std.debug.warn("\n", .{});
+ if (stderr) |s| {
+ std.debug.warn("Output:\n==========\n{}\n==========\n", .{s});
+ }
+}
+
+/// Caller owns returned memory.
+pub fn detectNativeDynamicLinker(allocator: *Allocator) error{
+ OutOfMemory,
+ TargetHasNoDynamicLinker,
+ UnknownDynamicLinkerPath,
+}![:0]u8 {
+ if (!comptime Target.current.hasDynamicLinker()) {
+ return error.TargetHasNoDynamicLinker;
+ }
+
+ // The current target's ABI cannot be relied on for this. For example, we may build the zig
+ // compiler for target riscv64-linux-musl and provide a tarball for users to download.
+ // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined
+ // and supported by Zig. But that means that we must detect the system ABI here rather than
+ // relying on `std.Target.current`.
+
+ const LdInfo = struct {
+ ld_path: []u8,
+ abi: Target.Abi,
+ };
+ var ld_info_list = std.ArrayList(LdInfo).init(allocator);
+ defer {
+ for (ld_info_list.toSlice()) |ld_info| allocator.free(ld_info.ld_path);
+ ld_info_list.deinit();
+ }
+
+ const all_abis = comptime blk: {
+ const fields = std.meta.fields(Target.Abi);
+ var array: [fields.len]Target.Abi = undefined;
+ inline for (fields) |field, i| {
+ array[i] = @field(Target.Abi, field.name);
+ }
+ break :blk array;
+ };
+ for (all_abis) |abi| {
+ // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
+ // skip adding it to `ld_info_list`.
+ const target: Target = .{
+ .Cross = .{
+ .cpu = Target.Cpu.baseline(Target.current.getArch()),
+ .os = Target.current.getOs(),
+ .abi = abi,
+ },
+ };
+ const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => continue,
+ };
+ errdefer allocator.free(standard_ld_path);
+ try ld_info_list.append(.{
+ .ld_path = standard_ld_path,
+ .abi = abi,
+ });
+ }
+
+ // Best case scenario: the zig compiler is dynamically linked, and we can iterate
+ // over our own shared objects and find a dynamic linker.
+ {
+ const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator);
+ defer allocator.free(lib_paths);
+
+ // This is O(N^M) but typical case here is N=2 and M=10.
+ for (lib_paths) |lib_path| {
+ for (ld_info_list.toSlice()) |ld_info| {
+ const standard_ld_basename = fs.path.basename(ld_info.ld_path);
+ if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
+ return std.mem.dupeZ(allocator, u8, lib_path);
+ }
+ }
+ }
+ }
+
+ // If Zig is statically linked, such as via distributed binary static builds, the above
+ // trick won't work. What are we left with? Try to run the system C compiler and get
+ // it to tell us the dynamic linker path.
+ // TODO: instead of this, look at the shared libs of /usr/bin/env.
+ for (ld_info_list.toSlice()) |ld_info| {
+ const standard_ld_basename = fs.path.basename(ld_info.ld_path);
+
+ const full_ld_path = ccPrintFileName(.{
+ .allocator = allocator,
+ .search_basename = standard_ld_basename,
+ .want_dirname = .full_path,
+ }) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.LibCRuntimeNotFound,
+ error.CCompilerExitCode,
+ error.CCompilerCrashed,
+ error.UnableToSpawnCCompiler,
+ => continue,
+ };
+ return full_ld_path;
}
+
+ // Finally, we fall back on the standard path.
+ return Target.current.getStandardDynamicLinkerPath(allocator);
}
const Search = struct {
@@ -436,34 +719,25 @@ const Search = struct {
version: []const u8,
};
-fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
+fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search {
var search_end: usize = 0;
- if (sdk.path10_ptr != 0) {
- if (sdk.version10_ptr != 0) {
+ if (sdk.path10_ptr) |path10_ptr| {
+ if (sdk.version10_ptr) |version10_ptr| {
search_buf[search_end] = Search{
- .path = sdk.path10_ptr[0..sdk.path10_len],
- .version = sdk.version10_ptr[0..sdk.version10_len],
+ .path = path10_ptr[0..sdk.path10_len],
+ .version = version10_ptr[0..sdk.version10_len],
};
search_end += 1;
}
}
- if (sdk.path81_ptr != 0) {
- if (sdk.version81_ptr != 0) {
+ if (sdk.path81_ptr) |path81_ptr| {
+ if (sdk.version81_ptr) |version81_ptr| {
search_buf[search_end] = Search{
- .path = sdk.path81_ptr[0..sdk.path81_len],
- .version = sdk.version81_ptr[0..sdk.version81_len],
+ .path = path81_ptr[0..sdk.path81_len],
+ .version = version81_ptr[0..sdk.version81_len],
};
search_end += 1;
}
}
return search_buf[0..search_end];
}
-
-fn fileExists(path: []const u8) !bool {
- if (fs.File.access(path)) |_| {
- return true;
- } else |err| switch (err) {
- error.FileNotFound => return false,
- else => return error.FileSystem,
- }
-}
diff --git a/src-self-hosted/print_targets.zig b/src-self-hosted/print_targets.zig
@@ -113,37 +113,14 @@ pub fn cmdTargets(
try jws.beginObject();
try jws.objectField("arch");
- try jws.beginObject();
+ try jws.beginArray();
{
- inline for (@typeInfo(Target.Arch).Union.fields) |field| {
- try jws.objectField(field.name);
- if (field.field_type == void) {
- try jws.emitNull();
- } else {
- try jws.emitString(@typeName(field.field_type));
- }
- }
- }
- try jws.endObject();
-
- try jws.objectField("subArch");
- try jws.beginObject();
- const sub_arch_list = [_]type{
- Target.Arch.Arm32,
- Target.Arch.Arm64,
- Target.Arch.Kalimba,
- Target.Arch.Mips,
- };
- inline for (sub_arch_list) |SubArch| {
- try jws.objectField(@typeName(SubArch));
- try jws.beginArray();
- inline for (@typeInfo(SubArch).Enum.fields) |field| {
+ inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| {
try jws.arrayElem();
try jws.emitString(field.name);
}
- try jws.endArray();
}
- try jws.endObject();
+ try jws.endArray();
try jws.objectField("os");
try jws.beginArray();
@@ -179,15 +156,15 @@ pub fn cmdTargets(
try jws.objectField("cpus");
try jws.beginObject();
- inline for (@typeInfo(Target.Arch).Union.fields) |field| {
+ inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| {
try jws.objectField(field.name);
try jws.beginObject();
- const arch = @unionInit(Target.Arch, field.name, undefined);
- for (arch.allCpus()) |cpu| {
- try jws.objectField(cpu.name);
+ const arch = @field(Target.Cpu.Arch, field.name);
+ for (arch.allCpuModels()) |model| {
+ try jws.objectField(model.name);
try jws.beginArray();
for (arch.allFeaturesList()) |feature, i| {
- if (cpu.features.isEnabled(@intCast(u8, i))) {
+ if (model.features.isEnabled(@intCast(u8, i))) {
try jws.arrayElem();
try jws.emitString(feature.name);
}
@@ -200,10 +177,10 @@ pub fn cmdTargets(
try jws.objectField("cpuFeatures");
try jws.beginObject();
- inline for (@typeInfo(Target.Arch).Union.fields) |field| {
+ inline for (@typeInfo(Target.Cpu.Arch).Enum.fields) |field| {
try jws.objectField(field.name);
try jws.beginArray();
- const arch = @unionInit(Target.Arch, field.name, undefined);
+ const arch = @field(Target.Cpu.Arch, field.name);
for (arch.allFeaturesList()) |feature| {
try jws.arrayElem();
try jws.emitString(feature.name);
@@ -220,27 +197,34 @@ pub fn cmdTargets(
try jws.objectField("triple");
try jws.emitString(triple);
}
- try jws.objectField("arch");
- try jws.emitString(@tagName(native_target.getArch()));
- try jws.objectField("os");
- try jws.emitString(@tagName(native_target.getOs()));
- try jws.objectField("abi");
- try jws.emitString(@tagName(native_target.getAbi()));
- try jws.objectField("cpuName");
- const cpu_features = native_target.getCpuFeatures();
- try jws.emitString(cpu_features.cpu.name);
{
- try jws.objectField("cpuFeatures");
- try jws.beginArray();
- for (native_target.getArch().allFeaturesList()) |feature, i_usize| {
- const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
- if (cpu_features.features.isEnabled(index)) {
- try jws.arrayElem();
- try jws.emitString(feature.name);
+ try jws.objectField("cpu");
+ try jws.beginObject();
+ try jws.objectField("arch");
+ try jws.emitString(@tagName(native_target.getArch()));
+
+ try jws.objectField("name");
+ const cpu = native_target.getCpu();
+ try jws.emitString(cpu.model.name);
+
+ {
+ try jws.objectField("features");
+ try jws.beginArray();
+ for (native_target.getArch().allFeaturesList()) |feature, i_usize| {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
+ if (cpu.features.isEnabled(index)) {
+ try jws.arrayElem();
+ try jws.emitString(feature.name);
+ }
}
+ try jws.endArray();
}
- try jws.endArray();
+ try jws.endObject();
}
+ try jws.objectField("os");
+ try jws.emitString(@tagName(native_target.getOs()));
+ try jws.objectField("abi");
+ try jws.emitString(@tagName(native_target.getAbi()));
// TODO implement native glibc version detection in self-hosted
try jws.endObject();
diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig
@@ -1,832 +0,0 @@
-// This is Zig code that is used by both stage1 and stage2.
-// The prototypes in src/userland.h must match these definitions.
-
-const std = @import("std");
-const io = std.io;
-const mem = std.mem;
-const fs = std.fs;
-const process = std.process;
-const Allocator = mem.Allocator;
-const ArrayList = std.ArrayList;
-const Buffer = std.Buffer;
-const Target = std.Target;
-const self_hosted_main = @import("main.zig");
-const errmsg = @import("errmsg.zig");
-const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
-const assert = std.debug.assert;
-
-var stderr_file: fs.File = undefined;
-var stderr: *io.OutStream(fs.File.WriteError) = undefined;
-var stdout: *io.OutStream(fs.File.WriteError) = undefined;
-
-comptime {
- _ = @import("dep_tokenizer.zig");
-}
-
-// ABI warning
-export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
- const info_zen = @import("main.zig").info_zen;
- ptr.* = info_zen;
- len.* = info_zen.len;
-}
-
-// ABI warning
-export fn stage2_panic(ptr: [*]const u8, len: usize) void {
- @panic(ptr[0..len]);
-}
-
-// ABI warning
-const Error = extern enum {
- None,
- OutOfMemory,
- InvalidFormat,
- SemanticAnalyzeFail,
- AccessDenied,
- Interrupted,
- SystemResources,
- FileNotFound,
- FileSystem,
- FileTooBig,
- DivByZero,
- Overflow,
- PathAlreadyExists,
- Unexpected,
- ExactDivRemainder,
- NegativeDenominator,
- ShiftedOutOneBits,
- CCompileErrors,
- EndOfFile,
- IsDir,
- NotDir,
- UnsupportedOperatingSystem,
- SharingViolation,
- PipeBusy,
- PrimitiveTypeNotFound,
- CacheUnavailable,
- PathTooLong,
- CCompilerCannotFindFile,
- NoCCompilerInstalled,
- ReadingDepFile,
- InvalidDepFile,
- MissingArchitecture,
- MissingOperatingSystem,
- UnknownArchitecture,
- UnknownOperatingSystem,
- UnknownABI,
- InvalidFilename,
- DiskQuota,
- DiskSpace,
- UnexpectedWriteFailure,
- UnexpectedSeekFailure,
- UnexpectedFileTruncationFailure,
- Unimplemented,
- OperationAborted,
- BrokenPipe,
- NoSpaceLeft,
- NotLazy,
- IsAsync,
- ImportOutsidePkgPath,
- UnknownCpu,
- UnknownSubArchitecture,
- UnknownCpuFeature,
- InvalidCpuFeatures,
- InvalidLlvmCpuFeaturesFormat,
- UnknownApplicationBinaryInterface,
-};
-
-const FILE = std.c.FILE;
-const ast = std.zig.ast;
-const translate_c = @import("translate_c.zig");
-
-/// Args should have a null terminating last arg.
-export fn stage2_translate_c(
- out_ast: **ast.Tree,
- out_errors_ptr: *[*]translate_c.ClangErrMsg,
- out_errors_len: *usize,
- args_begin: [*]?[*]const u8,
- args_end: [*]?[*]const u8,
- resources_path: [*:0]const u8,
-) Error {
- var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
- out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
- error.SemanticAnalyzeFail => {
- out_errors_ptr.* = errors.ptr;
- out_errors_len.* = errors.len;
- return Error.CCompileErrors;
- },
- error.OutOfMemory => return Error.OutOfMemory,
- };
- return Error.None;
-}
-
-export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
- translate_c.freeErrors(errors_ptr[0..errors_len]);
-}
-
-export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
- const c_out_stream = &std.io.COutStream.init(output_file).stream;
- _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
- error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
- error.SystemResources => return Error.SystemResources,
- error.OperationAborted => return Error.OperationAborted,
- error.BrokenPipe => return Error.BrokenPipe,
- error.DiskQuota => return Error.DiskQuota,
- error.FileTooBig => return Error.FileTooBig,
- error.NoSpaceLeft => return Error.NoSpaceLeft,
- error.AccessDenied => return Error.AccessDenied,
- error.OutOfMemory => return Error.OutOfMemory,
- error.Unexpected => return Error.Unexpected,
- error.InputOutput => return Error.FileSystem,
- };
- return Error.None;
-}
-
-// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
-// we use a blocking implementation.
-export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int {
- if (std.debug.runtime_safety) {
- fmtMain(argc, argv) catch unreachable;
- } else {
- fmtMain(argc, argv) catch |e| {
- std.debug.warn("{}\n", .{@errorName(e)});
- return -1;
- };
- }
- return 0;
-}
-
-fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
- const allocator = std.heap.c_allocator;
- var args_list = std.ArrayList([]const u8).init(allocator);
- const argc_usize = @intCast(usize, argc);
- var arg_i: usize = 0;
- while (arg_i < argc_usize) : (arg_i += 1) {
- try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
- }
-
- stdout = &std.io.getStdOut().outStream().stream;
- stderr_file = std.io.getStdErr();
- stderr = &stderr_file.outStream().stream;
-
- const args = args_list.toSliceConst()[2..];
-
- var color: errmsg.Color = .Auto;
- var stdin_flag: bool = false;
- var check_flag: bool = false;
- var input_files = ArrayList([]const u8).init(allocator);
-
- {
- var i: usize = 0;
- while (i < args.len) : (i += 1) {
- const arg = args[i];
- if (mem.startsWith(u8, arg, "-")) {
- if (mem.eql(u8, arg, "--help")) {
- try stdout.write(self_hosted_main.usage_fmt);
- process.exit(0);
- } else if (mem.eql(u8, arg, "--color")) {
- if (i + 1 >= args.len) {
- try stderr.write("expected [auto|on|off] after --color\n");
- process.exit(1);
- }
- i += 1;
- const next_arg = args[i];
- if (mem.eql(u8, next_arg, "auto")) {
- color = .Auto;
- } else if (mem.eql(u8, next_arg, "on")) {
- color = .On;
- } else if (mem.eql(u8, next_arg, "off")) {
- color = .Off;
- } else {
- try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
- process.exit(1);
- }
- } else if (mem.eql(u8, arg, "--stdin")) {
- stdin_flag = true;
- } else if (mem.eql(u8, arg, "--check")) {
- check_flag = true;
- } else {
- try stderr.print("unrecognized parameter: '{}'", .{arg});
- process.exit(1);
- }
- } else {
- try input_files.append(arg);
- }
- }
- }
-
- if (stdin_flag) {
- if (input_files.len != 0) {
- try stderr.write("cannot use --stdin with positional arguments\n");
- process.exit(1);
- }
-
- const stdin_file = io.getStdIn();
- var stdin = stdin_file.inStream();
-
- const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
- defer allocator.free(source_code);
-
- const tree = std.zig.parse(allocator, source_code) catch |err| {
- try stderr.print("error parsing stdin: {}\n", .{err});
- process.exit(1);
- };
- defer tree.deinit();
-
- var error_it = tree.errors.iterator(0);
- while (error_it.next()) |parse_error| {
- try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
- }
- if (tree.errors.len != 0) {
- process.exit(1);
- }
- if (check_flag) {
- const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
- const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
- process.exit(code);
- }
-
- _ = try std.zig.render(allocator, stdout, tree);
- return;
- }
-
- if (input_files.len == 0) {
- try stderr.write("expected at least one source file argument\n");
- process.exit(1);
- }
-
- var fmt = Fmt{
- .seen = Fmt.SeenMap.init(allocator),
- .any_error = false,
- .color = color,
- .allocator = allocator,
- };
-
- for (input_files.toSliceConst()) |file_path| {
- try fmtPath(&fmt, file_path, check_flag);
- }
- if (fmt.any_error) {
- process.exit(1);
- }
-}
-
-const FmtError = error{
- SystemResources,
- OperationAborted,
- IoPending,
- BrokenPipe,
- Unexpected,
- WouldBlock,
- FileClosed,
- DestinationAddressRequired,
- DiskQuota,
- FileTooBig,
- InputOutput,
- NoSpaceLeft,
- AccessDenied,
- OutOfMemory,
- RenameAcrossMountPoints,
- ReadOnlyFileSystem,
- LinkQuotaExceeded,
- FileBusy,
-} || fs.File.OpenError;
-
-fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
- if (fmt.seen.exists(file_path)) return;
- try fmt.seen.put(file_path);
-
- const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
- error.IsDir, error.AccessDenied => {
- // TODO make event based (and dir.next())
- var dir = try fs.cwd().openDirList(file_path);
- defer dir.close();
-
- var dir_it = dir.iterate();
-
- while (try dir_it.next()) |entry| {
- if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
- const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name });
- try fmtPath(fmt, full_path, check_mode);
- }
- }
- return;
- },
- else => {
- // TODO lock stderr printing
- try stderr.print("unable to open '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
- },
- };
- defer fmt.allocator.free(source_code);
-
- const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
- try stderr.print("error parsing file '{}': {}\n", .{ file_path, err });
- fmt.any_error = true;
- return;
- };
- defer tree.deinit();
-
- var error_it = tree.errors.iterator(0);
- while (error_it.next()) |parse_error| {
- try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
- }
- if (tree.errors.len != 0) {
- fmt.any_error = true;
- return;
- }
-
- if (check_mode) {
- const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
- if (anything_changed) {
- try stderr.print("{}\n", .{file_path});
- fmt.any_error = true;
- }
- } else {
- const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
- defer baf.destroy();
-
- const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
- if (anything_changed) {
- try stderr.print("{}\n", .{file_path});
- try baf.finish();
- }
- }
-}
-
-const Fmt = struct {
- seen: SeenMap,
- any_error: bool,
- color: errmsg.Color,
- allocator: *mem.Allocator,
-
- const SeenMap = std.BufSet;
-};
-
-fn printErrMsgToFile(
- allocator: *mem.Allocator,
- parse_error: *const ast.Error,
- tree: *ast.Tree,
- path: []const u8,
- file: fs.File,
- color: errmsg.Color,
-) !void {
- const color_on = switch (color) {
- .Auto => file.isTty(),
- .On => true,
- .Off => false,
- };
- const lok_token = parse_error.loc();
- const span = errmsg.Span{
- .first = lok_token,
- .last = lok_token,
- };
-
- const first_token = tree.tokens.at(span.first);
- const last_token = tree.tokens.at(span.last);
- const start_loc = tree.tokenLocationPtr(0, first_token);
- const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
-
- var text_buf = try std.Buffer.initSize(allocator, 0);
- var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
- try parse_error.render(&tree.tokens, out_stream);
- const text = text_buf.toOwnedSlice();
-
- const stream = &file.outStream().stream;
- try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text });
-
- if (!color_on) return;
-
- // Print \r and \t as one space each so that column counts line up
- for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| {
- try stream.writeByte(switch (byte) {
- '\r', '\t' => ' ',
- else => byte,
- });
- }
- try stream.writeByte('\n');
- try stream.writeByteNTimes(' ', start_loc.column);
- try stream.writeByteNTimes('~', last_token.end - first_token.start);
- try stream.writeByte('\n');
-}
-
-export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer {
- const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer");
- t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]);
- return stage2_DepTokenizer{
- .handle = t,
- };
-}
-
-export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void {
- self.handle.deinit();
-}
-
-export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult {
- const otoken = self.handle.next() catch {
- const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text");
- return stage2_DepNextResult{
- .type_id = .error_,
- .textz = textz.toSlice().ptr,
- };
- };
- const token = otoken orelse {
- return stage2_DepNextResult{
- .type_id = .null_,
- .textz = undefined,
- };
- };
- const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
- return stage2_DepNextResult{
- .type_id = switch (token.id) {
- .target => .target,
- .prereq => .prereq,
- },
- .textz = textz.toSlice().ptr,
- };
-}
-
-const stage2_DepTokenizer = extern struct {
- handle: *DepTokenizer,
-};
-
-const stage2_DepNextResult = extern struct {
- type_id: TypeId,
-
- // when type_id == error --> error text
- // when type_id == null --> undefined
- // when type_id == target --> target pathname
- // when type_id == prereq --> prereq pathname
- textz: [*]const u8,
-
- const TypeId = extern enum {
- error_,
- null_,
- target,
- prereq,
- };
-};
-
-// ABI warning
-export fn stage2_attach_segfault_handler() void {
- if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
- std.debug.attachSegfaultHandler();
- }
-}
-
-// ABI warning
-export fn stage2_progress_create() *std.Progress {
- const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
- ptr.* = std.Progress{};
- return ptr;
-}
-
-// ABI warning
-export fn stage2_progress_destroy(progress: *std.Progress) void {
- std.heap.c_allocator.destroy(progress);
-}
-
-// ABI warning
-export fn stage2_progress_start_root(
- progress: *std.Progress,
- name_ptr: [*]const u8,
- name_len: usize,
- estimated_total_items: usize,
-) *std.Progress.Node {
- return progress.start(
- name_ptr[0..name_len],
- if (estimated_total_items == 0) null else estimated_total_items,
- ) catch @panic("timer unsupported");
-}
-
-// ABI warning
-export fn stage2_progress_disable_tty(progress: *std.Progress) void {
- progress.terminal = null;
-}
-
-// ABI warning
-export fn stage2_progress_start(
- node: *std.Progress.Node,
- name_ptr: [*]const u8,
- name_len: usize,
- estimated_total_items: usize,
-) *std.Progress.Node {
- const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
- child_node.* = node.start(
- name_ptr[0..name_len],
- if (estimated_total_items == 0) null else estimated_total_items,
- );
- child_node.activate();
- return child_node;
-}
-
-// ABI warning
-export fn stage2_progress_end(node: *std.Progress.Node) void {
- node.end();
- if (&node.context.root != node) {
- std.heap.c_allocator.destroy(node);
- }
-}
-
-// ABI warning
-export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
- node.completeOne();
-}
-
-// ABI warning
-export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
- node.completed_items = done_count;
- node.estimated_total_items = total_count;
- node.activate();
- node.context.maybeRefresh();
-}
-
-fn cpuFeaturesFromLLVM(
- arch: Target.Arch,
- llvm_cpu_name_z: ?[*:0]const u8,
- llvm_cpu_features_opt: ?[*:0]const u8,
-) !Target.CpuFeatures {
- var result = arch.getBaselineCpuFeatures();
-
- if (llvm_cpu_name_z) |cpu_name_z| {
- const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
-
- for (arch.allCpus()) |cpu| {
- const this_llvm_name = cpu.llvm_name orelse continue;
- if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
- // Here we use the non-dependencies-populated set,
- // so that subtracting features later in this function
- // affect the prepopulated set.
- result = Target.CpuFeatures{
- .cpu = cpu,
- .features = cpu.features,
- };
- break;
- }
- }
- }
-
- const all_features = arch.allFeaturesList();
-
- if (llvm_cpu_features_opt) |llvm_cpu_features| {
- var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
- while (it.next()) |decorated_llvm_feat| {
- var op: enum {
- add,
- sub,
- } = undefined;
- var llvm_feat: []const u8 = undefined;
- if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
- op = .add;
- llvm_feat = decorated_llvm_feat[1..];
- } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
- op = .sub;
- llvm_feat = decorated_llvm_feat[1..];
- } else {
- return error.InvalidLlvmCpuFeaturesFormat;
- }
- for (all_features) |feature, index_usize| {
- const this_llvm_name = feature.llvm_name orelse continue;
- if (mem.eql(u8, llvm_feat, this_llvm_name)) {
- const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
- switch (op) {
- .add => result.features.addFeature(index),
- .sub => result.features.removeFeature(index),
- }
- break;
- }
- }
- }
- }
-
- result.features.populateDependencies(all_features);
- return result;
-}
-
-// ABI warning
-export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
- cmdTargets(zig_triple) catch |err| {
- std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
- return -1;
- };
- return 0;
-}
-
-fn cmdTargets(zig_triple: [*:0]const u8) !void {
- var target = try Target.parse(mem.toSliceConst(u8, zig_triple));
- target.Cross.cpu_features = blk: {
- const llvm = @import("llvm.zig");
- const llvm_cpu_name = llvm.GetHostCPUName();
- const llvm_cpu_features = llvm.GetNativeFeatures();
- break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features);
- };
- return @import("print_targets.zig").cmdTargets(
- std.heap.c_allocator,
- &[0][]u8{},
- &std.io.getStdOut().outStream().stream,
- target,
- );
-}
-
-const Stage2CpuFeatures = struct {
- allocator: *mem.Allocator,
- cpu_features: Target.CpuFeatures,
-
- llvm_features_str: ?[*:0]const u8,
-
- builtin_str: [:0]const u8,
- cache_hash: [:0]const u8,
-
- const Self = @This();
-
- fn createFromNative(allocator: *mem.Allocator) !*Self {
- const arch = Target.current.getArch();
- const llvm = @import("llvm.zig");
- const llvm_cpu_name = llvm.GetHostCPUName();
- const llvm_cpu_features = llvm.GetNativeFeatures();
- const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features);
- return createFromCpuFeatures(allocator, arch, cpu_features);
- }
-
- fn createFromCpuFeatures(
- allocator: *mem.Allocator,
- arch: Target.Arch,
- cpu_features: Target.CpuFeatures,
- ) !*Self {
- const self = try allocator.create(Self);
- errdefer allocator.destroy(self);
-
- const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
- cpu_features.cpu.name,
- cpu_features.features.asBytes(),
- });
- errdefer allocator.free(cache_hash);
-
- const generic_arch_name = arch.genericName();
- var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
- \\CpuFeatures{{
- \\ .cpu = &Target.{}.cpu.{},
- \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
- \\
- , .{
- generic_arch_name,
- cpu_features.cpu.name,
- generic_arch_name,
- generic_arch_name,
- });
- defer builtin_str_buffer.deinit();
-
- var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
- defer llvm_features_buffer.deinit();
-
- for (arch.allFeaturesList()) |feature, index_usize| {
- const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
- const is_enabled = cpu_features.features.isEnabled(index);
-
- if (feature.llvm_name) |llvm_name| {
- const plus_or_minus = "-+"[@boolToInt(is_enabled)];
- try llvm_features_buffer.appendByte(plus_or_minus);
- try llvm_features_buffer.append(llvm_name);
- try llvm_features_buffer.append(",");
- }
-
- if (is_enabled) {
- // TODO some kind of "zig identifier escape" function rather than
- // unconditionally using @"" syntax
- try builtin_str_buffer.append(" .@\"");
- try builtin_str_buffer.append(feature.name);
- try builtin_str_buffer.append("\",\n");
- }
- }
-
- try builtin_str_buffer.append(
- \\ }),
- \\};
- \\
- );
-
- assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
- llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
-
- self.* = Self{
- .allocator = allocator,
- .cpu_features = cpu_features,
- .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr,
- .builtin_str = builtin_str_buffer.toOwnedSlice(),
- .cache_hash = cache_hash,
- };
- return self;
- }
-
- fn destroy(self: *Self) void {
- self.allocator.free(self.cache_hash);
- self.allocator.free(self.builtin_str);
- // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str);
- self.allocator.destroy(self);
- }
-};
-
-// ABI warning
-export fn stage2_cpu_features_parse(
- result: **Stage2CpuFeatures,
- zig_triple: ?[*:0]const u8,
- cpu_name: ?[*:0]const u8,
- cpu_features: ?[*:0]const u8,
-) Error {
- result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) {
- error.OutOfMemory => return .OutOfMemory,
- error.UnknownArchitecture => return .UnknownArchitecture,
- error.UnknownSubArchitecture => return .UnknownSubArchitecture,
- error.UnknownOperatingSystem => return .UnknownOperatingSystem,
- error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
- error.MissingOperatingSystem => return .MissingOperatingSystem,
- error.MissingArchitecture => return .MissingArchitecture,
- error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
- error.InvalidCpuFeatures => return .InvalidCpuFeatures,
- };
- return .None;
-}
-
-fn stage2ParseCpuFeatures(
- zig_triple_oz: ?[*:0]const u8,
- cpu_name_oz: ?[*:0]const u8,
- cpu_features_oz: ?[*:0]const u8,
-) !*Stage2CpuFeatures {
- const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator);
- const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z));
- const arch = target.Cross.arch;
-
- const cpu = if (cpu_name_oz) |cpu_name_z| blk: {
- const cpu_name = mem.toSliceConst(u8, cpu_name_z);
- break :blk arch.parseCpu(cpu_name) catch |err| switch (err) {
- error.UnknownCpu => {
- std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
- cpu_name,
- @tagName(arch),
- });
- for (arch.allCpus()) |cpu| {
- std.debug.warn(" {}\n", .{cpu.name});
- }
- process.exit(1);
- },
- else => |e| return e,
- };
- } else target.Cross.cpu_features.cpu;
-
- var set = if (cpu_features_oz) |cpu_features_z| blk: {
- const cpu_features = mem.toSliceConst(u8, cpu_features_z);
- break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) {
- error.UnknownCpuFeature => {
- std.debug.warn(
- \\Unknown CPU features specified.
- \\Available CPU features for architecture '{}':
- \\
- , .{@tagName(arch)});
- for (arch.allFeaturesList()) |feature| {
- std.debug.warn(" {}\n", .{feature.name});
- }
- process.exit(1);
- },
- else => |e| return e,
- };
- } else cpu.features;
-
- if (arch.subArchFeature()) |index| {
- set.addFeature(index);
- }
- set.populateDependencies(arch.allFeaturesList());
-
- return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{
- .cpu = cpu,
- .features = set,
- });
-}
-
-// ABI warning
-export fn stage2_cpu_features_get_cache_hash(
- cpu_features: *const Stage2CpuFeatures,
- ptr: *[*:0]const u8,
- len: *usize,
-) void {
- ptr.* = cpu_features.cache_hash.ptr;
- len.* = cpu_features.cache_hash.len;
-}
-
-// ABI warning
-export fn stage2_cpu_features_get_builtin_str(
- cpu_features: *const Stage2CpuFeatures,
- ptr: *[*:0]const u8,
- len: *usize,
-) void {
- ptr.* = cpu_features.builtin_str.ptr;
- len.* = cpu_features.builtin_str.len;
-}
-
-// ABI warning
-export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
- return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null;
-}
-
-// ABI warning
-export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 {
- return cpu_features.llvm_features_str;
-}
diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig
@@ -0,0 +1,1064 @@
+// This is Zig code that is used by both stage1 and stage2.
+// The prototypes in src/userland.h must match these definitions.
+
+const std = @import("std");
+const io = std.io;
+const mem = std.mem;
+const fs = std.fs;
+const process = std.process;
+const Allocator = mem.Allocator;
+const ArrayList = std.ArrayList;
+const Buffer = std.Buffer;
+const Target = std.Target;
+const self_hosted_main = @import("main.zig");
+const errmsg = @import("errmsg.zig");
+const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
+const assert = std.debug.assert;
+const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
+
+var stderr_file: fs.File = undefined;
+var stderr: *io.OutStream(fs.File.WriteError) = undefined;
+var stdout: *io.OutStream(fs.File.WriteError) = undefined;
+
+comptime {
+ _ = @import("dep_tokenizer.zig");
+}
+
+// ABI warning
+export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
+ const info_zen = @import("main.zig").info_zen;
+ ptr.* = info_zen;
+ len.* = info_zen.len;
+}
+
+// ABI warning
+export fn stage2_panic(ptr: [*]const u8, len: usize) void {
+ @panic(ptr[0..len]);
+}
+
+// ABI warning
+const Error = extern enum {
+ None,
+ OutOfMemory,
+ InvalidFormat,
+ SemanticAnalyzeFail,
+ AccessDenied,
+ Interrupted,
+ SystemResources,
+ FileNotFound,
+ FileSystem,
+ FileTooBig,
+ DivByZero,
+ Overflow,
+ PathAlreadyExists,
+ Unexpected,
+ ExactDivRemainder,
+ NegativeDenominator,
+ ShiftedOutOneBits,
+ CCompileErrors,
+ EndOfFile,
+ IsDir,
+ NotDir,
+ UnsupportedOperatingSystem,
+ SharingViolation,
+ PipeBusy,
+ PrimitiveTypeNotFound,
+ CacheUnavailable,
+ PathTooLong,
+ CCompilerCannotFindFile,
+ NoCCompilerInstalled,
+ ReadingDepFile,
+ InvalidDepFile,
+ MissingArchitecture,
+ MissingOperatingSystem,
+ UnknownArchitecture,
+ UnknownOperatingSystem,
+ UnknownABI,
+ InvalidFilename,
+ DiskQuota,
+ DiskSpace,
+ UnexpectedWriteFailure,
+ UnexpectedSeekFailure,
+ UnexpectedFileTruncationFailure,
+ Unimplemented,
+ OperationAborted,
+ BrokenPipe,
+ NoSpaceLeft,
+ NotLazy,
+ IsAsync,
+ ImportOutsidePkgPath,
+ UnknownCpu,
+ UnknownCpuFeature,
+ InvalidCpuFeatures,
+ InvalidLlvmCpuFeaturesFormat,
+ UnknownApplicationBinaryInterface,
+ ASTUnitFailure,
+ BadPathName,
+ SymLinkLoop,
+ ProcessFdQuotaExceeded,
+ SystemFdQuotaExceeded,
+ NoDevice,
+ DeviceBusy,
+ UnableToSpawnCCompiler,
+ CCompilerExitCode,
+ CCompilerCrashed,
+ CCompilerCannotFindHeaders,
+ LibCRuntimeNotFound,
+ LibCStdLibHeaderNotFound,
+ LibCKernel32LibNotFound,
+ UnsupportedArchitecture,
+ WindowsSdkNotFound,
+ UnknownDynamicLinkerPath,
+ TargetHasNoDynamicLinker,
+};
+
+const FILE = std.c.FILE;
+const ast = std.zig.ast;
+const translate_c = @import("translate_c.zig");
+
+/// Args should have a null terminating last arg.
+export fn stage2_translate_c(
+ out_ast: **ast.Tree,
+ out_errors_ptr: *[*]translate_c.ClangErrMsg,
+ out_errors_len: *usize,
+ args_begin: [*]?[*]const u8,
+ args_end: [*]?[*]const u8,
+ resources_path: [*:0]const u8,
+) Error {
+ var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
+ out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
+ error.SemanticAnalyzeFail => {
+ out_errors_ptr.* = errors.ptr;
+ out_errors_len.* = errors.len;
+ return .CCompileErrors;
+ },
+ error.ASTUnitFailure => return .ASTUnitFailure,
+ error.OutOfMemory => return .OutOfMemory,
+ };
+ return .None;
+}
+
+export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
+ translate_c.freeErrors(errors_ptr[0..errors_len]);
+}
+
+export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
+ const c_out_stream = &std.io.COutStream.init(output_file).stream;
+ _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
+ error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
+ error.SystemResources => return .SystemResources,
+ error.OperationAborted => return .OperationAborted,
+ error.BrokenPipe => return .BrokenPipe,
+ error.DiskQuota => return .DiskQuota,
+ error.FileTooBig => return .FileTooBig,
+ error.NoSpaceLeft => return .NoSpaceLeft,
+ error.AccessDenied => return .AccessDenied,
+ error.OutOfMemory => return .OutOfMemory,
+ error.Unexpected => return .Unexpected,
+ error.InputOutput => return .FileSystem,
+ };
+ return .None;
+}
+
+// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
+// we use a blocking implementation.
+export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int {
+ if (std.debug.runtime_safety) {
+ fmtMain(argc, argv) catch unreachable;
+ } else {
+ fmtMain(argc, argv) catch |e| {
+ std.debug.warn("{}\n", .{@errorName(e)});
+ return -1;
+ };
+ }
+ return 0;
+}
+
+fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
+ const allocator = std.heap.c_allocator;
+ var args_list = std.ArrayList([]const u8).init(allocator);
+ const argc_usize = @intCast(usize, argc);
+ var arg_i: usize = 0;
+ while (arg_i < argc_usize) : (arg_i += 1) {
+ try args_list.append(mem.toSliceConst(u8, argv[arg_i]));
+ }
+
+ stdout = &std.io.getStdOut().outStream().stream;
+ stderr_file = std.io.getStdErr();
+ stderr = &stderr_file.outStream().stream;
+
+ const args = args_list.toSliceConst()[2..];
+
+ var color: errmsg.Color = .Auto;
+ var stdin_flag: bool = false;
+ var check_flag: bool = false;
+ var input_files = ArrayList([]const u8).init(allocator);
+
+ {
+ var i: usize = 0;
+ while (i < args.len) : (i += 1) {
+ const arg = args[i];
+ if (mem.startsWith(u8, arg, "-")) {
+ if (mem.eql(u8, arg, "--help")) {
+ try stdout.write(self_hosted_main.usage_fmt);
+ process.exit(0);
+ } else if (mem.eql(u8, arg, "--color")) {
+ if (i + 1 >= args.len) {
+ try stderr.write("expected [auto|on|off] after --color\n");
+ process.exit(1);
+ }
+ i += 1;
+ const next_arg = args[i];
+ if (mem.eql(u8, next_arg, "auto")) {
+ color = .Auto;
+ } else if (mem.eql(u8, next_arg, "on")) {
+ color = .On;
+ } else if (mem.eql(u8, next_arg, "off")) {
+ color = .Off;
+ } else {
+ try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
+ process.exit(1);
+ }
+ } else if (mem.eql(u8, arg, "--stdin")) {
+ stdin_flag = true;
+ } else if (mem.eql(u8, arg, "--check")) {
+ check_flag = true;
+ } else {
+ try stderr.print("unrecognized parameter: '{}'", .{arg});
+ process.exit(1);
+ }
+ } else {
+ try input_files.append(arg);
+ }
+ }
+ }
+
+ if (stdin_flag) {
+ if (input_files.len != 0) {
+ try stderr.write("cannot use --stdin with positional arguments\n");
+ process.exit(1);
+ }
+
+ const stdin_file = io.getStdIn();
+ var stdin = stdin_file.inStream();
+
+ const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
+ defer allocator.free(source_code);
+
+ const tree = std.zig.parse(allocator, source_code) catch |err| {
+ try stderr.print("error parsing stdin: {}\n", .{err});
+ process.exit(1);
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color);
+ }
+ if (tree.errors.len != 0) {
+ process.exit(1);
+ }
+ if (check_flag) {
+ const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
+ const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
+ process.exit(code);
+ }
+
+ _ = try std.zig.render(allocator, stdout, tree);
+ return;
+ }
+
+ if (input_files.len == 0) {
+ try stderr.write("expected at least one source file argument\n");
+ process.exit(1);
+ }
+
+ var fmt = Fmt{
+ .seen = Fmt.SeenMap.init(allocator),
+ .any_error = false,
+ .color = color,
+ .allocator = allocator,
+ };
+
+ for (input_files.toSliceConst()) |file_path| {
+ try fmtPath(&fmt, file_path, check_flag);
+ }
+ if (fmt.any_error) {
+ process.exit(1);
+ }
+}
+
+const FmtError = error{
+ SystemResources,
+ OperationAborted,
+ IoPending,
+ BrokenPipe,
+ Unexpected,
+ WouldBlock,
+ FileClosed,
+ DestinationAddressRequired,
+ DiskQuota,
+ FileTooBig,
+ InputOutput,
+ NoSpaceLeft,
+ AccessDenied,
+ OutOfMemory,
+ RenameAcrossMountPoints,
+ ReadOnlyFileSystem,
+ LinkQuotaExceeded,
+ FileBusy,
+} || fs.File.OpenError;
+
+fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
+ if (fmt.seen.exists(file_path)) return;
+ try fmt.seen.put(file_path);
+
+ const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
+ error.IsDir, error.AccessDenied => {
+ // TODO make event based (and dir.next())
+ var dir = try fs.cwd().openDirList(file_path);
+ defer dir.close();
+
+ var dir_it = dir.iterate();
+
+ while (try dir_it.next()) |entry| {
+ if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
+ const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name });
+ try fmtPath(fmt, full_path, check_mode);
+ }
+ }
+ return;
+ },
+ else => {
+ // TODO lock stderr printing
+ try stderr.print("unable to open '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ },
+ };
+ defer fmt.allocator.free(source_code);
+
+ const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
+ try stderr.print("error parsing file '{}': {}\n", .{ file_path, err });
+ fmt.any_error = true;
+ return;
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color);
+ }
+ if (tree.errors.len != 0) {
+ fmt.any_error = true;
+ return;
+ }
+
+ if (check_mode) {
+ const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", .{file_path});
+ fmt.any_error = true;
+ }
+ } else {
+ const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
+ defer baf.destroy();
+
+ const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", .{file_path});
+ try baf.finish();
+ }
+ }
+}
+
+const Fmt = struct {
+ seen: SeenMap,
+ any_error: bool,
+ color: errmsg.Color,
+ allocator: *mem.Allocator,
+
+ const SeenMap = std.BufSet;
+};
+
+fn printErrMsgToFile(
+ allocator: *mem.Allocator,
+ parse_error: *const ast.Error,
+ tree: *ast.Tree,
+ path: []const u8,
+ file: fs.File,
+ color: errmsg.Color,
+) !void {
+ const color_on = switch (color) {
+ .Auto => file.isTty(),
+ .On => true,
+ .Off => false,
+ };
+ const lok_token = parse_error.loc();
+ const span = errmsg.Span{
+ .first = lok_token,
+ .last = lok_token,
+ };
+
+ const first_token = tree.tokens.at(span.first);
+ const last_token = tree.tokens.at(span.last);
+ const start_loc = tree.tokenLocationPtr(0, first_token);
+ const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
+
+ var text_buf = try std.Buffer.initSize(allocator, 0);
+ var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
+ try parse_error.render(&tree.tokens, out_stream);
+ const text = text_buf.toOwnedSlice();
+
+ const stream = &file.outStream().stream;
+ try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text });
+
+ if (!color_on) return;
+
+ // Print \r and \t as one space each so that column counts line up
+ for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| {
+ try stream.writeByte(switch (byte) {
+ '\r', '\t' => ' ',
+ else => byte,
+ });
+ }
+ try stream.writeByte('\n');
+ try stream.writeByteNTimes(' ', start_loc.column);
+ try stream.writeByteNTimes('~', last_token.end - first_token.start);
+ try stream.writeByte('\n');
+}
+
+export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer {
+ const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer");
+ t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]);
+ return stage2_DepTokenizer{
+ .handle = t,
+ };
+}
+
+export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void {
+ self.handle.deinit();
+}
+
+export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult {
+ const otoken = self.handle.next() catch {
+ const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text");
+ return stage2_DepNextResult{
+ .type_id = .error_,
+ .textz = textz.toSlice().ptr,
+ };
+ };
+ const token = otoken orelse {
+ return stage2_DepNextResult{
+ .type_id = .null_,
+ .textz = undefined,
+ };
+ };
+ const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
+ return stage2_DepNextResult{
+ .type_id = switch (token.id) {
+ .target => .target,
+ .prereq => .prereq,
+ },
+ .textz = textz.toSlice().ptr,
+ };
+}
+
+const stage2_DepTokenizer = extern struct {
+ handle: *DepTokenizer,
+};
+
+const stage2_DepNextResult = extern struct {
+ type_id: TypeId,
+
+ // when type_id == error --> error text
+ // when type_id == null --> undefined
+ // when type_id == target --> target pathname
+ // when type_id == prereq --> prereq pathname
+ textz: [*]const u8,
+
+ const TypeId = extern enum {
+ error_,
+ null_,
+ target,
+ prereq,
+ };
+};
+
+// ABI warning
+export fn stage2_attach_segfault_handler() void {
+ if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) {
+ std.debug.attachSegfaultHandler();
+ }
+}
+
+// ABI warning
+export fn stage2_progress_create() *std.Progress {
+ const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
+ ptr.* = std.Progress{};
+ return ptr;
+}
+
+// ABI warning
+export fn stage2_progress_destroy(progress: *std.Progress) void {
+ std.heap.c_allocator.destroy(progress);
+}
+
+// ABI warning
+export fn stage2_progress_start_root(
+ progress: *std.Progress,
+ name_ptr: [*]const u8,
+ name_len: usize,
+ estimated_total_items: usize,
+) *std.Progress.Node {
+ return progress.start(
+ name_ptr[0..name_len],
+ if (estimated_total_items == 0) null else estimated_total_items,
+ ) catch @panic("timer unsupported");
+}
+
+// ABI warning
+export fn stage2_progress_disable_tty(progress: *std.Progress) void {
+ progress.terminal = null;
+}
+
+// ABI warning
+export fn stage2_progress_start(
+ node: *std.Progress.Node,
+ name_ptr: [*]const u8,
+ name_len: usize,
+ estimated_total_items: usize,
+) *std.Progress.Node {
+ const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
+ child_node.* = node.start(
+ name_ptr[0..name_len],
+ if (estimated_total_items == 0) null else estimated_total_items,
+ );
+ child_node.activate();
+ return child_node;
+}
+
+// ABI warning
+export fn stage2_progress_end(node: *std.Progress.Node) void {
+ node.end();
+ if (&node.context.root != node) {
+ std.heap.c_allocator.destroy(node);
+ }
+}
+
+// ABI warning
+export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
+ node.completeOne();
+}
+
+// ABI warning
+export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void {
+ node.completed_items = done_count;
+ node.estimated_total_items = total_count;
+ node.activate();
+ node.context.maybeRefresh();
+}
+
+fn detectNativeCpuWithLLVM(
+ arch: Target.Cpu.Arch,
+ llvm_cpu_name_z: ?[*:0]const u8,
+ llvm_cpu_features_opt: ?[*:0]const u8,
+) !Target.Cpu {
+ var result = Target.Cpu.baseline(arch);
+
+ if (llvm_cpu_name_z) |cpu_name_z| {
+ const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z);
+
+ for (arch.allCpuModels()) |model| {
+ const this_llvm_name = model.llvm_name orelse continue;
+ if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) {
+ // Here we use the non-dependencies-populated set,
+ // so that subtracting features later in this function
+ // affect the prepopulated set.
+ result = Target.Cpu{
+ .arch = arch,
+ .model = model,
+ .features = model.features,
+ };
+ break;
+ }
+ }
+ }
+
+ const all_features = arch.allFeaturesList();
+
+ if (llvm_cpu_features_opt) |llvm_cpu_features| {
+ var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ",");
+ while (it.next()) |decorated_llvm_feat| {
+ var op: enum {
+ add,
+ sub,
+ } = undefined;
+ var llvm_feat: []const u8 = undefined;
+ if (mem.startsWith(u8, decorated_llvm_feat, "+")) {
+ op = .add;
+ llvm_feat = decorated_llvm_feat[1..];
+ } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) {
+ op = .sub;
+ llvm_feat = decorated_llvm_feat[1..];
+ } else {
+ return error.InvalidLlvmCpuFeaturesFormat;
+ }
+ for (all_features) |feature, index_usize| {
+ const this_llvm_name = feature.llvm_name orelse continue;
+ if (mem.eql(u8, llvm_feat, this_llvm_name)) {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
+ switch (op) {
+ .add => result.features.addFeature(index),
+ .sub => result.features.removeFeature(index),
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ result.features.populateDependencies(all_features);
+ return result;
+}
+
+// ABI warning
+export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
+ cmdTargets(zig_triple) catch |err| {
+ std.debug.warn("unable to list targets: {}\n", .{@errorName(err)});
+ return -1;
+ };
+ return 0;
+}
+
+fn cmdTargets(zig_triple: [*:0]const u8) !void {
+ var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });
+ target.Cross.cpu = blk: {
+ const llvm = @import("llvm.zig");
+ const llvm_cpu_name = llvm.GetHostCPUName();
+ const llvm_cpu_features = llvm.GetNativeFeatures();
+ break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features);
+ };
+ return @import("print_targets.zig").cmdTargets(
+ std.heap.c_allocator,
+ &[0][]u8{},
+ &std.io.getStdOut().outStream().stream,
+ target,
+ );
+}
+
+// ABI warning
+export fn stage2_target_parse(
+ target: *Stage2Target,
+ zig_triple: ?[*:0]const u8,
+ mcpu: ?[*:0]const u8,
+) Error {
+ stage2TargetParse(target, zig_triple, mcpu) catch |err| switch (err) {
+ error.OutOfMemory => return .OutOfMemory,
+ error.UnknownArchitecture => return .UnknownArchitecture,
+ error.UnknownOperatingSystem => return .UnknownOperatingSystem,
+ error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface,
+ error.MissingOperatingSystem => return .MissingOperatingSystem,
+ error.MissingArchitecture => return .MissingArchitecture,
+ error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
+ error.UnexpectedExtraField => return .SemanticAnalyzeFail,
+ };
+ return .None;
+}
+
+fn stage2TargetParse(
+ stage1_target: *Stage2Target,
+ zig_triple_oz: ?[*:0]const u8,
+ mcpu_oz: ?[*:0]const u8,
+) !void {
+ const target: Target = if (zig_triple_oz) |zig_triple_z| blk: {
+ const zig_triple = mem.toSliceConst(u8, zig_triple_z);
+ const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline";
+ var diags: std.Target.ParseOptions.Diagnostics = .{};
+ break :blk Target.parse(.{
+ .arch_os_abi = zig_triple,
+ .cpu_features = mcpu,
+ .diagnostics = &diags,
+ }) catch |err| switch (err) {
+ error.UnknownCpu => {
+ std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
+ diags.cpu_name.?,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allCpuModels()) |cpu| {
+ std.debug.warn(" {}\n", .{cpu.name});
+ }
+ process.exit(1);
+ },
+ error.UnknownCpuFeature => {
+ std.debug.warn(
+ \\Unknown CPU feature: '{}'
+ \\Available CPU features for architecture '{}':
+ \\
+ , .{
+ diags.unknown_feature_name,
+ @tagName(diags.arch.?),
+ });
+ for (diags.arch.?.allFeaturesList()) |feature| {
+ std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
+ }
+ process.exit(1);
+ },
+ else => |e| return e,
+ };
+ } else Target.Native;
+
+ try stage1_target.fromTarget(target);
+}
+
+fn initStage1TargetCpuFeatures(stage1_target: *Stage2Target, cpu: Target.Cpu) !void {
+ const allocator = std.heap.c_allocator;
+ const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
+ cpu.model.name,
+ cpu.features.asBytes(),
+ });
+ errdefer allocator.free(cache_hash);
+
+ const generic_arch_name = cpu.arch.genericName();
+ var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
+ \\Cpu{{
+ \\ .arch = .{},
+ \\ .model = &Target.{}.cpu.{},
+ \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
+ \\
+ , .{
+ @tagName(cpu.arch),
+ generic_arch_name,
+ cpu.model.name,
+ generic_arch_name,
+ generic_arch_name,
+ });
+ defer builtin_str_buffer.deinit();
+
+ var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
+ defer llvm_features_buffer.deinit();
+
+ for (cpu.arch.allFeaturesList()) |feature, index_usize| {
+ const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
+ const is_enabled = cpu.features.isEnabled(index);
+
+ if (feature.llvm_name) |llvm_name| {
+ const plus_or_minus = "-+"[@boolToInt(is_enabled)];
+ try llvm_features_buffer.appendByte(plus_or_minus);
+ try llvm_features_buffer.append(llvm_name);
+ try llvm_features_buffer.append(",");
+ }
+
+ if (is_enabled) {
+ // TODO some kind of "zig identifier escape" function rather than
+ // unconditionally using @"" syntax
+ try builtin_str_buffer.append(" .@\"");
+ try builtin_str_buffer.append(feature.name);
+ try builtin_str_buffer.append("\",\n");
+ }
+ }
+
+ try builtin_str_buffer.append(
+ \\ }),
+ \\};
+ \\
+ );
+
+ assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
+ llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
+
+ stage1_target.llvm_cpu_name = if (cpu.model.llvm_name) |s| s.ptr else null;
+ stage1_target.llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr;
+ stage1_target.builtin_str = builtin_str_buffer.toOwnedSlice().ptr;
+ stage1_target.cache_hash = cache_hash.ptr;
+}
+
+// ABI warning
+const Stage2LibCInstallation = extern struct {
+ include_dir: [*:0]const u8,
+ include_dir_len: usize,
+ sys_include_dir: [*:0]const u8,
+ sys_include_dir_len: usize,
+ crt_dir: [*:0]const u8,
+ crt_dir_len: usize,
+ static_crt_dir: [*:0]const u8,
+ static_crt_dir_len: usize,
+ msvc_lib_dir: [*:0]const u8,
+ msvc_lib_dir_len: usize,
+ kernel32_lib_dir: [*:0]const u8,
+ kernel32_lib_dir_len: usize,
+
+ fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void {
+ if (libc.include_dir) |s| {
+ self.include_dir = s.ptr;
+ self.include_dir_len = s.len;
+ } else {
+ self.include_dir = "";
+ self.include_dir_len = 0;
+ }
+ if (libc.sys_include_dir) |s| {
+ self.sys_include_dir = s.ptr;
+ self.sys_include_dir_len = s.len;
+ } else {
+ self.sys_include_dir = "";
+ self.sys_include_dir_len = 0;
+ }
+ if (libc.crt_dir) |s| {
+ self.crt_dir = s.ptr;
+ self.crt_dir_len = s.len;
+ } else {
+ self.crt_dir = "";
+ self.crt_dir_len = 0;
+ }
+ if (libc.static_crt_dir) |s| {
+ self.static_crt_dir = s.ptr;
+ self.static_crt_dir_len = s.len;
+ } else {
+ self.static_crt_dir = "";
+ self.static_crt_dir_len = 0;
+ }
+ if (libc.msvc_lib_dir) |s| {
+ self.msvc_lib_dir = s.ptr;
+ self.msvc_lib_dir_len = s.len;
+ } else {
+ self.msvc_lib_dir = "";
+ self.msvc_lib_dir_len = 0;
+ }
+ if (libc.kernel32_lib_dir) |s| {
+ self.kernel32_lib_dir = s.ptr;
+ self.kernel32_lib_dir_len = s.len;
+ } else {
+ self.kernel32_lib_dir = "";
+ self.kernel32_lib_dir_len = 0;
+ }
+ }
+
+ fn toStage2(self: Stage2LibCInstallation) LibCInstallation {
+ var libc: LibCInstallation = .{};
+ if (self.include_dir_len != 0) {
+ libc.include_dir = self.include_dir[0..self.include_dir_len :0];
+ }
+ if (self.sys_include_dir_len != 0) {
+ libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0];
+ }
+ if (self.crt_dir_len != 0) {
+ libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0];
+ }
+ if (self.static_crt_dir_len != 0) {
+ libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0];
+ }
+ if (self.msvc_lib_dir_len != 0) {
+ libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0];
+ }
+ if (self.kernel32_lib_dir_len != 0) {
+ libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0];
+ }
+ return libc;
+ }
+};
+
+// ABI warning
+export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error {
+ stderr_file = std.io.getStdErr();
+ stderr = &stderr_file.outStream().stream;
+ const libc_file = mem.toSliceConst(u8, libc_file_z);
+ var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) {
+ error.ParseError => return .SemanticAnalyzeFail,
+ error.DiskQuota => return .DiskQuota,
+ error.FileTooBig => return .FileTooBig,
+ error.InputOutput => return .FileSystem,
+ error.NoSpaceLeft => return .NoSpaceLeft,
+ error.AccessDenied => return .AccessDenied,
+ error.BrokenPipe => return .BrokenPipe,
+ error.SystemResources => return .SystemResources,
+ error.OperationAborted => return .OperationAborted,
+ error.WouldBlock => unreachable,
+ error.Unexpected => return .Unexpected,
+ error.EndOfStream => return .EndOfFile,
+ error.IsDir => return .IsDir,
+ error.ConnectionResetByPeer => unreachable,
+ error.OutOfMemory => return .OutOfMemory,
+ error.Unseekable => unreachable,
+ error.SharingViolation => return .SharingViolation,
+ error.PathAlreadyExists => unreachable,
+ error.FileNotFound => return .FileNotFound,
+ error.PipeBusy => return .PipeBusy,
+ error.NameTooLong => return .PathTooLong,
+ error.InvalidUtf8 => return .BadPathName,
+ error.BadPathName => return .BadPathName,
+ error.SymLinkLoop => return .SymLinkLoop,
+ error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded,
+ error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded,
+ error.NoDevice => return .NoDevice,
+ error.NotDir => return .NotDir,
+ error.DeviceBusy => return .DeviceBusy,
+ };
+ stage1_libc.initFromStage2(libc);
+ return .None;
+}
+
+// ABI warning
+export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
+ var libc = LibCInstallation.findNative(.{
+ .allocator = std.heap.c_allocator,
+ .verbose = true,
+ }) catch |err| switch (err) {
+ error.OutOfMemory => return .OutOfMemory,
+ error.FileSystem => return .FileSystem,
+ error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,
+ error.CCompilerExitCode => return .CCompilerExitCode,
+ error.CCompilerCrashed => return .CCompilerCrashed,
+ error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders,
+ error.LibCRuntimeNotFound => return .LibCRuntimeNotFound,
+ error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound,
+ error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound,
+ error.UnsupportedArchitecture => return .UnsupportedArchitecture,
+ error.WindowsSdkNotFound => return .WindowsSdkNotFound,
+ };
+ stage1_libc.initFromStage2(libc);
+ return .None;
+}
+
+// ABI warning
+export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error {
+ var libc = stage1_libc.toStage2();
+ const c_out_stream = &std.io.COutStream.init(output_file).stream;
+ libc.render(c_out_stream) catch |err| switch (err) {
+ error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
+ error.SystemResources => return .SystemResources,
+ error.OperationAborted => return .OperationAborted,
+ error.BrokenPipe => return .BrokenPipe,
+ error.DiskQuota => return .DiskQuota,
+ error.FileTooBig => return .FileTooBig,
+ error.NoSpaceLeft => return .NoSpaceLeft,
+ error.AccessDenied => return .AccessDenied,
+ error.Unexpected => return .Unexpected,
+ error.InputOutput => return .FileSystem,
+ };
+ return .None;
+}
+
+// ABI warning
+const Stage2Target = extern struct {
+ arch: c_int,
+ vendor: c_int,
+
+ abi: c_int,
+ os: c_int,
+
+ is_native: bool,
+
+ glibc_version: ?*Stage2GLibCVersion, // null means default
+
+ llvm_cpu_name: ?[*:0]const u8,
+ llvm_cpu_features: ?[*:0]const u8,
+ builtin_str: ?[*:0]const u8,
+ cache_hash: ?[*:0]const u8,
+
+ fn toTarget(in_target: Stage2Target) Target {
+ if (in_target.is_native) return .Native;
+
+ const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch
+ const in_os = in_target.os;
+ const in_abi = in_target.abi;
+
+ return .{
+ .Cross = .{
+ .cpu = Target.Cpu.baseline(enumInt(Target.Cpu.Arch, in_arch)),
+ .os = enumInt(Target.Os, in_os),
+ .abi = enumInt(Target.Abi, in_abi),
+ },
+ };
+ }
+
+ fn fromTarget(self: *Stage2Target, target: Target) !void {
+ const cpu = switch (target) {
+ .Native => blk: {
+ // TODO self-host CPU model and feature detection instead of relying on LLVM
+ const llvm = @import("llvm.zig");
+ const llvm_cpu_name = llvm.GetHostCPUName();
+ const llvm_cpu_features = llvm.GetNativeFeatures();
+ break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features);
+ },
+ .Cross => target.getCpu(),
+ };
+ self.* = .{
+ .arch = @enumToInt(target.getArch()) + 1, // skip over ZigLLVM_UnknownArch
+ .vendor = 0,
+ .os = @enumToInt(target.getOs()),
+ .abi = @enumToInt(target.getAbi()),
+ .llvm_cpu_name = null,
+ .llvm_cpu_features = null,
+ .builtin_str = null,
+ .cache_hash = null,
+ .is_native = target == .Native,
+ .glibc_version = null,
+ };
+ try initStage1TargetCpuFeatures(self, cpu);
+ }
+};
+
+// ABI warning
+const Stage2GLibCVersion = extern struct {
+ major: u32,
+ minor: u32,
+ patch: u32,
+};
+
+// ABI warning
+export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error {
+ const target = in_target.toTarget();
+ const result = @import("introspect.zig").detectDynamicLinker(
+ std.heap.c_allocator,
+ target,
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return .OutOfMemory,
+ error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath,
+ error.TargetHasNoDynamicLinker => return .TargetHasNoDynamicLinker,
+ };
+ out_ptr.* = result.ptr;
+ out_len.* = result.len;
+ return .None;
+}
+
+fn enumInt(comptime Enum: type, int: c_int) Enum {
+ return @intToEnum(Enum, @intCast(@TagType(Enum), int));
+}
+
+// ABI warning
+const Stage2NativePaths = extern struct {
+ include_dirs_ptr: [*][*:0]u8,
+ include_dirs_len: usize,
+ lib_dirs_ptr: [*][*:0]u8,
+ lib_dirs_len: usize,
+ rpaths_ptr: [*][*:0]u8,
+ rpaths_len: usize,
+ warnings_ptr: [*][*:0]u8,
+ warnings_len: usize,
+};
+// ABI warning
+export fn stage2_detect_native_paths(stage1_paths: *Stage2NativePaths) Error {
+ stage2DetectNativePaths(stage1_paths) catch |err| switch (err) {
+ error.OutOfMemory => return .OutOfMemory,
+ };
+ return .None;
+}
+
+fn stage2DetectNativePaths(stage1_paths: *Stage2NativePaths) !void {
+ var paths = try std.zig.system.NativePaths.detect(std.heap.c_allocator);
+ errdefer paths.deinit();
+
+ try convertSlice(paths.include_dirs.toSlice(), &stage1_paths.include_dirs_ptr, &stage1_paths.include_dirs_len);
+ try convertSlice(paths.lib_dirs.toSlice(), &stage1_paths.lib_dirs_ptr, &stage1_paths.lib_dirs_len);
+ try convertSlice(paths.rpaths.toSlice(), &stage1_paths.rpaths_ptr, &stage1_paths.rpaths_len);
+ try convertSlice(paths.warnings.toSlice(), &stage1_paths.warnings_ptr, &stage1_paths.warnings_len);
+}
+
+fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void {
+ len.* = slice.len;
+ const new_slice = try std.heap.c_allocator.alloc([*:0]u8, slice.len);
+ for (slice) |item, i| {
+ new_slice[i] = item.ptr;
+ }
+ ptr.* = new_slice.ptr;
+}
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
@@ -264,7 +264,7 @@ pub fn translate(
&errors.len,
resources_path,
) orelse {
- if (errors.len == 0) return error.OutOfMemory;
+ if (errors.len == 0) return error.ASTUnitFailure;
return error.SemanticAnalyzeFail;
};
defer ZigClangASTUnit_delete(ast_unit);
@@ -5382,15 +5382,15 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return error.ParseError;
}
- //if (@typeId(@TypeOf(x)) == .Pointer)
+ //if (@typeInfo(@TypeOf(x)) == .Pointer)
// @ptrCast(dest, x)
- //else if (@typeId(@TypeOf(x)) == .Integer)
+ //else if (@typeInfo(@TypeOf(x)) == .Integer)
// @intToPtr(dest, x)
//else
// @as(dest, x)
const if_1 = try transCreateNodeIf(c);
- const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeId");
+ const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
try type_id_1.params.push(&type_of_1.base);
try type_of_1.params.push(node_to_cast);
@@ -5417,7 +5417,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
if_1.@"else" = else_1;
const if_2 = try transCreateNodeIf(c);
- const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeId");
+ const type_id_2 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
const type_of_2 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
try type_id_2.params.push(&type_of_2.base);
try type_of_2.params.push(node_to_cast);
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
@@ -1042,7 +1042,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
switch (@typeInfo(@TypeOf(x))) {
.Int => |info| {
comptime var rng = comptime std.rand.DefaultPrng.init(seed);
- const unsigned_x = @bitCast(@IntType(false, info.bits), x);
+ const unsigned_x = @bitCast(std.meta.IntType(false, info.bits), x);
if (info.bits <= 32) {
return @as(u32, unsigned_x) *% comptime rng.random.scalar(u32);
} else {
diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig
@@ -2,144 +2,6 @@ const std = @import("std");
const Target = std.Target;
const llvm = @import("llvm.zig");
-pub const FloatAbi = enum {
- Hard,
- Soft,
- SoftFp,
-};
-
-/// TODO expose the arch and subarch separately
-pub fn isArmOrThumb(self: Target) bool {
- return switch (self.getArch()) {
- .arm,
- .armeb,
- .aarch64,
- .aarch64_be,
- .thumb,
- .thumbeb,
- => true,
- else => false,
- };
-}
-
-pub fn getFloatAbi(self: Target) FloatAbi {
- return switch (self.getAbi()) {
- .gnueabihf,
- .eabihf,
- .musleabihf,
- => .Hard,
- else => .Soft,
- };
-}
-
-pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
- const env = self.getAbi();
- const arch = self.getArch();
- const os = self.getOs();
- switch (os) {
- .freebsd => {
- return "/libexec/ld-elf.so.1";
- },
- .linux => {
- switch (env) {
- .android => {
- if (self.getArchPtrBitWidth() == 64) {
- return "/system/bin/linker64";
- } else {
- return "/system/bin/linker";
- }
- },
- .gnux32 => {
- if (arch == .x86_64) {
- return "/libx32/ld-linux-x32.so.2";
- }
- },
- .musl,
- .musleabi,
- .musleabihf,
- => {
- if (arch == .x86_64) {
- return "/lib/ld-musl-x86_64.so.1";
- }
- },
- else => {},
- }
- switch (arch) {
- .i386,
- .sparc,
- .sparcel,
- => return "/lib/ld-linux.so.2",
-
- .aarch64 => return "/lib/ld-linux-aarch64.so.1",
-
- .aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
-
- .arm,
- .thumb,
- => return switch (getFloatAbi(self)) {
- .Hard => return "/lib/ld-linux-armhf.so.3",
- else => return "/lib/ld-linux.so.3",
- },
-
- .armeb,
- .thumbeb,
- => return switch (getFloatAbi(self)) {
- .Hard => return "/lib/ld-linux-armhf.so.3",
- else => return "/lib/ld-linux.so.3",
- },
-
- .mips,
- .mipsel,
- .mips64,
- .mips64el,
- => return null,
-
- .powerpc => return "/lib/ld.so.1",
- .powerpc64 => return "/lib64/ld64.so.2",
- .powerpc64le => return "/lib64/ld64.so.2",
- .s390x => return "/lib64/ld64.so.1",
- .sparcv9 => return "/lib64/ld-linux.so.2",
- .x86_64 => return "/lib64/ld-linux-x86-64.so.2",
-
- .arc,
- .avr,
- .bpfel,
- .bpfeb,
- .hexagon,
- .msp430,
- .r600,
- .amdgcn,
- .riscv32,
- .riscv64,
- .tce,
- .tcele,
- .xcore,
- .nvptx,
- .nvptx64,
- .le32,
- .le64,
- .amdil,
- .amdil64,
- .hsail,
- .hsail64,
- .spir,
- .spir64,
- .kalimba,
- .shave,
- .lanai,
- .wasm32,
- .wasm64,
- .renderscript32,
- .renderscript64,
- .aarch64_32,
- .ve,
- => return null,
- }
- },
- else => return null,
- }
-}
-
pub fn getDarwinArchString(self: Target) [:0]const u8 {
const arch = self.getArch();
switch (arch) {
diff --git a/src-self-hosted/windows_sdk.zig b/src-self-hosted/windows_sdk.zig
@@ -0,0 +1,22 @@
+// C API bindings for src/windows_sdk.h
+
+pub const ZigWindowsSDK = extern struct {
+ path10_ptr: ?[*]const u8,
+ path10_len: usize,
+ version10_ptr: ?[*]const u8,
+ version10_len: usize,
+ path81_ptr: ?[*]const u8,
+ path81_len: usize,
+ version81_ptr: ?[*]const u8,
+ version81_len: usize,
+ msvc_lib_dir_ptr: ?[*]const u8,
+ msvc_lib_dir_len: usize,
+};
+pub const ZigFindWindowsSdkError = extern enum {
+ None,
+ OutOfMemory,
+ NotFound,
+ PathTooLong,
+};
+pub extern fn zig_find_windows_sdk(out_sdk: **ZigWindowsSDK) ZigFindWindowsSdkError;
+pub extern fn zig_free_windows_sdk(sdk: *ZigWindowsSDK) void;
diff --git a/src/all_types.hpp b/src/all_types.hpp
@@ -18,7 +18,6 @@
#include "bigfloat.hpp"
#include "target.hpp"
#include "tokenizer.hpp"
-#include "libc_installation.hpp"
struct AstNode;
struct ZigFn;
@@ -370,12 +369,22 @@ enum LazyValueId {
LazyValueIdFnType,
LazyValueIdErrUnionType,
LazyValueIdArrayType,
+ LazyValueIdTypeInfoDecls,
};
struct LazyValue {
LazyValueId id;
};
+struct LazyValueTypeInfoDecls {
+ LazyValue base;
+
+ IrAnalyze *ira;
+
+ ScopeDecls *decls_scope;
+ IrInst *source_instr;
+};
+
struct LazyValueAlignOf {
LazyValue base;
@@ -1139,6 +1148,7 @@ struct AstNodeErrorType {
};
struct AstNodeAwaitExpr {
+ Token *noasync_token;
AstNode *expr;
};
@@ -1685,9 +1695,6 @@ enum BuiltinFnId {
BuiltinFnIdMemset,
BuiltinFnIdSizeof,
BuiltinFnIdAlignOf,
- BuiltinFnIdMemberCount,
- BuiltinFnIdMemberType,
- BuiltinFnIdMemberName,
BuiltinFnIdField,
BuiltinFnIdTypeInfo,
BuiltinFnIdType,
@@ -1740,8 +1747,6 @@ enum BuiltinFnId {
BuiltinFnIdIntCast,
BuiltinFnIdFloatCast,
BuiltinFnIdErrSetCast,
- BuiltinFnIdToBytes,
- BuiltinFnIdFromBytes,
BuiltinFnIdIntToFloat,
BuiltinFnIdFloatToInt,
BuiltinFnIdBoolToInt,
@@ -1749,7 +1754,6 @@ enum BuiltinFnId {
BuiltinFnIdIntToErr,
BuiltinFnIdEnumToInt,
BuiltinFnIdIntToEnum,
- BuiltinFnIdIntType,
BuiltinFnIdVectorType,
BuiltinFnIdShuffle,
BuiltinFnIdSplat,
@@ -1768,7 +1772,6 @@ enum BuiltinFnId {
BuiltinFnIdByteOffsetOf,
BuiltinFnIdBitOffsetOf,
BuiltinFnIdAsyncCall,
- BuiltinFnIdTypeId,
BuiltinFnIdShlExact,
BuiltinFnIdShrExact,
BuiltinFnIdSetEvalBranchQuota,
@@ -1776,7 +1779,6 @@ enum BuiltinFnId {
BuiltinFnIdOpaqueType,
BuiltinFnIdThis,
BuiltinFnIdSetAlignStack,
- BuiltinFnIdArgType,
BuiltinFnIdExport,
BuiltinFnIdErrorReturnTrace,
BuiltinFnIdAtomicRmw,
@@ -1810,7 +1812,6 @@ enum PanicMsgId {
PanicMsgIdDivisionByZero,
PanicMsgIdRemainderDivisionByZero,
PanicMsgIdExactDivisionRemainder,
- PanicMsgIdSliceWidenRemainder,
PanicMsgIdUnwrapOptionalFail,
PanicMsgIdInvalidErrorCode,
PanicMsgIdIncorrectAlignment,
@@ -1955,12 +1956,6 @@ enum CodeModel {
CodeModelLarge,
};
-enum EmitFileType {
- EmitFileTypeBinary,
- EmitFileTypeAssembly,
- EmitFileTypeLLVMIr,
-};
-
struct LinkLib {
Buf *name;
Buf *path;
@@ -2131,13 +2126,15 @@ struct CodeGen {
Buf llvm_triple_str;
Buf global_asm;
- Buf output_file_path;
Buf o_file_output_path;
+ Buf bin_file_output_path;
+ Buf asm_file_output_path;
+ Buf llvm_ir_file_output_path;
Buf *cache_dir;
// As an input parameter, mutually exclusive with enable_cache. But it gets
// populated in codegen_build_and_link.
Buf *output_dir;
- Buf **libc_include_dir_list;
+ const char **libc_include_dir_list;
size_t libc_include_dir_len;
Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir.
@@ -2218,14 +2215,13 @@ struct CodeGen {
ZigList<const char *> lib_dirs;
ZigList<const char *> framework_dirs;
- ZigLibCInstallation *libc;
+ Stage2LibCInstallation *libc;
size_t version_major;
size_t version_minor;
size_t version_patch;
const char *linker_script;
- EmitFileType emit_file_type;
BuildMode build_mode;
OutType out_type;
const ZigTarget *zig_target;
@@ -2247,7 +2243,9 @@ struct CodeGen {
bool function_sections;
bool enable_dump_analysis;
bool enable_doc_generation;
- bool disable_bin_generation;
+ bool emit_bin;
+ bool emit_asm;
+ bool emit_llvm_ir;
bool test_is_evented;
CodeModel code_model;
@@ -2625,7 +2623,6 @@ enum IrInstSrcId {
IrInstSrcIdIntToFloat,
IrInstSrcIdFloatToInt,
IrInstSrcIdBoolToInt,
- IrInstSrcIdIntType,
IrInstSrcIdVectorType,
IrInstSrcIdShuffleVector,
IrInstSrcIdSplat,
@@ -2633,9 +2630,6 @@ enum IrInstSrcId {
IrInstSrcIdMemset,
IrInstSrcIdMemcpy,
IrInstSrcIdSlice,
- IrInstSrcIdMemberCount,
- IrInstSrcIdMemberType,
- IrInstSrcIdMemberName,
IrInstSrcIdBreakpoint,
IrInstSrcIdReturnAddress,
IrInstSrcIdFrameAddress,
@@ -2672,7 +2666,6 @@ enum IrInstSrcId {
IrInstSrcIdTypeInfo,
IrInstSrcIdType,
IrInstSrcIdHasField,
- IrInstSrcIdTypeId,
IrInstSrcIdSetEvalBranchQuota,
IrInstSrcIdPtrType,
IrInstSrcIdAlignCast,
@@ -2691,8 +2684,6 @@ enum IrInstSrcId {
IrInstSrcIdSaveErrRetAddr,
IrInstSrcIdAddImplicitReturnType,
IrInstSrcIdErrSetCast,
- IrInstSrcIdToBytes,
- IrInstSrcIdFromBytes,
IrInstSrcIdCheckRuntimeScope,
IrInstSrcIdHasDecl,
IrInstSrcIdUndeclaredIdent,
@@ -2731,7 +2722,6 @@ enum IrInstGenId {
IrInstGenIdCall,
IrInstGenIdReturn,
IrInstGenIdCast,
- IrInstGenIdResizeSlice,
IrInstGenIdUnreachable,
IrInstGenIdAsm,
IrInstGenIdTestNonNull,
@@ -3263,13 +3253,6 @@ struct IrInstGenCast {
CastOp cast_op;
};
-struct IrInstGenResizeSlice {
- IrInstGen base;
-
- IrInstGen *operand;
- IrInstGen *result_loc;
-};
-
struct IrInstSrcContainerInitList {
IrInstSrc base;
@@ -3621,21 +3604,6 @@ struct IrInstSrcErrSetCast {
IrInstSrc *target;
};
-struct IrInstSrcToBytes {
- IrInstSrc base;
-
- IrInstSrc *target;
- ResultLoc *result_loc;
-};
-
-struct IrInstSrcFromBytes {
- IrInstSrc base;
-
- IrInstSrc *dest_child_type;
- IrInstSrc *target;
- ResultLoc *result_loc;
-};
-
struct IrInstSrcIntToFloat {
IrInstSrc base;
@@ -3656,13 +3624,6 @@ struct IrInstSrcBoolToInt {
IrInstSrc *target;
};
-struct IrInstSrcIntType {
- IrInstSrc base;
-
- IrInstSrc *is_signed;
- IrInstSrc *bit_count;
-};
-
struct IrInstSrcVectorType {
IrInstSrc base;
@@ -3735,26 +3696,6 @@ struct IrInstGenSlice {
bool safety_check_on;
};
-struct IrInstSrcMemberCount {
- IrInstSrc base;
-
- IrInstSrc *container;
-};
-
-struct IrInstSrcMemberType {
- IrInstSrc base;
-
- IrInstSrc *container_type;
- IrInstSrc *member_index;
-};
-
-struct IrInstSrcMemberName {
- IrInstSrc base;
-
- IrInstSrc *container_type;
- IrInstSrc *member_index;
-};
-
struct IrInstSrcBreakpoint {
IrInstSrc base;
};
@@ -4162,12 +4103,6 @@ struct IrInstSrcHasField {
IrInstSrc *field_name;
};
-struct IrInstSrcTypeId {
- IrInstSrc base;
-
- IrInstSrc *type_value;
-};
-
struct IrInstSrcSetEvalBranchQuota {
IrInstSrc base;
@@ -4499,6 +4434,7 @@ struct IrInstSrcAwait {
IrInstSrc *frame;
ResultLoc *result_loc;
+ bool is_noasync;
};
struct IrInstGenAwait {
@@ -4507,6 +4443,7 @@ struct IrInstGenAwait {
IrInstGen *frame;
IrInstGen *result_loc;
ZigFn *target_fn;
+ bool is_noasync;
};
struct IrInstSrcResume {
diff --git a/src/analyze.cpp b/src/analyze.cpp
@@ -1150,6 +1150,7 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdPtrType: {
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
@@ -1209,6 +1210,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdSliceType:
case LazyValueIdPtrType:
@@ -1230,6 +1232,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
@@ -1303,6 +1306,7 @@ start_over:
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
@@ -1370,6 +1374,7 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdSliceType:
case LazyValueIdPtrType:
@@ -1412,6 +1417,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
+ case LazyValueIdTypeInfoDecls:
zig_unreachable();
case LazyValueIdSliceType: // it has the len field
case LazyValueIdOptType: // it has the optional bit
@@ -4710,8 +4716,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
}
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstGenAwait *await = fn->await_list.at(i);
- // TODO If this is a noasync await, it doesn't count
- // https://github.com/ziglang/zig/issues/3157
+ if (await->is_noasync) continue;
switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async,
CallModifierNone))
{
@@ -6315,8 +6320,9 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
// The funtion call result of foo() must be spilled.
for (size_t i = 0; i < fn->await_list.length; i += 1) {
IrInstGenAwait *await = fn->await_list.at(i);
- // TODO If this is a noasync await, it doesn't suspend
- // https://github.com/ziglang/zig/issues/3157
+ if (await->is_noasync) {
+ continue;
+ }
if (await->base.value->special != ConstValSpecialRuntime) {
// Known at comptime. No spill, no suspend.
continue;
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
@@ -5,7 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
-#include "userland.h"
+#include "stage2.h"
#include "cache_hash.hpp"
#include "all_types.hpp"
#include "buffer.hpp"
diff --git a/src/codegen.cpp b/src/codegen.cpp
@@ -18,7 +18,7 @@
#include "target.hpp"
#include "util.hpp"
#include "zig_llvm.h"
-#include "userland.h"
+#include "stage2.h"
#include "dump_analysis.hpp"
#include "softfloat.hpp"
#include "mem_profile.hpp"
@@ -121,10 +121,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
g->version_patch = patch;
}
-void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
- g->emit_file_type = emit_file_type;
-}
-
void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) {
g->each_lib_rpath = each_lib_rpath;
}
@@ -975,8 +971,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
return buf_create_from_str("remainder division by zero or negative value");
case PanicMsgIdExactDivisionRemainder:
return buf_create_from_str("exact division produced remainder");
- case PanicMsgIdSliceWidenRemainder:
- return buf_create_from_str("slice widening size mismatch");
case PanicMsgIdUnwrapOptionalFail:
return buf_create_from_str("attempt to unwrap null");
case PanicMsgIdUnreachable:
@@ -3085,74 +3079,6 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in
}
}
-static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executable,
- IrInstGenResizeSlice *instruction)
-{
- ZigType *actual_type = instruction->operand->value->type;
- ZigType *wanted_type = instruction->base.value->type;
- LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
- assert(expr_val);
-
- LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
- assert(wanted_type->id == ZigTypeIdStruct);
- assert(wanted_type->data.structure.special == StructSpecialSlice);
- assert(actual_type->id == ZigTypeIdStruct);
- assert(actual_type->data.structure.special == StructSpecialSlice);
-
- ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry;
- ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type;
- ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry;
- ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
-
-
- size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index;
- size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index;
- size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index;
- size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index;
-
- LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, "");
- LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
- LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
- get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), "");
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc,
- (unsigned)wanted_ptr_index, "");
- gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
-
- LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, "");
- LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, "");
- uint64_t src_size = type_size(g, actual_child_type);
- uint64_t dest_size = type_size(g, wanted_child_type);
-
- LLVMValueRef new_len;
- if (dest_size == 1) {
- LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, src_size, false);
- new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
- } else if (src_size == 1) {
- LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, dest_size, false);
- if (ir_want_runtime_safety(g, &instruction->base)) {
- LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
- LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type);
- LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
- LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk");
- LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail");
- LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
-
- LLVMPositionBuilderAtEnd(g->builder, fail_block);
- gen_safety_crash(g, PanicMsgIdSliceWidenRemainder);
-
- LLVMPositionBuilderAtEnd(g->builder, ok_block);
- }
- new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
- } else {
- zig_unreachable();
- }
-
- LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, "");
- gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
-
- return result_loc;
-}
-
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable,
IrInstGenCast *cast_instruction)
{
@@ -5014,6 +4940,12 @@ static LLVMValueRef ir_render_ref(CodeGen *g, IrExecutableGen *executable, IrIns
if (!type_has_bits(instruction->base.value->type)) {
return nullptr;
}
+ if (instruction->operand->id == IrInstGenIdCall) {
+ IrInstGenCall *call = reinterpret_cast<IrInstGenCall *>(instruction->operand);
+ if (call->result_loc != nullptr) {
+ return ir_llvm_value(g, call->result_loc);
+ }
+ }
LLVMValueRef value = ir_llvm_value(g, instruction->operand);
if (handle_is_ptr(instruction->operand->value->type)) {
return value;
@@ -6177,7 +6109,9 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI
LLVMValueRef result_loc = (instruction->result_loc == nullptr) ?
nullptr : ir_llvm_value(g, instruction->result_loc);
- if (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)) {
+ if (instruction->is_noasync ||
+ (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn)))
+ {
return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type,
ptr_result_type, result_loc, true);
}
@@ -6476,8 +6410,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl
return ir_render_assert_zero(g, executable, (IrInstGenAssertZero *)instruction);
case IrInstGenIdAssertNonNull:
return ir_render_assert_non_null(g, executable, (IrInstGenAssertNonNull *)instruction);
- case IrInstGenIdResizeSlice:
- return ir_render_resize_slice(g, executable, (IrInstGenResizeSlice *)instruction);
case IrInstGenIdPtrOfArrayToSlice:
return ir_render_ptr_of_array_to_slice(g, executable, (IrInstGenPtrOfArrayToSlice *)instruction);
case IrInstGenIdSuspendBegin:
@@ -6528,7 +6460,7 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
set_debug_location(g, instruction);
}
instruction->llvm_value = ir_render_instruction(g, executable, instruction);
- if (instruction->spill != nullptr) {
+ if (instruction->spill != nullptr && instruction->llvm_value != nullptr) {
LLVMValueRef spill_ptr = ir_llvm_value(g, instruction->spill);
gen_assign_raw(g, spill_ptr, instruction->spill->value->type, instruction->llvm_value);
instruction->llvm_value = nullptr;
@@ -7912,50 +7844,44 @@ static void zig_llvm_emit_output(CodeGen *g) {
bool is_small = g->build_mode == BuildModeSmallRelease;
- Buf *output_path = &g->o_file_output_path;
char *err_msg = nullptr;
- switch (g->emit_file_type) {
- case EmitFileTypeBinary:
- if (g->disable_bin_generation)
- return;
- if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
- ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
- g->enable_time_report))
- {
- zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
- }
- validate_inline_fns(g);
- g->link_objects.append(output_path);
- if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
- (g->out_type == OutTypeLib && !g->is_dynamic)))
- {
- zig_link_add_compiler_rt(g, g->sub_progress_node);
- }
- break;
+ const char *asm_filename = nullptr;
+ const char *bin_filename = nullptr;
+ const char *llvm_ir_filename = nullptr;
+
+ if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path);
+ if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path);
+ if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
+
+ // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire
+ // pipeline multiple times if this is requested.
+ if (asm_filename != nullptr && bin_filename != nullptr) {
+ if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
+ is_small, g->enable_time_report, nullptr, bin_filename, llvm_ir_filename))
+ {
+ fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
+ exit(1);
+ }
+ bin_filename = nullptr;
+ llvm_ir_filename = nullptr;
+ }
- case EmitFileTypeAssembly:
- if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
- ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small,
- g->enable_time_report))
- {
- zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
- }
- validate_inline_fns(g);
- break;
+ if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
+ is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename))
+ {
+ fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
+ exit(1);
+ }
- case EmitFileTypeLLVMIr:
- if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
- ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small,
- g->enable_time_report))
- {
- zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
- }
- validate_inline_fns(g);
- break;
+ validate_inline_fns(g);
- default:
- zig_unreachable();
+ if (g->emit_bin) {
+ g->link_objects.append(&g->o_file_output_path);
+ if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) {
+ zig_link_add_compiler_rt(g, g->sub_progress_node);
+ }
}
+
LLVMDisposeModule(g->module);
g->module = nullptr;
LLVMDisposeTargetData(g->target_data_ref);
@@ -8221,9 +8147,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, BuiltinFnIdMemberCount, "memberCount", 1);
- create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2);
- create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2);
create_builtin_fn(g, BuiltinFnIdField, "field", 2);
create_builtin_fn(g, BuiltinFnIdTypeInfo, "typeInfo", 1);
create_builtin_fn(g, BuiltinFnIdType, "Type", 1);
@@ -8261,7 +8184,6 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdIntToEnum, "intToEnum", 2);
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
- create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
@@ -8299,22 +8221,18 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdRound, "round", 1);
create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
- create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2);
create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
create_builtin_fn(g, BuiltinFnIdSetEvalBranchQuota, "setEvalBranchQuota", 1);
create_builtin_fn(g, BuiltinFnIdAlignCast, "alignCast", 2);
create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0);
create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1);
- create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2);
create_builtin_fn(g, BuiltinFnIdExport, "export", 2);
create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4);
create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
- create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
- create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2);
create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3);
@@ -8361,9 +8279,11 @@ static bool detect_dynamic_link(CodeGen *g) {
return true;
if (g->zig_target->os == OsFreestanding)
return false;
- if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr))
+ if (target_os_requires_libc(g->zig_target->os))
return true;
- // If there are no dynamic libraries then we can disable PIC
+ if (g->libc_link_lib != nullptr && target_is_glibc(g->zig_target))
+ return true;
+ // If there are no dynamic libraries then we can disable dynamic linking.
for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
LinkLib *link_lib = g->link_libs_list.at(i);
if (target_is_libc_lib_name(g->zig_target, buf_ptr(link_lib->name)))
@@ -8498,25 +8418,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
ZigLLVM_ArchType arch = target_arch_enum(arch_i);
const char *arch_name = target_arch_name(arch);
- SubArchList sub_arch_list = target_subarch_list(arch);
- if (sub_arch_list == SubArchListNone) {
- if (arch == g->zig_target->arch) {
- g->target_arch_index = arch_i;
- cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name));
- }
- } else {
- const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list);
- if (arch == g->zig_target->arch) {
- size_t sub_count = target_subarch_count(sub_arch_list);
- for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
- ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
- if (sub == g->zig_target->sub_arch) {
- g->target_sub_arch_index = sub_i;
- cur_arch = buf_ptr(buf_sprintf("Arch{ .%s = Arch.%s.%s }",
- arch_name, sub_arch_list_name, target_subarch_name(sub)));
- }
- }
- }
+ if (arch == g->zig_target->arch) {
+ g->target_arch_index = arch_i;
+ cur_arch = arch_name;
}
}
}
@@ -8610,22 +8514,19 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
break;
}
buf_appendf(contents, "pub const output_mode = OutputMode.%s;\n", out_type);
- const char *link_type = g->is_dynamic ? "Dynamic" : "Static";
+ const char *link_type = g->have_dynamic_link ? "Dynamic" : "Static";
buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", link_type);
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
- buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
+ buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
{
- buf_append_str(contents, "pub const cpu_features: CpuFeatures = ");
- if (g->zig_target->cpu_features != nullptr) {
- const char *ptr;
- size_t len;
- stage2_cpu_features_get_builtin_str(g->zig_target->cpu_features, &ptr, &len);
- buf_append_mem(contents, ptr, len);
+ buf_append_str(contents, "pub const cpu: Cpu = ");
+ if (g->zig_target->builtin_str != nullptr) {
+ buf_append_str(contents, g->zig_target->builtin_str);
} else {
- buf_append_str(contents, "arch.getBaselineCpuFeatures();\n");
+ buf_append_str(contents, "Target.Cpu.baseline(arch);\n");
}
}
if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {
@@ -8717,22 +8618,18 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_int(&cache_hash, g->build_mode);
cache_bool(&cache_hash, g->strip_debug_symbols);
cache_int(&cache_hash, g->out_type);
- cache_bool(&cache_hash, g->is_dynamic);
+ cache_bool(&cache_hash, detect_dynamic_link(g));
cache_bool(&cache_hash, g->is_test_build);
cache_bool(&cache_hash, g->is_single_threaded);
cache_bool(&cache_hash, g->test_is_evented);
cache_int(&cache_hash, g->code_model);
cache_int(&cache_hash, g->zig_target->is_native);
cache_int(&cache_hash, g->zig_target->arch);
- cache_int(&cache_hash, g->zig_target->sub_arch);
cache_int(&cache_hash, g->zig_target->vendor);
cache_int(&cache_hash, g->zig_target->os);
cache_int(&cache_hash, g->zig_target->abi);
- if (g->zig_target->cpu_features != nullptr) {
- const char *ptr;
- size_t len;
- stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len);
- cache_str(&cache_hash, ptr);
+ if (g->zig_target->cache_hash != nullptr) {
+ cache_str(&cache_hash, g->zig_target->cache_hash);
}
if (g->zig_target->glibc_version != nullptr) {
cache_int(&cache_hash, g->zig_target->glibc_version->major);
@@ -8867,9 +8764,11 @@ static void init(CodeGen *g) {
}
// Override CPU and features if defined by user.
- if (g->zig_target->cpu_features != nullptr) {
- target_specific_cpu_args = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features);
- target_specific_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features);
+ if (g->zig_target->llvm_cpu_name != nullptr) {
+ target_specific_cpu_args = g->zig_target->llvm_cpu_name;
+ }
+ if (g->zig_target->llvm_cpu_features != nullptr) {
+ target_specific_features = g->zig_target->llvm_cpu_features;
}
if (g->verbose_llvm_cpu_features) {
fprintf(stderr, "name=%s triple=%s\n", buf_ptr(g->root_out_name), buf_ptr(&g->llvm_triple_str));
@@ -8943,6 +8842,8 @@ static void init(CodeGen *g) {
}
static void detect_dynamic_linker(CodeGen *g) {
+ Error err;
+
if (g->dynamic_linker_path != nullptr)
return;
if (!g->have_dynamic_link)
@@ -8950,42 +8851,16 @@ static void detect_dynamic_linker(CodeGen *g) {
if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))
return;
- const char *standard_ld_path = target_dynamic_linker(g->zig_target);
- if (standard_ld_path == nullptr)
- return;
-
- if (g->zig_target->is_native) {
- // target_dynamic_linker is usually correct. However on some systems, such as NixOS
- // it will be incorrect. See if we can do better by looking at what zig's own
- // dynamic linker path is.
- g->dynamic_linker_path = get_self_dynamic_linker_path();
- if (g->dynamic_linker_path != nullptr)
- return;
-
- // If Zig is statically linked, such as via distributed binary static builds, the above
- // trick won't work. What are we left with? Try to run the system C compiler and get
- // it to tell us the dynamic linker path
-#if defined(ZIG_OS_LINUX)
- {
- Error err;
- Buf *result = buf_alloc();
- for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) {
- const char *lib_name = possible_ld_names[i];
- if ((err = zig_libc_cc_print_file_name(lib_name, result, false, true))) {
- if (err != ErrorCCompilerCannotFindFile && err != ErrorNoCCompilerInstalled) {
- fprintf(stderr, "Unable to detect native dynamic linker: %s\n", err_str(err));
- exit(1);
- }
- continue;
- }
- g->dynamic_linker_path = result;
- return;
- }
- }
-#endif
+ char *dynamic_linker_ptr;
+ size_t dynamic_linker_len;
+ if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) {
+ if (err == ErrorTargetHasNoDynamicLinker) return;
+ fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err));
+ exit(1);
}
-
- g->dynamic_linker_path = buf_create_from_str(standard_ld_path);
+ g->dynamic_linker_path = buf_create_from_mem(dynamic_linker_ptr, dynamic_linker_len);
+ // Skips heap::c_allocator because the memory is allocated by stage2 library.
+ free(dynamic_linker_ptr);
}
static void detect_libc(CodeGen *g) {
@@ -9014,16 +8889,16 @@ static void detect_libc(CodeGen *g) {
buf_ptr(g->zig_lib_dir), target_os_name(g->zig_target->os));
g->libc_include_dir_len = 4;
- g->libc_include_dir_list = heap::c_allocator.allocate<Buf*>(g->libc_include_dir_len);
- g->libc_include_dir_list[0] = arch_include_dir;
- g->libc_include_dir_list[1] = generic_include_dir;
- g->libc_include_dir_list[2] = arch_os_include_dir;
- g->libc_include_dir_list[3] = generic_os_include_dir;
+ g->libc_include_dir_list = heap::c_allocator.allocate<const char*>(g->libc_include_dir_len);
+ g->libc_include_dir_list[0] = buf_ptr(arch_include_dir);
+ g->libc_include_dir_list[1] = buf_ptr(generic_include_dir);
+ g->libc_include_dir_list[2] = buf_ptr(arch_os_include_dir);
+ g->libc_include_dir_list[3] = buf_ptr(generic_os_include_dir);
return;
}
if (g->zig_target->is_native) {
- g->libc = heap::c_allocator.create<ZigLibCInstallation>();
+ g->libc = heap::c_allocator.create<Stage2LibCInstallation>();
// search for native_libc.txt in following dirs:
// - LOCAL_CACHE_DIR
@@ -9068,8 +8943,8 @@ static void detect_libc(CodeGen *g) {
if (libc_txt == nullptr)
libc_txt = &global_libc_txt;
- if ((err = zig_libc_parse(g->libc, libc_txt, g->zig_target, false))) {
- if ((err = zig_libc_find_native(g->libc, true))) {
+ if ((err = stage2_libc_parse(g->libc, buf_ptr(libc_txt)))) {
+ if ((err = stage2_libc_find_native(g->libc))) {
fprintf(stderr,
"Unable to link against libc: Unable to find libc installation: %s\n"
"See `zig libc --help` for more details.\n", err_str(err));
@@ -9089,7 +8964,7 @@ static void detect_libc(CodeGen *g) {
fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
exit(1);
}
- zig_libc_render(g->libc, file);
+ stage2_libc_render(g->libc, file);
if (fclose(file) != 0) {
fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
exit(1);
@@ -9099,27 +8974,28 @@ static void detect_libc(CodeGen *g) {
exit(1);
}
}
- bool want_sys_dir = !buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir);
+ bool want_sys_dir = !mem_eql_mem(g->libc->include_dir, g->libc->include_dir_len,
+ g->libc->sys_include_dir, g->libc->sys_include_dir_len);
size_t want_um_and_shared_dirs = (g->zig_target->os == OsWindows) ? 2 : 0;
size_t dir_count = 1 + want_sys_dir + want_um_and_shared_dirs;
g->libc_include_dir_len = 0;
- g->libc_include_dir_list = heap::c_allocator.allocate<Buf*>(dir_count);
+ g->libc_include_dir_list = heap::c_allocator.allocate<const char *>(dir_count);
- g->libc_include_dir_list[g->libc_include_dir_len] = &g->libc->include_dir;
+ g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->include_dir;
g->libc_include_dir_len += 1;
if (want_sys_dir) {
- g->libc_include_dir_list[g->libc_include_dir_len] = &g->libc->sys_include_dir;
+ g->libc_include_dir_list[g->libc_include_dir_len] = g->libc->sys_include_dir;
g->libc_include_dir_len += 1;
}
if (want_um_and_shared_dirs != 0) {
- g->libc_include_dir_list[g->libc_include_dir_len] = buf_sprintf("%s" OS_SEP ".." OS_SEP "um",
- buf_ptr(&g->libc->include_dir));
+ g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf(
+ "%s" OS_SEP ".." OS_SEP "um", g->libc->include_dir));
g->libc_include_dir_len += 1;
- g->libc_include_dir_list[g->libc_include_dir_len] = buf_sprintf("%s" OS_SEP ".." OS_SEP "shared",
- buf_ptr(&g->libc->include_dir));
+ g->libc_include_dir_list[g->libc_include_dir_len] = buf_ptr(buf_sprintf(
+ "%s" OS_SEP ".." OS_SEP "shared", g->libc->include_dir));
g->libc_include_dir_len += 1;
}
assert(g->libc_include_dir_len == dir_count);
@@ -9194,9 +9070,9 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
args.append(buf_ptr(g->zig_c_headers_dir));
for (size_t i = 0; i < g->libc_include_dir_len; i += 1) {
- Buf *include_dir = g->libc_include_dir_list[i];
+ const char *include_dir = g->libc_include_dir_list[i];
args.append("-isystem");
- args.append(buf_ptr(include_dir));
+ args.append(include_dir);
}
if (g->zig_target->is_native) {
@@ -9207,19 +9083,17 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
args.append("-target");
args.append(buf_ptr(&g->llvm_triple_str));
- const char *llvm_cpu = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features);
- if (llvm_cpu != nullptr) {
+ if (g->zig_target->llvm_cpu_name != nullptr) {
args.append("-Xclang");
args.append("-target-cpu");
args.append("-Xclang");
- args.append(llvm_cpu);
+ args.append(g->zig_target->llvm_cpu_name);
}
- const char *llvm_target_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features);
- if (llvm_target_features != nullptr) {
+ if (g->zig_target->llvm_cpu_features != nullptr) {
args.append("-Xclang");
args.append("-target-feature");
args.append("-Xclang");
- args.append(llvm_target_features);
+ args.append(g->zig_target->llvm_cpu_features);
}
}
@@ -9652,10 +9526,9 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
cache_buf(cache_hash, compiler_id);
cache_int(cache_hash, g->err_color);
cache_buf(cache_hash, g->zig_c_headers_dir);
- cache_list_of_buf(cache_hash, g->libc_include_dir_list, g->libc_include_dir_len);
+ cache_list_of_str(cache_hash, g->libc_include_dir_list, g->libc_include_dir_len);
cache_int(cache_hash, g->zig_target->is_native);
cache_int(cache_hash, g->zig_target->arch);
- cache_int(cache_hash, g->zig_target->sub_arch);
cache_int(cache_hash, g->zig_target->vendor);
cache_int(cache_hash, g->zig_target->os);
cache_int(cache_hash, g->zig_target->abi);
@@ -10419,15 +10292,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->out_type);
cache_bool(ch, g->zig_target->is_native);
cache_int(ch, g->zig_target->arch);
- cache_int(ch, g->zig_target->sub_arch);
cache_int(ch, g->zig_target->vendor);
cache_int(ch, g->zig_target->os);
cache_int(ch, g->zig_target->abi);
- if (g->zig_target->cpu_features != nullptr) {
- const char *ptr;
- size_t len;
- stage2_cpu_features_get_cache_hash(g->zig_target->cpu_features, &ptr, &len);
- cache_str(ch, ptr);
+ if (g->zig_target->cache_hash != nullptr) {
+ cache_str(ch, g->zig_target->cache_hash);
}
if (g->zig_target->glibc_version != nullptr) {
cache_int(ch, g->zig_target->glibc_version->major);
@@ -10457,7 +10326,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->function_sections);
cache_bool(ch, g->enable_dump_analysis);
cache_bool(ch, g->enable_doc_generation);
- cache_bool(ch, g->disable_bin_generation);
+ cache_bool(ch, g->emit_bin);
+ cache_bool(ch, g->emit_llvm_ir);
+ cache_bool(ch, g->emit_asm);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
cache_usize(ch, g->version_major);
@@ -10468,11 +10339,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length);
if (g->libc) {
- cache_buf(ch, &g->libc->include_dir);
- cache_buf(ch, &g->libc->sys_include_dir);
- cache_buf(ch, &g->libc->crt_dir);
- cache_buf(ch, &g->libc->msvc_lib_dir);
- cache_buf(ch, &g->libc->kernel32_lib_dir);
+ cache_str(ch, g->libc->include_dir);
+ cache_str(ch, g->libc->sys_include_dir);
+ cache_str(ch, g->libc->crt_dir);
+ cache_str(ch, g->libc->msvc_lib_dir);
+ cache_str(ch, g->libc->kernel32_lib_dir);
}
cache_buf_opt(ch, g->dynamic_linker_path);
cache_buf_opt(ch, g->version_script_path);
@@ -10502,58 +10373,54 @@ static void resolve_out_paths(CodeGen *g) {
assert(g->output_dir != nullptr);
assert(g->root_out_name != nullptr);
- Buf *out_basename = buf_create_from_buf(g->root_out_name);
- Buf *o_basename = buf_create_from_buf(g->root_out_name);
- switch (g->emit_file_type) {
- case EmitFileTypeBinary: {
- switch (g->out_type) {
- case OutTypeUnknown:
- zig_unreachable();
- case OutTypeObj:
- if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
- buf_init_from_buf(&g->output_file_path, g->link_objects.at(0));
- return;
- }
- if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
- buf_eql_buf(o_basename, out_basename))
- {
- // make it not collide with main output object
- buf_append_str(o_basename, ".root");
- }
- buf_append_str(o_basename, target_o_file_ext(g->zig_target));
- buf_append_str(out_basename, target_o_file_ext(g->zig_target));
- break;
- case OutTypeExe:
- buf_append_str(o_basename, target_o_file_ext(g->zig_target));
- buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
- break;
- case OutTypeLib:
- buf_append_str(o_basename, target_o_file_ext(g->zig_target));
- buf_resize(out_basename, 0);
- buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
- buf_append_buf(out_basename, g->root_out_name);
- buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
- g->version_major, g->version_minor, g->version_patch));
- break;
- }
- break;
- }
- case EmitFileTypeAssembly: {
- const char *asm_ext = target_asm_file_ext(g->zig_target);
- buf_append_str(o_basename, asm_ext);
- buf_append_str(out_basename, asm_ext);
- break;
- }
- case EmitFileTypeLLVMIr: {
- const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
- buf_append_str(o_basename, llvm_ir_ext);
- buf_append_str(out_basename, llvm_ir_ext);
- break;
+ if (g->emit_bin) {
+ Buf *out_basename = buf_create_from_buf(g->root_out_name);
+ Buf *o_basename = buf_create_from_buf(g->root_out_name);
+ switch (g->out_type) {
+ case OutTypeUnknown:
+ zig_unreachable();
+ case OutTypeObj:
+ if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
+ buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0));
+ return;
+ }
+ if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
+ buf_eql_buf(o_basename, out_basename))
+ {
+ // make it not collide with main output object
+ buf_append_str(o_basename, ".root");
+ }
+ buf_append_str(o_basename, target_o_file_ext(g->zig_target));
+ buf_append_str(out_basename, target_o_file_ext(g->zig_target));
+ break;
+ case OutTypeExe:
+ buf_append_str(o_basename, target_o_file_ext(g->zig_target));
+ buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
+ break;
+ case OutTypeLib:
+ buf_append_str(o_basename, target_o_file_ext(g->zig_target));
+ buf_resize(out_basename, 0);
+ buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
+ buf_append_buf(out_basename, g->root_out_name);
+ buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
+ g->version_major, g->version_minor, g->version_patch));
+ break;
}
+ os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
+ os_path_join(g->output_dir, out_basename, &g->bin_file_output_path);
+ }
+ if (g->emit_asm) {
+ Buf *asm_basename = buf_create_from_buf(g->root_out_name);
+ const char *asm_ext = target_asm_file_ext(g->zig_target);
+ buf_append_str(asm_basename, asm_ext);
+ os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path);
+ }
+ if (g->emit_llvm_ir) {
+ Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name);
+ const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
+ buf_append_str(llvm_ir_basename, llvm_ir_ext);
+ os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path);
}
-
- os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
- os_path_join(g->output_dir, out_basename, &g->output_file_path);
}
void codegen_build_and_link(CodeGen *g) {
@@ -10715,7 +10582,7 @@ void codegen_build_and_link(CodeGen *g) {
// If there is more than one object, we have to link them (with -r).
// Finally, if we didn't make an object from zig source, and we don't have caching enabled,
// then we have an object from C source that we must copy to the output dir which we do with a -r link.
- if (!g->disable_bin_generation && g->emit_file_type == EmitFileTypeBinary &&
+ if (g->emit_bin &&
(g->out_type != OutTypeObj || g->link_objects.length > 1 ||
(!need_llvm_module(g) && !g->enable_cache)))
{
@@ -10751,7 +10618,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
}
CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
- ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *parent_progress_node)
+ Stage2LibCInstallation *libc, const char *name, Stage2ProgressNode *parent_progress_node)
{
Stage2ProgressNode *child_progress_node = stage2_progress_start(
parent_progress_node ? parent_progress_node : parent_gen->sub_progress_node,
@@ -10790,9 +10657,10 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
OutType out_type, BuildMode build_mode, Buf *override_lib_dir,
- ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node)
+ Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node)
{
CodeGen *g = heap::c_allocator.create<CodeGen>();
+ g->emit_bin = true;
g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
g->main_progress_node = progress_node;
diff --git a/src/codegen.hpp b/src/codegen.hpp
@@ -11,23 +11,21 @@
#include "parser.hpp"
#include "errmsg.hpp"
#include "target.hpp"
-#include "libc_installation.hpp"
-#include "userland.h"
+#include "stage2.h"
#include <stdio.h>
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
OutType out_type, BuildMode build_mode, Buf *zig_lib_dir,
- ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node);
+ Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node);
CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
- ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node);
+ Stage2LibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node);
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
-void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
void codegen_set_strip(CodeGen *codegen, bool strip);
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
diff --git a/src/compiler.cpp b/src/compiler.cpp
@@ -4,20 +4,6 @@
#include <stdio.h>
-static Buf saved_dynamic_linker_path = BUF_INIT;
-static bool searched_for_dyn_linker = false;
-
-static void detect_dynamic_linker(Buf *lib_path) {
-#if defined(ZIG_OS_LINUX)
- for (size_t i = 0; possible_ld_names[i] != NULL; i += 1) {
- if (buf_ends_with_str(lib_path, possible_ld_names[i])) {
- buf_init_from_buf(&saved_dynamic_linker_path, lib_path);
- break;
- }
- }
-#endif
-}
-
Buf *get_self_libc_path(void) {
static Buf saved_libc_path = BUF_INIT;
static bool searched_for_libc = false;
@@ -43,25 +29,6 @@ Buf *get_self_libc_path(void) {
}
}
-Buf *get_self_dynamic_linker_path(void) {
- for (;;) {
- if (saved_dynamic_linker_path.list.length != 0) {
- return &saved_dynamic_linker_path;
- }
- if (searched_for_dyn_linker)
- return nullptr;
- ZigList<Buf *> lib_paths = {};
- Error err;
- if ((err = os_self_exe_shared_libs(lib_paths)))
- return nullptr;
- for (size_t i = 0; i < lib_paths.length; i += 1) {
- Buf *lib_path = lib_paths.at(i);
- detect_dynamic_linker(lib_path);
- }
- searched_for_dyn_linker = true;
- }
-}
-
Error get_compiler_id(Buf **result) {
static Buf saved_compiler_id = BUF_INIT;
@@ -98,7 +65,6 @@ Error get_compiler_id(Buf **result) {
return err;
for (size_t i = 0; i < lib_paths.length; i += 1) {
Buf *lib_path = lib_paths.at(i);
- detect_dynamic_linker(lib_path);
if ((err = cache_add_file(ch, lib_path)))
return err;
}
diff --git a/src/compiler.hpp b/src/compiler.hpp
@@ -12,7 +12,6 @@
#include "error.hpp"
Error get_compiler_id(Buf **result);
-Buf *get_self_dynamic_linker_path(void);
Buf *get_self_libc_path(void);
Buf *get_zig_lib_dir(void);
diff --git a/src/error.cpp b/src/error.cpp
@@ -59,11 +59,28 @@ const char *err_str(Error err) {
case ErrorIsAsync: return "is async";
case ErrorImportOutsidePkgPath: return "import of file outside package path";
case ErrorUnknownCpu: return "unknown CPU";
- case ErrorUnknownSubArchitecture: return "unknown sub-architecture";
case ErrorUnknownCpuFeature: return "unknown CPU feature";
case ErrorInvalidCpuFeatures: return "invalid CPU features";
case ErrorInvalidLlvmCpuFeaturesFormat: return "invalid LLVM CPU features format";
case ErrorUnknownApplicationBinaryInterface: return "unknown application binary interface";
+ case ErrorASTUnitFailure: return "compiler bug: clang encountered a compile error, but the libclang API does not expose the error. See https://github.com/ziglang/zig/issues/4455 for more details";
+ case ErrorBadPathName: return "bad path name";
+ case ErrorSymLinkLoop: return "sym link loop";
+ case ErrorProcessFdQuotaExceeded: return "process fd quota exceeded";
+ case ErrorSystemFdQuotaExceeded: return "system fd quota exceeded";
+ case ErrorNoDevice: return "no device";
+ case ErrorDeviceBusy: return "device busy";
+ case ErrorUnableToSpawnCCompiler: return "unable to spawn system C compiler";
+ case ErrorCCompilerExitCode: return "system C compiler exited with failure code";
+ case ErrorCCompilerCrashed: return "system C compiler crashed";
+ case ErrorCCompilerCannotFindHeaders: return "system C compiler cannot find libc headers";
+ case ErrorLibCRuntimeNotFound: return "libc runtime not found";
+ case ErrorLibCStdLibHeaderNotFound: return "libc std lib headers not found";
+ case ErrorLibCKernel32LibNotFound: return "kernel32 library not found";
+ case ErrorUnsupportedArchitecture: return "unsupported architecture";
+ case ErrorWindowsSdkNotFound: return "Windows SDK not found";
+ case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path";
+ case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";
}
return "(invalid error)";
}
diff --git a/src/error.hpp b/src/error.hpp
@@ -8,7 +8,7 @@
#ifndef ERROR_HPP
#define ERROR_HPP
-#include "userland.h"
+#include "stage2.h"
const char *err_str(Error err);
diff --git a/src/glibc.cpp b/src/glibc.cpp
@@ -116,10 +116,8 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo
assert(opt_abi.is_some);
- err = target_parse_archsub(&target->arch, &target->sub_arch,
- (char*)opt_arch.value.ptr, opt_arch.value.len);
- // there's no sub arch so we might get an error, but the arch is still populated
- assert(err == ErrorNone || err == ErrorUnknownArchitecture);
+ err = target_parse_arch(&target->arch, (char*)opt_arch.value.ptr, opt_arch.value.len);
+ assert(err == ErrorNone);
target->os = OsLinux;
diff --git a/src/ir.cpp b/src/ir.cpp
@@ -14,6 +14,7 @@
#include "range_set.hpp"
#include "softfloat.hpp"
#include "util.hpp"
+#include "mem_list.hpp"
#include <errno.h>
@@ -28,6 +29,9 @@ struct IrBuilderGen {
CodeGen *codegen;
IrExecutableGen *exec;
IrBasicBlockGen *current_basic_block;
+
+ // track for immediate post-analysis destruction
+ mem::List<IrInstGenConst *> constants;
};
struct IrAnalyze {
@@ -383,18 +387,12 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatCast *>(inst));
case IrInstSrcIdErrSetCast:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcErrSetCast *>(inst));
- case IrInstSrcIdFromBytes:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFromBytes *>(inst));
- case IrInstSrcIdToBytes:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcToBytes *>(inst));
case IrInstSrcIdIntToFloat:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntToFloat *>(inst));
case IrInstSrcIdFloatToInt:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcFloatToInt *>(inst));
case IrInstSrcIdBoolToInt:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBoolToInt *>(inst));
- case IrInstSrcIdIntType:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcIntType *>(inst));
case IrInstSrcIdVectorType:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcVectorType *>(inst));
case IrInstSrcIdShuffleVector:
@@ -409,12 +407,6 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemcpy *>(inst));
case IrInstSrcIdSlice:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSlice *>(inst));
- case IrInstSrcIdMemberCount:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemberCount *>(inst));
- case IrInstSrcIdMemberType:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemberType *>(inst));
- case IrInstSrcIdMemberName:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcMemberName *>(inst));
case IrInstSrcIdBreakpoint:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcBreakpoint *>(inst));
case IrInstSrcIdReturnAddress:
@@ -481,8 +473,6 @@ static void destroy_instruction_src(IrInstSrc *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcType *>(inst));
case IrInstSrcIdHasField:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcHasField *>(inst));
- case IrInstSrcIdTypeId:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTypeId *>(inst));
case IrInstSrcIdSetEvalBranchQuota:
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSetEvalBranchQuota *>(inst));
case IrInstSrcIdAlignCast:
@@ -707,8 +697,6 @@ void destroy_instruction_gen(IrInstGen *inst) {
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenAssertZero *>(inst));
case IrInstGenIdAssertNonNull:
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenAssertNonNull *>(inst));
- case IrInstGenIdResizeSlice:
- return heap::c_allocator.destroy(reinterpret_cast<IrInstGenResizeSlice *>(inst));
case IrInstGenIdAlloca:
return heap::c_allocator.destroy(reinterpret_cast<IrInstGenAlloca *>(inst));
case IrInstGenIdSuspendBegin:
@@ -741,6 +729,10 @@ static void ira_ref(IrAnalyze *ira) {
static void ira_deref(IrAnalyze *ira) {
if (ira->ref_count > 1) {
ira->ref_count -= 1;
+
+ // immediate destruction of dangling IrInstGenConst is not possible
+ // free tracking memory because it will never be used
+ ira->new_irb.constants.deinit(&heap::c_allocator);
return;
}
assert(ira->ref_count != 0);
@@ -758,6 +750,15 @@ static void ira_deref(IrAnalyze *ira) {
heap::c_allocator.destroy(ira->old_irb.exec);
ira->src_implicit_return_type_list.deinit();
ira->resume_stack.deinit();
+
+ // destroy dangling IrInstGenConst
+ for (size_t i = 0; i < ira->new_irb.constants.length; i += 1) {
+ auto constant = ira->new_irb.constants.items[i];
+ if (constant->base.base.ref_count == 0 && !ir_inst_gen_has_side_effects(&constant->base))
+ destroy_instruction_gen(&constant->base);
+ }
+ ira->new_irb.constants.deinit(&heap::c_allocator);
+
heap::c_allocator.destroy(ira);
}
@@ -1299,10 +1300,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcBoolToInt *) {
return IrInstSrcIdBoolToInt;
}
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcIntType *) {
- return IrInstSrcIdIntType;
-}
-
static constexpr IrInstSrcId ir_inst_id(IrInstSrcVectorType *) {
return IrInstSrcIdVectorType;
}
@@ -1331,18 +1328,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSlice *) {
return IrInstSrcIdSlice;
}
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberCount *) {
- return IrInstSrcIdMemberCount;
-}
-
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberType *) {
- return IrInstSrcIdMemberType;
-}
-
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcMemberName *) {
- return IrInstSrcIdMemberName;
-}
-
static constexpr IrInstSrcId ir_inst_id(IrInstSrcBreakpoint *) {
return IrInstSrcIdBreakpoint;
}
@@ -1487,10 +1472,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcHasField *) {
return IrInstSrcIdHasField;
}
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcTypeId *) {
- return IrInstSrcIdTypeId;
-}
-
static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetEvalBranchQuota *) {
return IrInstSrcIdSetEvalBranchQuota;
}
@@ -1563,14 +1544,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) {
return IrInstSrcIdErrSetCast;
}
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcToBytes *) {
- return IrInstSrcIdToBytes;
-}
-
-static constexpr IrInstSrcId ir_inst_id(IrInstSrcFromBytes *) {
- return IrInstSrcIdFromBytes;
-}
-
static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) {
return IrInstSrcIdCheckRuntimeScope;
}
@@ -1700,10 +1673,6 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) {
return IrInstGenIdCast;
}
-static constexpr IrInstGenId ir_inst_id(IrInstGenResizeSlice *) {
- return IrInstGenIdResizeSlice;
-}
-
static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) {
return IrInstGenIdUnreachable;
}
@@ -2759,21 +2728,6 @@ static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instructi
return &inst->base;
}
-static IrInstGen *ir_build_resize_slice(IrAnalyze *ira, IrInst *source_instruction,
- IrInstGen *operand, ZigType *ty, IrInstGen *result_loc)
-{
- IrInstGenResizeSlice *instruction = ir_build_inst_gen<IrInstGenResizeSlice>(&ira->new_irb,
- source_instruction->scope, source_instruction->source_node);
- instruction->base.value->type = ty;
- instruction->operand = operand;
- instruction->result_loc = result_loc;
-
- ir_ref_inst_gen(operand, ira->new_irb.current_basic_block);
- if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc *target, IrInstSrc *options)
{
@@ -3540,32 +3494,6 @@ static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstSrc *ir_build_to_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target,
- ResultLoc *result_loc)
-{
- IrInstSrcToBytes *instruction = ir_build_instruction<IrInstSrcToBytes>(irb, scope, source_node);
- instruction->target = target;
- instruction->result_loc = result_loc;
-
- ir_ref_instruction(target, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstSrc *ir_build_from_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
- IrInstSrc *dest_child_type, IrInstSrc *target, ResultLoc *result_loc)
-{
- IrInstSrcFromBytes *instruction = ir_build_instruction<IrInstSrcFromBytes>(irb, scope, source_node);
- instruction->dest_child_type = dest_child_type;
- instruction->target = target;
- instruction->result_loc = result_loc;
-
- ir_ref_instruction(dest_child_type, irb->current_basic_block);
- ir_ref_instruction(target, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc *dest_type, IrInstSrc *target)
{
@@ -3601,19 +3529,6 @@ static IrInstSrc *ir_build_bool_to_int(IrBuilderSrc *irb, Scope *scope, AstNode
return &instruction->base;
}
-static IrInstSrc *ir_build_int_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *is_signed,
- IrInstSrc *bit_count)
-{
- IrInstSrcIntType *instruction = ir_build_instruction<IrInstSrcIntType>(irb, scope, source_node);
- instruction->is_signed = is_signed;
- instruction->bit_count = bit_count;
-
- ir_ref_instruction(is_signed, irb->current_basic_block);
- ir_ref_instruction(bit_count, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstSrc *ir_build_vector_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *len,
IrInstSrc *elem_type)
{
@@ -3808,41 +3723,6 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction,
return &instruction->base;
}
-static IrInstSrc *ir_build_member_count(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *container) {
- IrInstSrcMemberCount *instruction = ir_build_instruction<IrInstSrcMemberCount>(irb, scope, source_node);
- instruction->container = container;
-
- ir_ref_instruction(container, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstSrc *ir_build_member_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
- IrInstSrc *container_type, IrInstSrc *member_index)
-{
- IrInstSrcMemberType *instruction = ir_build_instruction<IrInstSrcMemberType>(irb, scope, source_node);
- instruction->container_type = container_type;
- instruction->member_index = member_index;
-
- ir_ref_instruction(container_type, irb->current_basic_block);
- ir_ref_instruction(member_index, irb->current_basic_block);
-
- return &instruction->base;
-}
-
-static IrInstSrc *ir_build_member_name(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
- IrInstSrc *container_type, IrInstSrc *member_index)
-{
- IrInstSrcMemberName *instruction = ir_build_instruction<IrInstSrcMemberName>(irb, scope, source_node);
- instruction->container_type = container_type;
- instruction->member_index = member_index;
-
- ir_ref_instruction(container_type, irb->current_basic_block);
- ir_ref_instruction(member_index, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstSrc *ir_build_breakpoint(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
IrInstSrcBreakpoint *instruction = ir_build_instruction<IrInstSrcBreakpoint>(irb, scope, source_node);
return &instruction->base;
@@ -4517,15 +4397,6 @@ static IrInstSrc *ir_build_type(IrBuilderSrc *irb, Scope *scope, AstNode *source
return &instruction->base;
}
-static IrInstSrc *ir_build_type_id(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *type_value) {
- IrInstSrcTypeId *instruction = ir_build_instruction<IrInstSrcTypeId>(irb, scope, source_node);
- instruction->type_value = type_value;
-
- ir_ref_instruction(type_value, irb->current_basic_block);
-
- return &instruction->base;
-}
-
static IrInstSrc *ir_build_set_eval_branch_quota(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
IrInstSrc *new_quota)
{
@@ -4956,11 +4827,12 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins
}
static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node,
- IrInstSrc *frame, ResultLoc *result_loc)
+ IrInstSrc *frame, ResultLoc *result_loc, bool is_noasync)
{
IrInstSrcAwait *instruction = ir_build_instruction<IrInstSrcAwait>(irb, scope, source_node);
instruction->frame = frame;
instruction->result_loc = result_loc;
+ instruction->is_noasync = is_noasync;
ir_ref_instruction(frame, irb->current_basic_block);
@@ -4968,13 +4840,14 @@ static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *s
}
static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction,
- IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc)
+ IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_noasync)
{
IrInstGenAwait *instruction = ir_build_inst_gen<IrInstGenAwait>(&ira->new_irb,
source_instruction->scope, source_instruction->source_node);
instruction->base.value->type = result_type;
instruction->frame = frame;
instruction->result_loc = result_loc;
+ instruction->is_noasync = is_noasync;
ir_ref_inst_gen(frame, ira->new_irb.current_basic_block);
if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
@@ -6595,31 +6468,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
- case BuiltinFnIdFromBytes:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_inst_src)
- return arg1_value;
-
- IrInstSrc *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc);
- return ir_lval_wrap(irb, scope, result, lval, result_loc);
- }
- case BuiltinFnIdToBytes:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- IrInstSrc *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc);
- return ir_lval_wrap(irb, scope, result, lval, result_loc);
- }
case BuiltinFnIdIntToFloat:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -6680,21 +6528,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
IrInstSrc *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, result, lval, result_loc);
}
- case BuiltinFnIdIntType:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_inst_src)
- return arg1_value;
-
- IrInstSrc *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, int_type, lval, result_loc);
- }
case BuiltinFnIdVectorType:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -6792,48 +6625,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
IrInstSrc *ir_memset = ir_build_memset_src(irb, scope, node, arg0_value, arg1_value, arg2_value);
return ir_lval_wrap(irb, scope, ir_memset, lval, result_loc);
}
- case BuiltinFnIdMemberCount:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- IrInstSrc *member_count = ir_build_member_count(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, member_count, lval, result_loc);
- }
- case BuiltinFnIdMemberType:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_inst_src)
- return arg1_value;
-
-
- IrInstSrc *member_type = ir_build_member_type(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_type, lval, result_loc);
- }
- case BuiltinFnIdMemberName:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_inst_src)
- return arg1_value;
-
-
- IrInstSrc *member_name = ir_build_member_name(irb, scope, node, arg0_value, arg1_value);
- return ir_lval_wrap(irb, scope, member_name, lval, result_loc);
- }
case BuiltinFnIdField:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -7158,16 +6949,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
}
case BuiltinFnIdAsyncCall:
return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);
- case BuiltinFnIdTypeId:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- IrInstSrc *type_id = ir_build_type_id(irb, scope, node, arg0_value);
- return ir_lval_wrap(irb, scope, type_id, lval, result_loc);
- }
case BuiltinFnIdShlExact:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -7243,21 +7024,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
IrInstSrc *set_align_stack = ir_build_set_align_stack(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, set_align_stack, lval, result_loc);
}
- case BuiltinFnIdArgType:
- {
- AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
- IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope);
- if (arg0_value == irb->codegen->invalid_inst_src)
- return arg0_value;
-
- AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
- IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope);
- if (arg1_value == irb->codegen->invalid_inst_src)
- return arg1_value;
-
- IrInstSrc *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false);
- return ir_lval_wrap(irb, scope, arg_type, lval, result_loc);
- }
case BuiltinFnIdExport:
{
// Cast the options parameter to the options type
@@ -8073,9 +7839,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
if (var_symbol) {
IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, &spill_scope->base, symbol_node,
err_val_ptr, false, false);
- IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?
- ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr;
- ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, var_ptr);
+ IrInstSrc *var_value = node->data.while_expr.var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr);
+ build_decl_var_and_init(irb, payload_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime);
}
ZigList<IrInstSrc *> incoming_values = {0};
@@ -8123,7 +7889,8 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
true, false, false, is_comptime);
Scope *err_scope = err_var->child_scope;
IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, err_symbol_node, err_val_ptr);
- ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, err_ptr);
+ IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, err_symbol_node, err_ptr);
+ build_decl_var_and_init(irb, err_scope, err_symbol_node, err_var, err_value, buf_ptr(err_symbol), is_comptime);
if (peer_parent->peers.length != 0) {
peer_parent->peers.last()->next_bb = else_block;
@@ -8184,9 +7951,9 @@ static IrInstSrc *ir_gen_while_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
ir_set_cursor_at_end_and_append_block(irb, body_block);
IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, &spill_scope->base, symbol_node, maybe_val_ptr, false, false);
- IrInstSrc *var_ptr = node->data.while_expr.var_is_ptr ?
- ir_build_ref_src(irb, &spill_scope->base, symbol_node, payload_ptr, true, false) : payload_ptr;
- ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, var_ptr);
+ IrInstSrc *var_value = node->data.while_expr.var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, symbol_node, payload_ptr);
+ build_decl_var_and_init(irb, child_scope, symbol_node, payload_var, var_value, buf_ptr(var_symbol), is_comptime);
ZigList<IrInstSrc *> incoming_values = {0};
ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
@@ -8425,9 +8192,9 @@ static IrInstSrc *ir_gen_for_expr(IrBuilderSrc *irb, Scope *parent_scope, AstNod
ZigVar *elem_var = ir_create_var(irb, elem_node, parent_scope, elem_var_name, true, false, false, is_comptime);
Scope *child_scope = elem_var->child_scope;
- IrInstSrc *var_ptr = node->data.for_expr.elem_is_ptr ?
- ir_build_ref_src(irb, &spill_scope->base, elem_node, elem_ptr, true, false) : elem_ptr;
- ir_build_var_decl_src(irb, parent_scope, elem_node, elem_var, nullptr, var_ptr);
+ IrInstSrc *elem_value = node->data.for_expr.elem_is_ptr ?
+ elem_ptr : ir_build_load_ptr(irb, &spill_scope->base, elem_node, elem_ptr);
+ build_decl_var_and_init(irb, parent_scope, elem_node, elem_var, elem_value, buf_ptr(elem_var_name), is_comptime);
ZigList<IrInstSrc *> incoming_values = {0};
ZigList<IrBasicBlockSrc *> incoming_blocks = {0};
@@ -8847,8 +8614,9 @@ static IrInstSrc *ir_gen_if_optional_expr(IrBuilderSrc *irb, Scope *scope, AstNo
var_symbol, is_const, is_const, is_shadowable, is_comptime);
IrInstSrc *payload_ptr = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false, false);
- IrInstSrc *var_ptr = var_is_ptr ? ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
- ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
+ IrInstSrc *var_value = var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, &spill_scope->base, node, payload_ptr);
+ build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), is_comptime);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -8929,9 +8697,9 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n
var_symbol, var_is_const, var_is_const, is_shadowable, var_is_comptime);
IrInstSrc *payload_ptr = ir_build_unwrap_err_payload_src(irb, subexpr_scope, node, err_val_ptr, false, false);
- IrInstSrc *var_ptr = var_is_ptr ?
- ir_build_ref_src(irb, subexpr_scope, node, payload_ptr, true, false) : payload_ptr;
- ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, var_ptr);
+ IrInstSrc *var_value = var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, subexpr_scope, node, payload_ptr);
+ build_decl_var_and_init(irb, subexpr_scope, node, var, var_value, buf_ptr(var_symbol), var_is_comptime);
var_scope = var->child_scope;
} else {
var_scope = subexpr_scope;
@@ -8956,7 +8724,8 @@ static IrInstSrc *ir_gen_if_err_expr(IrBuilderSrc *irb, Scope *scope, AstNode *n
err_symbol, is_const, is_const, is_shadowable, is_comptime);
IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, subexpr_scope, node, err_val_ptr);
- ir_build_var_decl_src(irb, subexpr_scope, node, var, nullptr, err_ptr);
+ IrInstSrc *err_value = ir_build_load_ptr(irb, subexpr_scope, node, err_ptr);
+ build_decl_var_and_init(irb, subexpr_scope, node, var, err_value, buf_ptr(err_symbol), is_comptime);
err_var_scope = var->child_scope;
} else {
err_var_scope = subexpr_scope;
@@ -9006,22 +8775,24 @@ static bool ir_gen_switch_prong_expr(IrBuilderSrc *irb, Scope *scope, AstNode *s
ZigVar *var = ir_create_var(irb, var_symbol_node, scope,
var_name, is_const, is_const, is_shadowable, var_is_comptime);
child_scope = var->child_scope;
- IrInstSrc *var_ptr;
+ IrInstSrc *var_value;
if (out_switch_else_var != nullptr) {
IrInstSrcSwitchElseVar *switch_else_var = ir_build_switch_else_var(irb, scope, var_symbol_node,
target_value_ptr);
*out_switch_else_var = switch_else_var;
IrInstSrc *payload_ptr = &switch_else_var->base;
- var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
+ var_value = var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr);
} else if (prong_values != nullptr) {
IrInstSrc *payload_ptr = ir_build_switch_var(irb, scope, var_symbol_node, target_value_ptr,
prong_values, prong_values_len);
- var_ptr = var_is_ptr ? ir_build_ref_src(irb, scope, var_symbol_node, payload_ptr, true, false) : payload_ptr;
+ var_value = var_is_ptr ?
+ payload_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, payload_ptr);
} else {
- var_ptr = var_is_ptr ?
- ir_build_ref_src(irb, scope, var_symbol_node, target_value_ptr, true, false) : target_value_ptr;
+ var_value = var_is_ptr ?
+ target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
}
- ir_build_var_decl_src(irb, scope, var_symbol_node, var, nullptr, var_ptr);
+ build_decl_var_and_init(irb, scope, var_symbol_node, var, var_value, buf_ptr(var_name), var_is_comptime);
} else {
child_scope = scope;
}
@@ -9594,7 +9365,8 @@ static IrInstSrc *ir_gen_catch(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
is_const, is_const, is_shadowable, is_comptime);
err_scope = var->child_scope;
IrInstSrc *err_ptr = ir_build_unwrap_err_code_src(irb, err_scope, node, err_union_ptr);
- ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, err_ptr);
+ IrInstSrc *err_value = ir_build_load_ptr(irb, err_scope, var_node, err_ptr);
+ build_decl_var_and_init(irb, err_scope, var_node, var, err_value, buf_ptr(var_name), is_comptime);
} else {
err_scope = subexpr_scope;
}
@@ -9914,6 +9686,8 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
{
assert(node->type == NodeTypeAwaitExpr);
+ bool is_noasync = node->data.await_expr.noasync_token != nullptr;
+
AstNode *expr_node = node->data.await_expr.expr;
if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr;
@@ -9946,7 +9720,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
if (target_inst == irb->codegen->invalid_inst_src)
return irb->codegen->invalid_inst_src;
- IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc);
+ IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_noasync);
return ir_lval_wrap(irb, scope, await_inst, lval, result_loc);
}
@@ -12703,12 +12477,14 @@ static IrInstGen *ir_const(IrAnalyze *ira, IrInst *inst, ZigType *ty) {
IrInstGen *new_instruction = &const_instruction->base;
new_instruction->value->type = ty;
new_instruction->value->special = ConstValSpecialStatic;
+ ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
return new_instruction;
}
static IrInstGen *ir_const_noval(IrAnalyze *ira, IrInst *old_instruction) {
IrInstGenConst *const_instruction = ir_create_inst_noval<IrInstGenConst>(&ira->new_irb,
old_instruction->scope, old_instruction->source_node);
+ ira->new_irb.constants.append(&heap::c_allocator, const_instruction);
return &const_instruction->base;
}
@@ -20599,12 +20375,12 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
if (type_is_invalid(array_ptr->value->type))
return ira->codegen->invalid_inst_gen;
- ZigValue *orig_array_ptr_val = array_ptr->value;
-
IrInstGen *elem_index = elem_ptr_instruction->elem_index->child;
if (type_is_invalid(elem_index->value->type))
return ira->codegen->invalid_inst_gen;
+ ZigValue *orig_array_ptr_val = array_ptr->value;
+
ZigType *ptr_type = orig_array_ptr_val->type;
assert(ptr_type->id == ZigTypeIdPointer);
@@ -20614,23 +20390,25 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
// We will adjust return_type's alignment before returning it.
ZigType *return_type;
- if (type_is_invalid(array_type)) {
+ if (type_is_invalid(array_type))
return ira->codegen->invalid_inst_gen;
- } else if (array_type->id == ZigTypeIdArray ||
- (array_type->id == ZigTypeIdPointer &&
- array_type->data.pointer.ptr_len == PtrLenSingle &&
- array_type->data.pointer.child_type->id == ZigTypeIdArray))
+
+ if (array_type->id == ZigTypeIdPointer &&
+ array_type->data.pointer.ptr_len == PtrLenSingle &&
+ array_type->data.pointer.child_type->id == ZigTypeIdArray)
{
- if (array_type->id == ZigTypeIdPointer) {
- array_type = array_type->data.pointer.child_type;
- ptr_type = ptr_type->data.pointer.child_type;
- if (orig_array_ptr_val->special != ConstValSpecialRuntime) {
- orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
- elem_ptr_instruction->base.base.source_node);
- if (orig_array_ptr_val == nullptr)
- return ira->codegen->invalid_inst_gen;
- }
- }
+ IrInstGen *ptr_value = ir_get_deref(ira, &elem_ptr_instruction->base.base,
+ array_ptr, nullptr);
+ if (type_is_invalid(ptr_value->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ array_type = array_type->data.pointer.child_type;
+ ptr_type = ptr_type->data.pointer.child_type;
+
+ orig_array_ptr_val = ptr_value->value;
+ }
+
+ if (array_type->id == ZigTypeIdArray) {
if (array_type->data.array.len == 0) {
ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
buf_sprintf("index 0 outside array of size 0"));
@@ -20768,8 +20546,14 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
orig_array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
(orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar || array_type->id == ZigTypeIdArray))
{
+ if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
+ elem_ptr_instruction->base.base.source_node, orig_array_ptr_val, UndefBad)))
+ {
+ return ira->codegen->invalid_inst_gen;
+ }
+
ZigValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
- elem_ptr_instruction->base.base.source_node);
+ elem_ptr_instruction->base.base.source_node);
if (array_ptr_val == nullptr)
return ira->codegen->invalid_inst_gen;
@@ -21178,6 +20962,13 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins
return ira->codegen->invalid_inst_gen;
if (type_is_invalid(struct_val->type))
return ira->codegen->invalid_inst_gen;
+
+ // This to allow lazy values to be resolved.
+ if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
+ source_instr->source_node, struct_val, UndefOk)))
+ {
+ return ira->codegen->invalid_inst_gen;
+ }
if (initializing && struct_val->special == ConstValSpecialUndef) {
struct_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, struct_type->data.structure.src_field_count);
struct_val->special = ConstValSpecialStatic;
@@ -23583,7 +23374,7 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
}
static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigValue *out_val,
- ScopeDecls *decls_scope)
+ ScopeDecls *decls_scope, bool resolve_types)
{
Error err;
ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr);
@@ -23594,6 +23385,24 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
ensure_field_index(type_info_declaration_type, "is_pub", 1);
ensure_field_index(type_info_declaration_type, "data", 2);
+ if (!resolve_types) {
+ ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, type_info_declaration_type,
+ false, false, PtrLenUnknown, 0, 0, 0, false);
+
+ out_val->special = ConstValSpecialLazy;
+ out_val->type = get_slice_type(ira->codegen, ptr_type);
+
+ LazyValueTypeInfoDecls *lazy_type_info_decls = heap::c_allocator.create<LazyValueTypeInfoDecls>();
+ lazy_type_info_decls->ira = ira; ira_ref(ira);
+ out_val->data.x_lazy = &lazy_type_info_decls->base;
+ lazy_type_info_decls->base.id = LazyValueIdTypeInfoDecls;
+
+ lazy_type_info_decls->source_instr = source_instr;
+ lazy_type_info_decls->decls_scope = decls_scope;
+
+ return ErrorNone;
+ }
+
ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type);
if ((err = type_resolve(ira->codegen, type_info_declaration_data_type, ResolveStatusSizeKnown)))
return err;
@@ -23606,14 +23415,13 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
if ((err = type_resolve(ira->codegen, type_info_fn_decl_inline_type, ResolveStatusSizeKnown)))
return err;
- // Loop through our declarations once to figure out how many declarations we will generate info for.
+ // The unresolved declarations are collected in a separate queue to avoid
+ // modifying decl_table while iterating over it
+ ZigList<Tld*> resolve_decl_queue{};
+
auto decl_it = decls_scope->decl_table.entry_iterator();
decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
- int declaration_count = 0;
-
while ((curr_entry = decl_it.next()) != nullptr) {
- // If the declaration is unresolved, force it to be resolved again.
- resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false);
if (curr_entry->value->resolution == TldResolutionInvalid) {
return ErrorSemanticAnalyzeFail;
}
@@ -23623,16 +23431,36 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInst* source_instr, ZigVa
return ErrorSemanticAnalyzeFail;
}
+ // If the declaration is unresolved, force it to be resolved again.
+ if (curr_entry->value->resolution == TldResolutionUnresolved)
+ resolve_decl_queue.append(curr_entry->value);
+ }
+
+ for (size_t i = 0; i < resolve_decl_queue.length; i++) {
+ Tld *decl = resolve_decl_queue.at(i);
+ resolve_top_level_decl(ira->codegen, decl, decl->source_node, false);
+ if (decl->resolution == TldResolutionInvalid) {
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ resolve_decl_queue.deinit();
+
+ // Loop through our declarations once to figure out how many declarations we will generate info for.
+ int declaration_count = 0;
+ decl_it = decls_scope->decl_table.entry_iterator();
+ while ((curr_entry = decl_it.next()) != nullptr) {
// Skip comptime blocks and test functions.
- if (curr_entry->value->id != TldIdCompTime) {
- if (curr_entry->value->id == TldIdFn) {
- ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
- if (fn_entry->is_test)
- continue;
- }
+ if (curr_entry->value->id == TldIdCompTime)
+ continue;
- declaration_count += 1;
+ if (curr_entry->value->id == TldIdFn) {
+ ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
+ if (fn_entry->is_test)
+ continue;
}
+
+ declaration_count += 1;
}
ZigValue *declaration_array = ira->codegen->pass1_arena->create<ZigValue>();
@@ -24146,7 +23974,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
// decls: []TypeInfo.Declaration
ensure_field_index(result->type, "decls", 3);
if ((err = ir_make_type_info_decls(ira, source_instr, fields[3],
- type_entry->data.enumeration.decls_scope)))
+ type_entry->data.enumeration.decls_scope, false)))
{
return err;
}
@@ -24318,7 +24146,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
// decls: []TypeInfo.Declaration
ensure_field_index(result->type, "decls", 3);
if ((err = ir_make_type_info_decls(ira, source_instr, fields[3],
- type_entry->data.unionation.decls_scope)))
+ type_entry->data.unionation.decls_scope, false)))
{
return err;
}
@@ -24410,7 +24238,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
// decls: []TypeInfo.Declaration
ensure_field_index(result->type, "decls", 2);
if ((err = ir_make_type_info_decls(ira, source_instr, fields[2],
- type_entry->data.structure.decls_scope)))
+ type_entry->data.structure.decls_scope, false)))
{
return err;
}
@@ -24784,19 +24612,6 @@ static IrInstGen *ir_analyze_instruction_type(IrAnalyze *ira, IrInstSrcType *ins
return ir_const_type(ira, &instruction->base.base, type);
}
-static IrInstGen *ir_analyze_instruction_type_id(IrAnalyze *ira, IrInstSrcTypeId *instruction) {
- IrInstGen *type_value = instruction->type_value->child;
- ZigType *type_entry = ir_resolve_type(ira, type_value);
- if (type_is_invalid(type_entry))
- return ira->codegen->invalid_inst_gen;
-
- ZigType *result_type = get_builtin_type(ira->codegen, "TypeId");
-
- IrInstGen *result = ir_const(ira, &instruction->base.base, result_type);
- bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry));
- return result;
-}
-
static IrInstGen *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
IrInstSrcSetEvalBranchQuota *instruction)
{
@@ -25394,171 +25209,6 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE
return ir_analyze_err_set_cast(ira, &instruction->base.base, target, dest_type);
}
-static IrInstGen *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstSrcFromBytes *instruction) {
- Error err;
-
- ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->child);
- if (type_is_invalid(dest_child_type))
- return ira->codegen->invalid_inst_gen;
-
- IrInstGen *target = instruction->target->child;
- if (type_is_invalid(target->value->type))
- return ira->codegen->invalid_inst_gen;
-
- bool src_ptr_const;
- bool src_ptr_volatile;
- uint32_t src_ptr_align;
- if (target->value->type->id == ZigTypeIdPointer) {
- src_ptr_const = target->value->type->data.pointer.is_const;
- src_ptr_volatile = target->value->type->data.pointer.is_volatile;
-
- if ((err = resolve_ptr_align(ira, target->value->type, &src_ptr_align)))
- return ira->codegen->invalid_inst_gen;
- } else if (is_slice(target->value->type)) {
- ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry;
- src_ptr_const = src_ptr_type->data.pointer.is_const;
- src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
-
- if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align)))
- return ira->codegen->invalid_inst_gen;
- } else {
- src_ptr_const = true;
- src_ptr_volatile = false;
-
- if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusAlignmentKnown)))
- return ira->codegen->invalid_inst_gen;
-
- src_ptr_align = get_abi_alignment(ira->codegen, target->value->type);
- }
-
- if (src_ptr_align != 0) {
- if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusAlignmentKnown)))
- return ira->codegen->invalid_inst_gen;
- }
-
- ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
- src_ptr_const, src_ptr_volatile, PtrLenUnknown,
- src_ptr_align, 0, 0, false);
- ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
-
- ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
- src_ptr_const, src_ptr_volatile, PtrLenUnknown,
- src_ptr_align, 0, 0, false);
- ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
-
- IrInstGen *casted_value = ir_implicit_cast2(ira, &instruction->target->base, target, u8_slice);
- if (type_is_invalid(casted_value->value->type))
- return ira->codegen->invalid_inst_gen;
-
- bool have_known_len = false;
- uint64_t known_len;
-
- if (instr_is_comptime(casted_value)) {
- ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad);
- if (!val)
- return ira->codegen->invalid_inst_gen;
-
- ZigValue *len_val = val->data.x_struct.fields[slice_len_index];
- if (value_is_comptime(len_val)) {
- known_len = bigint_as_u64(&len_val->data.x_bigint);
- have_known_len = true;
- }
- }
-
- IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
- dest_slice_type, nullptr, true, true);
- if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) {
- return result_loc;
- }
-
- if (target->value->type->id == ZigTypeIdPointer &&
- target->value->type->data.pointer.ptr_len == PtrLenSingle &&
- target->value->type->data.pointer.child_type->id == ZigTypeIdArray)
- {
- known_len = target->value->type->data.pointer.child_type->data.array.len;
- have_known_len = true;
- } else if (casted_value->value->data.rh_slice.id == RuntimeHintSliceIdLen) {
- known_len = casted_value->value->data.rh_slice.len;
- have_known_len = true;
- }
-
- if (have_known_len) {
- if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_inst_gen;
- uint64_t child_type_size = type_size(ira->codegen, dest_child_type);
- uint64_t remainder = known_len % child_type_size;
- if (remainder != 0) {
- ErrorMsg *msg = ir_add_error(ira, &instruction->base.base,
- buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch",
- known_len, buf_ptr(&dest_slice_type->name)));
- add_error_note(ira->codegen, msg, instruction->dest_child_type->base.source_node,
- buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64,
- buf_ptr(&dest_child_type->name), child_type_size, remainder));
- return ira->codegen->invalid_inst_gen;
- }
- }
-
- return ir_build_resize_slice(ira, &instruction->base.base, casted_value, dest_slice_type, result_loc);
-}
-
-static IrInstGen *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstSrcToBytes *instruction) {
- Error err;
-
- IrInstGen *target = instruction->target->child;
- if (type_is_invalid(target->value->type))
- return ira->codegen->invalid_inst_gen;
-
- if (!is_slice(target->value->type)) {
- ir_add_error(ira, &instruction->target->base,
- buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value->type->name)));
- return ira->codegen->invalid_inst_gen;
- }
-
- ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry;
-
- uint32_t alignment;
- if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment)))
- return ira->codegen->invalid_inst_gen;
-
- ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
- src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
- alignment, 0, 0, false);
- ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
-
- if (instr_is_comptime(target)) {
- ZigValue *target_val = ir_resolve_const(ira, target, UndefBad);
- if (target_val == nullptr)
- return ira->codegen->invalid_inst_gen;
-
- IrInstGen *result = ir_const(ira, &instruction->base.base, dest_slice_type);
- result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
-
- ZigValue *ptr_val = result->value->data.x_struct.fields[slice_ptr_index];
- ZigValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index];
- copy_const_val(ira->codegen, ptr_val, target_ptr_val);
- ptr_val->type = dest_ptr_type;
-
- ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index];
- len_val->special = ConstValSpecialStatic;
- len_val->type = ira->codegen->builtin_types.entry_usize;
- ZigValue *target_len_val = target_val->data.x_struct.fields[slice_len_index];
- ZigType *elem_type = src_ptr_type->data.pointer.child_type;
- BigInt elem_size_bigint;
- bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type));
- bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint);
-
- return result;
- }
-
- IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
- dest_slice_type, nullptr, true, true);
- if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
- return result_loc;
- }
-
- return ir_build_resize_slice(ira, &instruction->base.base, target, dest_slice_type, result_loc);
-}
-
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
Error err;
@@ -25672,20 +25322,6 @@ static IrInstGen *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstSrcBo
return ir_resolve_cast(ira, &instruction->base.base, target, u1_type, CastOpBoolToInt);
}
-static IrInstGen *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstSrcIntType *instruction) {
- IrInstGen *is_signed_value = instruction->is_signed->child;
- bool is_signed;
- if (!ir_resolve_bool(ira, is_signed_value, &is_signed))
- return ira->codegen->invalid_inst_gen;
-
- IrInstGen *bit_count_value = instruction->bit_count->child;
- uint64_t bit_count;
- if (!ir_resolve_unsigned(ira, bit_count_value, ira->codegen->builtin_types.entry_u16, &bit_count))
- return ira->codegen->invalid_inst_gen;
-
- return ir_const_type(ira, &instruction->base.base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
-}
-
static IrInstGen *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstSrcVectorType *instruction) {
uint64_t len;
if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
@@ -26582,148 +26218,21 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
return_type, nullptr, true, true);
- if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
- return result_loc;
- }
- return ir_build_slice_gen(ira, &instruction->base.base, return_type,
- ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc);
-}
-
-static IrInstGen *ir_analyze_instruction_member_count(IrAnalyze *ira, IrInstSrcMemberCount *instruction) {
- Error err;
- IrInstGen *container = instruction->container->child;
- if (type_is_invalid(container->value->type))
- return ira->codegen->invalid_inst_gen;
- ZigType *container_type = ir_resolve_type(ira, container);
-
- if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_inst_gen;
-
- uint64_t result;
- if (type_is_invalid(container_type)) {
- return ira->codegen->invalid_inst_gen;
- } else if (container_type->id == ZigTypeIdEnum) {
- result = container_type->data.enumeration.src_field_count;
- } else if (container_type->id == ZigTypeIdStruct) {
- result = container_type->data.structure.src_field_count;
- } else if (container_type->id == ZigTypeIdUnion) {
- result = container_type->data.unionation.src_field_count;
- } else if (container_type->id == ZigTypeIdErrorSet) {
- if (!resolve_inferred_error_set(ira->codegen, container_type, instruction->base.base.source_node)) {
- return ira->codegen->invalid_inst_gen;
- }
- if (type_is_global_error_set(container_type)) {
- ir_add_error(ira, &instruction->base.base, buf_sprintf("global error set member count not available at comptime"));
- return ira->codegen->invalid_inst_gen;
- }
- result = container_type->data.error_set.err_count;
- } else {
- ir_add_error(ira, &instruction->base.base, buf_sprintf("no value count available for type '%s'", buf_ptr(&container_type->name)));
- return ira->codegen->invalid_inst_gen;
- }
-
- return ir_const_unsigned(ira, &instruction->base.base, result);
-}
-
-static IrInstGen *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstSrcMemberType *instruction) {
- Error err;
- IrInstGen *container_type_value = instruction->container_type->child;
- ZigType *container_type = ir_resolve_type(ira, container_type_value);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_inst_gen;
-
- if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_inst_gen;
-
-
- uint64_t member_index;
- IrInstGen *index_value = instruction->member_index->child;
- if (!ir_resolve_usize(ira, index_value, &member_index))
- return ira->codegen->invalid_inst_gen;
- if (container_type->id == ZigTypeIdStruct) {
- if (member_index >= container_type->data.structure.src_field_count) {
- ir_add_error(ira, &index_value->base,
- buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
- member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
- return ira->codegen->invalid_inst_gen;
+ if (result_loc != nullptr) {
+ if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
+ return result_loc;
}
- TypeStructField *field = container_type->data.structure.fields[member_index];
-
- return ir_const_type(ira, &instruction->base.base, field->type_entry);
- } else if (container_type->id == ZigTypeIdUnion) {
- if (member_index >= container_type->data.unionation.src_field_count) {
- ir_add_error(ira, &index_value->base,
- buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
- member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
+ IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
+ dummy_value->value->special = ConstValSpecialRuntime;
+ IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
+ dummy_value, result_loc->value->type->data.pointer.child_type);
+ if (type_is_invalid(dummy_result->value->type))
return ira->codegen->invalid_inst_gen;
- }
- TypeUnionField *field = &container_type->data.unionation.fields[member_index];
-
- return ir_const_type(ira, &instruction->base.base, field->type_entry);
- } else {
- ir_add_error(ira, &container_type_value->base,
- buf_sprintf("type '%s' does not support @memberType", buf_ptr(&container_type->name)));
- return ira->codegen->invalid_inst_gen;
}
-}
-
-static IrInstGen *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstSrcMemberName *instruction) {
- Error err;
- IrInstGen *container_type_value = instruction->container_type->child;
- ZigType *container_type = ir_resolve_type(ira, container_type_value);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_inst_gen;
- if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_inst_gen;
-
- uint64_t member_index;
- IrInstGen *index_value = instruction->member_index->child;
- if (!ir_resolve_usize(ira, index_value, &member_index))
- return ira->codegen->invalid_inst_gen;
-
- if (container_type->id == ZigTypeIdStruct) {
- if (member_index >= container_type->data.structure.src_field_count) {
- ir_add_error(ira, &index_value->base,
- buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
- member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
- return ira->codegen->invalid_inst_gen;
- }
- TypeStructField *field = container_type->data.structure.fields[member_index];
-
- IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
- init_const_str_lit(ira->codegen, result->value, field->name);
- return result;
- } else if (container_type->id == ZigTypeIdEnum) {
- if (member_index >= container_type->data.enumeration.src_field_count) {
- ir_add_error(ira, &index_value->base,
- buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
- member_index, buf_ptr(&container_type->name), container_type->data.enumeration.src_field_count));
- return ira->codegen->invalid_inst_gen;
- }
- TypeEnumField *field = &container_type->data.enumeration.fields[member_index];
-
- IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
- init_const_str_lit(ira->codegen, result->value, field->name);
- return result;
- } else if (container_type->id == ZigTypeIdUnion) {
- if (member_index >= container_type->data.unionation.src_field_count) {
- ir_add_error(ira, &index_value->base,
- buf_sprintf("member index %" ZIG_PRI_u64 " out of bounds; '%s' has %" PRIu32 " members",
- member_index, buf_ptr(&container_type->name), container_type->data.unionation.src_field_count));
- return ira->codegen->invalid_inst_gen;
- }
- TypeUnionField *field = &container_type->data.unionation.fields[member_index];
-
- IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
- init_const_str_lit(ira->codegen, result->value, field->name);
- return result;
- } else {
- ir_add_error(ira, &container_type_value->base,
- buf_sprintf("type '%s' does not support @memberName", buf_ptr(&container_type->name)));
- return ira->codegen->invalid_inst_gen;
- }
+ return ir_build_slice_gen(ira, &instruction->base.base, return_type,
+ ptr_ptr, casted_start, end, instruction->safety_check_on, result_loc);
}
static IrInstGen *ir_analyze_instruction_has_field(IrAnalyze *ira, IrInstSrcHasField *instruction) {
@@ -29466,7 +28975,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i
ir_assert(fn_entry != nullptr, &instruction->base.base);
// If it's not @Frame(func) then it's definitely a suspend point
- if (target_fn == nullptr) {
+ if (target_fn == nullptr && !instruction->is_noasync) {
if (fn_entry->inferred_async_node == nullptr) {
fn_entry->inferred_async_node = instruction->base.base.source_node;
}
@@ -29489,7 +28998,8 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i
result_loc = nullptr;
}
- IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc);
+ IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc,
+ instruction->is_noasync);
result->target_fn = target_fn;
fn_entry->await_list.append(result);
return ir_finish_anal(ira, &result->base);
@@ -29677,18 +29187,12 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_float_cast(ira, (IrInstSrcFloatCast *)instruction);
case IrInstSrcIdErrSetCast:
return ir_analyze_instruction_err_set_cast(ira, (IrInstSrcErrSetCast *)instruction);
- case IrInstSrcIdFromBytes:
- return ir_analyze_instruction_from_bytes(ira, (IrInstSrcFromBytes *)instruction);
- case IrInstSrcIdToBytes:
- return ir_analyze_instruction_to_bytes(ira, (IrInstSrcToBytes *)instruction);
case IrInstSrcIdIntToFloat:
return ir_analyze_instruction_int_to_float(ira, (IrInstSrcIntToFloat *)instruction);
case IrInstSrcIdFloatToInt:
return ir_analyze_instruction_float_to_int(ira, (IrInstSrcFloatToInt *)instruction);
case IrInstSrcIdBoolToInt:
return ir_analyze_instruction_bool_to_int(ira, (IrInstSrcBoolToInt *)instruction);
- case IrInstSrcIdIntType:
- return ir_analyze_instruction_int_type(ira, (IrInstSrcIntType *)instruction);
case IrInstSrcIdVectorType:
return ir_analyze_instruction_vector_type(ira, (IrInstSrcVectorType *)instruction);
case IrInstSrcIdShuffleVector:
@@ -29703,12 +29207,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_memcpy(ira, (IrInstSrcMemcpy *)instruction);
case IrInstSrcIdSlice:
return ir_analyze_instruction_slice(ira, (IrInstSrcSlice *)instruction);
- case IrInstSrcIdMemberCount:
- return ir_analyze_instruction_member_count(ira, (IrInstSrcMemberCount *)instruction);
- case IrInstSrcIdMemberType:
- return ir_analyze_instruction_member_type(ira, (IrInstSrcMemberType *)instruction);
- case IrInstSrcIdMemberName:
- return ir_analyze_instruction_member_name(ira, (IrInstSrcMemberName *)instruction);
case IrInstSrcIdBreakpoint:
return ir_analyze_instruction_breakpoint(ira, (IrInstSrcBreakpoint *)instruction);
case IrInstSrcIdReturnAddress:
@@ -29763,8 +29261,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
return ir_analyze_instruction_type(ira, (IrInstSrcType *)instruction);
case IrInstSrcIdHasField:
return ir_analyze_instruction_has_field(ira, (IrInstSrcHasField *) instruction);
- case IrInstSrcIdTypeId:
- return ir_analyze_instruction_type_id(ira, (IrInstSrcTypeId *)instruction);
case IrInstSrcIdSetEvalBranchQuota:
return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction);
case IrInstSrcIdPtrType:
@@ -30007,7 +29503,6 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) {
case IrInstGenIdCmpxchg:
case IrInstGenIdAssertZero:
case IrInstGenIdAssertNonNull:
- case IrInstGenIdResizeSlice:
case IrInstGenIdPtrOfArrayToSlice:
case IrInstGenIdSlice:
case IrInstGenIdOptionalWrap:
@@ -30180,15 +29675,11 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdRef:
case IrInstSrcIdEmbedFile:
case IrInstSrcIdTruncate:
- case IrInstSrcIdIntType:
case IrInstSrcIdVectorType:
case IrInstSrcIdShuffleVector:
case IrInstSrcIdSplat:
case IrInstSrcIdBoolNot:
case IrInstSrcIdSlice:
- case IrInstSrcIdMemberCount:
- case IrInstSrcIdMemberType:
- case IrInstSrcIdMemberName:
case IrInstSrcIdAlignOf:
case IrInstSrcIdReturnAddress:
case IrInstSrcIdFrameAddress:
@@ -30215,7 +29706,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdTypeInfo:
case IrInstSrcIdType:
case IrInstSrcIdHasField:
- case IrInstSrcIdTypeId:
case IrInstSrcIdAlignCast:
case IrInstSrcIdImplicitCast:
case IrInstSrcIdResolveResult:
@@ -30233,8 +29723,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
case IrInstSrcIdIntToFloat:
case IrInstSrcIdFloatToInt:
case IrInstSrcIdBoolToInt:
- case IrInstSrcIdFromBytes:
- case IrInstSrcIdToBytes:
case IrInstSrcIdEnumToInt:
case IrInstSrcIdHasDecl:
case IrInstSrcIdAlloca:
@@ -30347,6 +29835,18 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
switch (val->data.x_lazy->id) {
case LazyValueIdInvalid:
zig_unreachable();
+ case LazyValueIdTypeInfoDecls: {
+ LazyValueTypeInfoDecls *type_info_decls = reinterpret_cast<LazyValueTypeInfoDecls *>(val->data.x_lazy);
+ IrAnalyze *ira = type_info_decls->ira;
+
+ if ((err = ir_make_type_info_decls(ira, type_info_decls->source_instr, val, type_info_decls->decls_scope, true)))
+ {
+ return err;
+ };
+
+ // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
+ return ErrorNone;
+ }
case LazyValueIdAlignOf: {
LazyValueAlignOf *lazy_align_of = reinterpret_cast<LazyValueAlignOf *>(val->data.x_lazy);
IrAnalyze *ira = lazy_align_of->ira;
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
@@ -179,8 +179,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcFloatToInt";
case IrInstSrcIdBoolToInt:
return "SrcBoolToInt";
- case IrInstSrcIdIntType:
- return "SrcIntType";
case IrInstSrcIdVectorType:
return "SrcVectorType";
case IrInstSrcIdBoolNot:
@@ -191,12 +189,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcMemcpy";
case IrInstSrcIdSlice:
return "SrcSlice";
- case IrInstSrcIdMemberCount:
- return "SrcMemberCount";
- case IrInstSrcIdMemberType:
- return "SrcMemberType";
- case IrInstSrcIdMemberName:
- return "SrcMemberName";
case IrInstSrcIdBreakpoint:
return "SrcBreakpoint";
case IrInstSrcIdReturnAddress:
@@ -269,8 +261,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcType";
case IrInstSrcIdHasField:
return "SrcHasField";
- case IrInstSrcIdTypeId:
- return "SrcTypeId";
case IrInstSrcIdSetEvalBranchQuota:
return "SrcSetEvalBranchQuota";
case IrInstSrcIdPtrType:
@@ -307,10 +297,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
return "SrcAddImplicitReturnType";
case IrInstSrcIdErrSetCast:
return "SrcErrSetCast";
- case IrInstSrcIdToBytes:
- return "SrcToBytes";
- case IrInstSrcIdFromBytes:
- return "SrcFromBytes";
case IrInstSrcIdCheckRuntimeScope:
return "SrcCheckRuntimeScope";
case IrInstSrcIdHasDecl:
@@ -383,8 +369,6 @@ const char* ir_inst_gen_type_str(IrInstGenId id) {
return "GenReturn";
case IrInstGenIdCast:
return "GenCast";
- case IrInstGenIdResizeSlice:
- return "GenResizeSlice";
case IrInstGenIdUnreachable:
return "GenUnreachable";
case IrInstGenIdAsm:
@@ -590,11 +574,6 @@ static void ir_print_const_value(CodeGen *g, FILE *f, ZigValue *const_val) {
static void ir_print_other_inst_gen(IrPrintGen *irp, IrInstGen *inst) {
if (inst == nullptr) {
fprintf(irp->f, "(null)");
- return;
- }
-
- if (inst->value->special != ConstValSpecialRuntime) {
- ir_print_const_value(irp->codegen, irp->f, inst->value);
} else {
ir_print_var_gen(irp, inst);
}
@@ -1649,20 +1628,6 @@ static void ir_print_err_set_cast(IrPrintSrc *irp, IrInstSrcErrSetCast *instruct
fprintf(irp->f, ")");
}
-static void ir_print_from_bytes(IrPrintSrc *irp, IrInstSrcFromBytes *instruction) {
- fprintf(irp->f, "@bytesToSlice(");
- ir_print_other_inst_src(irp, instruction->dest_child_type);
- fprintf(irp->f, ", ");
- ir_print_other_inst_src(irp, instruction->target);
- fprintf(irp->f, ")");
-}
-
-static void ir_print_to_bytes(IrPrintSrc *irp, IrInstSrcToBytes *instruction) {
- fprintf(irp->f, "@sliceToBytes(");
- ir_print_other_inst_src(irp, instruction->target);
- fprintf(irp->f, ")");
-}
-
static void ir_print_int_to_float(IrPrintSrc *irp, IrInstSrcIntToFloat *instruction) {
fprintf(irp->f, "@intToFloat(");
ir_print_other_inst_src(irp, instruction->dest_type);
@@ -1685,14 +1650,6 @@ static void ir_print_bool_to_int(IrPrintSrc *irp, IrInstSrcBoolToInt *instructio
fprintf(irp->f, ")");
}
-static void ir_print_int_type(IrPrintSrc *irp, IrInstSrcIntType *instruction) {
- fprintf(irp->f, "@IntType(");
- ir_print_other_inst_src(irp, instruction->is_signed);
- fprintf(irp->f, ", ");
- ir_print_other_inst_src(irp, instruction->bit_count);
- fprintf(irp->f, ")");
-}
-
static void ir_print_vector_type(IrPrintSrc *irp, IrInstSrcVectorType *instruction) {
fprintf(irp->f, "@Vector(");
ir_print_other_inst_src(irp, instruction->len);
@@ -1809,28 +1766,6 @@ static void ir_print_slice_gen(IrPrintGen *irp, IrInstGenSlice *instruction) {
ir_print_other_inst_gen(irp, instruction->result_loc);
}
-static void ir_print_member_count(IrPrintSrc *irp, IrInstSrcMemberCount *instruction) {
- fprintf(irp->f, "@memberCount(");
- ir_print_other_inst_src(irp, instruction->container);
- fprintf(irp->f, ")");
-}
-
-static void ir_print_member_type(IrPrintSrc *irp, IrInstSrcMemberType *instruction) {
- fprintf(irp->f, "@memberType(");
- ir_print_other_inst_src(irp, instruction->container_type);
- fprintf(irp->f, ", ");
- ir_print_other_inst_src(irp, instruction->member_index);
- fprintf(irp->f, ")");
-}
-
-static void ir_print_member_name(IrPrintSrc *irp, IrInstSrcMemberName *instruction) {
- fprintf(irp->f, "@memberName(");
- ir_print_other_inst_src(irp, instruction->container_type);
- fprintf(irp->f, ", ");
- ir_print_other_inst_src(irp, instruction->member_index);
- fprintf(irp->f, ")");
-}
-
static void ir_print_breakpoint(IrPrintSrc *irp, IrInstSrcBreakpoint *instruction) {
fprintf(irp->f, "@breakpoint()");
}
@@ -2147,13 +2082,6 @@ static void ir_print_assert_non_null(IrPrintGen *irp, IrInstGenAssertNonNull *in
fprintf(irp->f, ")");
}
-static void ir_print_resize_slice(IrPrintGen *irp, IrInstGenResizeSlice *instruction) {
- fprintf(irp->f, "@resizeSlice(");
- ir_print_other_inst_gen(irp, instruction->operand);
- fprintf(irp->f, ")result=");
- ir_print_other_inst_gen(irp, instruction->result_loc);
-}
-
static void ir_print_alloca_src(IrPrintSrc *irp, IrInstSrcAlloca *instruction) {
fprintf(irp->f, "Alloca(align=");
ir_print_other_inst_src(irp, instruction->align);
@@ -2311,12 +2239,6 @@ static void ir_print_has_field(IrPrintSrc *irp, IrInstSrcHasField *instruction)
fprintf(irp->f, ")");
}
-static void ir_print_type_id(IrPrintSrc *irp, IrInstSrcTypeId *instruction) {
- fprintf(irp->f, "@typeId(");
- ir_print_other_inst_src(irp, instruction->type_value);
- fprintf(irp->f, ")");
-}
-
static void ir_print_set_eval_branch_quota(IrPrintSrc *irp, IrInstSrcSetEvalBranchQuota *instruction) {
fprintf(irp->f, "@setEvalBranchQuota(");
ir_print_other_inst_src(irp, instruction->new_quota);
@@ -2798,12 +2720,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdErrSetCast:
ir_print_err_set_cast(irp, (IrInstSrcErrSetCast *)instruction);
break;
- case IrInstSrcIdFromBytes:
- ir_print_from_bytes(irp, (IrInstSrcFromBytes *)instruction);
- break;
- case IrInstSrcIdToBytes:
- ir_print_to_bytes(irp, (IrInstSrcToBytes *)instruction);
- break;
case IrInstSrcIdIntToFloat:
ir_print_int_to_float(irp, (IrInstSrcIntToFloat *)instruction);
break;
@@ -2813,9 +2729,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdBoolToInt:
ir_print_bool_to_int(irp, (IrInstSrcBoolToInt *)instruction);
break;
- case IrInstSrcIdIntType:
- ir_print_int_type(irp, (IrInstSrcIntType *)instruction);
- break;
case IrInstSrcIdVectorType:
ir_print_vector_type(irp, (IrInstSrcVectorType *)instruction);
break;
@@ -2837,15 +2750,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdSlice:
ir_print_slice_src(irp, (IrInstSrcSlice *)instruction);
break;
- case IrInstSrcIdMemberCount:
- ir_print_member_count(irp, (IrInstSrcMemberCount *)instruction);
- break;
- case IrInstSrcIdMemberType:
- ir_print_member_type(irp, (IrInstSrcMemberType *)instruction);
- break;
- case IrInstSrcIdMemberName:
- ir_print_member_name(irp, (IrInstSrcMemberName *)instruction);
- break;
case IrInstSrcIdBreakpoint:
ir_print_breakpoint(irp, (IrInstSrcBreakpoint *)instruction);
break;
@@ -2945,9 +2849,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
case IrInstSrcIdHasField:
ir_print_has_field(irp, (IrInstSrcHasField *)instruction);
break;
- case IrInstSrcIdTypeId:
- ir_print_type_id(irp, (IrInstSrcTypeId *)instruction);
- break;
case IrInstSrcIdSetEvalBranchQuota:
ir_print_set_eval_branch_quota(irp, (IrInstSrcSetEvalBranchQuota *)instruction);
break;
@@ -3278,9 +3179,6 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai
case IrInstGenIdAssertNonNull:
ir_print_assert_non_null(irp, (IrInstGenAssertNonNull *)instruction);
break;
- case IrInstGenIdResizeSlice:
- ir_print_resize_slice(irp, (IrInstGenResizeSlice *)instruction);
- break;
case IrInstGenIdAlloca:
ir_print_alloca_gen(irp, (IrInstGenAlloca *)instruction);
break;
diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp
@@ -1,498 +0,0 @@
-/*
- * Copyright (c) 2019 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#include "libc_installation.hpp"
-#include "os.hpp"
-#include "windows_sdk.h"
-#include "target.hpp"
-
-static const char *zig_libc_keys[] = {
- "include_dir",
- "sys_include_dir",
- "crt_dir",
- "static_crt_dir",
- "msvc_lib_dir",
- "kernel32_lib_dir",
-};
-
-static const size_t zig_libc_keys_len = array_length(zig_libc_keys);
-
-static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *found_keys,
- size_t index, Buf *field_ptr)
-{
- if (!memEql(name, str(zig_libc_keys[index]))) return false;
- buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len);
- found_keys[index] = true;
- return true;
-}
-
-static void zig_libc_init_empty(ZigLibCInstallation *libc) {
- *libc = {};
- buf_init_from_str(&libc->include_dir, "");
- buf_init_from_str(&libc->sys_include_dir, "");
- buf_init_from_str(&libc->crt_dir, "");
- buf_init_from_str(&libc->static_crt_dir, "");
- buf_init_from_str(&libc->msvc_lib_dir, "");
- buf_init_from_str(&libc->kernel32_lib_dir, "");
-}
-
-Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) {
- Error err;
- zig_libc_init_empty(libc);
-
- bool found_keys[array_length(zig_libc_keys)] = {};
-
- Buf *contents = buf_alloc();
- if ((err = os_fetch_file_path(libc_file, contents))) {
- if (err != ErrorFileNotFound && verbose) {
- fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
- }
- return err;
- }
-
- SplitIterator it = memSplit(buf_to_slice(contents), str("\n"));
- for (;;) {
- Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it);
- if (!opt_line.is_some)
- break;
-
- if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#')
- continue;
-
- SplitIterator line_it = memSplit(opt_line.value, str("="));
- Slice<uint8_t> name;
- if (!SplitIterator_next(&line_it).unwrap(&name)) {
- if (verbose) {
- fprintf(stderr, "missing equal sign after field name\n");
- }
- return ErrorSemanticAnalyzeFail;
- }
- Slice<uint8_t> value = SplitIterator_rest(&line_it);
- bool match = false;
- match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->static_crt_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
- match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
- }
-
- for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
- if (!found_keys[i]) {
- if (verbose) {
- fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]);
- }
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- if (buf_len(&libc->include_dir) == 0) {
- if (verbose) {
- fprintf(stderr, "include_dir may not be empty\n");
- }
- return ErrorSemanticAnalyzeFail;
- }
-
- if (buf_len(&libc->sys_include_dir) == 0) {
- if (verbose) {
- fprintf(stderr, "sys_include_dir may not be empty\n");
- }
- return ErrorSemanticAnalyzeFail;
- }
-
- if (buf_len(&libc->crt_dir) == 0) {
- if (!target_os_is_darwin(target->os)) {
- if (verbose) {
- fprintf(stderr, "crt_dir may not be empty for %s\n", target_os_name(target->os));
- }
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- if (buf_len(&libc->static_crt_dir) == 0) {
- if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
- if (verbose) {
- fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os));
- }
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- if (buf_len(&libc->msvc_lib_dir) == 0) {
- if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
- if (verbose) {
- fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", target_os_name(target->os));
- }
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- if (buf_len(&libc->kernel32_lib_dir) == 0) {
- if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
- if (verbose) {
- fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", target_os_name(target->os));
- }
- return ErrorSemanticAnalyzeFail;
- }
- }
-
- return ErrorNone;
-}
-
-#if defined(ZIG_OS_WINDOWS)
-#define CC_EXE "cc.exe"
-#else
-#define CC_EXE "cc"
-#endif
-
-static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) {
- const char *cc_exe = getenv("CC");
- cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
- ZigList<const char *> args = {};
- args.append(cc_exe);
- args.append("-E");
- args.append("-Wp,-v");
- args.append("-xc");
- #if defined(ZIG_OS_WINDOWS)
- args.append("nul");
- #else
- args.append("/dev/null");
- #endif
-
- Termination term;
- Buf *out_stderr = buf_alloc();
- Buf *out_stdout = buf_alloc();
- Error err;
- if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
- if (verbose) {
- fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
- }
- return err;
- }
- if (term.how != TerminationIdClean || term.code != 0) {
- if (verbose) {
- fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
- }
- return ErrorCCompileErrors;
- }
- char *prev_newline = buf_ptr(out_stderr);
- ZigList<const char *> search_paths = {};
- for (;;) {
- char *newline = strchr(prev_newline, '\n');
- if (newline == nullptr) {
- break;
- }
-
- #if defined(ZIG_OS_WINDOWS)
- *(newline - 1) = 0;
- #endif
- *newline = 0;
-
- if (prev_newline[0] == ' ') {
- search_paths.append(prev_newline);
- }
- prev_newline = newline + 1;
- }
- if (search_paths.length == 0) {
- if (verbose) {
- fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe);
- }
- return ErrorCCompileErrors;
- }
- for (size_t i = 0; i < search_paths.length; i += 1) {
- // search in reverse order
- const char *search_path = search_paths.items[search_paths.length - i - 1];
- // cut off spaces
- while (*search_path == ' ') {
- search_path += 1;
- }
-
- #if defined(ZIG_OS_WINDOWS)
- if (buf_len(&self->include_dir) == 0) {
- Buf *stdlib_path = buf_sprintf("%s\\stdlib.h", search_path);
- bool exists;
- if ((err = os_file_exists(stdlib_path, &exists))) {
- exists = false;
- }
- if (exists) {
- buf_init_from_str(&self->include_dir, search_path);
- }
- }
- if (buf_len(&self->sys_include_dir) == 0) {
- Buf *stdlib_path = buf_sprintf("%s\\sys\\types.h", search_path);
- bool exists;
- if ((err = os_file_exists(stdlib_path, &exists))) {
- exists = false;
- }
- if (exists) {
- buf_init_from_str(&self->sys_include_dir, search_path);
- }
- }
- #else
- if (buf_len(&self->include_dir) == 0) {
- Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
- bool exists;
- if ((err = os_file_exists(stdlib_path, &exists))) {
- exists = false;
- }
- if (exists) {
- buf_init_from_str(&self->include_dir, search_path);
- }
- }
- if (buf_len(&self->sys_include_dir) == 0) {
- Buf *stdlib_path = buf_sprintf("%s/sys/errno.h", search_path);
- bool exists;
- if ((err = os_file_exists(stdlib_path, &exists))) {
- exists = false;
- }
- if (exists) {
- buf_init_from_str(&self->sys_include_dir, search_path);
- }
- }
- #endif
-
- if (buf_len(&self->include_dir) != 0 && buf_len(&self->sys_include_dir) != 0) {
- return ErrorNone;
- }
- }
- if (verbose) {
- if (buf_len(&self->include_dir) == 0) {
- fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe);
- }
- if (buf_len(&self->sys_include_dir) == 0) {
- #if defined(ZIG_OS_WINDOWS)
- fprintf(stderr, "unable to determine libc include path: sys/types.h not found in '%s' search paths\n", cc_exe);
- #else
- fprintf(stderr, "unable to determine libc include path: sys/errno.h not found in '%s' search paths\n", cc_exe);
- #endif
- }
- }
- return ErrorFileNotFound;
-}
-
-Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) {
- const char *cc_exe = getenv("CC");
- cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
- ZigList<const char *> args = {};
- args.append(cc_exe);
- args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
- Termination term;
- Buf *out_stderr = buf_alloc();
- Buf *out_stdout = buf_alloc();
- Error err;
- if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
- if (err == ErrorFileNotFound)
- return ErrorNoCCompilerInstalled;
- if (verbose) {
- fprintf(stderr, "unable to determine libc library path: executing '%s': %s\n", cc_exe, err_str(err));
- }
- return err;
- }
- if (term.how != TerminationIdClean || term.code != 0) {
- if (verbose) {
- fprintf(stderr, "unable to determine libc library path: executing '%s' failed\n", cc_exe);
- }
- return ErrorCCompileErrors;
- }
- #if defined(ZIG_OS_WINDOWS)
- if (buf_ends_with_str(out_stdout, "\r\n")) {
- buf_resize(out_stdout, buf_len(out_stdout) - 2);
- }
- #else
- if (buf_ends_with_str(out_stdout, "\n")) {
- buf_resize(out_stdout, buf_len(out_stdout) - 1);
- }
- #endif
- if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
- return ErrorCCompilerCannotFindFile;
- }
- if (want_dirname) {
- os_path_dirname(out_stdout, out);
- } else {
- buf_init_from_buf(out, out_stdout);
- }
- return ErrorNone;
-}
-
-#undef CC_EXE
-
-#if defined(ZIG_OS_WINDOWS) || defined(ZIG_OS_LINUX) || defined(ZIG_OS_DRAGONFLY)
-static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
- return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose);
-}
-#endif
-
-#if defined(ZIG_OS_WINDOWS)
-static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
- return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose);
-}
-
-static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
- Error err;
- if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {
- if (verbose) {
- fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err));
- }
- return err;
- }
- return ErrorNone;
-}
-
-static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
- bool verbose)
-{
- Error err;
- if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch))) {
- if (verbose) {
- fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err));
- }
- return err;
- }
- return ErrorNone;
-}
-
-static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
- bool verbose)
-{
- Error err;
- if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch))) {
- if (verbose) {
- fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err));
- }
- return err;
- }
- return ErrorNone;
-}
-
-static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
- if (sdk->msvc_lib_dir_ptr == nullptr) {
- if (verbose) {
- fprintf(stderr, "Unable to determine vcruntime.lib path\n");
- }
- return ErrorFileNotFound;
- }
- buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
- return ErrorNone;
-}
-
-static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
- Error err;
- if (sdk->msvc_lib_dir_ptr == nullptr) {
- if (verbose) {
- fprintf(stderr, "Unable to determine vcruntime.h path\n");
- }
- return ErrorFileNotFound;
- }
- Buf search_path = BUF_INIT;
- buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
- buf_append_str(&search_path, "..\\..\\include");
-
- Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path));
- bool exists;
- if ((err = os_file_exists(vcruntime_path, &exists))) {
- exists = false;
- }
- if (exists) {
- self->sys_include_dir = search_path;
- return ErrorNone;
- }
-
- if (verbose) {
- fprintf(stderr, "Unable to determine vcruntime.h path\n");
- }
- return ErrorFileNotFound;
-}
-#endif
-
-void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
- fprintf(file,
- "# The directory that contains `stdlib.h`.\n"
- "# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`\n"
- "include_dir=%s\n"
- "\n"
- "# The system-specific include directory. May be the same as `include_dir`.\n"
- "# On Windows it's the directory that includes `vcruntime.h`.\n"
- "# On POSIX it's the directory that includes `sys/errno.h`.\n"
- "sys_include_dir=%s\n"
- "\n"
- "# The directory that contains `crt1.o` or `crt2.o`.\n"
- "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
- "# Not needed when targeting MacOS.\n"
- "crt_dir=%s\n"
- "\n"
- "# The directory that contains `crtbegin.o`.\n"
- "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
- "# Not needed when targeting MacOS.\n"
- "static_crt_dir=%s\n"
- "\n"
- "# The directory that contains `vcruntime.lib`.\n"
- "# Only needed when targeting MSVC on Windows.\n"
- "msvc_lib_dir=%s\n"
- "\n"
- "# The directory that contains `kernel32.lib`.\n"
- "# Only needed when targeting MSVC on Windows.\n"
- "kernel32_lib_dir=%s\n"
- "\n",
- buf_ptr(&self->include_dir),
- buf_ptr(&self->sys_include_dir),
- buf_ptr(&self->crt_dir),
- buf_ptr(&self->static_crt_dir),
- buf_ptr(&self->msvc_lib_dir),
- buf_ptr(&self->kernel32_lib_dir)
- );
-}
-
-Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
- Error err;
- zig_libc_init_empty(self);
-#if defined(ZIG_OS_WINDOWS)
- ZigTarget native_target;
- get_native_target(&native_target);
- if (target_abi_is_gnu(native_target.abi)) {
- if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
- return err;
- if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
- return err;
- if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose)))
- return err;
- return ErrorNone;
- } else {
- ZigWindowsSDK *sdk;
- switch (zig_find_windows_sdk(&sdk)) {
- case ZigFindWindowsSdkErrorNone:
- if ((err = zig_libc_find_native_msvc_include_dir(self, sdk, verbose)))
- return err;
- if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose)))
- return err;
- if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose)))
- return err;
- if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
- return err;
- if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose)))
- return err;
- return ErrorNone;
- case ZigFindWindowsSdkErrorOutOfMemory:
- return ErrorNoMem;
- case ZigFindWindowsSdkErrorNotFound:
- return ErrorFileNotFound;
- case ZigFindWindowsSdkErrorPathTooLong:
- return ErrorPathTooLong;
- }
- }
- zig_unreachable();
-#else
- if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
- return err;
-#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
- buf_init_from_str(&self->crt_dir, "/usr/lib");
-#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_DRAGONFLY)
- if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
- return err;
-#endif
- return ErrorNone;
-#endif
-}
diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2019 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#ifndef ZIG_LIBC_INSTALLATION_HPP
-#define ZIG_LIBC_INSTALLATION_HPP
-
-#include <stdio.h>
-
-#include "buffer.hpp"
-#include "error.hpp"
-#include "target.hpp"
-
-// Must be synchronized with zig_libc_keys
-struct ZigLibCInstallation {
- Buf include_dir;
- Buf sys_include_dir;
- Buf crt_dir;
- Buf static_crt_dir;
- Buf msvc_lib_dir;
- Buf kernel32_lib_dir;
-};
-
-Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file,
- const ZigTarget *target, bool verbose);
-void zig_libc_render(ZigLibCInstallation *self, FILE *file);
-
-Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
-
-Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose);
-
-#endif
diff --git a/src/link.cpp b/src/link.cpp
@@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
c_source_files.append(c_file);
child_gen->c_source_files = c_source_files;
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
}
static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) {
@@ -682,7 +682,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress
}
child_gen->c_source_files = c_source_files;
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
}
static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) {
@@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node
child_gen->c_source_files = c_source_files;
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
}
static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
@@ -1253,7 +1253,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
child_gen->c_source_files.append(c_file);
}
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
} else if (strcmp(file, "msvcrt-os.lib") == 0) {
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node);
@@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
}
}
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
} else if (strcmp(file, "mingwex.lib") == 0) {
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node);
@@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
zig_unreachable();
}
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
} else {
zig_unreachable();
}
@@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
codegen_add_object(child_gen, buf_create_from_str(start_os));
codegen_add_object(child_gen, buf_create_from_str(abi_note_o));
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
} else if (strcmp(file, "libc_nonshared.a") == 0) {
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node);
{
@@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
build_libc_object(parent, deps[i].name, c_file, progress_node)));
}
codegen_build_and_link(child_gen);
- return buf_ptr(&child_gen->output_file_path);
+ return buf_ptr(&child_gen->bin_file_output_path);
} else {
zig_unreachable();
}
@@ -1483,7 +1483,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
} else {
assert(parent->libc != nullptr);
Buf *out_buf = buf_alloc();
- os_path_join(&parent->libc->crt_dir, buf_create_from_str(file), out_buf);
+ os_path_join(buf_create_from_str(parent->libc->crt_dir), buf_create_from_str(file), out_buf);
return buf_ptr(out_buf);
}
}
@@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
child_gen->want_stack_check = WantStackCheckDisabled;
codegen_build_and_link(child_gen);
- return &child_gen->output_file_path;
+ return &child_gen->bin_file_output_path;
}
static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) {
@@ -1681,7 +1681,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
} else if (is_dyn_lib) {
lj->args.append("-shared");
- assert(buf_len(&g->output_file_path) != 0);
+ assert(buf_len(&g->bin_file_output_path) != 0);
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
}
@@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
}
lj->args.append("-o");
- lj->args.append(buf_ptr(&g->output_file_path));
+ lj->args.append(buf_ptr(&g->bin_file_output_path));
if (lj->link_in_crt) {
const char *crt1o;
@@ -1747,7 +1747,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
if (g->libc_link_lib != nullptr) {
if (g->libc != nullptr) {
lj->args.append("-L");
- lj->args.append(buf_ptr(&g->libc->crt_dir));
+ lj->args.append(g->libc->crt_dir);
}
if (g->have_dynamic_link && (is_dyn_lib || g->out_type == OutTypeExe)) {
@@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
}
lj->args.append("--allow-undefined");
lj->args.append("-o");
- lj->args.append(buf_ptr(&g->output_file_path));
+ lj->args.append(buf_ptr(&g->bin_file_output_path));
// .o files
for (size_t i = 0; i < g->link_objects.length; i += 1) {
@@ -2253,17 +2253,17 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append("-DLL");
}
- lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
+ lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path))));
if (g->libc_link_lib != nullptr && g->libc != nullptr) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir)));
if (target_abi_is_gnu(g->zig_target->abi)) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->sys_include_dir)));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->include_dir)));
} else {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->msvc_lib_dir)));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->kernel32_lib_dir)));
}
}
@@ -2506,7 +2506,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
//lj->args.append("-install_name");
//lj->args.append(buf_ptr(dylib_install_name));
- assert(buf_len(&g->output_file_path) != 0);
+ assert(buf_len(&g->bin_file_output_path) != 0);
}
lj->args.append("-arch");
@@ -2537,14 +2537,14 @@ static void construct_linker_job_macho(LinkJob *lj) {
}
lj->args.append("-o");
- lj->args.append(buf_ptr(&g->output_file_path));
+ lj->args.append(buf_ptr(&g->bin_file_output_path));
for (size_t i = 0; i < g->rpath_list.length; i += 1) {
Buf *rpath = g->rpath_list.at(i);
add_rpath(lj, rpath);
}
if (is_dyn_lib) {
- add_rpath(lj, &g->output_file_path);
+ add_rpath(lj, &g->bin_file_output_path);
}
if (is_dyn_lib) {
@@ -2664,14 +2664,14 @@ void codegen_link(CodeGen *g) {
progress_name, strlen(progress_name), 0));
}
if (g->verbose_link) {
- fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
+ fprintf(stderr, "ar rcs %s", buf_ptr(&g->bin_file_output_path));
for (size_t i = 0; i < file_names.length; i += 1) {
fprintf(stderr, " %s", file_names.at(i));
}
fprintf(stderr, "\n");
}
- 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));
+ if (ZigLLVMWriteArchive(buf_ptr(&g->bin_file_output_path), file_names.items, file_names.length, os_type)) {
+ fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path));
exit(1);
}
return;
diff --git a/src/main.cpp b/src/main.cpp
@@ -14,8 +14,7 @@
#include "heap.hpp"
#include "os.hpp"
#include "target.hpp"
-#include "libc_installation.hpp"
-#include "userland.h"
+#include "stage2.h"
#include "glibc.hpp"
#include "dump_analysis.hpp"
#include "mem_profile.hpp"
@@ -63,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -fno-stack-check disable stack probing in safe builds\n"
" -fsanitize-c enable C undefined behavior detection in unsafe builds\n"
" -fno-sanitize-c disable C undefined behavior detection in safe builds\n"
- " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
+ " --emit [asm|bin|llvm-ir] (deprecated) emit a specific file format as compilation output\n"
" -fPIC enable Position Independent Code\n"
" -fno-PIC disable Position Independent Code\n"
" -ftime-report print timing diagnostics\n"
" -fstack-report print stack size diagnostics\n"
-#ifdef ZIG_ENABLE_MEM_PROFILE
" -fmem-report print memory usage diagnostics\n"
-#endif
" -fdump-analysis write analysis.json file with type information\n"
" -femit-docs create a docs/ dir with html documentation\n"
- " -fno-emit-bin skip emitting machine code\n"
+ " -fno-emit-docs do not produce docs/ dir with html documentation\n"
+ " -femit-bin (default) output machine code\n"
+ " -fno-emit-bin do not output machine code\n"
+ " -femit-asm output .s (assembly code)\n"
+ " -fno-emit-asm (default) do not output .s (assembly code)\n"
+ " -femit-llvm-ir produce a .ll file with LLVM IR\n"
+ " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
" --libc [file] Provide a file which specifies libc paths\n"
" --name [name] override output name\n"
" --output-dir [dir] override output directory (defaults to cwd)\n"
@@ -103,8 +106,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --override-lib-dir [arg] override path to Zig lib directory\n"
" -ffunction-sections places each function in a separate section\n"
" -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n"
- " -target-cpu [cpu] target one specific CPU by name\n"
- " -target-feature [features] specify the set of CPU features to target\n"
+ " -mcpu [cpu] specify target CPU and feature set\n"
" -code-model [default|tiny| set target code model\n"
" small|kernel|\n"
" medium|large]\n"
@@ -235,6 +237,14 @@ static int zig_error_no_build_file(void) {
return EXIT_FAILURE;
}
+static bool str_starts_with(const char *s1, const char *s2) {
+ size_t s2_len = strlen(s2);
+ if (strlen(s1) < s2_len) {
+ return false;
+ }
+ return memcmp(s1, s2, s2_len) == 0;
+}
+
extern "C" int ZigClang_main(int argc, char **argv);
#ifdef ZIG_ENABLE_MEM_PROFILE
@@ -378,7 +388,6 @@ static int main0(int argc, char **argv) {
}
Cmd cmd = CmdNone;
- EmitFileType emit_file_type = EmitFileTypeBinary;
const char *in_file = nullptr;
Buf *output_dir = nullptr;
bool strip = false;
@@ -426,7 +435,9 @@ static int main0(int argc, char **argv) {
bool stack_report = false;
bool enable_dump_analysis = false;
bool enable_doc_generation = false;
- bool disable_bin_generation = false;
+ bool emit_bin = true;
+ bool emit_asm = false;
+ bool emit_llvm_ir = false;
const char *cache_dir = nullptr;
CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
BuildMode build_mode = BuildModeDebug;
@@ -444,8 +455,7 @@ static int main0(int argc, char **argv) {
WantStackCheck want_stack_check = WantStackCheckAuto;
WantCSanitize want_sanitize_c = WantCSanitizeAuto;
bool function_sections = false;
- const char *cpu = nullptr;
- const char *features = nullptr;
+ const char *mcpu = nullptr;
CodeModel code_model = CodeModelDefault;
ZigList<const char *> llvm_argv = {0};
@@ -554,7 +564,7 @@ static int main0(int argc, char **argv) {
}
Termination term;
- args.items[0] = buf_ptr(&g->output_file_path);
+ args.items[0] = buf_ptr(&g->bin_file_output_path);
os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nBuild failed. The following command failed:\n");
@@ -633,8 +643,6 @@ static int main0(int argc, char **argv) {
enable_dump_analysis = true;
} else if (strcmp(arg, "-femit-docs") == 0) {
enable_doc_generation = true;
- } else if (strcmp(arg, "-fno-emit-bin") == 0) {
- disable_bin_generation = true;
} else if (strcmp(arg, "--enable-valgrind") == 0) {
valgrind_support = ValgrindSupportEnabled;
} else if (strcmp(arg, "--disable-valgrind") == 0) {
@@ -703,6 +711,20 @@ static int main0(int argc, char **argv) {
function_sections = true;
} else if (strcmp(arg, "--test-evented-io") == 0) {
test_evented_io = true;
+ } else if (strcmp(arg, "-femit-bin") == 0) {
+ emit_bin = true;
+ } else if (strcmp(arg, "-fno-emit-bin") == 0) {
+ emit_bin = false;
+ } else if (strcmp(arg, "-femit-asm") == 0) {
+ emit_asm = true;
+ } else if (strcmp(arg, "-fno-emit-asm") == 0) {
+ emit_asm = false;
+ } else if (strcmp(arg, "-femit-llvm-ir") == 0) {
+ emit_llvm_ir = true;
+ } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
+ emit_llvm_ir = false;
+ } else if (str_starts_with(arg, "-mcpu=")) {
+ mcpu = arg + strlen("-mcpu=");
} else if (i + 1 >= argc) {
fprintf(stderr, "Expected another argument after %s\n", arg);
return print_error_usage(arg0);
@@ -734,11 +756,13 @@ static int main0(int argc, char **argv) {
}
} else if (strcmp(arg, "--emit") == 0) {
if (strcmp(argv[i], "asm") == 0) {
- emit_file_type = EmitFileTypeAssembly;
+ emit_asm = true;
+ emit_bin = false;
} else if (strcmp(argv[i], "bin") == 0) {
- emit_file_type = EmitFileTypeBinary;
+ emit_bin = true;
} else if (strcmp(argv[i], "llvm-ir") == 0) {
- emit_file_type = EmitFileTypeLLVMIr;
+ emit_llvm_ir = true;
+ emit_bin = false;
} else {
fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
return print_error_usage(arg0);
@@ -877,10 +901,8 @@ static int main0(int argc, char **argv) {
, argv[i]);
return EXIT_FAILURE;
}
- } else if (strcmp(arg, "-target-cpu") == 0) {
- cpu = argv[i];
- } else if (strcmp(arg, "-target-feature") == 0) {
- features = argv[i];
+ } else if (strcmp(arg, "-mcpu") == 0) {
+ mcpu = argv[i];
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return print_error_usage(arg0);
@@ -956,58 +978,54 @@ static int main0(int argc, char **argv) {
init_all_targets();
ZigTarget target;
- if (target_string == nullptr) {
- get_native_target(&target);
+ if ((err = target_parse_triple(&target, target_string, mcpu))) {
+ fprintf(stderr, "invalid target: %s\n"
+ "See `%s targets` to display valid targets.\n", err_str(err), arg0);
+ return print_error_usage(arg0);
+ }
+ if (target_is_glibc(&target)) {
+ target.glibc_version = heap::c_allocator.create<ZigGLibCVersion>();
+
if (target_glibc != nullptr) {
- fprintf(stderr, "-target-glibc provided but no -target parameter\n");
- return print_error_usage(arg0);
- }
- } else {
- if ((err = target_parse_triple(&target, target_string))) {
- if (err == ErrorUnknownArchitecture && target.arch != ZigLLVM_UnknownArch) {
- fprintf(stderr, "'%s' requires a sub-architecture. Try one of these:\n",
- target_arch_name(target.arch));
- SubArchList sub_arch_list = target_subarch_list(target.arch);
- size_t subarch_count = target_subarch_count(sub_arch_list);
- for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
- ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
- fprintf(stderr, " %s%s\n", target_arch_name(target.arch), target_subarch_name(sub));
- }
- return print_error_usage(arg0);
- } else {
- fprintf(stderr, "invalid target: %s\n", err_str(err));
+ if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) {
+ fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err));
return print_error_usage(arg0);
}
- }
- if (target_is_glibc(&target)) {
- target.glibc_version = heap::c_allocator.create<ZigGLibCVersion>();
-
- if (target_glibc != nullptr) {
- if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) {
- fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err));
- return print_error_usage(arg0);
+ } else {
+ target_init_default_glibc_version(&target);
+#if defined(ZIG_OS_LINUX)
+ if (target.is_native) {
+ // TODO self-host glibc version detection, and then this logic can go away
+ if ((err = glibc_detect_native_version(target.glibc_version))) {
+ // Fall back to the default version.
}
- } else {
- target_init_default_glibc_version(&target);
}
- } else if (target_glibc != nullptr) {
- fprintf(stderr, "'%s' is not a glibc-compatible target", target_string);
- return print_error_usage(arg0);
+#endif
}
+ } else if (target_glibc != nullptr) {
+ fprintf(stderr, "'%s' is not a glibc-compatible target", target_string);
+ return print_error_usage(arg0);
}
Buf zig_triple_buf = BUF_INIT;
target_triple_zig(&zig_triple_buf, &target);
- const char *stage2_triple_arg = target.is_native ? nullptr : buf_ptr(&zig_triple_buf);
- if ((err = stage2_cpu_features_parse(&target.cpu_features, stage2_triple_arg, cpu, features))) {
- fprintf(stderr, "unable to initialize CPU features: %s\n", err_str(err));
- return main_exit(root_progress_node, EXIT_FAILURE);
- }
-
+ // If both output_dir and enable_cache are provided, and doing build-lib, we
+ // will just do a file copy at the end. This helps when bootstrapping zig from zig0
+ // because we want to pass something like this:
+ // zig0 build-lib --cache on --output-dir ${CMAKE_BINARY_DIR}
+ // And we don't have access to `zig0 build` because that would require detecting native libc
+ // on systems where we are not able to build a libc from source for them.
+ // But that's the only reason this works, so otherwise we give an error here.
+ Buf *final_output_dir_step = nullptr;
if (output_dir != nullptr && enable_cache == CacheOptOn) {
- fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n");
- return print_error_usage(arg0);
+ if (cmd == CmdBuild && out_type == OutTypeLib) {
+ final_output_dir_step = output_dir;
+ output_dir = nullptr;
+ } else {
+ fprintf(stderr, "`--output-dir` is incompatible with --cache on.\n");
+ return print_error_usage(arg0);
+ }
}
if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) {
@@ -1015,8 +1033,8 @@ static int main0(int argc, char **argv) {
return print_error_usage(arg0);
}
- if (emit_file_type != EmitFileTypeBinary && in_file == nullptr) {
- fprintf(stderr, "A root source file is required when using `--emit asm` or `--emit llvm-ir`\n");
+ if ((emit_asm || emit_llvm_ir) && in_file == nullptr) {
+ fprintf(stderr, "A root source file is required when using `-femit-asm` or `-femit-llvm-ir`\n");
return print_error_usage(arg0);
}
@@ -1028,15 +1046,22 @@ static int main0(int argc, char **argv) {
switch (cmd) {
case CmdLibC: {
if (in_file) {
- ZigLibCInstallation libc;
- if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))
+ Stage2LibCInstallation libc;
+ if ((err = stage2_libc_parse(&libc, in_file))) {
+ fprintf(stderr, "unable to parse libc file: %s\n", err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
+ }
return main_exit(root_progress_node, EXIT_SUCCESS);
}
- ZigLibCInstallation libc;
- if ((err = zig_libc_find_native(&libc, true)))
+ Stage2LibCInstallation libc;
+ if ((err = stage2_libc_find_native(&libc))) {
+ fprintf(stderr, "unable to find native libc file: %s\n", err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
- zig_libc_render(&libc, stdout);
+ }
+ if ((err = stage2_libc_render(&libc, stdout))) {
+ fprintf(stderr, "unable to print libc file: %s\n", err_str(err));
+ return main_exit(root_progress_node, EXIT_FAILURE);
+ }
return main_exit(root_progress_node, EXIT_SUCCESS);
}
case CmdBuiltin: {
@@ -1080,11 +1105,38 @@ static int main0(int argc, char **argv) {
{
fprintf(stderr, "Expected source file argument.\n");
return print_error_usage(arg0);
- } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) {
- fprintf(stderr, "Cannot run non-executable file.\n");
+ } else if (cmd == CmdRun && !emit_bin) {
+ fprintf(stderr, "Cannot run without emitting a binary file.\n");
return print_error_usage(arg0);
}
+ if (target.is_native && link_libs.length != 0) {
+ Error err;
+ Stage2NativePaths paths;
+ if ((err = stage2_detect_native_paths(&paths))) {
+ fprintf(stderr, "unable to detect native system paths: %s\n", err_str(err));
+ exit(1);
+ }
+ for (size_t i = 0; i < paths.warnings_len; i += 1) {
+ const char *warning = paths.warnings_ptr[i];
+ fprintf(stderr, "warning: %s\n", warning);
+ }
+ for (size_t i = 0; i < paths.include_dirs_len; i += 1) {
+ const char *include_dir = paths.include_dirs_ptr[i];
+ clang_argv.append("-I");
+ clang_argv.append(include_dir);
+ }
+ for (size_t i = 0; i < paths.lib_dirs_len; i += 1) {
+ const char *lib_dir = paths.lib_dirs_ptr[i];
+ lib_dirs.append(lib_dir);
+ }
+ for (size_t i = 0; i < paths.rpaths_len; i += 1) {
+ const char *rpath = paths.rpaths_ptr[i];
+ rpath_list.append(rpath);
+ }
+ }
+
+
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
@@ -1126,10 +1178,10 @@ static int main0(int argc, char **argv) {
if (cmd == CmdRun && buf_out_name == nullptr) {
buf_out_name = buf_create_from_str("run");
}
- ZigLibCInstallation *libc = nullptr;
+ Stage2LibCInstallation *libc = nullptr;
if (libc_txt != nullptr) {
- libc = heap::c_allocator.create<ZigLibCInstallation>();
- if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {
+ libc = heap::c_allocator.create<Stage2LibCInstallation>();
+ if ((err = stage2_libc_parse(libc, libc_txt))) {
fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
}
@@ -1158,7 +1210,10 @@ static int main0(int argc, char **argv) {
g->enable_stack_report = stack_report;
g->enable_dump_analysis = enable_dump_analysis;
g->enable_doc_generation = enable_doc_generation;
- g->disable_bin_generation = disable_bin_generation;
+ g->emit_bin = emit_bin;
+ g->emit_asm = emit_asm;
+ g->emit_llvm_ir = emit_llvm_ir;
+
codegen_set_out_name(g, buf_out_name);
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
g->want_single_threaded = want_single_threaded;
@@ -1188,7 +1243,6 @@ static int main0(int argc, char **argv) {
g->function_sections = function_sections;
g->code_model = code_model;
-
for (size_t i = 0; i < lib_dirs.length; i += 1) {
codegen_add_lib_dir(g, lib_dirs.at(i));
}
@@ -1244,8 +1298,6 @@ static int main0(int argc, char **argv) {
if (cmd == CmdBuild || cmd == CmdRun) {
- codegen_set_emit_file_type(g, emit_file_type);
-
g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
codegen_build_and_link(g);
if (root_progress_node != nullptr) {
@@ -1263,7 +1315,7 @@ static int main0(int argc, char **argv) {
mem::print_report();
#endif
- const char *exec_path = buf_ptr(&g->output_file_path);
+ const char *exec_path = buf_ptr(&g->bin_file_output_path);
ZigList<const char*> args = {0};
args.append(exec_path);
@@ -1283,10 +1335,23 @@ static int main0(int argc, char **argv) {
} else if (cmd == CmdBuild) {
if (g->enable_cache) {
#if defined(ZIG_OS_WINDOWS)
- buf_replace(&g->output_file_path, '/', '\\');
+ buf_replace(&g->bin_file_output_path, '/', '\\');
#endif
- if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
- return main_exit(root_progress_node, EXIT_FAILURE);
+ if (final_output_dir_step != nullptr) {
+ Buf *dest_basename = buf_alloc();
+ os_path_split(&g->bin_file_output_path, nullptr, dest_basename);
+ Buf *dest_path = buf_alloc();
+ os_path_join(final_output_dir_step, dest_basename, dest_path);
+
+ if ((err = os_update_file(&g->bin_file_output_path, dest_path))) {
+ fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path),
+ buf_ptr(dest_path), err_str(err));
+ return main_exit(root_progress_node, EXIT_FAILURE);
+ }
+ } else {
+ if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0)
+ return main_exit(root_progress_node, EXIT_FAILURE);
+ }
}
return main_exit(root_progress_node, EXIT_SUCCESS);
} else {
@@ -1299,8 +1364,6 @@ static int main0(int argc, char **argv) {
codegen_print_timing_report(g, stderr);
return main_exit(root_progress_node, EXIT_SUCCESS);
} else if (cmd == CmdTest) {
- codegen_set_emit_file_type(g, emit_file_type);
-
ZigTarget native;
get_native_target(&native);
@@ -1319,17 +1382,17 @@ static int main0(int argc, char **argv) {
zig_print_stack_report(g, stdout);
}
- if (g->disable_bin_generation) {
+ if (!g->emit_bin) {
fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");
return main_exit(root_progress_node, EXIT_SUCCESS);
}
- Buf *test_exe_path_unresolved = &g->output_file_path;
+ Buf *test_exe_path_unresolved = &g->bin_file_output_path;
Buf *test_exe_path = buf_alloc();
*test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
- if (emit_file_type != EmitFileTypeBinary) {
- fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
+ if (!g->emit_bin) {
+ fprintf(stderr, "Created %s but skipping execution because no binary generated.\n",
buf_ptr(test_exe_path));
return main_exit(root_progress_node, EXIT_SUCCESS);
}
diff --git a/src/mem_list.hpp b/src/mem_list.hpp
@@ -14,11 +14,14 @@ namespace mem {
template<typename T>
struct List {
- void deinit(Allocator& allocator) {
- allocator.deallocate<T>(items, capacity);
+ void deinit(Allocator *allocator) {
+ allocator->deallocate<T>(items, capacity);
+ items = nullptr;
+ length = 0;
+ capacity = 0;
}
- void append(Allocator& allocator, const T& item) {
+ void append(Allocator *allocator, const T& item) {
ensure_capacity(allocator, length + 1);
items[length++] = item;
}
@@ -57,7 +60,7 @@ struct List {
return items[length - 1];
}
- void resize(Allocator& allocator, size_t new_length) {
+ void resize(Allocator *allocator, size_t new_length) {
assert(new_length != SIZE_MAX);
ensure_capacity(allocator, new_length);
length = new_length;
@@ -67,7 +70,7 @@ struct List {
length = 0;
}
- void ensure_capacity(Allocator& allocator, size_t new_capacity) {
+ void ensure_capacity(Allocator *allocator, size_t new_capacity) {
if (capacity >= new_capacity)
return;
@@ -76,7 +79,7 @@ struct List {
better_capacity = better_capacity * 5 / 2 + 8;
} while (better_capacity < new_capacity);
- items = allocator.reallocate_nonzero<T>(items, capacity, better_capacity);
+ items = allocator->reallocate_nonzero<T>(items, capacity, better_capacity);
capacity = better_capacity;
}
diff --git a/src/mem_profile.cpp b/src/mem_profile.cpp
@@ -92,7 +92,7 @@ void Profile::print_report(FILE *file) {
auto entry = it.next();
if (!entry)
break;
- list.append(heap::bootstrap_allocator, &entry->value);
+ list.append(&heap::bootstrap_allocator, &entry->value);
}
qsort(list.items, list.length, sizeof(const Entry *), entry_compare);
@@ -143,7 +143,7 @@ void Profile::print_report(FILE *file) {
fprintf(file, "\n Total calls alloc: %zu, dealloc: %zu, remain: %zu\n",
total_calls_alloc, total_calls_dealloc, (total_calls_alloc - total_calls_dealloc));
- list.deinit(heap::bootstrap_allocator);
+ list.deinit(&heap::bootstrap_allocator);
}
uint32_t Profile::usage_hash(UsageKey key) {
diff --git a/src/os.cpp b/src/os.cpp
@@ -81,11 +81,7 @@ static clock_serv_t macos_monotonic_clock;
#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())
-#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
+#if !defined(environ)
extern char **environ;
#endif
@@ -826,7 +822,9 @@ static Error os_exec_process_posix(ZigList<const char *> &args,
if (errno == ENOENT) {
report_err = ErrorFileNotFound;
}
- write(err_pipe[1], &report_err, sizeof(Error));
+ if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) {
+ zig_panic("write failed");
+ }
exit(1);
} else {
// parent
@@ -851,9 +849,13 @@ static Error os_exec_process_posix(ZigList<const char *> &args,
if (err2) return err2;
Error child_err = ErrorNone;
- write(err_pipe[1], &child_err, sizeof(Error));
+ if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) {
+ zig_panic("write failed");
+ }
close(err_pipe[1]);
- read(err_pipe[0], &child_err, sizeof(Error));
+ if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) {
+ zig_panic("write failed");
+ }
close(err_pipe[0]);
return child_err;
}
@@ -1029,6 +1031,124 @@ Error os_write_file(Buf *full_path, Buf *contents) {
return ErrorNone;
}
+static Error copy_open_files(FILE *src_f, FILE *dest_f) {
+ static const size_t buf_size = 2048;
+ char buf[buf_size];
+ for (;;) {
+ size_t amt_read = fread(buf, 1, buf_size, src_f);
+ if (amt_read != buf_size) {
+ if (ferror(src_f)) {
+ return ErrorFileSystem;
+ }
+ }
+ size_t amt_written = fwrite(buf, 1, amt_read, dest_f);
+ if (amt_written != amt_read) {
+ return ErrorFileSystem;
+ }
+ if (feof(src_f)) {
+ return ErrorNone;
+ }
+ }
+}
+
+#if defined(ZIG_OS_WINDOWS)
+static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
+ mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
+ mtime->nsec = 0;
+}
+static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) {
+ FILETIME result;
+ result.dwHighDateTime = mtime.sec >> 32;
+ result.dwLowDateTime = mtime.sec;
+ return result;
+}
+#endif
+
+static Error set_file_times(OsFile file, OsTimeStamp ts) {
+#if defined(ZIG_OS_WINDOWS)
+ FILETIME ft = windows_os_timestamp_to_filetime(ts);
+ if (SetFileTime(file, nullptr, &ft, &ft) == 0) {
+ return ErrorUnexpected;
+ }
+ return ErrorNone;
+#else
+ struct timespec times[2] = {
+ { ts.sec, ts.nsec },
+ { ts.sec, ts.nsec },
+ };
+ if (futimens(file, times) == -1) {
+ switch (errno) {
+ case EBADF:
+ zig_panic("futimens EBADF");
+ default:
+ return ErrorUnexpected;
+ }
+ }
+ return ErrorNone;
+#endif
+}
+
+Error os_update_file(Buf *src_path, Buf *dst_path) {
+ Error err;
+
+ OsFile src_file;
+ OsFileAttr src_attr;
+ if ((err = os_file_open_r(src_path, &src_file, &src_attr))) {
+ return err;
+ }
+
+ OsFile dst_file;
+ OsFileAttr dst_attr;
+ if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) {
+ os_file_close(&src_file);
+ return err;
+ }
+
+ if (src_attr.size == dst_attr.size &&
+ src_attr.mode == dst_attr.mode &&
+ src_attr.mtime.sec == dst_attr.mtime.sec &&
+ src_attr.mtime.nsec == dst_attr.mtime.nsec)
+ {
+ os_file_close(&src_file);
+ os_file_close(&dst_file);
+ return ErrorNone;
+ }
+#if defined(ZIG_OS_WINDOWS)
+ if (SetEndOfFile(dst_file) == 0) {
+ return ErrorUnexpected;
+ }
+#else
+ if (ftruncate(dst_file, 0) == -1) {
+ return ErrorUnexpected;
+ }
+#endif
+#if defined(ZIG_OS_WINDOWS)
+ FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb");
+ FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb");
+#else
+ FILE *src_libc_file = fdopen(src_file, "rb");
+ FILE *dst_libc_file = fdopen(dst_file, "wb");
+#endif
+ assert(src_libc_file);
+ assert(dst_libc_file);
+
+ if ((err = copy_open_files(src_libc_file, dst_libc_file))) {
+ fclose(src_libc_file);
+ fclose(dst_libc_file);
+ return err;
+ }
+ if (fflush(src_libc_file) == -1) {
+ return ErrorUnexpected;
+ }
+ if (fflush(dst_libc_file) == -1) {
+ return ErrorUnexpected;
+ }
+ err = set_file_times(dst_file, src_attr.mtime);
+ fclose(src_libc_file);
+ fclose(dst_libc_file);
+ return err;
+}
+
Error os_copy_file(Buf *src_path, Buf *dest_path) {
FILE *src_f = fopen(buf_ptr(src_path), "rb");
if (!src_f) {
@@ -1055,30 +1175,10 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
return ErrorFileSystem;
}
}
-
- static const size_t buf_size = 2048;
- char buf[buf_size];
- for (;;) {
- size_t amt_read = fread(buf, 1, buf_size, src_f);
- if (amt_read != buf_size) {
- if (ferror(src_f)) {
- fclose(src_f);
- fclose(dest_f);
- return ErrorFileSystem;
- }
- }
- size_t amt_written = fwrite(buf, 1, amt_read, dest_f);
- if (amt_written != amt_read) {
- fclose(src_f);
- fclose(dest_f);
- return ErrorFileSystem;
- }
- if (feof(src_f)) {
- fclose(src_f);
- fclose(dest_f);
- return ErrorNone;
- }
- }
+ Error err = copy_open_files(src_f, dest_f);
+ fclose(src_f);
+ fclose(dest_f);
+ return err;
}
Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
@@ -1218,13 +1318,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
return ErrorNone;
}
-#if defined(ZIG_OS_WINDOWS)
-static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
- mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
- mtime->nsec = 0;
-}
-#endif
-
OsTimeStamp os_timestamp_calendar(void) {
OsTimeStamp result;
#if defined(ZIG_OS_WINDOWS)
@@ -1551,108 +1644,6 @@ void os_stderr_set_color(TermColor color) {
#endif
}
-Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
-#if defined(ZIG_OS_WINDOWS)
- buf_resize(output_buf, 0);
- buf_appendf(output_buf, "%sLib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr);
- switch (platform_type) {
- case ZigLLVM_x86:
- buf_append_str(output_buf, "x86\\");
- break;
- case ZigLLVM_x86_64:
- buf_append_str(output_buf, "x64\\");
- break;
- case ZigLLVM_arm:
- buf_append_str(output_buf, "arm\\");
- break;
- default:
- zig_panic("Attempted to use vcruntime for non-supported platform.");
- }
- Buf* tmp_buf = buf_alloc();
- buf_init_from_buf(tmp_buf, output_buf);
- buf_append_str(tmp_buf, "ucrt.lib");
- if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return ErrorNone;
- }
- else {
- buf_resize(output_buf, 0);
- return ErrorFileNotFound;
- }
-#else
- return ErrorFileNotFound;
-#endif
-}
-
-Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
-#if defined(ZIG_OS_WINDOWS)
- buf_resize(output_buf, 0);
- buf_appendf(output_buf, "%sInclude\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);
- if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {
- return ErrorNone;
- }
- else {
- buf_resize(output_buf, 0);
- return ErrorFileNotFound;
- }
-#else
- return ErrorFileNotFound;
-#endif
-}
-
-Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
-#if defined(ZIG_OS_WINDOWS)
- {
- buf_resize(output_buf, 0);
- buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path10_ptr, sdk->version10_ptr);
- switch (platform_type) {
- case ZigLLVM_x86:
- buf_append_str(output_buf, "x86\\");
- break;
- case ZigLLVM_x86_64:
- buf_append_str(output_buf, "x64\\");
- break;
- case ZigLLVM_arm:
- buf_append_str(output_buf, "arm\\");
- break;
- default:
- zig_panic("Attempted to use vcruntime for non-supported platform.");
- }
- Buf* tmp_buf = buf_alloc();
- buf_init_from_buf(tmp_buf, output_buf);
- buf_append_str(tmp_buf, "kernel32.lib");
- if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return ErrorNone;
- }
- }
- {
- buf_resize(output_buf, 0);
- buf_appendf(output_buf, "%sLib\\%s\\um\\", sdk->path81_ptr, sdk->version81_ptr);
- switch (platform_type) {
- case ZigLLVM_x86:
- buf_append_str(output_buf, "x86\\");
- break;
- case ZigLLVM_x86_64:
- buf_append_str(output_buf, "x64\\");
- break;
- case ZigLLVM_arm:
- buf_append_str(output_buf, "arm\\");
- break;
- default:
- zig_panic("Attempted to use vcruntime for non-supported platform.");
- }
- Buf* tmp_buf = buf_alloc();
- buf_init_from_buf(tmp_buf, output_buf);
- buf_append_str(tmp_buf, "kernel32.lib");
- if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return ErrorNone;
- }
- }
- return ErrorFileNotFound;
-#else
- return ErrorFileNotFound;
-#endif
-}
-
#if defined(ZIG_OS_WINDOWS)
// Ported from std/unicode.zig
struct Utf16LeIterator {
@@ -1835,10 +1826,15 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
#endif
}
-Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
+Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
#if defined(ZIG_OS_WINDOWS)
// TODO use CreateFileW
- HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ HANDLE result = CreateFileA(buf_ptr(full_path),
+ need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
+ need_write ? 0 : FILE_SHARE_READ,
+ nullptr,
+ need_write ? OPEN_ALWAYS : OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, nullptr);
if (result == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
@@ -1871,12 +1867,15 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
}
windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime);
attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
+ attr->mode = 0;
+ attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow;
}
return ErrorNone;
#else
for (;;) {
- int fd = open(buf_ptr(full_path), O_RDONLY|O_CLOEXEC);
+ int fd = open(buf_ptr(full_path),
+ need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode);
if (fd == -1) {
switch (errno) {
case EINTR:
@@ -1886,6 +1885,7 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
case EFAULT:
zig_unreachable();
case EACCES:
+ case EPERM:
return ErrorAccess;
case EISDIR:
return ErrorIsDir;
@@ -1915,12 +1915,22 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
attr->mtime.sec = statbuf.st_mtim.tv_sec;
attr->mtime.nsec = statbuf.st_mtim.tv_nsec;
#endif
+ attr->mode = statbuf.st_mode;
+ attr->size = statbuf.st_size;
}
return ErrorNone;
}
#endif
}
+Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
+ return os_file_open_rw(full_path, out_file, attr, false, 0);
+}
+
+Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) {
+ return os_file_open_rw(full_path, out_file, attr, true, mode);
+}
+
Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
#if defined(ZIG_OS_WINDOWS)
for (;;) {
@@ -1966,6 +1976,7 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
case EFAULT:
zig_unreachable();
case EACCES:
+ case EPERM:
return ErrorAccess;
case EISDIR:
return ErrorIsDir;
@@ -2114,21 +2125,3 @@ void os_file_close(OsFile *file) {
*file = -1;
#endif
}
-
-#ifdef ZIG_OS_LINUX
-const char *possible_ld_names[] = {
-#if defined(ZIG_ARCH_X86_64)
- "ld-linux-x86-64.so.2",
- "ld-musl-x86_64.so.1",
-#elif defined(ZIG_ARCH_ARM64)
- "ld-linux-aarch64.so.1",
- "ld-musl-aarch64.so.1",
-#elif defined(ZIG_ARCH_ARM)
- "ld-linux-armhf.so.3",
- "ld-musl-armhf.so.1",
- "ld-linux.so.3",
- "ld-musl-arm.so.1",
-#endif
- NULL,
-};
-#endif
diff --git a/src/os.hpp b/src/os.hpp
@@ -43,10 +43,6 @@
#define ZIG_ARCH_UNKNOWN
#endif
-#ifdef ZIG_OS_LINUX
-extern const char *possible_ld_names[];
-#endif
-
#if defined(ZIG_OS_WINDOWS)
#define ZIG_PRI_usize "I64u"
#define ZIG_PRI_i64 "I64d"
@@ -93,13 +89,15 @@ struct Termination {
#endif
struct OsTimeStamp {
- uint64_t sec;
- uint64_t nsec;
+ int64_t sec;
+ int64_t nsec;
};
struct OsFileAttr {
OsTimeStamp mtime;
+ uint64_t size;
uint64_t inode;
+ uint32_t mode;
};
int os_init(void);
@@ -121,6 +119,7 @@ Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr);
+Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode);
Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
@@ -129,6 +128,7 @@ void os_file_close(OsFile *file);
Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
+Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
@@ -152,10 +152,6 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
-Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
-Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
-Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
-
Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
#endif
diff --git a/src/parser.cpp b/src/parser.cpp
@@ -689,6 +689,9 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B
AstNode *res = fn_proto;
if (body != nullptr) {
+ if (fn_proto->data.fn_proto.is_extern) {
+ ast_error(pc, first, "extern functions have no body");
+ }
res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
res->data.fn_def.fn_proto = fn_proto;
res->data.fn_def.body = body;
@@ -2596,10 +2599,14 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {
return res;
}
+ Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync);
Token *await = eat_token_if(pc, TokenIdKeywordAwait);
if (await != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
+ res->data.await_expr.noasync_token = noasync_token;
return res;
+ } else if (noasync_token != nullptr) {
+ put_back_token(pc);
}
return nullptr;
diff --git a/src/stage2.cpp b/src/stage2.cpp
@@ -0,0 +1,208 @@
+// This file is a shim for zig1. The real implementations of these are in
+// src-self-hosted/stage1.zig
+
+#include "stage2.h"
+#include "util.hpp"
+#include "zig_llvm.h"
+#include "target.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+Error stage2_translate_c(struct Stage2Ast **out_ast,
+ struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
+ const char **args_begin, const char **args_end, const char *resources_path)
+{
+ const char *msg = "stage0 called stage2_translate_c";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
+ const char *msg = "stage0 called stage2_free_clang_errors";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_zen(const char **ptr, size_t *len) {
+ const char *msg = "stage0 called stage2_zen";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_attach_segfault_handler(void) { }
+
+void stage2_panic(const char *ptr, size_t len) {
+ fwrite(ptr, 1, len, stderr);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ abort();
+}
+
+void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
+ const char *msg = "stage0 called stage2_render_ast";
+ stage2_panic(msg, strlen(msg));
+}
+
+int stage2_fmt(int argc, char **argv) {
+ const char *msg = "stage0 called stage2_fmt";
+ stage2_panic(msg, strlen(msg));
+}
+
+stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
+ const char *msg = "stage0 called stage2_DepTokenizer_init";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
+ const char *msg = "stage0 called stage2_DepTokenizer_deinit";
+ stage2_panic(msg, strlen(msg));
+}
+
+stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
+ const char *msg = "stage0 called stage2_DepTokenizer_next";
+ stage2_panic(msg, strlen(msg));
+}
+
+
+struct Stage2Progress {
+ int trash;
+};
+
+struct Stage2ProgressNode {
+ int trash;
+};
+
+Stage2Progress *stage2_progress_create(void) {
+ return nullptr;
+}
+
+void stage2_progress_destroy(Stage2Progress *progress) {}
+
+Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
+ const char *name_ptr, size_t name_len, size_t estimated_total_items)
+{
+ return nullptr;
+}
+Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
+ const char *name_ptr, size_t name_len, size_t estimated_total_items)
+{
+ return nullptr;
+}
+void stage2_progress_end(Stage2ProgressNode *node) {}
+void stage2_progress_complete_one(Stage2ProgressNode *node) {}
+void stage2_progress_disable_tty(Stage2Progress *progress) {}
+void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
+
+Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu) {
+ Error err;
+
+ if (zig_triple == nullptr) {
+ get_native_target(target);
+
+ if (mcpu == nullptr) {
+ target->llvm_cpu_name = ZigLLVMGetHostCPUName();
+ target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
+ target->builtin_str = "Target.Cpu.baseline(arch);\n";
+ target->cache_hash = "native\n\n";
+ } else if (strcmp(mcpu, "baseline") == 0) {
+ target->is_native = false;
+ target->llvm_cpu_name = "";
+ target->llvm_cpu_features = "";
+ target->builtin_str = "Target.Cpu.baseline(arch);\n";
+ target->cache_hash = "baseline\n\n";
+ } else {
+ const char *msg = "stage0 can't handle CPU/features in the target";
+ stage2_panic(msg, strlen(msg));
+ }
+ } else {
+ // first initialize all to zero
+ *target = {};
+
+ SplitIterator it = memSplit(str(zig_triple), str("-"));
+
+ Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
+ Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
+ Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
+
+ if (!opt_archsub.is_some)
+ return ErrorMissingArchitecture;
+
+ if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
+ return err;
+ }
+
+ if (!opt_os.is_some)
+ return ErrorMissingOperatingSystem;
+
+ if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
+ return err;
+ }
+
+ if (opt_abi.is_some) {
+ if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
+ return err;
+ }
+ } else {
+ target->abi = target_default_abi(target->arch, target->os);
+ }
+
+ if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
+ const char *msg = "stage0 can't handle CPU/features in the target";
+ stage2_panic(msg, strlen(msg));
+ }
+ target->builtin_str = "Target.Cpu.baseline(arch);\n";
+ target->cache_hash = "\n\n";
+ }
+
+ return ErrorNone;
+}
+
+int stage2_cmd_targets(const char *zig_triple) {
+ const char *msg = "stage0 called stage2_cmd_targets";
+ stage2_panic(msg, strlen(msg));
+}
+
+enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) {
+ libc->include_dir = "/dummy/include";
+ libc->include_dir_len = strlen(libc->include_dir);
+ libc->sys_include_dir = "/dummy/sys/include";
+ libc->sys_include_dir_len = strlen(libc->sys_include_dir);
+ libc->crt_dir = "";
+ libc->crt_dir_len = strlen(libc->crt_dir);
+ libc->static_crt_dir = "";
+ libc->static_crt_dir_len = strlen(libc->static_crt_dir);
+ libc->msvc_lib_dir = "";
+ libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir);
+ libc->kernel32_lib_dir = "";
+ libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir);
+ return ErrorNone;
+}
+
+enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) {
+ const char *msg = "stage0 called stage2_libc_render";
+ stage2_panic(msg, strlen(msg));
+}
+
+enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) {
+ const char *msg = "stage0 called stage2_libc_find_native";
+ stage2_panic(msg, strlen(msg));
+}
+
+enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len) {
+ const char *msg = "stage0 called stage2_detect_dynamic_linker";
+ stage2_panic(msg, strlen(msg));
+}
+
+enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {
+ native_paths->include_dirs_ptr = nullptr;
+ native_paths->include_dirs_len = 0;
+
+ native_paths->lib_dirs_ptr = nullptr;
+ native_paths->lib_dirs_len = 0;
+
+ native_paths->rpaths_ptr = nullptr;
+ native_paths->rpaths_len = 0;
+
+ native_paths->warnings_ptr = nullptr;
+ native_paths->warnings_len = 0;
+
+ return ErrorNone;
+}
diff --git a/src/stage2.h b/src/stage2.h
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_STAGE2_H
+#define ZIG_STAGE2_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "zig_llvm.h"
+
+#ifdef __cplusplus
+#define ZIG_EXTERN_C extern "C"
+#else
+#define ZIG_EXTERN_C
+#endif
+
+#if defined(_MSC_VER)
+#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
+#else
+#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
+#endif
+
+// ABI warning: the types and declarations in this file must match both those in
+// stage2.cpp and src-self-hosted/stage2.zig.
+
+// ABI warning
+enum Error {
+ ErrorNone,
+ ErrorNoMem,
+ ErrorInvalidFormat,
+ ErrorSemanticAnalyzeFail,
+ ErrorAccess,
+ ErrorInterrupted,
+ ErrorSystemResources,
+ ErrorFileNotFound,
+ ErrorFileSystem,
+ ErrorFileTooBig,
+ ErrorDivByZero,
+ ErrorOverflow,
+ ErrorPathAlreadyExists,
+ ErrorUnexpected,
+ ErrorExactDivRemainder,
+ ErrorNegativeDenominator,
+ ErrorShiftedOutOneBits,
+ ErrorCCompileErrors,
+ ErrorEndOfFile,
+ ErrorIsDir,
+ ErrorNotDir,
+ ErrorUnsupportedOperatingSystem,
+ ErrorSharingViolation,
+ ErrorPipeBusy,
+ ErrorPrimitiveTypeNotFound,
+ ErrorCacheUnavailable,
+ ErrorPathTooLong,
+ ErrorCCompilerCannotFindFile,
+ ErrorNoCCompilerInstalled,
+ ErrorReadingDepFile,
+ ErrorInvalidDepFile,
+ ErrorMissingArchitecture,
+ ErrorMissingOperatingSystem,
+ ErrorUnknownArchitecture,
+ ErrorUnknownOperatingSystem,
+ ErrorUnknownABI,
+ ErrorInvalidFilename,
+ ErrorDiskQuota,
+ ErrorDiskSpace,
+ ErrorUnexpectedWriteFailure,
+ ErrorUnexpectedSeekFailure,
+ ErrorUnexpectedFileTruncationFailure,
+ ErrorUnimplemented,
+ ErrorOperationAborted,
+ ErrorBrokenPipe,
+ ErrorNoSpaceLeft,
+ ErrorNotLazy,
+ ErrorIsAsync,
+ ErrorImportOutsidePkgPath,
+ ErrorUnknownCpu,
+ ErrorUnknownCpuFeature,
+ ErrorInvalidCpuFeatures,
+ ErrorInvalidLlvmCpuFeaturesFormat,
+ ErrorUnknownApplicationBinaryInterface,
+ ErrorASTUnitFailure,
+ ErrorBadPathName,
+ ErrorSymLinkLoop,
+ ErrorProcessFdQuotaExceeded,
+ ErrorSystemFdQuotaExceeded,
+ ErrorNoDevice,
+ ErrorDeviceBusy,
+ ErrorUnableToSpawnCCompiler,
+ ErrorCCompilerExitCode,
+ ErrorCCompilerCrashed,
+ ErrorCCompilerCannotFindHeaders,
+ ErrorLibCRuntimeNotFound,
+ ErrorLibCStdLibHeaderNotFound,
+ ErrorLibCKernel32LibNotFound,
+ ErrorUnsupportedArchitecture,
+ ErrorWindowsSdkNotFound,
+ ErrorUnknownDynamicLinkerPath,
+ ErrorTargetHasNoDynamicLinker,
+};
+
+// ABI warning
+struct Stage2ErrorMsg {
+ const char *filename_ptr; // can be null
+ size_t filename_len;
+ const char *msg_ptr;
+ size_t msg_len;
+ const char *source; // valid until the ASTUnit is freed. can be null
+ unsigned line; // 0 based
+ unsigned column; // 0 based
+ unsigned offset; // byte offset into source
+};
+
+// ABI warning
+struct Stage2Ast;
+
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
+ struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
+ const char **args_begin, const char **args_end, const char *resources_path);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_attach_segfault_handler(void);
+
+// ABI warning
+ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
+
+// ABI warning
+struct stage2_DepTokenizer {
+ void *handle;
+};
+
+// ABI warning
+struct stage2_DepNextResult {
+ enum TypeId {
+ error,
+ null,
+ target,
+ prereq,
+ };
+
+ TypeId type_id;
+
+ // when ent == error --> error text
+ // when ent == null --> undefined
+ // when ent == target --> target pathname
+ // when ent == prereq --> prereq pathname
+ const char *textz;
+};
+
+// ABI warning
+ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
+
+// ABI warning
+ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
+
+// ABI warning
+struct Stage2Progress;
+// ABI warning
+struct Stage2ProgressNode;
+// ABI warning
+ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
+// ABI warning
+ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
+// ABI warning
+ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
+// ABI warning
+ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
+ const char *name_ptr, size_t name_len, size_t estimated_total_items);
+// ABI warning
+ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
+ const char *name_ptr, size_t name_len, size_t estimated_total_items);
+// ABI warning
+ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
+// ABI warning
+ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
+// ABI warning
+ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
+ size_t completed_count, size_t estimated_total_items);
+
+// ABI warning
+ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
+
+// ABI warning
+struct Stage2LibCInstallation {
+ const char *include_dir;
+ size_t include_dir_len;
+ const char *sys_include_dir;
+ size_t sys_include_dir_len;
+ const char *crt_dir;
+ size_t crt_dir_len;
+ const char *static_crt_dir;
+ size_t static_crt_dir_len;
+ const char *msvc_lib_dir;
+ size_t msvc_lib_dir_len;
+ const char *kernel32_lib_dir;
+ size_t kernel32_lib_dir_len;
+};
+
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file);
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file);
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc);
+
+// ABI warning
+// Synchronize with target.cpp::os_list
+enum Os {
+ OsFreestanding,
+ OsAnanas,
+ OsCloudABI,
+ OsDragonFly,
+ OsFreeBSD,
+ OsFuchsia,
+ OsIOS,
+ OsKFreeBSD,
+ OsLinux,
+ OsLv2, // PS3
+ OsMacOSX,
+ OsNetBSD,
+ OsOpenBSD,
+ OsSolaris,
+ OsWindows,
+ OsHaiku,
+ OsMinix,
+ OsRTEMS,
+ OsNaCl, // Native Client
+ OsCNK, // BG/P Compute-Node Kernel
+ OsAIX,
+ OsCUDA, // NVIDIA CUDA
+ OsNVCL, // NVIDIA OpenCL
+ OsAMDHSA, // AMD HSA Runtime
+ OsPS4,
+ OsELFIAMCU,
+ OsTvOS, // Apple tvOS
+ OsWatchOS, // Apple watchOS
+ OsMesa3D,
+ OsContiki,
+ OsAMDPAL,
+ OsHermitCore,
+ OsHurd,
+ OsWASI,
+ OsEmscripten,
+ OsUefi,
+ OsOther,
+};
+
+// ABI warning
+struct ZigGLibCVersion {
+ uint32_t major; // always 2
+ uint32_t minor;
+ uint32_t patch;
+};
+
+struct Stage2TargetData;
+
+// ABI warning
+struct ZigTarget {
+ enum ZigLLVM_ArchType arch;
+ enum ZigLLVM_VendorType vendor;
+
+ enum ZigLLVM_EnvironmentType abi;
+ Os os;
+
+ bool is_native;
+
+ struct ZigGLibCVersion *glibc_version; // null means default
+
+ const char *llvm_cpu_name;
+ const char *llvm_cpu_features;
+ const char *builtin_str;
+ const char *cache_hash;
+};
+
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target,
+ char **out_ptr, size_t *out_len);
+
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu);
+
+
+// ABI warning
+struct Stage2NativePaths {
+ const char **include_dirs_ptr;
+ size_t include_dirs_len;
+ const char **lib_dirs_ptr;
+ size_t lib_dirs_len;
+ const char **rpaths_ptr;
+ size_t rpaths_len;
+ const char **warnings_ptr;
+ size_t warnings_len;
+};
+// ABI warning
+ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths);
+
+#endif
diff --git a/src/target.cpp b/src/target.cpp
@@ -15,65 +15,6 @@
#include <stdio.h>
-static const SubArchList subarch_list_list[] = {
- SubArchListNone,
- SubArchListArm32,
- SubArchListArm64,
- SubArchListKalimba,
- SubArchListMips,
- SubArchListPPC,
-};
-
-static const ZigLLVM_SubArchType subarch_list_arm32[] = {
- ZigLLVM_ARMSubArch_v8_5a,
- ZigLLVM_ARMSubArch_v8_4a,
- ZigLLVM_ARMSubArch_v8_3a,
- ZigLLVM_ARMSubArch_v8_2a,
- ZigLLVM_ARMSubArch_v8_1a,
- ZigLLVM_ARMSubArch_v8,
- ZigLLVM_ARMSubArch_v8r,
- ZigLLVM_ARMSubArch_v8m_baseline,
- ZigLLVM_ARMSubArch_v8m_mainline,
- ZigLLVM_ARMSubArch_v8_1m_mainline,
- ZigLLVM_ARMSubArch_v7,
- ZigLLVM_ARMSubArch_v7em,
- ZigLLVM_ARMSubArch_v7m,
- ZigLLVM_ARMSubArch_v7s,
- ZigLLVM_ARMSubArch_v7k,
- ZigLLVM_ARMSubArch_v7ve,
- ZigLLVM_ARMSubArch_v6,
- ZigLLVM_ARMSubArch_v6m,
- ZigLLVM_ARMSubArch_v6k,
- ZigLLVM_ARMSubArch_v6t2,
- ZigLLVM_ARMSubArch_v5,
- ZigLLVM_ARMSubArch_v5te,
- ZigLLVM_ARMSubArch_v4t,
-
-};
-
-static const ZigLLVM_SubArchType subarch_list_arm64[] = {
- ZigLLVM_ARMSubArch_v8_5a,
- ZigLLVM_ARMSubArch_v8_4a,
- ZigLLVM_ARMSubArch_v8_3a,
- ZigLLVM_ARMSubArch_v8_2a,
- ZigLLVM_ARMSubArch_v8_1a,
- ZigLLVM_ARMSubArch_v8,
-};
-
-static const ZigLLVM_SubArchType subarch_list_kalimba[] = {
- ZigLLVM_KalimbaSubArch_v5,
- ZigLLVM_KalimbaSubArch_v4,
- ZigLLVM_KalimbaSubArch_v3,
-};
-
-static const ZigLLVM_SubArchType subarch_list_mips[] = {
- ZigLLVM_MipsSubArch_r6,
-};
-
-static const ZigLLVM_SubArchType subarch_list_ppc[] = {
- ZigLLVM_PPCSubArch_spe,
-};
-
static const ZigLLVM_ArchType arch_list[] = {
ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale
ZigLLVM_armeb, // ARM (big endian): armeb
@@ -513,7 +454,6 @@ void get_native_target(ZigTarget *target) {
ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
ZigLLVMGetNativeTarget(
&target->arch,
- &target->sub_arch,
&target->vendor,
&os_type,
&target->abi,
@@ -526,12 +466,6 @@ void get_native_target(ZigTarget *target) {
if (target_is_glibc(target)) {
target->glibc_version = heap::c_allocator.create<ZigGLibCVersion>();
target_init_default_glibc_version(target);
-#ifdef ZIG_OS_LINUX
- Error err;
- if ((err = glibc_detect_native_version(target->glibc_version))) {
- // Fall back to the default version.
- }
-#endif
}
}
@@ -539,233 +473,18 @@ void target_init_default_glibc_version(ZigTarget *target) {
*target->glibc_version = {2, 17, 0};
}
-Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
- const char *archsub_ptr, size_t archsub_len)
-{
+Error target_parse_arch(ZigLLVM_ArchType *out_arch, const char *arch_ptr, size_t arch_len) {
*out_arch = ZigLLVM_UnknownArch;
- *out_sub = ZigLLVM_NoSubArch;
for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
ZigLLVM_ArchType arch = arch_list[arch_i];
- SubArchList sub_arch_list = target_subarch_list(arch);
- size_t subarch_count = target_subarch_count(sub_arch_list);
- if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
+ if (mem_eql_str(arch_ptr, arch_len, target_arch_name(arch))) {
*out_arch = arch;
- if (subarch_count == 0) {
- return ErrorNone;
- }
- }
- for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
- ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
- char arch_name[64];
- int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub));
- if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) {
- *out_arch = arch;
- *out_sub = sub;
- return ErrorNone;
- }
+ return ErrorNone;
}
}
return ErrorUnknownArchitecture;
}
-SubArchList target_subarch_list(ZigLLVM_ArchType arch) {
- switch (arch) {
- case ZigLLVM_UnknownArch:
- zig_unreachable();
- case ZigLLVM_arm:
- case ZigLLVM_armeb:
- case ZigLLVM_thumb:
- case ZigLLVM_thumbeb:
- return SubArchListArm32;
-
- case ZigLLVM_aarch64:
- case ZigLLVM_aarch64_be:
- case ZigLLVM_aarch64_32:
- return SubArchListArm64;
-
- case ZigLLVM_kalimba:
- return SubArchListKalimba;
-
- case ZigLLVM_arc:
- case ZigLLVM_avr:
- case ZigLLVM_bpfel:
- case ZigLLVM_bpfeb:
- case ZigLLVM_hexagon:
- case ZigLLVM_mips:
- case ZigLLVM_mipsel:
- case ZigLLVM_mips64:
- case ZigLLVM_mips64el:
- case ZigLLVM_msp430:
- case ZigLLVM_ppc:
- case ZigLLVM_ppc64:
- case ZigLLVM_ppc64le:
- case ZigLLVM_r600:
- case ZigLLVM_amdgcn:
- case ZigLLVM_riscv32:
- case ZigLLVM_riscv64:
- case ZigLLVM_sparc:
- case ZigLLVM_sparcv9:
- case ZigLLVM_sparcel:
- case ZigLLVM_systemz:
- case ZigLLVM_tce:
- case ZigLLVM_tcele:
- case ZigLLVM_x86:
- case ZigLLVM_x86_64:
- case ZigLLVM_xcore:
- case ZigLLVM_nvptx:
- case ZigLLVM_nvptx64:
- case ZigLLVM_le32:
- case ZigLLVM_le64:
- case ZigLLVM_amdil:
- case ZigLLVM_amdil64:
- case ZigLLVM_hsail:
- case ZigLLVM_hsail64:
- case ZigLLVM_spir:
- case ZigLLVM_spir64:
- case ZigLLVM_shave:
- case ZigLLVM_lanai:
- case ZigLLVM_wasm32:
- case ZigLLVM_wasm64:
- case ZigLLVM_renderscript32:
- case ZigLLVM_renderscript64:
- case ZigLLVM_ve:
- return SubArchListNone;
- }
- zig_unreachable();
-}
-
-size_t target_subarch_count(SubArchList sub_arch_list) {
- switch (sub_arch_list) {
- case SubArchListNone:
- return 0;
- case SubArchListArm32:
- return array_length(subarch_list_arm32);
- case SubArchListArm64:
- return array_length(subarch_list_arm64);
- case SubArchListKalimba:
- return array_length(subarch_list_kalimba);
- case SubArchListMips:
- return array_length(subarch_list_mips);
- case SubArchListPPC:
- return array_length(subarch_list_ppc);
- }
- zig_unreachable();
-}
-
-ZigLLVM_SubArchType target_subarch_enum(SubArchList sub_arch_list, size_t i) {
- switch (sub_arch_list) {
- case SubArchListNone:
- zig_unreachable();
- case SubArchListArm32:
- assert(i < array_length(subarch_list_arm32));
- return subarch_list_arm32[i];
- case SubArchListArm64:
- assert(i < array_length(subarch_list_arm64));
- return subarch_list_arm64[i];
- case SubArchListKalimba:
- assert(i < array_length(subarch_list_kalimba));
- return subarch_list_kalimba[i];
- case SubArchListMips:
- assert(i < array_length(subarch_list_mips));
- return subarch_list_mips[i];
- case SubArchListPPC:
- assert(i < array_length(subarch_list_ppc));
- return subarch_list_ppc[i];
- }
- zig_unreachable();
-}
-
-const char *target_subarch_name(ZigLLVM_SubArchType subarch) {
- switch (subarch) {
- case ZigLLVM_NoSubArch:
- return "";
- case ZigLLVM_ARMSubArch_v8_5a:
- return "v8_5a";
- case ZigLLVM_ARMSubArch_v8_4a:
- return "v8_4a";
- case ZigLLVM_ARMSubArch_v8_3a:
- return "v8_3a";
- case ZigLLVM_ARMSubArch_v8_2a:
- return "v8_2a";
- case ZigLLVM_ARMSubArch_v8_1a:
- return "v8_1a";
- case ZigLLVM_ARMSubArch_v8:
- return "v8a";
- case ZigLLVM_ARMSubArch_v8r:
- return "v8r";
- case ZigLLVM_ARMSubArch_v8m_baseline:
- return "v8m_baseline";
- case ZigLLVM_ARMSubArch_v8m_mainline:
- return "v8m_mainline";
- case ZigLLVM_ARMSubArch_v8_1m_mainline:
- return "v8_1m_mainline";
- case ZigLLVM_ARMSubArch_v7:
- return "v7a";
- case ZigLLVM_ARMSubArch_v7em:
- return "v7em";
- case ZigLLVM_ARMSubArch_v7m:
- return "v7m";
- case ZigLLVM_ARMSubArch_v7s:
- return "v7s";
- case ZigLLVM_ARMSubArch_v7k:
- return "v7k";
- case ZigLLVM_ARMSubArch_v7ve:
- return "v7ve";
- case ZigLLVM_ARMSubArch_v6:
- return "v6";
- case ZigLLVM_ARMSubArch_v6m:
- return "v6m";
- case ZigLLVM_ARMSubArch_v6k:
- return "v6k";
- case ZigLLVM_ARMSubArch_v6t2:
- return "v6t2";
- case ZigLLVM_ARMSubArch_v5:
- return "v5";
- case ZigLLVM_ARMSubArch_v5te:
- return "v5te";
- case ZigLLVM_ARMSubArch_v4t:
- return "v4t";
- case ZigLLVM_KalimbaSubArch_v3:
- return "v3";
- case ZigLLVM_KalimbaSubArch_v4:
- return "v4";
- case ZigLLVM_KalimbaSubArch_v5:
- return "v5";
- case ZigLLVM_MipsSubArch_r6:
- return "r6";
- case ZigLLVM_PPCSubArch_spe:
- return "spe";
- }
- zig_unreachable();
-}
-
-size_t target_subarch_list_count(void) {
- return array_length(subarch_list_list);
-}
-
-SubArchList target_subarch_list_enum(size_t index) {
- assert(index < array_length(subarch_list_list));
- return subarch_list_list[index];
-}
-
-const char *target_subarch_list_name(SubArchList sub_arch_list) {
- switch (sub_arch_list) {
- case SubArchListNone:
- return "None";
- case SubArchListArm32:
- return "Arm32";
- case SubArchListArm64:
- return "Arm64";
- case SubArchListKalimba:
- return "Kalimba";
- case SubArchListMips:
- return "Mips";
- case SubArchListPPC:
- return "PPC";
- }
- zig_unreachable();
-}
-
Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
for (size_t i = 0; i < array_length(os_list); i += 1) {
Os os = os_list[i];
@@ -790,42 +509,8 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
return ErrorUnknownABI;
}
-Error target_parse_triple(ZigTarget *target, const char *triple) {
- Error err;
-
- // first initialize all to zero
- *target = {};
-
- SplitIterator it = memSplit(str(triple), str("-"));
-
- Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
- Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
- Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
-
- if (!opt_archsub.is_some)
- return ErrorMissingArchitecture;
-
- if ((err = target_parse_archsub(&target->arch, &target->sub_arch,
- (char*)opt_archsub.value.ptr, opt_archsub.value.len)))
- {
- return err;
- }
-
- if (!opt_os.is_some)
- return ErrorMissingOperatingSystem;
-
- if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
- return err;
- }
-
- if (opt_abi.is_some) {
- if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
- return err;
- }
- } else {
- target->abi = target_default_abi(target->arch, target->os);
- }
- return ErrorNone;
+Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu) {
+ return stage2_target_parse(target, triple, mcpu);
}
const char *target_arch_name(ZigLLVM_ArchType arch) {
@@ -842,18 +527,16 @@ void init_all_targets(void) {
void target_triple_zig(Buf *triple, const ZigTarget *target) {
buf_resize(triple, 0);
- buf_appendf(triple, "%s%s-%s-%s",
+ buf_appendf(triple, "%s-%s-%s",
target_arch_name(target->arch),
- target_subarch_name(target->sub_arch),
target_os_name(target->os),
target_abi_name(target->abi));
}
void target_triple_llvm(Buf *triple, const ZigTarget *target) {
buf_resize(triple, 0);
- buf_appendf(triple, "%s%s-%s-%s-%s",
+ buf_appendf(triple, "%s-%s-%s-%s",
ZigLLVMGetArchTypeName(target->arch),
- ZigLLVMGetSubArchTypeName(target->sub_arch),
ZigLLVMGetVendorTypeName(target->vendor),
ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
ZigLLVMGetEnvironmentTypeName(target->abi));
@@ -1220,214 +903,10 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
}
}
-enum FloatAbi {
- FloatAbiHard,
- FloatAbiSoft,
- FloatAbiSoftFp,
-};
-
-static FloatAbi get_float_abi(const ZigTarget *target) {
- const ZigLLVM_EnvironmentType env = target->abi;
- if (env == ZigLLVM_GNUEABIHF ||
- env == ZigLLVM_EABIHF ||
- env == ZigLLVM_MuslEABIHF)
- {
- return FloatAbiHard;
- } else {
- return FloatAbiSoft;
- }
-}
-
-static bool is_64_bit(ZigLLVM_ArchType arch) {
- return target_arch_pointer_bit_width(arch) == 64;
-}
-
bool target_is_android(const ZigTarget *target) {
return target->abi == ZigLLVM_Android;
}
-const char *target_dynamic_linker(const ZigTarget *target) {
- if (target_is_android(target)) {
- return is_64_bit(target->arch) ? "/system/bin/linker64" : "/system/bin/linker";
- }
-
- if (target_is_musl(target)) {
- Buf buf = BUF_INIT;
- buf_init_from_str(&buf, "/lib/ld-musl-");
- bool is_arm = false;
- switch (target->arch) {
- case ZigLLVM_arm:
- case ZigLLVM_thumb:
- buf_append_str(&buf, "arm");
- is_arm = true;
- break;
- case ZigLLVM_armeb:
- case ZigLLVM_thumbeb:
- buf_append_str(&buf, "armeb");
- is_arm = true;
- break;
- default:
- buf_append_str(&buf, target_arch_name(target->arch));
- }
- if (is_arm && get_float_abi(target) == FloatAbiHard) {
- buf_append_str(&buf, "hf");
- }
- buf_append_str(&buf, ".so.1");
- return buf_ptr(&buf);
- }
-
- switch (target->os) {
- case OsFreeBSD:
- return "/libexec/ld-elf.so.1";
- case OsNetBSD:
- return "/libexec/ld.elf_so";
- case OsDragonFly:
- return "/libexec/ld-elf.so.2";
- case OsLinux: {
- const ZigLLVM_EnvironmentType abi = target->abi;
- switch (target->arch) {
- case ZigLLVM_UnknownArch:
- zig_unreachable();
- case ZigLLVM_x86:
- case ZigLLVM_sparc:
- case ZigLLVM_sparcel:
- return "/lib/ld-linux.so.2";
-
- case ZigLLVM_aarch64:
- return "/lib/ld-linux-aarch64.so.1";
-
- case ZigLLVM_aarch64_be:
- return "/lib/ld-linux-aarch64_be.so.1";
-
- case ZigLLVM_aarch64_32:
- return "/lib/ld-linux-aarch64_32.so.1";
-
- case ZigLLVM_arm:
- case ZigLLVM_thumb:
- if (get_float_abi(target) == FloatAbiHard) {
- return "/lib/ld-linux-armhf.so.3";
- } else {
- return "/lib/ld-linux.so.3";
- }
-
- case ZigLLVM_armeb:
- case ZigLLVM_thumbeb:
- if (get_float_abi(target) == FloatAbiHard) {
- return "/lib/ld-linux-armhf.so.3";
- } else {
- return "/lib/ld-linux.so.3";
- }
-
- case ZigLLVM_mips:
- case ZigLLVM_mipsel:
- case ZigLLVM_mips64:
- case ZigLLVM_mips64el:
- zig_panic("TODO implement target_dynamic_linker for mips");
-
- case ZigLLVM_ppc:
- return "/lib/ld.so.1";
-
- case ZigLLVM_ppc64:
- return "/lib64/ld64.so.2";
-
- case ZigLLVM_ppc64le:
- return "/lib64/ld64.so.2";
-
- case ZigLLVM_systemz:
- return "/lib64/ld64.so.1";
-
- case ZigLLVM_sparcv9:
- return "/lib64/ld-linux.so.2";
-
- case ZigLLVM_x86_64:
- if (abi == ZigLLVM_GNUX32) {
- return "/libx32/ld-linux-x32.so.2";
- }
- if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) {
- return "/lib/ld-musl-x86_64.so.1";
- }
- return "/lib64/ld-linux-x86-64.so.2";
-
- case ZigLLVM_wasm32:
- case ZigLLVM_wasm64:
- return nullptr;
-
- case ZigLLVM_riscv32:
- return "/lib/ld-linux-riscv32-ilp32.so.1";
- case ZigLLVM_riscv64:
- return "/lib/ld-linux-riscv64-lp64.so.1";
-
- case ZigLLVM_arc:
- case ZigLLVM_avr:
- case ZigLLVM_bpfel:
- case ZigLLVM_bpfeb:
- case ZigLLVM_hexagon:
- case ZigLLVM_msp430:
- case ZigLLVM_r600:
- case ZigLLVM_amdgcn:
- case ZigLLVM_tce:
- case ZigLLVM_tcele:
- case ZigLLVM_xcore:
- case ZigLLVM_nvptx:
- case ZigLLVM_nvptx64:
- case ZigLLVM_le32:
- case ZigLLVM_le64:
- case ZigLLVM_amdil:
- case ZigLLVM_amdil64:
- case ZigLLVM_hsail:
- case ZigLLVM_hsail64:
- case ZigLLVM_spir:
- case ZigLLVM_spir64:
- case ZigLLVM_kalimba:
- case ZigLLVM_shave:
- case ZigLLVM_lanai:
- case ZigLLVM_renderscript32:
- case ZigLLVM_renderscript64:
- case ZigLLVM_ve:
- zig_panic("TODO implement target_dynamic_linker for this arch");
- }
- zig_unreachable();
- }
- case OsFreestanding:
- case OsIOS:
- case OsTvOS:
- case OsWatchOS:
- case OsMacOSX:
- case OsUefi:
- case OsWindows:
- case OsEmscripten:
- case OsOther:
- return nullptr;
-
- case OsAnanas:
- case OsCloudABI:
- case OsFuchsia:
- case OsKFreeBSD:
- case OsLv2:
- case OsOpenBSD:
- case OsSolaris:
- case OsHaiku:
- case OsMinix:
- case OsRTEMS:
- case OsNaCl:
- case OsCNK:
- case OsAIX:
- case OsCUDA:
- case OsNVCL:
- case OsAMDHSA:
- case OsPS4:
- case OsELFIAMCU:
- case OsMesa3D:
- case OsContiki:
- case OsAMDPAL:
- case OsHermitCore:
- case OsHurd:
- case OsWASI:
- zig_panic("TODO implement target_dynamic_linker for this OS");
- }
- zig_unreachable();
-}
-
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) {
assert(host_target != nullptr);
@@ -1436,10 +915,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
return true;
}
- if (guest_target->os == host_target->os && guest_target->arch == host_target->arch &&
- guest_target->sub_arch == host_target->sub_arch)
- {
- // OS, arch, and sub-arch match
+ if (guest_target->os == host_target->os && guest_target->arch == host_target->arch) {
+ // OS and arch match
return true;
}
@@ -1861,7 +1338,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) {
out_target->arch = libcs_available[index].arch;
out_target->os = libcs_available[index].os;
out_target->abi = libcs_available[index].abi;
- out_target->sub_arch = ZigLLVM_NoSubArch;
out_target->vendor = ZigLLVM_UnknownVendor;
out_target->is_native = false;
}
diff --git a/src/target.hpp b/src/target.hpp
@@ -8,61 +8,10 @@
#ifndef ZIG_TARGET_HPP
#define ZIG_TARGET_HPP
-#include <zig_llvm.h>
+#include "stage2.h"
struct Buf;
-// Synchronize with target.cpp::os_list
-enum Os {
- OsFreestanding,
- OsAnanas,
- OsCloudABI,
- OsDragonFly,
- OsFreeBSD,
- OsFuchsia,
- OsIOS,
- OsKFreeBSD,
- OsLinux,
- OsLv2, // PS3
- OsMacOSX,
- OsNetBSD,
- OsOpenBSD,
- OsSolaris,
- OsWindows,
- OsHaiku,
- OsMinix,
- OsRTEMS,
- OsNaCl, // Native Client
- OsCNK, // BG/P Compute-Node Kernel
- OsAIX,
- OsCUDA, // NVIDIA CUDA
- OsNVCL, // NVIDIA OpenCL
- OsAMDHSA, // AMD HSA Runtime
- OsPS4,
- OsELFIAMCU,
- OsTvOS, // Apple tvOS
- OsWatchOS, // Apple watchOS
- OsMesa3D,
- OsContiki,
- OsAMDPAL,
- OsHermitCore,
- OsHurd,
- OsWASI,
- OsEmscripten,
- OsUefi,
- OsOther,
-};
-
-// Synchronize with target.cpp::subarch_list_list
-enum SubArchList {
- SubArchListNone,
- SubArchListArm32,
- SubArchListArm64,
- SubArchListKalimba,
- SubArchListMips,
- SubArchListPPC,
-};
-
enum TargetSubsystem {
TargetSubsystemConsole,
TargetSubsystemWindows,
@@ -79,23 +28,6 @@ enum TargetSubsystem {
TargetSubsystemAuto
};
-struct ZigGLibCVersion {
- uint32_t major; // always 2
- uint32_t minor;
- uint32_t patch;
-};
-
-struct ZigTarget {
- ZigLLVM_ArchType arch;
- ZigLLVM_SubArchType sub_arch;
- ZigLLVM_VendorType vendor;
- Os os;
- ZigLLVM_EnvironmentType abi;
- ZigGLibCVersion *glibc_version; // null means default
- Stage2CpuFeatures *cpu_features;
- bool is_native;
-};
-
enum CIntType {
CIntTypeShort,
CIntTypeUShort,
@@ -109,9 +41,8 @@ enum CIntType {
CIntTypeCount,
};
-Error target_parse_triple(ZigTarget *target, const char *triple);
-Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub,
- const char *archsub_ptr, size_t archsub_len);
+Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu);
+Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
@@ -122,15 +53,6 @@ size_t target_arch_count(void);
ZigLLVM_ArchType target_arch_enum(size_t index);
const char *target_arch_name(ZigLLVM_ArchType arch);
-SubArchList target_subarch_list(ZigLLVM_ArchType arch);
-size_t target_subarch_count(SubArchList sub_arch_list);
-ZigLLVM_SubArchType target_subarch_enum(SubArchList subarch_list, size_t index);
-const char *target_subarch_name(ZigLLVM_SubArchType subarch);
-
-size_t target_subarch_list_count(void);
-SubArchList target_subarch_list_enum(size_t index);
-const char *target_subarch_list_name(SubArchList sub_arch_list);
-
const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch);
size_t target_vendor_count(void);
@@ -169,8 +91,6 @@ const char *target_lib_file_prefix(const ZigTarget *target);
const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
size_t version_major, size_t version_minor, size_t version_patch);
-const char *target_dynamic_linker(const ZigTarget *target);
-
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
ZigLLVM_OSType get_llvm_os_type(Os os_type);
diff --git a/src/userland.cpp b/src/userland.cpp
@@ -1,146 +0,0 @@
-// This file is a shim for zig1. The real implementations of these are in
-// src-self-hosted/stage1.zig
-
-#include "userland.h"
-#include "util.hpp"
-#include "zig_llvm.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-Error stage2_translate_c(struct Stage2Ast **out_ast,
- struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
- const char **args_begin, const char **args_end, const char *resources_path)
-{
- const char *msg = "stage0 called stage2_translate_c";
- stage2_panic(msg, strlen(msg));
-}
-
-void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
- const char *msg = "stage0 called stage2_free_clang_errors";
- stage2_panic(msg, strlen(msg));
-}
-
-void stage2_zen(const char **ptr, size_t *len) {
- const char *msg = "stage0 called stage2_zen";
- stage2_panic(msg, strlen(msg));
-}
-
-void stage2_attach_segfault_handler(void) { }
-
-void stage2_panic(const char *ptr, size_t len) {
- fwrite(ptr, 1, len, stderr);
- fprintf(stderr, "\n");
- fflush(stderr);
- abort();
-}
-
-void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) {
- const char *msg = "stage0 called stage2_render_ast";
- stage2_panic(msg, strlen(msg));
-}
-
-int stage2_fmt(int argc, char **argv) {
- const char *msg = "stage0 called stage2_fmt";
- stage2_panic(msg, strlen(msg));
-}
-
-stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
- const char *msg = "stage0 called stage2_DepTokenizer_init";
- stage2_panic(msg, strlen(msg));
-}
-
-void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
- const char *msg = "stage0 called stage2_DepTokenizer_deinit";
- stage2_panic(msg, strlen(msg));
-}
-
-stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
- const char *msg = "stage0 called stage2_DepTokenizer_next";
- stage2_panic(msg, strlen(msg));
-}
-
-
-struct Stage2Progress {
- int trash;
-};
-
-struct Stage2ProgressNode {
- int trash;
-};
-
-Stage2Progress *stage2_progress_create(void) {
- return nullptr;
-}
-
-void stage2_progress_destroy(Stage2Progress *progress) {}
-
-Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
- const char *name_ptr, size_t name_len, size_t estimated_total_items)
-{
- return nullptr;
-}
-Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
- const char *name_ptr, size_t name_len, size_t estimated_total_items)
-{
- return nullptr;
-}
-void stage2_progress_end(Stage2ProgressNode *node) {}
-void stage2_progress_complete_one(Stage2ProgressNode *node) {}
-void stage2_progress_disable_tty(Stage2Progress *progress) {}
-void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
-
-struct Stage2CpuFeatures {
- const char *llvm_cpu_name;
- const char *llvm_cpu_features;
- const char *builtin_str;
- const char *cache_hash;
-};
-
-Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple,
- const char *cpu_name, const char *cpu_features)
-{
- if (zig_triple == nullptr) {
- Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
- result->llvm_cpu_name = ZigLLVMGetHostCPUName();
- result->llvm_cpu_features = ZigLLVMGetNativeFeatures();
- result->builtin_str = "arch.getBaselineCpuFeatures();\n";
- result->cache_hash = "native\n\n";
- *out = result;
- return ErrorNone;
- }
- if (cpu_name == nullptr && cpu_features == nullptr) {
- Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>();
- result->builtin_str = "arch.getBaselineCpuFeatures();\n";
- result->cache_hash = "\n\n";
- *out = result;
- return ErrorNone;
- }
-
- const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features";
- stage2_panic(msg, strlen(msg));
-}
-
-void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features,
- const char **ptr, size_t *len)
-{
- *ptr = cpu_features->cache_hash;
- *len = strlen(cpu_features->cache_hash);
-}
-const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) {
- return cpu_features->llvm_cpu_name;
-}
-const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) {
- return cpu_features->llvm_cpu_features;
-}
-void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features,
- const char **ptr, size_t *len)
-{
- *ptr = cpu_features->builtin_str;
- *len = strlen(cpu_features->builtin_str);
-}
-
-int stage2_cmd_targets(const char *zig_triple) {
- const char *msg = "stage0 called stage2_cmd_targets";
- stage2_panic(msg, strlen(msg));
-}
diff --git a/src/userland.h b/src/userland.h
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2019 Andrew Kelley
- *
- * This file is part of zig, which is MIT licensed.
- * See http://opensource.org/licenses/MIT
- */
-
-#ifndef ZIG_USERLAND_H
-#define ZIG_USERLAND_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-#define ZIG_EXTERN_C extern "C"
-#else
-#define ZIG_EXTERN_C
-#endif
-
-#if defined(_MSC_VER)
-#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
-#else
-#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
-#endif
-
-// ABI warning: the types and declarations in this file must match both those in
-// userland.cpp and src-self-hosted/stage1.zig.
-
-// ABI warning
-enum Error {
- ErrorNone,
- ErrorNoMem,
- ErrorInvalidFormat,
- ErrorSemanticAnalyzeFail,
- ErrorAccess,
- ErrorInterrupted,
- ErrorSystemResources,
- ErrorFileNotFound,
- ErrorFileSystem,
- ErrorFileTooBig,
- ErrorDivByZero,
- ErrorOverflow,
- ErrorPathAlreadyExists,
- ErrorUnexpected,
- ErrorExactDivRemainder,
- ErrorNegativeDenominator,
- ErrorShiftedOutOneBits,
- ErrorCCompileErrors,
- ErrorEndOfFile,
- ErrorIsDir,
- ErrorNotDir,
- ErrorUnsupportedOperatingSystem,
- ErrorSharingViolation,
- ErrorPipeBusy,
- ErrorPrimitiveTypeNotFound,
- ErrorCacheUnavailable,
- ErrorPathTooLong,
- ErrorCCompilerCannotFindFile,
- ErrorNoCCompilerInstalled,
- ErrorReadingDepFile,
- ErrorInvalidDepFile,
- ErrorMissingArchitecture,
- ErrorMissingOperatingSystem,
- ErrorUnknownArchitecture,
- ErrorUnknownOperatingSystem,
- ErrorUnknownABI,
- ErrorInvalidFilename,
- ErrorDiskQuota,
- ErrorDiskSpace,
- ErrorUnexpectedWriteFailure,
- ErrorUnexpectedSeekFailure,
- ErrorUnexpectedFileTruncationFailure,
- ErrorUnimplemented,
- ErrorOperationAborted,
- ErrorBrokenPipe,
- ErrorNoSpaceLeft,
- ErrorNotLazy,
- ErrorIsAsync,
- ErrorImportOutsidePkgPath,
- ErrorUnknownCpu,
- ErrorUnknownSubArchitecture,
- ErrorUnknownCpuFeature,
- ErrorInvalidCpuFeatures,
- ErrorInvalidLlvmCpuFeaturesFormat,
- ErrorUnknownApplicationBinaryInterface,
-};
-
-// ABI warning
-struct Stage2ErrorMsg {
- const char *filename_ptr; // can be null
- size_t filename_len;
- const char *msg_ptr;
- size_t msg_len;
- const char *source; // valid until the ASTUnit is freed. can be null
- unsigned line; // 0 based
- unsigned column; // 0 based
- unsigned offset; // byte offset into source
-};
-
-// ABI warning
-struct Stage2Ast;
-
-// ABI warning
-ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
- struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
- const char **args_begin, const char **args_end, const char *resources_path);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_attach_segfault_handler(void);
-
-// ABI warning
-ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
-
-// ABI warning
-ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
-
-// ABI warning
-struct stage2_DepTokenizer {
- void *handle;
-};
-
-// ABI warning
-struct stage2_DepNextResult {
- enum TypeId {
- error,
- null,
- target,
- prereq,
- };
-
- TypeId type_id;
-
- // when ent == error --> error text
- // when ent == null --> undefined
- // when ent == target --> target pathname
- // when ent == prereq --> prereq pathname
- const char *textz;
-};
-
-// ABI warning
-ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
-
-// ABI warning
-ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
-
-// ABI warning
-struct Stage2Progress;
-// ABI warning
-struct Stage2ProgressNode;
-// ABI warning
-ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
-// ABI warning
-ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
-// ABI warning
-ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
-// ABI warning
-ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
- const char *name_ptr, size_t name_len, size_t estimated_total_items);
-// ABI warning
-ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
- const char *name_ptr, size_t name_len, size_t estimated_total_items);
-// ABI warning
-ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
-// ABI warning
-ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
-// ABI warning
-ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
- size_t completed_count, size_t estimated_total_items);
-
-// ABI warning
-struct Stage2CpuFeatures;
-
-// ABI warning
-ZIG_EXTERN_C Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result,
- const char *zig_triple, const char *cpu_name, const char *cpu_features);
-
-// ABI warning
-ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features);
-
-// ABI warning
-ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features,
- const char **ptr, size_t *len);
-
-// ABI warning
-ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features,
- const char **ptr, size_t *len);
-
-// ABI warning
-ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple);
-
-
-#endif
diff --git a/src/util.cpp b/src/util.cpp
@@ -6,7 +6,7 @@
*/
#include "util.hpp"
-#include "userland.h"
+#include "stage2.h"
#include <stdio.h>
#include <stdarg.h>
diff --git a/src/windows_sdk.h b/src/windows_sdk.h
@@ -16,6 +16,7 @@
#include <stddef.h>
+// ABI warning - src-self-hosted/windows_sdk.zig
struct ZigWindowsSDK {
const char *path10_ptr;
size_t path10_len;
@@ -33,6 +34,7 @@ struct ZigWindowsSDK {
size_t msvc_lib_dir_len;
};
+// ABI warning - src-self-hosted/windows_sdk.zig
enum ZigFindWindowsSdkError {
ZigFindWindowsSdkErrorNone,
ZigFindWindowsSdkErrorOutOfMemory,
@@ -40,8 +42,10 @@ enum ZigFindWindowsSdkError {
ZigFindWindowsSdkErrorPathTooLong,
};
+// ABI warning - src-self-hosted/windows_sdk.zig
ZIG_EXTERN_C enum ZigFindWindowsSdkError zig_find_windows_sdk(struct ZigWindowsSDK **out_sdk);
+// ABI warning - src-self-hosted/windows_sdk.zig
ZIG_EXTERN_C void zig_free_windows_sdk(struct ZigWindowsSDK *sdk);
#endif
diff --git a/src/zig_clang.h b/src/zig_clang.h
@@ -8,7 +8,7 @@
#ifndef ZIG_ZIG_CLANG_H
#define ZIG_ZIG_CLANG_H
-#include "userland.h"
+#include "stage2.h"
#include <inttypes.h>
#include <stdbool.h>
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
@@ -162,17 +162,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
}
bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
- const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
- bool is_small, bool time_report)
+ char **error_message, bool is_debug,
+ bool is_small, bool time_report,
+ const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)
{
TimePassesIsEnabled = time_report;
- std::error_code EC;
- raw_fd_ostream dest(filename, EC, sys::fs::F_None);
- if (EC) {
- *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
- return true;
+ raw_fd_ostream *dest_asm = nullptr;
+ raw_fd_ostream *dest_bin = nullptr;
+
+ if (asm_filename) {
+ std::error_code EC;
+ dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None);
+ if (EC) {
+ *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
+ return true;
+ }
}
+ if (bin_filename) {
+ std::error_code EC;
+ dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None);
+ if (EC) {
+ *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
+ return true;
+ }
+ }
+
TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
target_machine->setO0WantsFastISel(true);
@@ -223,49 +238,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
}
PMBuilder->populateFunctionPassManager(FPM);
- // Set up the per-module pass manager.
- legacy::PassManager MPM;
- MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
- PMBuilder->populateModulePassManager(MPM);
-
- // Set output pass.
- CodeGenFileType ft;
- if (output_type != ZigLLVM_EmitLLVMIr) {
- switch (output_type) {
- case ZigLLVM_EmitAssembly:
- ft = CGFT_AssemblyFile;
- break;
- case ZigLLVM_EmitBinary:
- ft = CGFT_ObjectFile;
- break;
- default:
- abort();
+ {
+ // Set up the per-module pass manager.
+ legacy::PassManager MPM;
+ MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
+ PMBuilder->populateModulePassManager(MPM);
+
+ // Set output passes.
+ if (dest_bin) {
+ if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, CGFT_ObjectFile)) {
+ *error_message = strdup("TargetMachine can't emit an object file");
+ return true;
+ }
}
-
- if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) {
- *error_message = strdup("TargetMachine can't emit a file of this type");
- return true;
+ if (dest_asm) {
+ if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, CGFT_AssemblyFile)) {
+ *error_message = strdup("TargetMachine can't emit an assembly file");
+ return true;
+ }
}
- }
- // run per function optimization passes
- FPM.doInitialization();
- for (Function &F : *module)
- if (!F.isDeclaration())
- FPM.run(F);
- FPM.doFinalization();
+ // run per function optimization passes
+ FPM.doInitialization();
+ for (Function &F : *module)
+ if (!F.isDeclaration())
+ FPM.run(F);
+ FPM.doFinalization();
- MPM.run(*module);
+ MPM.run(*module);
- if (output_type == ZigLLVM_EmitLLVMIr) {
- if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
- return true;
+ if (llvm_ir_filename) {
+ if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {
+ return true;
+ }
+ }
+
+ if (time_report) {
+ TimerGroup::printAll(errs());
}
- }
- if (time_report) {
- TimerGroup::printAll(errs());
+ // MPM goes out of scope and writes to the out streams
}
+
+ delete dest_asm;
+ delete dest_bin;
+
return false;
}
@@ -792,7 +809,7 @@ const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) {
return (const char*)Triple::getEnvironmentTypeName((Triple::EnvironmentType)env_type).bytes_begin();
}
-void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *sub_arch_type,
+void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type,
ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
ZigLLVM_ObjectFormatType *oformat)
{
@@ -800,7 +817,6 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
Triple triple(Triple::normalize(native_triple));
*arch_type = (ZigLLVM_ArchType)triple.getArch();
- *sub_arch_type = (ZigLLVM_SubArchType)triple.getSubArch();
*vendor_type = (ZigLLVM_VendorType)triple.getVendor();
*os_type = (ZigLLVM_OSType)triple.getOS();
*environ_type = (ZigLLVM_EnvironmentType)triple.getEnvironment();
@@ -809,70 +825,6 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
free(native_triple);
}
-const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
- switch (sub_arch) {
- case ZigLLVM_NoSubArch:
- return "";
- case ZigLLVM_ARMSubArch_v8_5a:
- return "v8.5a";
- case ZigLLVM_ARMSubArch_v8_4a:
- return "v8.4a";
- case ZigLLVM_ARMSubArch_v8_3a:
- return "v8.3a";
- case ZigLLVM_ARMSubArch_v8_2a:
- return "v8.2a";
- case ZigLLVM_ARMSubArch_v8_1a:
- return "v8.1a";
- case ZigLLVM_ARMSubArch_v8:
- return "v8a";
- case ZigLLVM_ARMSubArch_v8r:
- return "v8r";
- case ZigLLVM_ARMSubArch_v8m_baseline:
- return "v8m.base";
- case ZigLLVM_ARMSubArch_v8m_mainline:
- return "v8m.main";
- case ZigLLVM_ARMSubArch_v8_1m_mainline:
- return "v8.1m.main";
- case ZigLLVM_ARMSubArch_v7:
- return "v7a";
- case ZigLLVM_ARMSubArch_v7em:
- return "v7em";
- case ZigLLVM_ARMSubArch_v7m:
- return "v7m";
- case ZigLLVM_ARMSubArch_v7s:
- return "v7s";
- case ZigLLVM_ARMSubArch_v7k:
- return "v7k";
- case ZigLLVM_ARMSubArch_v7ve:
- return "v7ve";
- case ZigLLVM_ARMSubArch_v6:
- return "v6";
- case ZigLLVM_ARMSubArch_v6m:
- return "v6m";
- case ZigLLVM_ARMSubArch_v6k:
- return "v6k";
- case ZigLLVM_ARMSubArch_v6t2:
- return "v6t2";
- case ZigLLVM_ARMSubArch_v5:
- return "v5";
- case ZigLLVM_ARMSubArch_v5te:
- return "v5te";
- case ZigLLVM_ARMSubArch_v4t:
- return "v4t";
- case ZigLLVM_KalimbaSubArch_v3:
- return "v3";
- case ZigLLVM_KalimbaSubArch_v4:
- return "v4";
- case ZigLLVM_KalimbaSubArch_v5:
- return "v5";
- case ZigLLVM_MipsSubArch_r6:
- return "r6";
- case ZigLLVM_PPCSubArch_spe:
- return "spe";
- }
- abort();
-}
-
void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) {
unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
@@ -1210,36 +1162,6 @@ static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64
static_assert((Triple::ArchType)ZigLLVM_ve == Triple::ve, "");
static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
-static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1m_mainline == Triple::ARMSubArch_v8_1m_mainline, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, "");
-static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, "");
-static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, "");
-static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, "");
-static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
-static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
-static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, "");
-static_assert((Triple::SubArchType)ZigLLVM_PPCSubArch_spe == Triple::PPCSubArch_spe, "");
-
static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, "");
static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, "");
static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, "");
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
@@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
-// We use a custom enum here since LLVM does not expose LLVMIr as an emit
-// output through the same mechanism as assembly/binary.
-enum ZigLLVM_EmitOutputType {
- ZigLLVM_EmitAssembly,
- ZigLLVM_EmitBinary,
- ZigLLVM_EmitLLVMIr,
-};
-
ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
- const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
- bool is_small, bool time_report);
+ char **error_message, bool is_debug,
+ bool is_small, bool time_report,
+ const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename);
ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
@@ -332,43 +325,6 @@ enum ZigLLVM_ArchType {
ZigLLVM_LastArchType = ZigLLVM_ve
};
-// synchronize with lists in target.cpp
-enum ZigLLVM_SubArchType {
- ZigLLVM_NoSubArch,
-
- ZigLLVM_ARMSubArch_v8_5a,
- ZigLLVM_ARMSubArch_v8_4a,
- ZigLLVM_ARMSubArch_v8_3a,
- ZigLLVM_ARMSubArch_v8_2a,
- ZigLLVM_ARMSubArch_v8_1a,
- ZigLLVM_ARMSubArch_v8,
- ZigLLVM_ARMSubArch_v8r,
- ZigLLVM_ARMSubArch_v8m_baseline,
- ZigLLVM_ARMSubArch_v8m_mainline,
- ZigLLVM_ARMSubArch_v8_1m_mainline,
- ZigLLVM_ARMSubArch_v7,
- ZigLLVM_ARMSubArch_v7em,
- ZigLLVM_ARMSubArch_v7m,
- ZigLLVM_ARMSubArch_v7s,
- ZigLLVM_ARMSubArch_v7k,
- ZigLLVM_ARMSubArch_v7ve,
- ZigLLVM_ARMSubArch_v6,
- ZigLLVM_ARMSubArch_v6m,
- ZigLLVM_ARMSubArch_v6k,
- ZigLLVM_ARMSubArch_v6t2,
- ZigLLVM_ARMSubArch_v5,
- ZigLLVM_ARMSubArch_v5te,
- ZigLLVM_ARMSubArch_v4t,
-
- ZigLLVM_KalimbaSubArch_v3,
- ZigLLVM_KalimbaSubArch_v4,
- ZigLLVM_KalimbaSubArch_v5,
-
- ZigLLVM_MipsSubArch_r6,
-
- ZigLLVM_PPCSubArch_spe,
-};
-
enum ZigLLVM_VendorType {
ZigLLVM_UnknownVendor,
@@ -526,7 +482,6 @@ LLVMValueRef ZigLLVMBuildAtomicRMW(LLVMBuilderRef B, enum ZigLLVM_AtomicRMWBinOp
#define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29)
ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
-ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
ZIG_EXTERN_C const char *ZigLLVMGetOSTypeName(enum ZigLLVM_OSType os);
ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentType abi);
@@ -541,7 +496,7 @@ ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **fil
bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,
const char *output_lib_path, const bool kill_at);
-ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,
+ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type,
enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
enum ZigLLVM_ObjectFormatType *oformat);
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
@@ -3,6 +3,35 @@ const builtin = @import("builtin");
const Target = @import("std").Target;
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.addTest("slice to pointer conversion mismatch",
+ \\pub fn bytesAsSlice(bytes: var) [*]align(1) const u16 {
+ \\ return @ptrCast([*]align(1) const u16, bytes.ptr)[0..1];
+ \\}
+ \\test "bytesAsSlice" {
+ \\ const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF };
+ \\ const slice = bytesAsSlice(bytes[0..]);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:54: error: expected type '[*]align(1) const u16', found '[]align(1) const u16'",
+ });
+
+ cases.addTest("access invalid @typeInfo decl",
+ \\const A = B;
+ \\test "Crash" {
+ \\ _ = @typeInfo(@This()).Struct.decls[0];
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:1:11: error: use of undeclared identifier 'B'",
+ });
+
+ cases.addTest("reject extern function definitions with body",
+ \\extern "c" fn definitelyNotInLibC(a: i32, b: i32) i32 {
+ \\ return a + b;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:1:1: error: extern functions have no body",
+ });
+
cases.addTest("duplicate field in anonymous struct literal",
\\export fn entry() void {
\\ const anon = .{
@@ -30,10 +59,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'",
});
- cases.addTest("dependency loop in top-level decl with @TypeInfo",
- \\export const foo = @typeInfo(@This());
+ cases.addTest("dependency loop in top-level decl with @TypeInfo when accessing the decls",
+ \\export const foo = @typeInfo(@This()).Struct.decls;
, &[_][]const u8{
"tmp.zig:1:20: error: dependency loop detected",
+ "tmp.zig:1:45: note: referenced here",
});
cases.add("function call assigned to incorrect type",
@@ -332,8 +362,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
tc.target = Target{
.Cross = .{
- .arch = .wasm32,
- .cpu_features = Target.Arch.wasm32.getBaselineCpuFeatures(),
+ .cpu = Target.Cpu.baseline(.wasm32),
.os = .wasi,
.abi = .none,
},
@@ -734,8 +763,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
tc.target = Target{
.Cross = .{
- .arch = .x86_64,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .linux,
.abi = .gnu,
},
@@ -1346,24 +1374,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:8:28: note: referenced here",
});
- cases.add("@typeInfo causing depend on itself compile error",
- \\const start = struct {
- \\ fn crash() bug() {
- \\ return bug;
- \\ }
- \\};
- \\fn bug() void {
- \\ _ = @typeInfo(start).Struct;
- \\}
- \\export fn entry() void {
- \\ var boom = start.crash();
- \\}
- , &[_][]const u8{
- "tmp.zig:7:9: error: dependency loop detected",
- "tmp.zig:2:19: note: referenced here",
- "tmp.zig:10:21: note: referenced here",
- });
-
cases.add("enum field value references enum",
\\pub const Foo = extern enum {
\\ A = Foo.B,
@@ -1647,7 +1657,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ var ptr: [*c]u8 = (1 << 64) + 1;
\\}
\\export fn b() void {
- \\ var x: @IntType(false, 65) = 0x1234;
+ \\ var x: u65 = 0x1234;
\\ var ptr: [*c]u8 = x;
\\}
, &[_][]const u8{
@@ -1886,13 +1896,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add("exceeded maximum bit width of integer",
\\export fn entry1() void {
- \\ const T = @IntType(false, 65536);
+ \\ const T = u65536;
\\}
\\export fn entry2() void {
\\ var x: i65536 = 1;
\\}
, &[_][]const u8{
- "tmp.zig:2:31: error: integer value 65536 cannot be coerced to type 'u16'",
"tmp.zig:5:12: error: primitive integer type 'i65536' exceeds maximum bit width of 65535",
});
@@ -2932,14 +2941,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:11:13: error: error.B not a member of error set 'Set2'",
});
- cases.add("@memberCount of error",
- \\comptime {
- \\ _ = @memberCount(anyerror);
- \\}
- , &[_][]const u8{
- "tmp.zig:2:9: error: global error set member count not available at comptime",
- });
-
cases.add("duplicate error value in error set",
\\const Foo = error {
\\ Bar,
@@ -4735,16 +4736,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'",
});
- cases.add("convert fixed size array to slice with invalid size",
- \\export fn f() void {
- \\ var array: [5]u8 = undefined;
- \\ var foo = @bytesToSlice(u32, &array)[0];
- \\}
- , &[_][]const u8{
- "tmp.zig:3:15: error: unable to convert [5]u8 to []align(1) u32: size mismatch",
- "tmp.zig:3:29: note: u32 has size 4; remaining bytes: 1",
- });
-
cases.add("non-pure function returns type",
\\var a: u32 = 0;
\\pub fn List(comptime T: type) type {
@@ -5606,7 +5597,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add("globally shadowing a primitive type",
- \\const u16 = @intType(false, 8);
+ \\const u16 = u8;
\\export fn entry() void {
\\ const a: u16 = 300;
\\}
@@ -5947,93 +5938,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:2:1: error: invalid character: '\\t'",
});
- cases.add("@ArgType given non function parameter",
- \\comptime {
- \\ _ = @ArgType(i32, 3);
- \\}
- , &[_][]const u8{
- "tmp.zig:2:18: error: expected function, found 'i32'",
- });
-
- cases.add("@ArgType arg index out of bounds",
- \\comptime {
- \\ _ = @ArgType(@TypeOf(add), 2);
- \\}
- \\fn add(a: i32, b: i32) i32 { return a + b; }
- , &[_][]const u8{
- "tmp.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments",
- });
-
- cases.add("@memberType on unsupported type",
- \\comptime {
- \\ _ = @memberType(i32, 0);
- \\}
- , &[_][]const u8{
- "tmp.zig:2:21: error: type 'i32' does not support @memberType",
- });
-
- cases.add("@memberType on enum",
- \\comptime {
- \\ _ = @memberType(Foo, 0);
- \\}
- \\const Foo = enum {A,};
- , &[_][]const u8{
- "tmp.zig:2:21: error: type 'Foo' does not support @memberType",
- });
-
- cases.add("@memberType struct out of bounds",
- \\comptime {
- \\ _ = @memberType(Foo, 0);
- \\}
- \\const Foo = struct {};
- , &[_][]const u8{
- "tmp.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members",
- });
-
- cases.add("@memberType union out of bounds",
- \\comptime {
- \\ _ = @memberType(Foo, 1);
- \\}
- \\const Foo = union {A: void,};
- , &[_][]const u8{
- "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members",
- });
-
- cases.add("@memberName on unsupported type",
- \\comptime {
- \\ _ = @memberName(i32, 0);
- \\}
- , &[_][]const u8{
- "tmp.zig:2:21: error: type 'i32' does not support @memberName",
- });
-
- cases.add("@memberName struct out of bounds",
- \\comptime {
- \\ _ = @memberName(Foo, 0);
- \\}
- \\const Foo = struct {};
- , &[_][]const u8{
- "tmp.zig:2:26: error: member index 0 out of bounds; 'Foo' has 0 members",
- });
-
- cases.add("@memberName enum out of bounds",
- \\comptime {
- \\ _ = @memberName(Foo, 1);
- \\}
- \\const Foo = enum {A,};
- , &[_][]const u8{
- "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members",
- });
-
- cases.add("@memberName union out of bounds",
- \\comptime {
- \\ _ = @memberName(Foo, 1);
- \\}
- \\const Foo = union {A:i32,};
- , &[_][]const u8{
- "tmp.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members",
- });
-
cases.add("calling var args extern function, passing array instead of pointer",
\\export fn entry() void {
\\ foo("hello".*,);
@@ -6457,15 +6361,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(var) var' is generic",
});
- cases.add("getting @ArgType of generic function",
- \\fn generic(a: var) void {}
- \\comptime {
- \\ _ = @ArgType(@TypeOf(generic), 0);
- \\}
- , &[_][]const u8{
- "tmp.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var) var' is generic",
- });
-
cases.add("unsupported modifier at start of asm output constraint",
\\export fn foo() void {
\\ var bar: u32 = 3;
diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig
@@ -553,15 +553,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
);
cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size",
- \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
- \\ @import("std").os.exit(126);
+ \\const std = @import("std");
+ \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ \\ std.os.exit(126);
\\}
\\pub fn main() !void {
\\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
\\ if (x.len == 0) return error.Whatever;
\\}
\\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
- \\ return @bytesToSlice(i32, slice);
+ \\ return std.mem.bytesAsSlice(i32, slice);
\\}
);
@@ -656,17 +657,18 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
);
cases.addRuntimeSafety("@alignCast misaligned",
- \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
- \\ @import("std").os.exit(126);
+ \\const std = @import("std");
+ \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+ \\ std.os.exit(126);
\\}
\\pub fn main() !void {
\\ var array align(4) = [_]u32{0x11111111, 0x11111111};
- \\ const bytes = @sliceToBytes(array[0..]);
+ \\ const bytes = std.mem.sliceAsBytes(array[0..]);
\\ if (foo(bytes) != 0x11111111) return error.Wrong;
\\}
\\fn foo(bytes: []u8) u32 {
\\ const slice4 = bytes[1..5];
- \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
+ \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
\\ return int_slice[0];
\\}
);
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
@@ -38,6 +38,7 @@ comptime {
_ = @import("behavior/bugs/3112.zig");
_ = @import("behavior/bugs/3367.zig");
_ = @import("behavior/bugs/3384.zig");
+ _ = @import("behavior/bugs/3586.zig");
_ = @import("behavior/bugs/3742.zig");
_ = @import("behavior/bugs/394.zig");
_ = @import("behavior/bugs/421.zig");
@@ -91,7 +92,6 @@ comptime {
_ = @import("behavior/shuffle.zig");
_ = @import("behavior/sizeof_and_typeof.zig");
_ = @import("behavior/slice.zig");
- _ = @import("behavior/slicetobytes.zig");
_ = @import("behavior/struct.zig");
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig
@@ -81,20 +81,6 @@ fn testBytesAlign(b: u8) void {
expect(ptr.* == 0x33333333);
}
-test "specifying alignment allows slice cast" {
- testBytesAlignSlice(0x33);
-}
-fn testBytesAlignSlice(b: u8) void {
- var bytes align(4) = [_]u8{
- b,
- b,
- b,
- b,
- };
- const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
- expect(slice[0] == 0x33333333);
-}
-
test "@alignCast pointers" {
var x: u32 align(4) = 1;
expectsOnly1(&x);
diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig
@@ -334,7 +334,7 @@ test "async fn with inferred error set" {
var frame: [1]@Frame(middle) = undefined;
var fn_ptr = middle;
var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined;
- _ = @asyncCall(@sliceToBytes(frame[0..]), &result, fn_ptr);
+ _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr);
resume global_frame;
std.testing.expectError(error.Fail, result);
}
@@ -954,7 +954,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
fn doTheTest() void {
var frame: [1]@Frame(middle) = undefined;
var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined;
- _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle);
+ _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle);
resume global_frame;
std.testing.expectError(error.Fail, result);
}
@@ -1481,3 +1481,53 @@ test "handle defer interfering with return value spill" {
};
S.doTheTest();
}
+
+test "take address of temporary async frame" {
+ const S = struct {
+ var global_frame: anyframe = undefined;
+ var finished = false;
+
+ fn doTheTest() void {
+ _ = async asyncDoTheTest();
+ resume global_frame;
+ expect(finished);
+ }
+
+ fn asyncDoTheTest() void {
+ expect(finishIt(&async foo(10)) == 1245);
+ finished = true;
+ }
+
+ fn foo(arg: i32) i32 {
+ global_frame = @frame();
+ suspend;
+ return arg + 1234;
+ }
+
+ fn finishIt(frame: anyframe->i32) i32 {
+ return (await frame) + 1;
+ }
+ };
+ S.doTheTest();
+}
+
+test "noasync await" {
+ const S = struct {
+ var finished = false;
+
+ fn doTheTest() void {
+ var frame = async foo(false);
+ expect(noasync await frame == 42);
+ finished = true;
+ }
+
+ fn foo(want_suspend: bool) i32 {
+ if (want_suspend) {
+ suspend;
+ }
+ return 42;
+ }
+ };
+ S.doTheTest();
+ expect(S.finished);
+}
diff --git a/test/stage1/behavior/bit_shifting.zig b/test/stage1/behavior/bit_shifting.zig
@@ -2,9 +2,9 @@ const std = @import("std");
const expect = std.testing.expect;
fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
- expect(Key == @IntType(false, Key.bit_count));
+ expect(Key == std.meta.IntType(false, Key.bit_count));
expect(Key.bit_count >= mask_bit_count);
- const ShardKey = @IntType(false, mask_bit_count);
+ const ShardKey = std.meta.IntType(false, mask_bit_count);
const shift_amount = Key.bit_count - ShardKey.bit_count;
return struct {
const Self = @This();
diff --git a/test/stage1/behavior/bugs/1851.zig b/test/stage1/behavior/bugs/1851.zig
@@ -13,7 +13,7 @@ test "allocation and looping over 3-byte integer" {
x[0] = 0xFFFFFF;
x[1] = 0xFFFFFF;
- const bytes = @sliceToBytes(x);
+ const bytes = std.mem.sliceAsBytes(x);
expect(@TypeOf(bytes) == []align(4) u8);
expect(bytes.len == 8);
diff --git a/test/stage1/behavior/bugs/3586.zig b/test/stage1/behavior/bugs/3586.zig
@@ -0,0 +1,11 @@
+const NoteParams = struct {};
+
+const Container = struct {
+ params: ?NoteParams,
+};
+
+test "fixed" {
+ var ctr = Container{
+ .params = NoteParams{},
+ };
+}
diff --git a/test/stage1/behavior/bugs/3742.zig b/test/stage1/behavior/bugs/3742.zig
@@ -17,7 +17,7 @@ pub const GET = struct {
};
pub fn isCommand(comptime T: type) bool {
- const tid = @typeId(T);
+ const tid = @typeInfo(T);
return (tid == .Struct or tid == .Enum or tid == .Union) and
@hasDecl(T, "Redis") and @hasDecl(T.Redis, "Command");
}
diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig
@@ -300,20 +300,6 @@ fn cast128Float(x: u128) f128 {
return @bitCast(f128, x);
}
-test "const slice widen cast" {
- const bytes align(4) = [_]u8{
- 0x12,
- 0x12,
- 0x12,
- 0x12,
- };
-
- const u32_value = @bytesToSlice(u32, bytes[0..])[0];
- expect(u32_value == 0x12121212);
-
- expect(@bitCast(u32, bytes) == 0x12121212);
-}
-
test "single-item pointer of array to slice and to unknown length pointer" {
testCastPtrOfArrayToSliceAndPtr();
comptime testCastPtrOfArrayToSliceAndPtr();
@@ -388,12 +374,6 @@ test "comptime_int @intToFloat" {
}
}
-test "@bytesToSlice keeps pointer alignment" {
- var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 };
- const numbers = @bytesToSlice(u32, bytes[0..]);
- comptime expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32);
-}
-
test "@intCast i32 to u7" {
var x: u128 = maxInt(u128);
var y: i32 = 120;
diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig
@@ -96,8 +96,8 @@ test "enum type" {
const bar = Bar.B;
expect(bar == Bar.B);
- expect(@memberCount(Foo) == 3);
- expect(@memberCount(Bar) == 4);
+ expect(@typeInfo(Foo).Union.fields.len == 3);
+ expect(@typeInfo(Bar).Enum.fields.len == 4);
expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
expect(@sizeOf(Bar) == 1);
}
diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig
@@ -3,7 +3,6 @@ const expect = std.testing.expect;
const expectError = std.testing.expectError;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
-const builtin = @import("builtin");
pub fn foo() anyerror!i32 {
const x = try bar();
@@ -84,8 +83,8 @@ test "error union type " {
fn testErrorUnionType() void {
const x: anyerror!i32 = 1234;
if (x) |value| expect(value == 1234) else |_| unreachable;
- expect(@typeId(@TypeOf(x)) == builtin.TypeId.ErrorUnion);
- expect(@typeId(@TypeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
+ expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
+ expect(@typeInfo(@TypeOf(x).ErrorSet) == .ErrorSet);
expect(@TypeOf(x).ErrorSet == anyerror);
}
@@ -100,7 +99,7 @@ const MyErrSet = error{
};
fn testErrorSetType() void {
- expect(@memberCount(MyErrSet) == 2);
+ expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2);
const a: MyErrSet!i32 = 5678;
const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig
@@ -654,8 +654,8 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
expect(b == 2);
}
-test "@tagName of @typeId" {
- const str = @tagName(@typeId(u8));
+test "@tagName of @typeInfo" {
+ const str = @tagName(@typeInfo(u8));
expect(std.mem.eql(u8, str, "Int"));
}
@@ -711,16 +711,6 @@ test "bit shift a u1" {
expect(y == 1);
}
-test "@bytesToslice on a packed struct" {
- const F = packed struct {
- a: u8,
- };
-
- var b = [1]u8{9};
- var f = @bytesToSlice(F, &b);
- expect(f[0].a == 9);
-}
-
test "comptime pointer cast array and then slice" {
const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
diff --git a/test/stage1/behavior/for.zig b/test/stage1/behavior/for.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
const mem = std.mem;
test "continue in for loop" {
@@ -142,3 +143,30 @@ test "for with null and T peer types and inferred result location type" {
S.doTheTest(&[_]u8{ 1, 2 });
comptime S.doTheTest(&[_]u8{ 1, 2 });
}
+
+test "for copies its payload" {
+ const S = struct {
+ fn doTheTest() void {
+ var x = [_]usize{ 1, 2, 3 };
+ for (x) |value, i| {
+ // Modify the original array
+ x[i] += 99;
+ expectEqual(value, i + 1);
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
+
+test "for on slice with allowzero ptr" {
+ const S = struct {
+ fn doTheTest(slice: []u8) void {
+ var ptr = @ptrCast([*]allowzero u8, slice.ptr)[0..slice.len];
+ for (ptr) |x, i| expect(x == i + 1);
+ for (ptr) |*x, i| expect(x.* == i + 1);
+ }
+ };
+ S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
+ comptime S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
+}
diff --git a/test/stage1/behavior/if.zig b/test/stage1/behavior/if.zig
@@ -1,4 +1,6 @@
-const expect = @import("std").testing.expect;
+const std = @import("std");
+const expect = std.testing.expect;
+const expectEqual = std.testing.expectEqual;
test "if statements" {
shouldBeEqual(1, 1);
@@ -90,3 +92,18 @@ test "if prongs cast to expected type instead of peer type resolution" {
S.doTheTest(false);
comptime S.doTheTest(false);
}
+
+test "while copies its payload" {
+ const S = struct {
+ fn doTheTest() void {
+ var tmp: ?i32 = 10;
+ if (tmp) |value| {
+ // Modify the original variable
+ tmp = null;
+ expectEqual(@as(i32, 10), value);
+ } else unreachable;
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig
@@ -266,7 +266,7 @@ fn testBinaryNot(x: u16) void {
}
test "small int addition" {
- var x: @IntType(false, 2) = 0;
+ var x: u2 = 0;
expect(x == 0);
x += 1;
diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig
@@ -3,7 +3,6 @@ const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const mem = std.mem;
const builtin = @import("builtin");
-const maxInt = std.math.maxInt;
// normal comment
@@ -25,35 +24,6 @@ test "call disabled extern fn" {
disabledExternFn();
}
-test "@IntType builtin" {
- expect(@IntType(true, 8) == i8);
- expect(@IntType(true, 16) == i16);
- expect(@IntType(true, 32) == i32);
- expect(@IntType(true, 64) == i64);
-
- expect(@IntType(false, 8) == u8);
- expect(@IntType(false, 16) == u16);
- expect(@IntType(false, 32) == u32);
- expect(@IntType(false, 64) == u64);
-
- expect(i8.bit_count == 8);
- expect(i16.bit_count == 16);
- expect(i32.bit_count == 32);
- expect(i64.bit_count == 64);
-
- expect(i8.is_signed);
- expect(i16.is_signed);
- expect(i32.is_signed);
- expect(i64.is_signed);
- expect(isize.is_signed);
-
- expect(!u8.is_signed);
- expect(!u16.is_signed);
- expect(!u32.is_signed);
- expect(!u64.is_signed);
- expect(!usize.is_signed);
-}
-
test "floating point primitive bit counts" {
expect(f16.bit_count == 16);
expect(f32.bit_count == 32);
@@ -377,26 +347,6 @@ test "string concatenation" {
expect(b[len] == 0);
}
-test "cast slice to u8 slice" {
- expect(@sizeOf(i32) == 4);
- var big_thing_array = [_]i32{ 1, 2, 3, 4 };
- const big_thing_slice: []i32 = big_thing_array[0..];
- const bytes = @sliceToBytes(big_thing_slice);
- expect(bytes.len == 4 * 4);
- bytes[4] = 0;
- bytes[5] = 0;
- bytes[6] = 0;
- bytes[7] = 0;
- expect(big_thing_slice[1] == 0);
- const big_thing_again = @bytesToSlice(i32, bytes);
- expect(big_thing_again[2] == 3);
- big_thing_again[2] = -1;
- expect(bytes[8] == maxInt(u8));
- expect(bytes[9] == maxInt(u8));
- expect(bytes[10] == maxInt(u8));
- expect(bytes[11] == maxInt(u8));
-}
-
test "pointer to void return type" {
testPointerToVoidReturnType() catch unreachable;
}
@@ -428,7 +378,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) void {
expect(ptr2[1] == 2.0);
}
-const Tid = builtin.TypeId;
const AStruct = struct {
x: i32,
};
@@ -445,40 +394,6 @@ const AUnion = union {
Two: void,
};
-test "@typeId" {
- comptime {
- expect(@typeId(type) == Tid.Type);
- expect(@typeId(void) == Tid.Void);
- expect(@typeId(bool) == Tid.Bool);
- expect(@typeId(noreturn) == Tid.NoReturn);
- expect(@typeId(i8) == Tid.Int);
- expect(@typeId(u8) == Tid.Int);
- expect(@typeId(i64) == Tid.Int);
- expect(@typeId(u64) == Tid.Int);
- expect(@typeId(f32) == Tid.Float);
- expect(@typeId(f64) == Tid.Float);
- expect(@typeId(*f32) == Tid.Pointer);
- expect(@typeId([2]u8) == Tid.Array);
- expect(@typeId(AStruct) == Tid.Struct);
- expect(@typeId(@TypeOf(1)) == Tid.ComptimeInt);
- expect(@typeId(@TypeOf(1.0)) == Tid.ComptimeFloat);
- expect(@typeId(@TypeOf(undefined)) == Tid.Undefined);
- expect(@typeId(@TypeOf(null)) == Tid.Null);
- expect(@typeId(?i32) == Tid.Optional);
- expect(@typeId(anyerror!i32) == Tid.ErrorUnion);
- expect(@typeId(anyerror) == Tid.ErrorSet);
- expect(@typeId(AnEnum) == Tid.Enum);
- expect(@typeId(@TypeOf(AUnionEnum.One)) == Tid.Enum);
- expect(@typeId(AUnionEnum) == Tid.Union);
- expect(@typeId(AUnion) == Tid.Union);
- expect(@typeId(fn () void) == Tid.Fn);
- expect(@typeId(@TypeOf(builtin)) == Tid.Type);
- // TODO bound fn
- // TODO arg tuple
- // TODO opaque
- }
-}
-
test "@typeName" {
const Struct = struct {};
const Union = union {
diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig
@@ -16,9 +16,9 @@ test "reflection: function return type, var args, and param types" {
expect(@TypeOf(dummy).ReturnType == i32);
expect(!@TypeOf(dummy).is_var_args);
expect(@TypeOf(dummy).arg_count == 3);
- expect(@ArgType(@TypeOf(dummy), 0) == bool);
- expect(@ArgType(@TypeOf(dummy), 1) == i32);
- expect(@ArgType(@TypeOf(dummy), 2) == f32);
+ expect(@typeInfo(@TypeOf(dummy)).Fn.args[0].arg_type.? == bool);
+ expect(@typeInfo(@TypeOf(dummy)).Fn.args[1].arg_type.? == i32);
+ expect(@typeInfo(@TypeOf(dummy)).Fn.args[2].arg_type.? == f32);
}
}
@@ -26,36 +26,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 {
return 1234;
}
-test "reflection: struct member types and names" {
- comptime {
- expect(@memberCount(Foo) == 3);
-
- expect(@memberType(Foo, 0) == i32);
- expect(@memberType(Foo, 1) == bool);
- expect(@memberType(Foo, 2) == void);
-
- expect(mem.eql(u8, @memberName(Foo, 0), "one"));
- expect(mem.eql(u8, @memberName(Foo, 1), "two"));
- expect(mem.eql(u8, @memberName(Foo, 2), "three"));
- }
-}
-
-test "reflection: enum member types and names" {
- comptime {
- expect(@memberCount(Bar) == 4);
-
- expect(@memberType(Bar, 0) == void);
- expect(@memberType(Bar, 1) == i32);
- expect(@memberType(Bar, 2) == bool);
- expect(@memberType(Bar, 3) == f64);
-
- expect(mem.eql(u8, @memberName(Bar, 0), "One"));
- expect(mem.eql(u8, @memberName(Bar, 1), "Two"));
- expect(mem.eql(u8, @memberName(Bar, 2), "Three"));
- expect(mem.eql(u8, @memberName(Bar, 3), "Four"));
- }
-}
-
test "reflection: @field" {
var f = Foo{
.one = 42,
diff --git a/test/stage1/behavior/slicetobytes.zig b/test/stage1/behavior/slicetobytes.zig
@@ -1,29 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const expect = std.testing.expect;
-
-test "@sliceToBytes packed struct at runtime and comptime" {
- const Foo = packed struct {
- a: u4,
- b: u4,
- };
- const S = struct {
- fn doTheTest() void {
- var foo: Foo = undefined;
- var slice = @sliceToBytes(@as(*[1]Foo, &foo)[0..1]);
- slice[0] = 0x13;
- switch (builtin.endian) {
- builtin.Endian.Big => {
- expect(foo.a == 0x1);
- expect(foo.b == 0x3);
- },
- builtin.Endian.Little => {
- expect(foo.a == 0x3);
- expect(foo.b == 0x1);
- },
- }
- }
- };
- S.doTheTest();
- comptime S.doTheTest();
-}
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
@@ -315,7 +315,7 @@ test "packed array 24bits" {
var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
bytes[bytes.len - 1] = 0xaa;
- const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
+ const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
expect(ptr.a == 0);
expect(ptr.b[0].field == 0);
expect(ptr.b[1].field == 0);
@@ -364,7 +364,7 @@ test "aligned array of packed struct" {
}
var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned);
- const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
+ const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0];
expect(ptr.a[0].a == 0xbb);
expect(ptr.a[0].b == 0xbb);
diff --git a/test/stage1/behavior/switch.zig b/test/stage1/behavior/switch.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const expect = std.testing.expect;
const expectError = std.testing.expectError;
+const expectEqual = std.testing.expectEqual;
test "switch with numbers" {
testSwitchWithNumbers(13);
@@ -493,3 +494,24 @@ test "switch on error set with single else" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "while copies its payload" {
+ const S = struct {
+ fn doTheTest() void {
+ var tmp: union(enum) {
+ A: u8,
+ B: u32,
+ } = .{ .A = 42 };
+ switch (tmp) {
+ .A => |value| {
+ // Modify the original union
+ tmp = .{ .B = 0x10101010 };
+ expectEqual(@as(u8, 42), value);
+ },
+ else => unreachable,
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
@@ -375,3 +375,14 @@ test "sentinel of opaque pointer type" {
const c_void_info = @typeInfo(*c_void);
expect(c_void_info.Pointer.sentinel == null);
}
+
+test "@typeInfo does not force declarations into existence" {
+ const S = struct {
+ x: i32,
+
+ fn doNotReferenceMe() void {
+ @compileError("test failed");
+ }
+ };
+ comptime expect(@typeInfo(S).Struct.fields.len == 1);
+}
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
@@ -531,7 +531,7 @@ var glbl: Foo1 = undefined;
test "global union with single field is correctly initialized" {
glbl = Foo1{
- .f = @memberType(Foo1, 0){ .x = 123 },
+ .f = @typeInfo(Foo1).Union.fields[0].field_type{ .x = 123 },
};
expect(glbl.f.x == 123);
}
diff --git a/test/stage1/behavior/while.zig b/test/stage1/behavior/while.zig
@@ -1,4 +1,5 @@
-const expect = @import("std").testing.expect;
+const std = @import("std");
+const expect = std.testing.expect;
test "while loop" {
var i: i32 = 0;
@@ -271,3 +272,18 @@ test "while error 2 break statements and an else" {
S.entry(true, false);
comptime S.entry(true, false);
}
+
+test "while copies its payload" {
+ const S = struct {
+ fn doTheTest() void {
+ var tmp: ?i32 = 10;
+ while (tmp) |value| {
+ // Modify the original variable
+ tmp = null;
+ expect(value == 10);
+ }
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
diff --git a/test/standalone/guess_number/main.zig b/test/standalone/guess_number/main.zig
@@ -5,6 +5,7 @@ const fmt = std.fmt;
pub fn main() !void {
const stdout = &io.getStdOut().outStream().stream;
+ const stdin = io.getStdIn();
try stdout.print("Welcome to the Guess Number Game in Zig.\n", .{});
@@ -22,13 +23,12 @@ pub fn main() !void {
try stdout.print("\nGuess a number between 1 and 100: ", .{});
var line_buf: [20]u8 = undefined;
- const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) {
- error.OutOfMemory => {
- try stdout.print("Input too long.\n", .{});
- continue;
- },
- else => return err,
- };
+ const amt = try stdin.read(&line_buf);
+ if (amt == line_buf.len) {
+ try stdout.print("Input too long.\n", .{});
+ continue;
+ }
+ const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n");
const guess = fmt.parseUnsigned(u8, line, 10) catch {
try stdout.print("Invalid number.\n", .{});
diff --git a/test/tests.zig b/test/tests.zig
@@ -55,20 +55,18 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .linux,
- .arch = .x86_64,
.abi = .none,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
},
},
},
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .linux,
- .arch = .x86_64,
.abi = .gnu,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
},
},
.link_libc = true,
@@ -76,9 +74,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .linux,
- .arch = .x86_64,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .musl,
},
},
@@ -88,9 +85,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.i386),
.os = .linux,
- .arch = .i386,
- .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .none,
},
},
@@ -98,9 +94,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.i386),
.os = .linux,
- .arch = .i386,
- .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .musl,
},
},
@@ -110,9 +105,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.aarch64),
.os = .linux,
- .arch = Target.Arch{ .aarch64 = .v8a },
- .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .none,
},
},
@@ -120,9 +114,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.aarch64),
.os = .linux,
- .arch = Target.Arch{ .aarch64 = .v8a },
- .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .musl,
},
},
@@ -131,9 +124,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.aarch64),
.os = .linux,
- .arch = Target.Arch{ .aarch64 = .v8a },
- .cpu_features = (Target.Arch{ .aarch64 = .v8a }).getBaselineCpuFeatures(),
.abi = .gnu,
},
},
@@ -141,45 +133,32 @@ const test_targets = blk: {
},
TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = Target.Arch{ .arm = .v8a },
- .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
- .abi = .none,
- },
- },
+ .target = Target.parse(.{
+ .arch_os_abi = "arm-linux-none",
+ .cpu_features = "generic+v8a",
+ }) catch unreachable,
},
TestTarget{
- .target = Target{
- .Cross = CrossTarget{
- .os = .linux,
- .arch = Target.Arch{ .arm = .v8a },
- .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
- .abi = .musleabihf,
- },
- },
+ .target = Target.parse(.{
+ .arch_os_abi = "arm-linux-musleabihf",
+ .cpu_features = "generic+v8a",
+ }) catch unreachable,
.link_libc = true,
},
// TODO https://github.com/ziglang/zig/issues/3287
//TestTarget{
- // .target = Target{
- // .Cross = CrossTarget{
- // .os = .linux,
- // .arch = Target.Arch{ .arm = .v8a },
- // .cpu_features = (Target.Arch{ .arm = .v8a }).getBaselineCpuFeatures(),
- // .abi = .gnueabihf,
- // },
- // },
+ // .target = Target.parse(.{
+ // .arch_os_abi = "arm-linux-gnueabihf",
+ // .cpu_features = "generic+v8a",
+ // }) catch unreachable,
// .link_libc = true,
//},
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.mipsel),
.os = .linux,
- .arch = .mipsel,
- .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
.abi = .none,
},
},
@@ -187,9 +166,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.mipsel),
.os = .linux,
- .arch = .mipsel,
- .cpu_features = Target.Arch.mipsel.getBaselineCpuFeatures(),
.abi = .musl,
},
},
@@ -236,9 +214,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .macosx,
- .arch = .x86_64,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
@@ -249,9 +226,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.i386),
.os = .windows,
- .arch = .i386,
- .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .msvc,
},
},
@@ -260,9 +236,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .windows,
- .arch = .x86_64,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .msvc,
},
},
@@ -271,9 +246,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.i386),
.os = .windows,
- .arch = .i386,
- .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
@@ -283,9 +257,8 @@ const test_targets = blk: {
TestTarget{
.target = Target{
.Cross = CrossTarget{
+ .cpu = Target.Cpu.baseline(.x86_64),
.os = .windows,
- .arch = .x86_64,
- .cpu_features = Target.Arch.x86_64.getBaselineCpuFeatures(),
.abi = .gnu,
},
},
@@ -513,7 +486,7 @@ pub fn addPkgTests(
const ArchTag = @TagType(builtin.Arch);
if (test_target.disable_native and
test_target.target.getOs() == builtin.os and
- @as(ArchTag, test_target.target.getArch()) == @as(ArchTag, builtin.arch))
+ test_target.target.getArch() == builtin.arch)
{
continue;
}
@@ -714,8 +687,10 @@ pub const StackTracesContext = struct {
const got: []const u8 = got_result: {
var buf = try Buffer.initSize(b.allocator, 0);
defer buf.deinit();
- var bytes = stderr.toSliceConst();
- if (bytes.len != 0 and bytes[bytes.len - 1] == '\n') bytes = bytes[0 .. bytes.len - 1];
+ const bytes = if (stderr.endsWith("\n"))
+ stderr.toSliceConst()[0 .. stderr.len() - 1]
+ else
+ stderr.toSliceConst()[0..stderr.len()];
var it = mem.separate(bytes, "\n");
process_lines: while (it.next()) |line| {
if (line.len == 0) continue;
diff --git a/test/translate_c.zig b/test/translate_c.zig
@@ -3,6 +3,13 @@ const builtin = @import("builtin");
const Target = @import("std").Target;
pub fn addCases(cases: *tests.TranslateCContext) void {
+ cases.add("macro line continuation",
+ \\#define FOO -\
+ \\BAR
+ , &[_][]const u8{
+ \\pub const FOO = -BAR;
+ });
+
cases.add("function prototype translated as optional",
\\typedef void (*fnptr_ty)(void);
\\typedef __attribute__((cdecl)) void (*fnptr_attr_ty)(void);
@@ -1088,10 +1095,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.addWithTarget("Calling convention", tests.Target{
.Cross = .{
+ .cpu = Target.Cpu.baseline(.i386),
.os = .linux,
- .arch = .i386,
.abi = .none,
- .cpu_features = Target.Arch.i386.getBaselineCpuFeatures(),
},
},
\\void __attribute__((fastcall)) foo1(float *a);
@@ -1107,14 +1113,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void;
});
- cases.addWithTarget("Calling convention", tests.Target{
- .Cross = .{
- .os = .linux,
- .arch = .{ .arm = .v8_5a },
- .abi = .none,
- .cpu_features = (Target.Arch{ .arm = .v8_5a }).getBaselineCpuFeatures(),
- },
- },
+ cases.addWithTarget("Calling convention", Target.parse(.{
+ .arch_os_abi = "arm-linux-none",
+ .cpu_features = "generic+v8_5a",
+ }) catch unreachable,
\\void __attribute__((pcs("aapcs"))) foo1(float *a);
\\void __attribute__((pcs("aapcs-vfp"))) foo2(float *a);
, &[_][]const u8{
@@ -1122,14 +1124,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo2(a: [*c]f32) callconv(.AAPCSVFP) void;
});
- cases.addWithTarget("Calling convention", tests.Target{
- .Cross = .{
- .os = .linux,
- .arch = .{ .aarch64 = .v8_5a },
- .abi = .none,
- .cpu_features = (Target.Arch{ .aarch64 = .v8_5a }).getBaselineCpuFeatures(),
- },
- },
+ cases.addWithTarget("Calling convention", Target.parse(.{
+ .arch_os_abi = "aarch64-linux-none",
+ .cpu_features = "generic+v8_5a",
+ }) catch unreachable,
\\void __attribute__((aarch64_vector_pcs)) foo1(float *a);
, &[_][]const u8{
\\pub fn foo1(a: [*c]f32) callconv(.Vectorcall) void;
@@ -1356,7 +1354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{
- \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
+ \\pub const NRF_GPIO = if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
});
cases.add("basic macro function",
@@ -2540,11 +2538,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO(bar) baz((void *)(baz))
\\#define BAR (void*) a
, &[_][]const u8{
- \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) {
- \\ return baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz));
+ \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) {
+ \\ return baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz));
\\}
,
- \\pub const BAR = if (@typeId(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeId(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a);
+ \\pub const BAR = if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a);
});
cases.add("macro conditional operator",