mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
Merge remote-tracking branch 'origin/master' into llvm10
This commit is contained in:
commit
97b2ac598b
@ -45,7 +45,6 @@ message("Configuring zig version ${ZIG_VERSION}")
|
||||
|
||||
set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
|
||||
set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
|
||||
set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
|
||||
set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation")
|
||||
|
||||
if(ZIG_STATIC)
|
||||
@ -414,19 +413,26 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
else()
|
||||
set(LIBUSERLAND_RELEASE_MODE "true")
|
||||
endif()
|
||||
if(ZIG_SKIP_INSTALL_LIB_FILES)
|
||||
set(ZIG_BUILD_INSTALL_STEP "")
|
||||
else()
|
||||
set(ZIG_BUILD_INSTALL_STEP "install")
|
||||
|
||||
set(BUILD_LIBUSERLAND_ARGS "build"
|
||||
--override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
|
||||
"-Doutput-dir=${CMAKE_BINARY_DIR}"
|
||||
"-Drelease=${LIBUSERLAND_RELEASE_MODE}"
|
||||
"-Dlib-files-only"
|
||||
--prefix "${CMAKE_INSTALL_PREFIX}"
|
||||
libuserland
|
||||
)
|
||||
|
||||
# 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
|
||||
--override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
|
||||
libuserland ${ZIG_BUILD_INSTALL_STEP}
|
||||
"-Doutput-dir=${CMAKE_BINARY_DIR}"
|
||||
"-Drelease=${LIBUSERLAND_RELEASE_MODE}"
|
||||
"-Dlib-files-only"
|
||||
--prefix "${CMAKE_INSTALL_PREFIX}"
|
||||
COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS}
|
||||
DEPENDS zig0
|
||||
BYPRODUCTS "${LIBUSERLAND}"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
@ -444,4 +450,15 @@ elseif(MINGW)
|
||||
target_link_libraries(zig ntdll)
|
||||
endif()
|
||||
add_dependencies(zig zig_build_libuserland)
|
||||
|
||||
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}\")")
|
||||
install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")")
|
||||
install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake)
|
||||
endif()
|
||||
|
@ -51,23 +51,28 @@ knowledge of Zig internals.**
|
||||
|
||||
### Editing Source Code
|
||||
|
||||
First, build the Stage 1 compiler as described in [the Building section](#building).
|
||||
First, build the Stage 1 compiler as described in [Building from Source](README.md#Building-from-Source).
|
||||
|
||||
One modification you may want to make is adding `-DZIG_SKIP_INSTALL_LIB_FILES=ON`
|
||||
to the cmake line. If you use the build directory as a working directory to run
|
||||
tests with, zig will find the lib files in the source directory, and they will not
|
||||
be "installed" every time you run `make`. This will allow you to make modifications
|
||||
directly to the standard library, for example, and have them effective immediately.
|
||||
Note that if you already ran `make` or `make install` with the default cmake
|
||||
settings, there will already be a `lib/` directory in your build directory. When
|
||||
executed from the build directory, zig will find this instead of the source lib/
|
||||
directory. Remove the unwanted directory so that the desired one can be found.
|
||||
Zig locates lib files relative to executable path by searching up the
|
||||
filesystem tree for a sub-path of `lib/zig/std/std.zig` or `lib/std/std.zig`.
|
||||
Typically the former is an install and the latter a git working tree which
|
||||
contains the build directory.
|
||||
|
||||
During development it is not necessary to perform installs when modifying
|
||||
stage1 or userland sources and in fact it is faster and simpler to run,
|
||||
test and debug from a git working tree.
|
||||
|
||||
- `make` is typically sufficient to build zig during development iterations.
|
||||
- `make install` performs a build __and__ install.
|
||||
- `msbuild -p:Configuration=Release INSTALL.vcxproj` on Windows performs a
|
||||
build and install. To avoid install, pass cmake option `-DZIG_SKIP_INSTALL_LIB_FILES=ON`.
|
||||
|
||||
To test changes, do the following from the build directory:
|
||||
|
||||
1. Run `make install` (on POSIX) or
|
||||
1. Run `make` (on POSIX) or
|
||||
`msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
|
||||
2. `bin/zig build test` (on POSIX) or `bin\zig.exe build test` (on Windows).
|
||||
2. `$BUILD_DIR/zig build test` (on POSIX) or
|
||||
`$BUILD_DIR/Release\zig.exe build test` (on Windows).
|
||||
|
||||
That runs the whole test suite, which does a lot of extra testing that you
|
||||
likely won't always need, and can take upwards of 1 hour. This is what the
|
||||
@ -85,8 +90,8 @@ Another example is choosing a different set of things to test. For example,
|
||||
not the other ones. Combining this suggestion with the previous one, you could
|
||||
do this:
|
||||
|
||||
`bin/zig build test-std -Dskip-release` (on POSIX) or
|
||||
`bin\zig.exe build test-std -Dskip-release` (on Windows).
|
||||
`$BUILD_DIR/bin/zig build test-std -Dskip-release` (on POSIX) or
|
||||
`$BUILD_DIR/Release\zig.exe build test-std -Dskip-release` (on Windows).
|
||||
|
||||
This will run only the standard library tests, in debug mode only, for all
|
||||
targets (it will cross-compile the tests for non-native targets but not run
|
||||
|
37
cmake/install.cmake
Normal file
37
cmake/install.cmake
Normal file
@ -0,0 +1,37 @@
|
||||
message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
if(NOT EXISTS ${zig0_EXE})
|
||||
message("::")
|
||||
message(":: ERROR: Executable not found")
|
||||
message(":: (execute_process)")
|
||||
message("::")
|
||||
message(":: executable: ${zig0_EXE}")
|
||||
message("::")
|
||||
message(FATAL_ERROR)
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
RESULT_VARIABLE _result
|
||||
)
|
||||
if(_result)
|
||||
message("::")
|
||||
message(":: ERROR: ${_result}")
|
||||
message(":: (execute_process)")
|
||||
|
||||
string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}")
|
||||
message("::")
|
||||
message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install")
|
||||
|
||||
set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS})
|
||||
list(LENGTH _args _len)
|
||||
math(EXPR _len "${_len} - 1")
|
||||
message("::")
|
||||
foreach(_i RANGE 0 ${_len})
|
||||
list(GET _args ${_i} _arg)
|
||||
message(":: argv[${_i}]: ${_arg}")
|
||||
endforeach()
|
||||
|
||||
message("::")
|
||||
message(FATAL_ERROR)
|
||||
endif()
|
@ -2893,6 +2893,47 @@ test "switch using enum literals" {
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|Non-exhaustive enum#}
|
||||
<p>
|
||||
A Non-exhaustive enum can be created by adding a trailing '_' field.
|
||||
It must specify a tag type and cannot consume every enumeration value.
|
||||
</p>
|
||||
<p>
|
||||
{#link|@intToEnum#} on a non-exhaustive enum cannot fail.
|
||||
</p>
|
||||
<p>
|
||||
A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
|
||||
with the difference being that it makes it a compile error if all the known tag names are not handled by the switch.
|
||||
</p>
|
||||
{#code_begin|test#}
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const Number = enum(u8) {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
_,
|
||||
};
|
||||
|
||||
test "switch on non-exhaustive enum" {
|
||||
const number = Number.One;
|
||||
const result = switch (number) {
|
||||
.One => true,
|
||||
.Two,
|
||||
.Three => false,
|
||||
_ => false,
|
||||
};
|
||||
assert(result);
|
||||
const is_one = switch (number) {
|
||||
.One => true,
|
||||
else => false,
|
||||
};
|
||||
assert(is_one);
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|union#}
|
||||
@ -6815,6 +6856,19 @@ async fn func(y: *i32) void {
|
||||
</p>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@bitSizeOf#}
|
||||
<pre>{#syntax#}@bitSizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
|
||||
<p>
|
||||
This function returns the number of bits it takes to store {#syntax#}T{#endsyntax#} in memory.
|
||||
The result is a target-specific compile time constant.
|
||||
</p>
|
||||
<p>
|
||||
This function measures the size at runtime. For types that are disallowed at runtime, such as
|
||||
{#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}.
|
||||
</p>
|
||||
{#see_also|@sizeOf|@typeInfo#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@breakpoint#}
|
||||
<pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
|
||||
<p>
|
||||
@ -8044,7 +8098,7 @@ test "@setRuntimeSafety" {
|
||||
This function measures the size at runtime. For types that are disallowed at runtime, such as
|
||||
{#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}.
|
||||
</p>
|
||||
{#see_also|@typeInfo#}
|
||||
{#see_also|@bitSizeOf|@typeInfo#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@sliceToBytes#}
|
||||
|
@ -1687,7 +1687,9 @@ pub const LibExeObjStep = struct {
|
||||
}
|
||||
|
||||
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable;
|
||||
self.link_objects.append(LinkObject{
|
||||
.AssemblyFile = .{ .path = self.builder.dupe(path) },
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void {
|
||||
|
@ -205,6 +205,7 @@ pub const TypeInfo = union(enum) {
|
||||
name: []const u8,
|
||||
offset: ?comptime_int,
|
||||
field_type: type,
|
||||
default_value: var,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
@ -253,6 +254,7 @@ pub const TypeInfo = union(enum) {
|
||||
tag_type: type,
|
||||
fields: []EnumField,
|
||||
decls: []Declaration,
|
||||
is_exhaustive: bool,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
|
@ -185,7 +185,7 @@ pub extern "c" fn getaddrinfo(
|
||||
noalias service: [*:0]const u8,
|
||||
noalias hints: *const addrinfo,
|
||||
noalias res: **addrinfo,
|
||||
) c_int;
|
||||
) EAI;
|
||||
|
||||
pub extern "c" fn freeaddrinfo(res: *addrinfo) void;
|
||||
|
||||
@ -197,9 +197,9 @@ pub extern "c" fn getnameinfo(
|
||||
noalias serv: [*]u8,
|
||||
servlen: socklen_t,
|
||||
flags: u32,
|
||||
) c_int;
|
||||
) EAI;
|
||||
|
||||
pub extern "c" fn gai_strerror(errcode: c_int) [*:0]const u8;
|
||||
pub extern "c" fn gai_strerror(errcode: EAI) [*:0]const u8;
|
||||
|
||||
pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int;
|
||||
|
||||
|
@ -70,47 +70,52 @@ pub const AI_NUMERICHOST = 0x00000004;
|
||||
/// prevent service name resolution
|
||||
pub const AI_NUMERICSERV = 0x00001000;
|
||||
|
||||
/// address family for hostname not supported
|
||||
pub const EAI_ADDRFAMILY = 1;
|
||||
pub const EAI = extern enum(c_int) {
|
||||
/// address family for hostname not supported
|
||||
ADDRFAMILY = 1,
|
||||
|
||||
/// temporary failure in name resolution
|
||||
pub const EAI_AGAIN = 2;
|
||||
/// temporary failure in name resolution
|
||||
AGAIN = 2,
|
||||
|
||||
/// invalid value for ai_flags
|
||||
pub const EAI_BADFLAGS = 3;
|
||||
/// invalid value for ai_flags
|
||||
BADFLAGS = 3,
|
||||
|
||||
/// non-recoverable failure in name resolution
|
||||
pub const EAI_FAIL = 4;
|
||||
/// non-recoverable failure in name resolution
|
||||
FAIL = 4,
|
||||
|
||||
/// ai_family not supported
|
||||
pub const EAI_FAMILY = 5;
|
||||
/// ai_family not supported
|
||||
FAMILY = 5,
|
||||
|
||||
/// memory allocation failure
|
||||
pub const EAI_MEMORY = 6;
|
||||
/// memory allocation failure
|
||||
MEMORY = 6,
|
||||
|
||||
/// no address associated with hostname
|
||||
pub const EAI_NODATA = 7;
|
||||
/// no address associated with hostname
|
||||
NODATA = 7,
|
||||
|
||||
/// hostname nor servname provided, or not known
|
||||
pub const EAI_NONAME = 8;
|
||||
/// hostname nor servname provided, or not known
|
||||
NONAME = 8,
|
||||
|
||||
/// servname not supported for ai_socktype
|
||||
pub const EAI_SERVICE = 9;
|
||||
/// servname not supported for ai_socktype
|
||||
SERVICE = 9,
|
||||
|
||||
/// ai_socktype not supported
|
||||
pub const EAI_SOCKTYPE = 10;
|
||||
/// ai_socktype not supported
|
||||
SOCKTYPE = 10,
|
||||
|
||||
/// system error returned in errno
|
||||
pub const EAI_SYSTEM = 11;
|
||||
/// system error returned in errno
|
||||
SYSTEM = 11,
|
||||
|
||||
/// invalid value for hints
|
||||
pub const EAI_BADHINTS = 12;
|
||||
/// invalid value for hints
|
||||
BADHINTS = 12,
|
||||
|
||||
/// resolved protocol is unknown
|
||||
pub const EAI_PROTOCOL = 13;
|
||||
/// resolved protocol is unknown
|
||||
PROTOCOL = 13,
|
||||
|
||||
/// argument buffer overflow
|
||||
OVERFLOW = 14,
|
||||
|
||||
_,
|
||||
};
|
||||
|
||||
/// argument buffer overflow
|
||||
pub const EAI_OVERFLOW = 14;
|
||||
pub const EAI_MAX = 15;
|
||||
|
||||
pub const pthread_mutex_t = extern struct {
|
||||
|
@ -23,47 +23,51 @@ pub const pthread_attr_t = extern struct {
|
||||
__align: c_long,
|
||||
};
|
||||
|
||||
/// address family for hostname not supported
|
||||
pub const EAI_ADDRFAMILY = 1;
|
||||
pub const EAI = extern enum(c_int) {
|
||||
/// address family for hostname not supported
|
||||
ADDRFAMILY = 1,
|
||||
|
||||
/// name could not be resolved at this time
|
||||
pub const EAI_AGAIN = 2;
|
||||
/// name could not be resolved at this time
|
||||
AGAIN = 2,
|
||||
|
||||
/// flags parameter had an invalid value
|
||||
pub const EAI_BADFLAGS = 3;
|
||||
/// flags parameter had an invalid value
|
||||
BADFLAGS = 3,
|
||||
|
||||
/// non-recoverable failure in name resolution
|
||||
pub const EAI_FAIL = 4;
|
||||
/// non-recoverable failure in name resolution
|
||||
FAIL = 4,
|
||||
|
||||
/// address family not recognized
|
||||
pub const EAI_FAMILY = 5;
|
||||
/// address family not recognized
|
||||
FAMILY = 5,
|
||||
|
||||
/// memory allocation failure
|
||||
pub const EAI_MEMORY = 6;
|
||||
/// memory allocation failure
|
||||
MEMORY = 6,
|
||||
|
||||
/// no address associated with hostname
|
||||
pub const EAI_NODATA = 7;
|
||||
/// no address associated with hostname
|
||||
NODATA = 7,
|
||||
|
||||
/// name does not resolve
|
||||
pub const EAI_NONAME = 8;
|
||||
/// name does not resolve
|
||||
NONAME = 8,
|
||||
|
||||
/// service not recognized for socket type
|
||||
pub const EAI_SERVICE = 9;
|
||||
/// service not recognized for socket type
|
||||
SERVICE = 9,
|
||||
|
||||
/// intended socket type was not recognized
|
||||
pub const EAI_SOCKTYPE = 10;
|
||||
/// intended socket type was not recognized
|
||||
SOCKTYPE = 10,
|
||||
|
||||
/// system error returned in errno
|
||||
pub const EAI_SYSTEM = 11;
|
||||
/// system error returned in errno
|
||||
SYSTEM = 11,
|
||||
|
||||
/// invalid value for hints
|
||||
pub const EAI_BADHINTS = 12;
|
||||
/// invalid value for hints
|
||||
BADHINTS = 12,
|
||||
|
||||
/// resolved protocol is unknown
|
||||
pub const EAI_PROTOCOL = 13;
|
||||
/// resolved protocol is unknown
|
||||
PROTOCOL = 13,
|
||||
|
||||
/// argument buffer overflow
|
||||
pub const EAI_OVERFLOW = 14;
|
||||
/// argument buffer overflow
|
||||
OVERFLOW = 14,
|
||||
|
||||
_,
|
||||
};
|
||||
|
||||
pub const EAI_MAX = 15;
|
||||
|
||||
|
@ -32,25 +32,29 @@ pub const NI_NAMEREQD = 0x08;
|
||||
pub const NI_DGRAM = 0x10;
|
||||
pub const NI_NUMERICSCOPE = 0x100;
|
||||
|
||||
pub const EAI_BADFLAGS = -1;
|
||||
pub const EAI_NONAME = -2;
|
||||
pub const EAI_AGAIN = -3;
|
||||
pub const EAI_FAIL = -4;
|
||||
pub const EAI_FAMILY = -6;
|
||||
pub const EAI_SOCKTYPE = -7;
|
||||
pub const EAI_SERVICE = -8;
|
||||
pub const EAI_MEMORY = -10;
|
||||
pub const EAI_SYSTEM = -11;
|
||||
pub const EAI_OVERFLOW = -12;
|
||||
pub const EAI = extern enum(c_int) {
|
||||
BADFLAGS = -1,
|
||||
NONAME = -2,
|
||||
AGAIN = -3,
|
||||
FAIL = -4,
|
||||
FAMILY = -6,
|
||||
SOCKTYPE = -7,
|
||||
SERVICE = -8,
|
||||
MEMORY = -10,
|
||||
SYSTEM = -11,
|
||||
OVERFLOW = -12,
|
||||
|
||||
pub const EAI_NODATA = -5;
|
||||
pub const EAI_ADDRFAMILY = -9;
|
||||
pub const EAI_INPROGRESS = -100;
|
||||
pub const EAI_CANCELED = -101;
|
||||
pub const EAI_NOTCANCELED = -102;
|
||||
pub const EAI_ALLDONE = -103;
|
||||
pub const EAI_INTR = -104;
|
||||
pub const EAI_IDN_ENCODE = -105;
|
||||
NODATA = -5,
|
||||
ADDRFAMILY = -9,
|
||||
INPROGRESS = -100,
|
||||
CANCELED = -101,
|
||||
NOTCANCELED = -102,
|
||||
ALLDONE = -103,
|
||||
INTR = -104,
|
||||
IDN_ENCODE = -105,
|
||||
|
||||
_,
|
||||
};
|
||||
|
||||
pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
|
||||
pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
|
||||
|
@ -277,7 +277,7 @@ pub const WindowsDynLib = struct {
|
||||
}
|
||||
|
||||
pub fn openC(path_c: [*:0]const u8) !WindowsDynLib {
|
||||
const path_w = try windows.cStrToPrefixedFileW(path);
|
||||
const path_w = try windows.cStrToPrefixedFileW(path_c);
|
||||
return openW(&path_w);
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ pub fn formatType(
|
||||
},
|
||||
else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
|
||||
},
|
||||
.Many => {
|
||||
.Many, .C => {
|
||||
if (ptr_info.child == u8) {
|
||||
if (fmt.len > 0 and fmt[0] == 's') {
|
||||
const len = mem.len(u8, value);
|
||||
@ -449,9 +449,6 @@ pub fn formatType(
|
||||
}
|
||||
return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
|
||||
},
|
||||
.C => {
|
||||
return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
|
||||
},
|
||||
},
|
||||
.Array => |info| {
|
||||
const Slice = @Type(builtin.TypeInfo{
|
||||
@ -1285,8 +1282,16 @@ test "pointer" {
|
||||
}
|
||||
|
||||
test "cstr" {
|
||||
try testFmt("cstr: Test C\n", "cstr: {s}\n", .{"Test C"});
|
||||
try testFmt("cstr: Test C \n", "cstr: {s:10}\n", .{"Test C"});
|
||||
try testFmt(
|
||||
"cstr: Test C\n",
|
||||
"cstr: {s}\n",
|
||||
.{@ptrCast([*c]const u8, "Test C")},
|
||||
);
|
||||
try testFmt(
|
||||
"cstr: Test C \n",
|
||||
"cstr: {s:10}\n",
|
||||
.{@ptrCast([*c]const u8, "Test C")},
|
||||
);
|
||||
}
|
||||
|
||||
test "filesize" {
|
||||
|
@ -47,11 +47,11 @@ const hashes = [_]Hash{
|
||||
.name = "adler32",
|
||||
},
|
||||
Hash{
|
||||
.ty = hash.crc.Crc32WithPoly(hash.crc.Polynomial.IEEE),
|
||||
.ty = hash.crc.Crc32WithPoly(.IEEE),
|
||||
.name = "crc32-slicing-by-8",
|
||||
},
|
||||
Hash{
|
||||
.ty = hash.crc.Crc32SmallWithPoly(hash.crc.Polynomial.IEEE),
|
||||
.ty = hash.crc.Crc32SmallWithPoly(.IEEE),
|
||||
.name = "crc32-half-byte-lookup",
|
||||
},
|
||||
Hash{
|
||||
|
@ -9,17 +9,18 @@ const std = @import("../std.zig");
|
||||
const debug = std.debug;
|
||||
const testing = std.testing;
|
||||
|
||||
pub const Polynomial = struct {
|
||||
pub const IEEE = 0xedb88320;
|
||||
pub const Castagnoli = 0x82f63b78;
|
||||
pub const Koopman = 0xeb31d82e;
|
||||
pub const Polynomial = enum(u32) {
|
||||
IEEE = 0xedb88320,
|
||||
Castagnoli = 0x82f63b78,
|
||||
Koopman = 0xeb31d82e,
|
||||
_,
|
||||
};
|
||||
|
||||
// IEEE is by far the most common CRC and so is aliased by default.
|
||||
pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
|
||||
pub const Crc32 = Crc32WithPoly(.IEEE);
|
||||
|
||||
// slicing-by-8 crc32 implementation.
|
||||
pub fn Crc32WithPoly(comptime poly: u32) type {
|
||||
pub fn Crc32WithPoly(comptime poly: Polynomial) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const lookup_tables = comptime block: {
|
||||
@ -31,7 +32,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
|
||||
var j: usize = 0;
|
||||
while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
crc = (crc >> 1) ^ @enumToInt(poly);
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
@ -100,7 +101,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
|
||||
}
|
||||
|
||||
test "crc32 ieee" {
|
||||
const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
|
||||
const Crc32Ieee = Crc32WithPoly(.IEEE);
|
||||
|
||||
testing.expect(Crc32Ieee.hash("") == 0x00000000);
|
||||
testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
|
||||
@ -108,7 +109,7 @@ test "crc32 ieee" {
|
||||
}
|
||||
|
||||
test "crc32 castagnoli" {
|
||||
const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
|
||||
const Crc32Castagnoli = Crc32WithPoly(.Castagnoli);
|
||||
|
||||
testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
|
||||
testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
|
||||
@ -116,7 +117,7 @@ test "crc32 castagnoli" {
|
||||
}
|
||||
|
||||
// half-byte lookup table implementation.
|
||||
pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const lookup_table = comptime block: {
|
||||
@ -127,7 +128,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
var j: usize = 0;
|
||||
while (j < 8) : (j += 1) {
|
||||
if (crc & 1 == 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
crc = (crc >> 1) ^ @enumToInt(poly);
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
@ -164,7 +165,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
|
||||
}
|
||||
|
||||
test "small crc32 ieee" {
|
||||
const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
|
||||
const Crc32Ieee = Crc32SmallWithPoly(.IEEE);
|
||||
|
||||
testing.expect(Crc32Ieee.hash("") == 0x00000000);
|
||||
testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
|
||||
@ -172,7 +173,7 @@ test "small crc32 ieee" {
|
||||
}
|
||||
|
||||
test "small crc32 castagnoli" {
|
||||
const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
|
||||
const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli);
|
||||
|
||||
testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
|
||||
testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
|
||||
|
@ -452,18 +452,18 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
|
||||
};
|
||||
var res: *os.addrinfo = undefined;
|
||||
switch (os.system.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res)) {
|
||||
0 => {},
|
||||
c.EAI_ADDRFAMILY => return error.HostLacksNetworkAddresses,
|
||||
c.EAI_AGAIN => return error.TemporaryNameServerFailure,
|
||||
c.EAI_BADFLAGS => unreachable, // Invalid hints
|
||||
c.EAI_FAIL => return error.NameServerFailure,
|
||||
c.EAI_FAMILY => return error.AddressFamilyNotSupported,
|
||||
c.EAI_MEMORY => return error.OutOfMemory,
|
||||
c.EAI_NODATA => return error.HostLacksNetworkAddresses,
|
||||
c.EAI_NONAME => return error.UnknownHostName,
|
||||
c.EAI_SERVICE => return error.ServiceUnavailable,
|
||||
c.EAI_SOCKTYPE => unreachable, // Invalid socket type requested in hints
|
||||
c.EAI_SYSTEM => switch (os.errno(-1)) {
|
||||
@intToEnum(os.system.EAI, 0) => {},
|
||||
.ADDRFAMILY => return error.HostLacksNetworkAddresses,
|
||||
.AGAIN => return error.TemporaryNameServerFailure,
|
||||
.BADFLAGS => unreachable, // Invalid hints
|
||||
.FAIL => return error.NameServerFailure,
|
||||
.FAMILY => return error.AddressFamilyNotSupported,
|
||||
.MEMORY => return error.OutOfMemory,
|
||||
.NODATA => return error.HostLacksNetworkAddresses,
|
||||
.NONAME => return error.UnknownHostName,
|
||||
.SERVICE => return error.ServiceUnavailable,
|
||||
.SOCKTYPE => unreachable, // Invalid socket type requested in hints
|
||||
.SYSTEM => switch (os.errno(-1)) {
|
||||
else => |e| return os.unexpectedErrno(e),
|
||||
},
|
||||
else => unreachable,
|
||||
|
@ -18,7 +18,7 @@ pub usingnamespace switch (builtin.arch) {
|
||||
else => struct {},
|
||||
};
|
||||
|
||||
const is_mips = builtin.arch == .mipsel;
|
||||
const is_mips = builtin.arch.isMIPS();
|
||||
|
||||
pub const pid_t = i32;
|
||||
pub const fd_t = i32;
|
||||
|
@ -16,42 +16,42 @@ comptime {
|
||||
else => {},
|
||||
}
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage });
|
||||
|
||||
if (!is_test) {
|
||||
@export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage });
|
||||
@export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
|
||||
}
|
||||
|
||||
@export(@import("compiler_rt/comparesf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparetf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/addXf3.zig").__addsf3, .{ .name = "__addsf3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/addXf3.zig").__adddf3, .{ .name = "__adddf3", .linkage = linkage });
|
||||
@ -146,8 +146,10 @@ comptime {
|
||||
@export(@import("compiler_rt/negXf2.zig").__negsf2, .{ .name = "__negsf2", .linkage = linkage });
|
||||
@export(@import("compiler_rt/negXf2.zig").__negdf2, .{ .name = "__negdf2", .linkage = linkage });
|
||||
|
||||
if (is_arm_arch and !is_arm_64 and !is_test) {
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage });
|
||||
|
||||
if (builtin.arch.isARM() and !is_test) {
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage });
|
||||
|
||||
@ -177,7 +179,9 @@ comptime {
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
|
||||
if (builtin.os == .linux) {
|
||||
@export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
|
||||
}
|
||||
|
||||
@export(@import("compiler_rt/extendXfYf2.zig").__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage });
|
||||
@export(@import("compiler_rt/floatsiXf.zig").__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage });
|
||||
@ -222,20 +226,29 @@ comptime {
|
||||
@export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage });
|
||||
@export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparesf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage });
|
||||
|
||||
@export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage });
|
||||
@export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/comparedf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage });
|
||||
@export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
|
||||
}
|
||||
|
||||
if (builtin.arch == .i386 and builtin.abi == .msvc) {
|
||||
// Don't let LLVM apply the stdcall name mangling on those MSVC builtins
|
||||
@export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
|
||||
}
|
||||
|
||||
if (builtin.os == .windows) {
|
||||
// Default stack-probe functions emitted by LLVM
|
||||
if (is_mingw) {
|
||||
@ -254,13 +267,6 @@ comptime {
|
||||
|
||||
switch (builtin.arch) {
|
||||
.i386 => {
|
||||
// Don't let LLVM apply the stdcall name mangling on those MSVC
|
||||
// builtin functions
|
||||
@export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage });
|
||||
@export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
|
||||
|
||||
@export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage });
|
||||
@export(@import("compiler_rt/multi3.zig").__multi3, .{ .name = "__multi3", .linkage = linkage });
|
||||
@ -295,16 +301,12 @@ comptime {
|
||||
@export(@import("compiler_rt/mulodi4.zig").__mulodi4, .{ .name = "__mulodi4", .linkage = linkage });
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
|
||||
// Avoid dragging in the runtime safety mechanisms into this .o file,
|
||||
// unless we're trying to test this file.
|
||||
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
|
||||
@setCold(true);
|
||||
if (is_test) {
|
||||
std.debug.panic("{}", .{msg});
|
||||
@import("std").debug.panic("{}", .{msg});
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
@ -320,23 +322,3 @@ extern var __stack_chk_guard: usize = blk: {
|
||||
buf[@sizeOf(usize) - 2] = '\n';
|
||||
break :blk @bitCast(usize, buf);
|
||||
};
|
||||
|
||||
const is_arm_64 = switch (builtin.arch) {
|
||||
builtin.Arch.aarch64,
|
||||
builtin.Arch.aarch64_be,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
|
||||
const is_arm_arch = switch (builtin.arch) {
|
||||
builtin.Arch.arm,
|
||||
builtin.Arch.armeb,
|
||||
builtin.Arch.aarch64,
|
||||
builtin.Arch.aarch64_be,
|
||||
builtin.Arch.thumb,
|
||||
builtin.Arch.thumbeb,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
|
||||
const is_arm_32 = is_arm_arch and !is_arm_64;
|
||||
|
@ -1,6 +1,5 @@
|
||||
// ARM specific builtins
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const __divmodsi4 = @import("int.zig").__divmodsi4;
|
||||
const __udivmodsi4 = @import("int.zig").__udivmodsi4;
|
||||
@ -33,18 +32,14 @@ pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void {
|
||||
_ = memset(dest, 0, n);
|
||||
}
|
||||
|
||||
pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {
|
||||
unreachable;
|
||||
}
|
||||
pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {
|
||||
unreachable;
|
||||
}
|
||||
pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {
|
||||
unreachable;
|
||||
}
|
||||
// Dummy functions to avoid errors during the linking phase
|
||||
pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {}
|
||||
pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {}
|
||||
pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {}
|
||||
|
||||
// This function can only clobber r0 according to the ABI
|
||||
pub fn __aeabi_read_tp() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
asm volatile (
|
||||
\\ mrc p15, 0, r0, c13, c0, 3
|
||||
\\ bx lr
|
||||
@ -56,6 +51,7 @@ pub fn __aeabi_read_tp() callconv(.Naked) void {
|
||||
// calling convention is always respected
|
||||
|
||||
pub fn __aeabi_uidivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r0 by r1; the quotient goes in r0, the remainder in r1
|
||||
asm volatile (
|
||||
\\ push {lr}
|
||||
@ -73,6 +69,7 @@ pub fn __aeabi_uidivmod() callconv(.Naked) void {
|
||||
}
|
||||
|
||||
pub fn __aeabi_uldivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2
|
||||
asm volatile (
|
||||
\\ push {r4, lr}
|
||||
@ -92,6 +89,7 @@ pub fn __aeabi_uldivmod() callconv(.Naked) void {
|
||||
}
|
||||
|
||||
pub fn __aeabi_idivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r0 by r1; the quotient goes in r0, the remainder in r1
|
||||
asm volatile (
|
||||
\\ push {lr}
|
||||
@ -109,6 +107,7 @@ pub fn __aeabi_idivmod() callconv(.Naked) void {
|
||||
}
|
||||
|
||||
pub fn __aeabi_ldivmod() callconv(.Naked) void {
|
||||
@setRuntimeSafety(false);
|
||||
// Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2
|
||||
asm volatile (
|
||||
\\ push {r4, lr}
|
||||
|
@ -1,95 +0,0 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_dcmp.S
|
||||
|
||||
const ConditionalOperator = enum {
|
||||
Eq,
|
||||
Lt,
|
||||
Le,
|
||||
Ge,
|
||||
Gt,
|
||||
};
|
||||
|
||||
pub fn __aeabi_dcmpeq() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmplt() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmple() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpge() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpgt() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn aeabi_dcmp(comptime cond: ConditionalOperator) void {
|
||||
@setRuntimeSafety(false);
|
||||
asm volatile (
|
||||
\\ push { r4, lr }
|
||||
);
|
||||
|
||||
switch (cond) {
|
||||
.Eq => asm volatile (
|
||||
\\ bl __eqdf2
|
||||
\\ cmp r0, #0
|
||||
\\ beq 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Lt => asm volatile (
|
||||
\\ bl __ltdf2
|
||||
\\ cmp r0, #0
|
||||
\\ blt 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Le => asm volatile (
|
||||
\\ bl __ledf2
|
||||
\\ cmp r0, #0
|
||||
\\ ble 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Ge => asm volatile (
|
||||
\\ bl __ltdf2
|
||||
\\ cmp r0, #0
|
||||
\\ bge 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Gt => asm volatile (
|
||||
\\ bl __gtdf2
|
||||
\\ cmp r0, #0
|
||||
\\ bgt 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
}
|
||||
asm volatile (
|
||||
\\ movs r0, #1
|
||||
\\ pop { r4, pc }
|
||||
);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_fcmp.S
|
||||
|
||||
const ConditionalOperator = enum {
|
||||
Eq,
|
||||
Lt,
|
||||
Le,
|
||||
Ge,
|
||||
Gt,
|
||||
};
|
||||
|
||||
pub fn __aeabi_fcmpeq() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmplt() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmple() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpge() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpgt() callconv(.Naked) noreturn {
|
||||
@setRuntimeSafety(false);
|
||||
@call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt});
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn aeabi_fcmp(comptime cond: ConditionalOperator) void {
|
||||
@setRuntimeSafety(false);
|
||||
asm volatile (
|
||||
\\ push { r4, lr }
|
||||
);
|
||||
|
||||
switch (cond) {
|
||||
.Eq => asm volatile (
|
||||
\\ bl __eqsf2
|
||||
\\ cmp r0, #0
|
||||
\\ beq 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Lt => asm volatile (
|
||||
\\ bl __ltsf2
|
||||
\\ cmp r0, #0
|
||||
\\ blt 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Le => asm volatile (
|
||||
\\ bl __lesf2
|
||||
\\ cmp r0, #0
|
||||
\\ ble 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Ge => asm volatile (
|
||||
\\ bl __ltsf2
|
||||
\\ cmp r0, #0
|
||||
\\ bge 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
.Gt => asm volatile (
|
||||
\\ bl __gtsf2
|
||||
\\ cmp r0, #0
|
||||
\\ bgt 1f
|
||||
\\ movs r0, #0
|
||||
\\ pop { r4, pc }
|
||||
\\ 1:
|
||||
),
|
||||
}
|
||||
asm volatile (
|
||||
\\ movs r0, #1
|
||||
\\ pop { r4, pc }
|
||||
);
|
||||
}
|
116
lib/std/special/compiler_rt/clzsi2.zig
Normal file
116
lib/std/special/compiler_rt/clzsi2.zig
Normal file
@ -0,0 +1,116 @@
|
||||
const builtin = @import("builtin");
|
||||
|
||||
fn __clzsi2_generic(a: i32) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
var x = @bitCast(u32, a);
|
||||
var n: i32 = 32;
|
||||
|
||||
// Count first bit set using binary search, from Hacker's Delight
|
||||
var y: u32 = 0;
|
||||
inline for ([_]i32{ 16, 8, 4, 2, 1 }) |shift| {
|
||||
y = x >> shift;
|
||||
if (y != 0) {
|
||||
n = n - shift;
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
|
||||
return n - @bitCast(i32, x);
|
||||
}
|
||||
|
||||
fn __clzsi2_thumb1() callconv(.Naked) void {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
// Similar to the generic version with the last two rounds replaced by a LUT
|
||||
asm volatile (
|
||||
\\ movs r1, #32
|
||||
\\ lsrs r2, r0, #16
|
||||
\\ beq 1f
|
||||
\\ subs r1, #16
|
||||
\\ movs r0, r2
|
||||
\\ 1:
|
||||
\\ lsrs r2, r0, #8
|
||||
\\ beq 1f
|
||||
\\ subs r1, #8
|
||||
\\ movs r0, r2
|
||||
\\ 1:
|
||||
\\ lsrs r2, r0, #4
|
||||
\\ beq 1f
|
||||
\\ subs r1, #4
|
||||
\\ movs r0, r2
|
||||
\\ 1:
|
||||
\\ ldr r3, =LUT
|
||||
\\ ldrb r0, [r3, r0]
|
||||
\\ subs r0, r1, r0
|
||||
\\ bx lr
|
||||
\\ .p2align 2
|
||||
\\ LUT:
|
||||
\\ .byte 4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0
|
||||
);
|
||||
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn __clzsi2_arm32() callconv(.Naked) void {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
asm volatile (
|
||||
\\ // Assumption: n != 0
|
||||
\\ // r0: n
|
||||
\\ // r1: count of leading zeros in n + 1
|
||||
\\ // r2: scratch register for shifted r0
|
||||
\\ mov r1, #1
|
||||
\\
|
||||
\\ // Basic block:
|
||||
\\ // if ((r0 >> SHIFT) == 0)
|
||||
\\ // r1 += SHIFT;
|
||||
\\ // else
|
||||
\\ // r0 >>= SHIFT;
|
||||
\\ // for descending powers of two as SHIFT.
|
||||
\\ lsrs r2, r0, #16
|
||||
\\ movne r0, r2
|
||||
\\ addeq r1, #16
|
||||
\\
|
||||
\\ lsrs r2, r0, #8
|
||||
\\ movne r0, r2
|
||||
\\ addeq r1, #8
|
||||
\\
|
||||
\\ lsrs r2, r0, #4
|
||||
\\ movne r0, r2
|
||||
\\ addeq r1, #4
|
||||
\\
|
||||
\\ lsrs r2, r0, #2
|
||||
\\ movne r0, r2
|
||||
\\ addeq r1, #2
|
||||
\\
|
||||
\\ // The basic block invariants at this point are (r0 >> 2) == 0 and
|
||||
\\ // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1.
|
||||
\\ //
|
||||
\\ // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)f
|
||||
\\ // ---+----------------+----------------+------------+--------------
|
||||
\\ // 1 | 1 | 0 | 0 | 1
|
||||
\\ // 2 | 0 | 1 | -1 | 0
|
||||
\\ // 3 | 0 | 1 | -1 | 0
|
||||
\\ //
|
||||
\\ // The r1's initial value of 1 compensates for the 1 here.
|
||||
\\ sub r0, r1, r0, lsr #1
|
||||
\\ bx lr
|
||||
);
|
||||
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub const __clzsi2 = blk: {
|
||||
if (builtin.arch.isARM()) {
|
||||
break :blk __clzsi2_arm32;
|
||||
} else if (builtin.arch.isThumb()) {
|
||||
break :blk __clzsi2_thumb1;
|
||||
} else {
|
||||
break :blk __clzsi2_generic;
|
||||
}
|
||||
};
|
||||
|
||||
test "test clzsi2" {
|
||||
_ = @import("clzsi2_test.zig");
|
||||
}
|
292
lib/std/special/compiler_rt/clzsi2_test.zig
Normal file
292
lib/std/special/compiler_rt/clzsi2_test.zig
Normal file
@ -0,0 +1,292 @@
|
||||
const clzsi2 = @import("clzsi2.zig");
|
||||
const testing = @import("std").testing;
|
||||
|
||||
fn test__clzsi2(a: u32, expected: i32) void {
|
||||
var nakedClzsi2 = clzsi2.__clzsi2;
|
||||
var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2);
|
||||
var x = @intCast(i32, a);
|
||||
var result = actualClzsi2(x);
|
||||
testing.expectEqual(expected, result);
|
||||
}
|
||||
|
||||
test "clzsi2" {
|
||||
test__clzsi2(0x00800000, 8);
|
||||
test__clzsi2(0x01000000, 7);
|
||||
test__clzsi2(0x02000000, 6);
|
||||
test__clzsi2(0x03000000, 6);
|
||||
test__clzsi2(0x04000000, 5);
|
||||
test__clzsi2(0x05000000, 5);
|
||||
test__clzsi2(0x06000000, 5);
|
||||
test__clzsi2(0x07000000, 5);
|
||||
test__clzsi2(0x08000000, 4);
|
||||
test__clzsi2(0x09000000, 4);
|
||||
test__clzsi2(0x0A000000, 4);
|
||||
test__clzsi2(0x0B000000, 4);
|
||||
test__clzsi2(0x0C000000, 4);
|
||||
test__clzsi2(0x0D000000, 4);
|
||||
test__clzsi2(0x0E000000, 4);
|
||||
test__clzsi2(0x0F000000, 4);
|
||||
test__clzsi2(0x10000000, 3);
|
||||
test__clzsi2(0x11000000, 3);
|
||||
test__clzsi2(0x12000000, 3);
|
||||
test__clzsi2(0x13000000, 3);
|
||||
test__clzsi2(0x14000000, 3);
|
||||
test__clzsi2(0x15000000, 3);
|
||||
test__clzsi2(0x16000000, 3);
|
||||
test__clzsi2(0x17000000, 3);
|
||||
test__clzsi2(0x18000000, 3);
|
||||
test__clzsi2(0x19000000, 3);
|
||||
test__clzsi2(0x1A000000, 3);
|
||||
test__clzsi2(0x1B000000, 3);
|
||||
test__clzsi2(0x1C000000, 3);
|
||||
test__clzsi2(0x1D000000, 3);
|
||||
test__clzsi2(0x1E000000, 3);
|
||||
test__clzsi2(0x1F000000, 3);
|
||||
test__clzsi2(0x20000000, 2);
|
||||
test__clzsi2(0x21000000, 2);
|
||||
test__clzsi2(0x22000000, 2);
|
||||
test__clzsi2(0x23000000, 2);
|
||||
test__clzsi2(0x24000000, 2);
|
||||
test__clzsi2(0x25000000, 2);
|
||||
test__clzsi2(0x26000000, 2);
|
||||
test__clzsi2(0x27000000, 2);
|
||||
test__clzsi2(0x28000000, 2);
|
||||
test__clzsi2(0x29000000, 2);
|
||||
test__clzsi2(0x2A000000, 2);
|
||||
test__clzsi2(0x2B000000, 2);
|
||||
test__clzsi2(0x2C000000, 2);
|
||||
test__clzsi2(0x2D000000, 2);
|
||||
test__clzsi2(0x2E000000, 2);
|
||||
test__clzsi2(0x2F000000, 2);
|
||||
test__clzsi2(0x30000000, 2);
|
||||
test__clzsi2(0x31000000, 2);
|
||||
test__clzsi2(0x32000000, 2);
|
||||
test__clzsi2(0x33000000, 2);
|
||||
test__clzsi2(0x34000000, 2);
|
||||
test__clzsi2(0x35000000, 2);
|
||||
test__clzsi2(0x36000000, 2);
|
||||
test__clzsi2(0x37000000, 2);
|
||||
test__clzsi2(0x38000000, 2);
|
||||
test__clzsi2(0x39000000, 2);
|
||||
test__clzsi2(0x3A000000, 2);
|
||||
test__clzsi2(0x3B000000, 2);
|
||||
test__clzsi2(0x3C000000, 2);
|
||||
test__clzsi2(0x3D000000, 2);
|
||||
test__clzsi2(0x3E000000, 2);
|
||||
test__clzsi2(0x3F000000, 2);
|
||||
test__clzsi2(0x40000000, 1);
|
||||
test__clzsi2(0x41000000, 1);
|
||||
test__clzsi2(0x42000000, 1);
|
||||
test__clzsi2(0x43000000, 1);
|
||||
test__clzsi2(0x44000000, 1);
|
||||
test__clzsi2(0x45000000, 1);
|
||||
test__clzsi2(0x46000000, 1);
|
||||
test__clzsi2(0x47000000, 1);
|
||||
test__clzsi2(0x48000000, 1);
|
||||
test__clzsi2(0x49000000, 1);
|
||||
test__clzsi2(0x4A000000, 1);
|
||||
test__clzsi2(0x4B000000, 1);
|
||||
test__clzsi2(0x4C000000, 1);
|
||||
test__clzsi2(0x4D000000, 1);
|
||||
test__clzsi2(0x4E000000, 1);
|
||||
test__clzsi2(0x4F000000, 1);
|
||||
test__clzsi2(0x50000000, 1);
|
||||
test__clzsi2(0x51000000, 1);
|
||||
test__clzsi2(0x52000000, 1);
|
||||
test__clzsi2(0x53000000, 1);
|
||||
test__clzsi2(0x54000000, 1);
|
||||
test__clzsi2(0x55000000, 1);
|
||||
test__clzsi2(0x56000000, 1);
|
||||
test__clzsi2(0x57000000, 1);
|
||||
test__clzsi2(0x58000000, 1);
|
||||
test__clzsi2(0x59000000, 1);
|
||||
test__clzsi2(0x5A000000, 1);
|
||||
test__clzsi2(0x5B000000, 1);
|
||||
test__clzsi2(0x5C000000, 1);
|
||||
test__clzsi2(0x5D000000, 1);
|
||||
test__clzsi2(0x5E000000, 1);
|
||||
test__clzsi2(0x5F000000, 1);
|
||||
test__clzsi2(0x60000000, 1);
|
||||
test__clzsi2(0x61000000, 1);
|
||||
test__clzsi2(0x62000000, 1);
|
||||
test__clzsi2(0x63000000, 1);
|
||||
test__clzsi2(0x64000000, 1);
|
||||
test__clzsi2(0x65000000, 1);
|
||||
test__clzsi2(0x66000000, 1);
|
||||
test__clzsi2(0x67000000, 1);
|
||||
test__clzsi2(0x68000000, 1);
|
||||
test__clzsi2(0x69000000, 1);
|
||||
test__clzsi2(0x6A000000, 1);
|
||||
test__clzsi2(0x6B000000, 1);
|
||||
test__clzsi2(0x6C000000, 1);
|
||||
test__clzsi2(0x6D000000, 1);
|
||||
test__clzsi2(0x6E000000, 1);
|
||||
test__clzsi2(0x6F000000, 1);
|
||||
test__clzsi2(0x70000000, 1);
|
||||
test__clzsi2(0x71000000, 1);
|
||||
test__clzsi2(0x72000000, 1);
|
||||
test__clzsi2(0x73000000, 1);
|
||||
test__clzsi2(0x74000000, 1);
|
||||
test__clzsi2(0x75000000, 1);
|
||||
test__clzsi2(0x76000000, 1);
|
||||
test__clzsi2(0x77000000, 1);
|
||||
test__clzsi2(0x78000000, 1);
|
||||
test__clzsi2(0x79000000, 1);
|
||||
test__clzsi2(0x7A000000, 1);
|
||||
test__clzsi2(0x7B000000, 1);
|
||||
test__clzsi2(0x7C000000, 1);
|
||||
test__clzsi2(0x7D000000, 1);
|
||||
test__clzsi2(0x7E000000, 1);
|
||||
test__clzsi2(0x7F000000, 1);
|
||||
test__clzsi2(0x80000000, 0);
|
||||
test__clzsi2(0x81000000, 0);
|
||||
test__clzsi2(0x82000000, 0);
|
||||
test__clzsi2(0x83000000, 0);
|
||||
test__clzsi2(0x84000000, 0);
|
||||
test__clzsi2(0x85000000, 0);
|
||||
test__clzsi2(0x86000000, 0);
|
||||
test__clzsi2(0x87000000, 0);
|
||||
test__clzsi2(0x88000000, 0);
|
||||
test__clzsi2(0x89000000, 0);
|
||||
test__clzsi2(0x8A000000, 0);
|
||||
test__clzsi2(0x8B000000, 0);
|
||||
test__clzsi2(0x8C000000, 0);
|
||||
test__clzsi2(0x8D000000, 0);
|
||||
test__clzsi2(0x8E000000, 0);
|
||||
test__clzsi2(0x8F000000, 0);
|
||||
test__clzsi2(0x90000000, 0);
|
||||
test__clzsi2(0x91000000, 0);
|
||||
test__clzsi2(0x92000000, 0);
|
||||
test__clzsi2(0x93000000, 0);
|
||||
test__clzsi2(0x94000000, 0);
|
||||
test__clzsi2(0x95000000, 0);
|
||||
test__clzsi2(0x96000000, 0);
|
||||
test__clzsi2(0x97000000, 0);
|
||||
test__clzsi2(0x98000000, 0);
|
||||
test__clzsi2(0x99000000, 0);
|
||||
test__clzsi2(0x9A000000, 0);
|
||||
test__clzsi2(0x9B000000, 0);
|
||||
test__clzsi2(0x9C000000, 0);
|
||||
test__clzsi2(0x9D000000, 0);
|
||||
test__clzsi2(0x9E000000, 0);
|
||||
test__clzsi2(0x9F000000, 0);
|
||||
test__clzsi2(0xA0000000, 0);
|
||||
test__clzsi2(0xA1000000, 0);
|
||||
test__clzsi2(0xA2000000, 0);
|
||||
test__clzsi2(0xA3000000, 0);
|
||||
test__clzsi2(0xA4000000, 0);
|
||||
test__clzsi2(0xA5000000, 0);
|
||||
test__clzsi2(0xA6000000, 0);
|
||||
test__clzsi2(0xA7000000, 0);
|
||||
test__clzsi2(0xA8000000, 0);
|
||||
test__clzsi2(0xA9000000, 0);
|
||||
test__clzsi2(0xAA000000, 0);
|
||||
test__clzsi2(0xAB000000, 0);
|
||||
test__clzsi2(0xAC000000, 0);
|
||||
test__clzsi2(0xAD000000, 0);
|
||||
test__clzsi2(0xAE000000, 0);
|
||||
test__clzsi2(0xAF000000, 0);
|
||||
test__clzsi2(0xB0000000, 0);
|
||||
test__clzsi2(0xB1000000, 0);
|
||||
test__clzsi2(0xB2000000, 0);
|
||||
test__clzsi2(0xB3000000, 0);
|
||||
test__clzsi2(0xB4000000, 0);
|
||||
test__clzsi2(0xB5000000, 0);
|
||||
test__clzsi2(0xB6000000, 0);
|
||||
test__clzsi2(0xB7000000, 0);
|
||||
test__clzsi2(0xB8000000, 0);
|
||||
test__clzsi2(0xB9000000, 0);
|
||||
test__clzsi2(0xBA000000, 0);
|
||||
test__clzsi2(0xBB000000, 0);
|
||||
test__clzsi2(0xBC000000, 0);
|
||||
test__clzsi2(0xBD000000, 0);
|
||||
test__clzsi2(0xBE000000, 0);
|
||||
test__clzsi2(0xBF000000, 0);
|
||||
test__clzsi2(0xC0000000, 0);
|
||||
test__clzsi2(0xC1000000, 0);
|
||||
test__clzsi2(0xC2000000, 0);
|
||||
test__clzsi2(0xC3000000, 0);
|
||||
test__clzsi2(0xC4000000, 0);
|
||||
test__clzsi2(0xC5000000, 0);
|
||||
test__clzsi2(0xC6000000, 0);
|
||||
test__clzsi2(0xC7000000, 0);
|
||||
test__clzsi2(0xC8000000, 0);
|
||||
test__clzsi2(0xC9000000, 0);
|
||||
test__clzsi2(0xCA000000, 0);
|
||||
test__clzsi2(0xCB000000, 0);
|
||||
test__clzsi2(0xCC000000, 0);
|
||||
test__clzsi2(0xCD000000, 0);
|
||||
test__clzsi2(0xCE000000, 0);
|
||||
test__clzsi2(0xCF000000, 0);
|
||||
test__clzsi2(0xD0000000, 0);
|
||||
test__clzsi2(0xD1000000, 0);
|
||||
test__clzsi2(0xD2000000, 0);
|
||||
test__clzsi2(0xD3000000, 0);
|
||||
test__clzsi2(0xD4000000, 0);
|
||||
test__clzsi2(0xD5000000, 0);
|
||||
test__clzsi2(0xD6000000, 0);
|
||||
test__clzsi2(0xD7000000, 0);
|
||||
test__clzsi2(0xD8000000, 0);
|
||||
test__clzsi2(0xD9000000, 0);
|
||||
test__clzsi2(0xDA000000, 0);
|
||||
test__clzsi2(0xDB000000, 0);
|
||||
test__clzsi2(0xDC000000, 0);
|
||||
test__clzsi2(0xDD000000, 0);
|
||||
test__clzsi2(0xDE000000, 0);
|
||||
test__clzsi2(0xDF000000, 0);
|
||||
test__clzsi2(0xE0000000, 0);
|
||||
test__clzsi2(0xE1000000, 0);
|
||||
test__clzsi2(0xE2000000, 0);
|
||||
test__clzsi2(0xE3000000, 0);
|
||||
test__clzsi2(0xE4000000, 0);
|
||||
test__clzsi2(0xE5000000, 0);
|
||||
test__clzsi2(0xE6000000, 0);
|
||||
test__clzsi2(0xE7000000, 0);
|
||||
test__clzsi2(0xE8000000, 0);
|
||||
test__clzsi2(0xE9000000, 0);
|
||||
test__clzsi2(0xEA000000, 0);
|
||||
test__clzsi2(0xEB000000, 0);
|
||||
test__clzsi2(0xEC000000, 0);
|
||||
test__clzsi2(0xED000000, 0);
|
||||
test__clzsi2(0xEE000000, 0);
|
||||
test__clzsi2(0xEF000000, 0);
|
||||
test__clzsi2(0xF0000000, 0);
|
||||
test__clzsi2(0xF1000000, 0);
|
||||
test__clzsi2(0xF2000000, 0);
|
||||
test__clzsi2(0xF3000000, 0);
|
||||
test__clzsi2(0xF4000000, 0);
|
||||
test__clzsi2(0xF5000000, 0);
|
||||
test__clzsi2(0xF6000000, 0);
|
||||
test__clzsi2(0xF7000000, 0);
|
||||
test__clzsi2(0xF8000000, 0);
|
||||
test__clzsi2(0xF9000000, 0);
|
||||
test__clzsi2(0xFA000000, 0);
|
||||
test__clzsi2(0xFB000000, 0);
|
||||
test__clzsi2(0xFC000000, 0);
|
||||
test__clzsi2(0xFD000000, 0);
|
||||
test__clzsi2(0xFE000000, 0);
|
||||
test__clzsi2(0xFF000000, 0);
|
||||
test__clzsi2(0x00000001, 31);
|
||||
test__clzsi2(0x00000002, 30);
|
||||
test__clzsi2(0x00000004, 29);
|
||||
test__clzsi2(0x00000008, 28);
|
||||
test__clzsi2(0x00000010, 27);
|
||||
test__clzsi2(0x00000020, 26);
|
||||
test__clzsi2(0x00000040, 25);
|
||||
test__clzsi2(0x00000080, 24);
|
||||
test__clzsi2(0x00000100, 23);
|
||||
test__clzsi2(0x00000200, 22);
|
||||
test__clzsi2(0x00000400, 21);
|
||||
test__clzsi2(0x00000800, 20);
|
||||
test__clzsi2(0x00001000, 19);
|
||||
test__clzsi2(0x00002000, 18);
|
||||
test__clzsi2(0x00004000, 17);
|
||||
test__clzsi2(0x00008000, 16);
|
||||
test__clzsi2(0x00010000, 15);
|
||||
test__clzsi2(0x00020000, 14);
|
||||
test__clzsi2(0x00040000, 13);
|
||||
test__clzsi2(0x00080000, 12);
|
||||
test__clzsi2(0x00100000, 11);
|
||||
test__clzsi2(0x00200000, 10);
|
||||
test__clzsi2(0x00400000, 9);
|
||||
}
|
253
lib/std/special/compiler_rt/compareXf2.zig
Normal file
253
lib/std/special/compiler_rt/compareXf2.zig
Normal file
@ -0,0 +1,253 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const LE = extern enum(i32) {
|
||||
Less = -1,
|
||||
Equal = 0,
|
||||
Greater = 1,
|
||||
Unordered = 1,
|
||||
};
|
||||
|
||||
const GE = extern enum(i32) {
|
||||
Less = -1,
|
||||
Equal = 0,
|
||||
Greater = 1,
|
||||
Unordered = -1,
|
||||
};
|
||||
|
||||
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 significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const infRep = @bitCast(rep_t, std.math.inf(T));
|
||||
|
||||
const aInt = @bitCast(srep_t, a);
|
||||
const bInt = @bitCast(srep_t, b);
|
||||
const aAbs = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep or bAbs > infRep) return .Unordered;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return .Equal;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return .Less;
|
||||
} else if (aInt == bInt) {
|
||||
return .Equal;
|
||||
} else return .Greater;
|
||||
}
|
||||
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
else {
|
||||
if (aInt > bInt) {
|
||||
return .Less;
|
||||
} else if (aInt == bInt) {
|
||||
return .Equal;
|
||||
} else return .Greater;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unordcmp(comptime T: type, a: T, b: T) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
|
||||
const rep_t = @IntType(false, T.bit_count);
|
||||
|
||||
const significandBits = std.math.floatMantissaBits(T);
|
||||
const exponentBits = std.math.floatExponentBits(T);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const infRep = @bitCast(rep_t, std.math.inf(T));
|
||||
|
||||
const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
|
||||
|
||||
return @boolToInt(aAbs > infRep or bAbs > infRep);
|
||||
}
|
||||
|
||||
// Comparison between f32
|
||||
|
||||
pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, LE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, GE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
return __gesf2(a, b);
|
||||
}
|
||||
|
||||
// Comparison between f64
|
||||
|
||||
pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, LE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, GE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
return __gedf2(a, b);
|
||||
}
|
||||
|
||||
// Comparison between f128
|
||||
|
||||
pub fn __letf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, LE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __getf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, GE, a, b }));
|
||||
}
|
||||
|
||||
pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __letf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __letf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __netf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __letf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
return __getf2(a, b);
|
||||
}
|
||||
|
||||
// Unordered comparison between f32/f64/f128
|
||||
|
||||
pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @call(.{ .modifier = .always_inline }, unordcmp, .{ f32, a, b });
|
||||
}
|
||||
|
||||
pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @call(.{ .modifier = .always_inline }, unordcmp, .{ f64, a, b });
|
||||
}
|
||||
|
||||
pub fn __unordtf2(a: f128, b: f128) callconv(.C) i32 {
|
||||
@setRuntimeSafety(builtin.is_test);
|
||||
return @call(.{ .modifier = .always_inline }, unordcmp, .{ f128, a, b });
|
||||
}
|
||||
|
||||
// ARM EABI intrinsics
|
||||
|
||||
pub fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __eqsf2, .{ a, b }) == 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __ltsf2, .{ a, b }) < 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __lesf2, .{ a, b }) <= 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __gesf2, .{ a, b }) >= 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __gtsf2, .{ a, b }) > 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b });
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __eqdf2, .{ a, b }) == 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __ltdf2, .{ a, b }) < 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __ledf2, .{ a, b }) <= 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __gedf2, .{ a, b }) >= 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @boolToInt(@call(.{ .modifier = .always_inline }, __gtdf2, .{ a, b }) > 0);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b });
|
||||
}
|
||||
|
||||
test "comparesf2" {
|
||||
_ = @import("comparesf2_test.zig");
|
||||
}
|
||||
test "comparedf2" {
|
||||
_ = @import("comparedf2_test.zig");
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparedf2.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const fp_t = f64;
|
||||
const rep_t = u64;
|
||||
const srep_t = i64;
|
||||
|
||||
const typeWidth = rep_t.bit_count;
|
||||
const significandBits = std.math.floatMantissaBits(fp_t);
|
||||
const exponentBits = std.math.floatExponentBits(fp_t);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const implicitBit = @as(rep_t, 1) << significandBits;
|
||||
const significandMask = implicitBit - 1;
|
||||
const exponentMask = absMask ^ significandMask;
|
||||
const infRep = @bitCast(rep_t, std.math.inf(fp_t));
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const LE_LESS = @as(c_int, -1);
|
||||
const LE_EQUAL = @as(c_int, 0);
|
||||
const LE_GREATER = @as(c_int, 1);
|
||||
const LE_UNORDERED = @as(c_int, 1);
|
||||
|
||||
pub fn __ledf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aInt: srep_t = @bitCast(srep_t, a);
|
||||
const bInt: srep_t = @bitCast(srep_t, b);
|
||||
const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return LE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return LE_EQUAL;
|
||||
} else return LE_GREATER;
|
||||
}
|
||||
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
else {
|
||||
if (aInt > bInt) {
|
||||
return LE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return LE_EQUAL;
|
||||
} else return LE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const GE_LESS = @as(c_int, -1);
|
||||
const GE_EQUAL = @as(c_int, 0);
|
||||
const GE_GREATER = @as(c_int, 1);
|
||||
const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
|
||||
|
||||
pub fn __gedf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aInt: srep_t = @bitCast(srep_t, a);
|
||||
const bInt: srep_t = @bitCast(srep_t, b);
|
||||
const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
|
||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return GE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return GE_EQUAL;
|
||||
} else return GE_GREATER;
|
||||
} else {
|
||||
if (aInt > bInt) {
|
||||
return GE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return GE_EQUAL;
|
||||
} else return GE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __unorddf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
|
||||
return @boolToInt(aAbs > infRep or bAbs > infRep);
|
||||
}
|
||||
|
||||
pub fn __eqdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __ltdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __nedf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __gtdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __gedf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __aeabi_dcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b });
|
||||
}
|
||||
|
||||
test "import comparedf2" {
|
||||
_ = @import("comparedf2_test.zig");
|
||||
}
|
@ -6,7 +6,7 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const comparedf2 = @import("comparedf2.zig");
|
||||
const comparedf2 = @import("compareXf2.zig");
|
||||
|
||||
const TestVector = struct {
|
||||
a: f64,
|
||||
|
@ -1,127 +0,0 @@
|
||||
// Ported from:
|
||||
//
|
||||
// https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const fp_t = f32;
|
||||
const rep_t = u32;
|
||||
const srep_t = i32;
|
||||
|
||||
const typeWidth = rep_t.bit_count;
|
||||
const significandBits = std.math.floatMantissaBits(fp_t);
|
||||
const exponentBits = std.math.floatExponentBits(fp_t);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const implicitBit = @as(rep_t, 1) << significandBits;
|
||||
const significandMask = implicitBit - 1;
|
||||
const exponentMask = absMask ^ significandMask;
|
||||
const infRep = @bitCast(rep_t, std.math.inf(fp_t));
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const LE_LESS = @as(c_int, -1);
|
||||
const LE_EQUAL = @as(c_int, 0);
|
||||
const LE_GREATER = @as(c_int, 1);
|
||||
const LE_UNORDERED = @as(c_int, 1);
|
||||
|
||||
pub fn __lesf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aInt: srep_t = @bitCast(srep_t, a);
|
||||
const bInt: srep_t = @bitCast(srep_t, b);
|
||||
const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return LE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return LE_EQUAL;
|
||||
} else return LE_GREATER;
|
||||
}
|
||||
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
else {
|
||||
if (aInt > bInt) {
|
||||
return LE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return LE_EQUAL;
|
||||
} else return LE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const GE_LESS = @as(c_int, -1);
|
||||
const GE_EQUAL = @as(c_int, 0);
|
||||
const GE_GREATER = @as(c_int, 1);
|
||||
const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
|
||||
|
||||
pub fn __gesf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aInt: srep_t = @bitCast(srep_t, a);
|
||||
const bInt: srep_t = @bitCast(srep_t, b);
|
||||
const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
|
||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) {
|
||||
return GE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return GE_EQUAL;
|
||||
} else return GE_GREATER;
|
||||
} else {
|
||||
if (aInt > bInt) {
|
||||
return GE_LESS;
|
||||
} else if (aInt == bInt) {
|
||||
return GE_EQUAL;
|
||||
} else return GE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __unordsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
|
||||
const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
|
||||
return @boolToInt(aAbs > infRep or bAbs > infRep);
|
||||
}
|
||||
|
||||
pub fn __eqsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __ltsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __nesf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __gtsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
|
||||
return __gesf2(a, b);
|
||||
}
|
||||
|
||||
pub fn __aeabi_fcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int {
|
||||
@setRuntimeSafety(false);
|
||||
return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b });
|
||||
}
|
||||
|
||||
test "import comparesf2" {
|
||||
_ = @import("comparesf2_test.zig");
|
||||
}
|
@ -6,7 +6,7 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
const comparesf2 = @import("comparesf2.zig");
|
||||
const comparesf2 = @import("compareXf2.zig");
|
||||
|
||||
const TestVector = struct {
|
||||
a: f32,
|
||||
|
@ -1,99 +0,0 @@
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const LE_LESS = @as(c_int, -1);
|
||||
const LE_EQUAL = @as(c_int, 0);
|
||||
const LE_GREATER = @as(c_int, 1);
|
||||
const LE_UNORDERED = @as(c_int, 1);
|
||||
|
||||
const rep_t = u128;
|
||||
const srep_t = i128;
|
||||
|
||||
const typeWidth = rep_t.bit_count;
|
||||
const significandBits = 112;
|
||||
const exponentBits = (typeWidth - significandBits - 1);
|
||||
const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
|
||||
const absMask = signBit - 1;
|
||||
const implicitBit = @as(rep_t, 1) << significandBits;
|
||||
const significandMask = implicitBit - 1;
|
||||
const exponentMask = absMask ^ significandMask;
|
||||
const infRep = exponentMask;
|
||||
|
||||
const builtin = @import("builtin");
|
||||
const is_test = builtin.is_test;
|
||||
|
||||
pub fn __letf2(a: f128, b: f128) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
|
||||
const aInt = @bitCast(rep_t, a);
|
||||
const bInt = @bitCast(rep_t, b);
|
||||
|
||||
const aAbs: rep_t = aInt & absMask;
|
||||
const bAbs: rep_t = bInt & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a floating-point compare.
|
||||
return if ((aInt & bInt) >= 0)
|
||||
if (aInt < bInt)
|
||||
LE_LESS
|
||||
else if (aInt == bInt)
|
||||
LE_EQUAL
|
||||
else
|
||||
LE_GREATER
|
||||
else
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
if (aInt > bInt)
|
||||
LE_LESS
|
||||
else if (aInt == bInt)
|
||||
LE_EQUAL
|
||||
else
|
||||
LE_GREATER;
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const GE_LESS = @as(c_int, -1);
|
||||
const GE_EQUAL = @as(c_int, 0);
|
||||
const GE_GREATER = @as(c_int, 1);
|
||||
const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
|
||||
|
||||
pub fn __getf2(a: f128, b: f128) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
|
||||
const aInt = @bitCast(srep_t, a);
|
||||
const bInt = @bitCast(srep_t, b);
|
||||
const aAbs = @bitCast(rep_t, aInt) & absMask;
|
||||
const bAbs = @bitCast(rep_t, bInt) & absMask;
|
||||
|
||||
if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
|
||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
||||
return if ((aInt & bInt) >= 0)
|
||||
if (aInt < bInt)
|
||||
GE_LESS
|
||||
else if (aInt == bInt)
|
||||
GE_EQUAL
|
||||
else
|
||||
GE_GREATER
|
||||
else if (aInt > bInt)
|
||||
GE_LESS
|
||||
else if (aInt == bInt)
|
||||
GE_EQUAL
|
||||
else
|
||||
GE_GREATER;
|
||||
}
|
||||
|
||||
pub fn __unordtf2(a: f128, b: f128) callconv(.C) c_int {
|
||||
@setRuntimeSafety(is_test);
|
||||
|
||||
const aAbs = @bitCast(rep_t, a) & absMask;
|
||||
const bAbs = @bitCast(rep_t, b) & absMask;
|
||||
return @boolToInt(aAbs > infRep or bAbs > infRep);
|
||||
}
|
@ -8,16 +8,7 @@ const uefi = std.os.uefi;
|
||||
|
||||
var starting_stack_ptr: [*]usize = undefined;
|
||||
|
||||
const is_wasm = switch (builtin.arch) {
|
||||
.wasm32, .wasm64 => true,
|
||||
else => false,
|
||||
};
|
||||
|
||||
const is_mips = switch (builtin.arch) {
|
||||
.mips, .mipsel, .mips64, .mips64el => true,
|
||||
else => false,
|
||||
};
|
||||
const start_sym_name = if (is_mips) "__start" else "_start";
|
||||
const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start";
|
||||
|
||||
comptime {
|
||||
if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
|
||||
@ -35,7 +26,7 @@ comptime {
|
||||
}
|
||||
} else if (builtin.os == .uefi) {
|
||||
if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" });
|
||||
} else if (is_wasm and builtin.os == .freestanding) {
|
||||
} else if (builtin.arch.isWasm() and builtin.os == .freestanding) {
|
||||
if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });
|
||||
} else if (builtin.os != .other and builtin.os != .freestanding) {
|
||||
if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });
|
||||
|
@ -125,6 +125,16 @@ pub const Target = union(enum) {
|
||||
v5,
|
||||
v5te,
|
||||
v4t,
|
||||
|
||||
pub fn version(version: Arm32) comptime_int {
|
||||
return switch (version) {
|
||||
.v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8,
|
||||
.v7, .v7em, .v7m, .v7s, .v7k, .v7ve => 7,
|
||||
.v6, .v6m, .v6k, .v6t2 => 6,
|
||||
.v5, .v5te => 5,
|
||||
.v4t => 4,
|
||||
};
|
||||
}
|
||||
};
|
||||
pub const Arm64 = enum {
|
||||
v8_5a,
|
||||
@ -146,6 +156,34 @@ pub const Target = union(enum) {
|
||||
r6,
|
||||
};
|
||||
|
||||
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 isMIPS(arch: Arch) bool {
|
||||
return switch (arch) {
|
||||
.mips, .mipsel, .mips64, .mips64el => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toElfMachine(arch: Arch) std.elf.EM {
|
||||
return switch (arch) {
|
||||
.avr => ._AVR,
|
||||
|
@ -289,8 +289,7 @@ pub fn translate(
|
||||
tree.errors = ast.Tree.ErrorList.init(arena);
|
||||
|
||||
tree.root_node = try arena.create(ast.Node.Root);
|
||||
tree.root_node.* = ast.Node.Root{
|
||||
.base = ast.Node{ .id = ast.Node.Id.Root },
|
||||
tree.root_node.* = .{
|
||||
.decls = ast.Node.Root.DeclList.init(arena),
|
||||
// initialized with the eof token at the end
|
||||
.eof_token = undefined,
|
||||
@ -440,7 +439,6 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
.PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
|
||||
.Auto => unreachable, // Not legal on functions
|
||||
.Register => unreachable, // Not legal on functions
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
||||
@ -877,25 +875,23 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
|
||||
// types, while that's not ISO-C compliant many compilers allow this and
|
||||
// default to the usual integer type used for all the enums.
|
||||
|
||||
// TODO only emit this tag type if the enum tag type is not the default.
|
||||
// I don't know what the default is, need to figure out how clang is deciding.
|
||||
// it appears to at least be different across gcc/msvc
|
||||
if (int_type.ptr != null and
|
||||
!isCBuiltinType(int_type, .UInt) and
|
||||
!isCBuiltinType(int_type, .Int))
|
||||
{
|
||||
_ = try appendToken(c, .LParen, "(");
|
||||
container_node.init_arg_expr = .{
|
||||
.Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
|
||||
// default to c_int since msvc and gcc default to different types
|
||||
_ = try appendToken(c, .LParen, "(");
|
||||
container_node.init_arg_expr = .{
|
||||
.Type = if (int_type.ptr != null and
|
||||
!isCBuiltinType(int_type, .UInt) and
|
||||
!isCBuiltinType(int_type, .Int))
|
||||
transQualType(rp, int_type, enum_loc) catch |err| switch (err) {
|
||||
error.UnsupportedType => {
|
||||
try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{});
|
||||
return null;
|
||||
},
|
||||
else => |e| return e,
|
||||
},
|
||||
};
|
||||
_ = try appendToken(c, .RParen, ")");
|
||||
}
|
||||
}
|
||||
else
|
||||
try transCreateNodeIdentifier(c, "c_int"),
|
||||
};
|
||||
_ = try appendToken(c, .RParen, ")");
|
||||
|
||||
container_node.lbrace_token = try appendToken(c, .LBrace, "{");
|
||||
|
||||
@ -953,6 +949,19 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
|
||||
tld_node.semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
try addTopLevelDecl(c, field_name, &tld_node.base);
|
||||
}
|
||||
// make non exhaustive
|
||||
const field_node = try c.a().create(ast.Node.ContainerField);
|
||||
field_node.* = .{
|
||||
.doc_comments = null,
|
||||
.comptime_token = null,
|
||||
.name_token = try appendIdentifier(c, "_"),
|
||||
.type_expr = null,
|
||||
.value_expr = null,
|
||||
.align_expr = null,
|
||||
};
|
||||
|
||||
try container_node.fields_and_decls.push(&field_node.base);
|
||||
_ = try appendToken(c, .Comma, ",");
|
||||
container_node.rbrace_token = try appendToken(c, .RBrace, "}");
|
||||
|
||||
break :blk &container_node.base;
|
||||
@ -1231,18 +1240,6 @@ fn transBinaryOperator(
|
||||
op_id = .BitOr;
|
||||
op_token = try appendToken(rp.c, .Pipe, "|");
|
||||
},
|
||||
.Assign,
|
||||
.MulAssign,
|
||||
.DivAssign,
|
||||
.RemAssign,
|
||||
.AddAssign,
|
||||
.SubAssign,
|
||||
.ShlAssign,
|
||||
.ShrAssign,
|
||||
.AndAssign,
|
||||
.XorAssign,
|
||||
.OrAssign,
|
||||
=> unreachable,
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
@ -1678,7 +1675,6 @@ fn transStringLiteral(
|
||||
"TODO: support string literal kind {}",
|
||||
.{kind},
|
||||
),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2206,6 +2202,19 @@ fn transDoWhileLoop(
|
||||
.id = .Loop,
|
||||
};
|
||||
|
||||
// if (!cond) break;
|
||||
const if_node = try transCreateNodeIf(rp.c);
|
||||
var cond_scope = Scope{
|
||||
.parent = scope,
|
||||
.id = .Condition,
|
||||
};
|
||||
const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!");
|
||||
prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true);
|
||||
_ = try appendToken(rp.c, .RParen, ")");
|
||||
if_node.condition = &prefix_op.base;
|
||||
if_node.body = &(try transCreateNodeBreak(rp.c, null)).base;
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
|
||||
const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: {
|
||||
// there's already a block in C, so we'll append our condition to it.
|
||||
// c: do {
|
||||
@ -2217,10 +2226,7 @@ fn transDoWhileLoop(
|
||||
// zig: b;
|
||||
// zig: if (!cond) break;
|
||||
// zig: }
|
||||
const body = (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
|
||||
// if this is used as an expression in Zig it needs to be immediately followed by a semicolon
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
break :blk body;
|
||||
break :blk (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
|
||||
} else blk: {
|
||||
// the C statement is without a block, so we need to create a block to contain it.
|
||||
// c: do
|
||||
@ -2236,19 +2242,6 @@ fn transDoWhileLoop(
|
||||
break :blk block;
|
||||
};
|
||||
|
||||
// if (!cond) break;
|
||||
const if_node = try transCreateNodeIf(rp.c);
|
||||
var cond_scope = Scope{
|
||||
.parent = scope,
|
||||
.id = .Condition,
|
||||
};
|
||||
const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!");
|
||||
prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true);
|
||||
_ = try appendToken(rp.c, .RParen, ")");
|
||||
if_node.condition = &prefix_op.base;
|
||||
if_node.body = &(try transCreateNodeBreak(rp.c, null)).base;
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
|
||||
try body_node.statements.push(&if_node.base);
|
||||
if (new)
|
||||
body_node.rbrace = try appendToken(rp.c, .RBrace, "}");
|
||||
@ -4783,8 +4776,7 @@ fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex {
|
||||
fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node {
|
||||
const token_index = try appendIdentifier(c, name);
|
||||
const identifier = try c.a().create(ast.Node.Identifier);
|
||||
identifier.* = ast.Node.Identifier{
|
||||
.base = ast.Node{ .id = ast.Node.Id.Identifier },
|
||||
identifier.* = .{
|
||||
.token = token_index,
|
||||
};
|
||||
return &identifier.base;
|
||||
@ -4923,8 +4915,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
|
||||
|
||||
const token_index = try appendToken(c, .Keyword_var, "var");
|
||||
const identifier = try c.a().create(ast.Node.Identifier);
|
||||
identifier.* = ast.Node.Identifier{
|
||||
.base = ast.Node{ .id = ast.Node.Id.Identifier },
|
||||
identifier.* = .{
|
||||
.token = token_index,
|
||||
};
|
||||
|
||||
|
@ -358,6 +358,8 @@ struct LazyValueSizeOf {
|
||||
|
||||
IrAnalyze *ira;
|
||||
IrInstruction *target_type;
|
||||
|
||||
bool bit_size;
|
||||
};
|
||||
|
||||
struct LazyValueSliceType {
|
||||
@ -1383,6 +1385,7 @@ struct ZigTypeEnum {
|
||||
ContainerLayout layout;
|
||||
ResolveStatus resolve_status;
|
||||
|
||||
bool non_exhaustive;
|
||||
bool resolve_loop_flag;
|
||||
};
|
||||
|
||||
@ -1754,6 +1757,7 @@ enum BuiltinFnId {
|
||||
BuiltinFnIdFrameSize,
|
||||
BuiltinFnIdAs,
|
||||
BuiltinFnIdCall,
|
||||
BuiltinFnIdBitSizeof,
|
||||
};
|
||||
|
||||
struct BuiltinFnEntry {
|
||||
@ -3146,6 +3150,7 @@ struct IrInstructionAsmGen {
|
||||
struct IrInstructionSizeOf {
|
||||
IrInstruction base;
|
||||
|
||||
bool bit_size;
|
||||
IrInstruction *type_value;
|
||||
};
|
||||
|
||||
@ -3665,6 +3670,7 @@ struct IrInstructionCheckSwitchProngs {
|
||||
IrInstructionCheckSwitchProngsRange *ranges;
|
||||
size_t range_count;
|
||||
bool have_else_prong;
|
||||
bool have_underscore_prong;
|
||||
};
|
||||
|
||||
struct IrInstructionCheckStatementIsVoid {
|
||||
|
@ -2569,15 +2569,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
|
||||
enum_type->data.enumeration.fields_by_name.init(field_count);
|
||||
|
||||
Scope *scope = &enum_type->data.enumeration.decls_scope->base;
|
||||
|
||||
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
|
||||
occupied_tag_values.init(field_count);
|
||||
|
||||
ZigType *tag_int_type;
|
||||
if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
|
||||
tag_int_type = get_c_int_type(g, CIntTypeInt);
|
||||
@ -2612,13 +2605,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
buf_ptr(&wanted_tag_int_type->name)));
|
||||
add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr,
|
||||
buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid"));
|
||||
return ErrorNone;
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
}
|
||||
tag_int_type = wanted_tag_int_type;
|
||||
}
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.non_exhaustive = false;
|
||||
enum_type->data.enumeration.tag_int_type = tag_int_type;
|
||||
enum_type->size_in_bits = tag_int_type->size_in_bits;
|
||||
enum_type->abi_size = tag_int_type->abi_size;
|
||||
@ -2627,6 +2621,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
BigInt bi_one;
|
||||
bigint_init_unsigned(&bi_one, 1);
|
||||
|
||||
AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
|
||||
if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
|
||||
field_count -= 1;
|
||||
if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (decl_node->data.container_decl.init_arg_expr == nullptr) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
if (last_field_node->data.struct_field.value != nullptr) {
|
||||
add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
enum_type->data.enumeration.non_exhaustive = true;
|
||||
}
|
||||
|
||||
enum_type->data.enumeration.src_field_count = field_count;
|
||||
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
|
||||
enum_type->data.enumeration.fields_by_name.init(field_count);
|
||||
|
||||
HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
|
||||
occupied_tag_values.init(field_count);
|
||||
|
||||
TypeEnumField *last_enum_field = nullptr;
|
||||
|
||||
for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
|
||||
@ -2648,6 +2667,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
buf_sprintf("consider 'union(enum)' here"));
|
||||
}
|
||||
|
||||
if (buf_eql_str(type_enum_field->name, "_")) {
|
||||
add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
|
||||
enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
|
||||
}
|
||||
|
||||
auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
|
||||
if (field_entry != nullptr) {
|
||||
ErrorMsg *msg = add_node_error(g, field_node,
|
||||
@ -8288,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu
|
||||
|
||||
uint32_t field_count = enum_type->data.enumeration.src_field_count;
|
||||
|
||||
assert(enum_type->data.enumeration.fields);
|
||||
assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr);
|
||||
ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count);
|
||||
|
||||
for (uint32_t i = 0; i < field_count; i += 1) {
|
||||
|
@ -3356,7 +3356,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable,
|
||||
LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base),
|
||||
instruction->target->value->type, tag_int_type, target_val);
|
||||
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && !wanted_type->data.enumeration.non_exhaustive) {
|
||||
LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue");
|
||||
LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue");
|
||||
size_t field_count = wanted_type->data.enumeration.src_field_count;
|
||||
@ -5065,6 +5065,11 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
|
||||
{
|
||||
ZigType *enum_type = instruction->target->value->type;
|
||||
assert(enum_type->id == ZigTypeIdEnum);
|
||||
if (enum_type->data.enumeration.non_exhaustive) {
|
||||
add_node_error(g, instruction->base.source_node,
|
||||
buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
|
||||
codegen_report_errors_and_exit(g);
|
||||
}
|
||||
|
||||
LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type);
|
||||
|
||||
@ -8299,6 +8304,7 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdAs, "as", 2);
|
||||
create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
|
||||
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
|
||||
}
|
||||
|
||||
static const char *bool_to_str(bool b) {
|
||||
|
187
src/ir.cpp
187
src/ir.cpp
@ -2392,9 +2392,10 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {
|
||||
static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, bool bit_size) {
|
||||
IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, scope, source_node);
|
||||
instruction->type_value = type_value;
|
||||
instruction->bit_size = bit_size;
|
||||
|
||||
ir_ref_instruction(type_value, irb->current_basic_block);
|
||||
|
||||
@ -3451,7 +3452,7 @@ static IrInstruction *ir_build_err_to_int(IrBuilder *irb, Scope *scope, AstNode
|
||||
|
||||
static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count,
|
||||
bool have_else_prong)
|
||||
bool have_else_prong, bool have_underscore_prong)
|
||||
{
|
||||
IrInstructionCheckSwitchProngs *instruction = ir_build_instruction<IrInstructionCheckSwitchProngs>(
|
||||
irb, scope, source_node);
|
||||
@ -3459,6 +3460,7 @@ static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope,
|
||||
instruction->ranges = ranges;
|
||||
instruction->range_count = range_count;
|
||||
instruction->have_else_prong = have_else_prong;
|
||||
instruction->have_underscore_prong = have_underscore_prong;
|
||||
|
||||
ir_ref_instruction(target_value, irb->current_basic_block);
|
||||
for (size_t i = 0; i < range_count; i += 1) {
|
||||
@ -5249,13 +5251,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdSizeof:
|
||||
case BuiltinFnIdBitSizeof:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value);
|
||||
IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof);
|
||||
return ir_lval_wrap(irb, scope, size_of, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdImport:
|
||||
@ -6027,8 +6030,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value);
|
||||
IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag);
|
||||
IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, arg0_value);
|
||||
return ir_lval_wrap(irb, scope, tag_name, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdTagType:
|
||||
@ -8090,34 +8092,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
|
||||
Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
|
||||
AstNode *else_prong = nullptr;
|
||||
AstNode *underscore_prong = nullptr;
|
||||
for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
|
||||
AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
|
||||
size_t prong_item_count = prong_node->data.switch_prong.items.length;
|
||||
if (prong_item_count == 0) {
|
||||
ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
|
||||
if (else_prong) {
|
||||
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
|
||||
buf_sprintf("multiple else prongs in switch expression"));
|
||||
add_error_note(irb->codegen, msg, else_prong,
|
||||
buf_sprintf("previous else prong is here"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
else_prong = prong_node;
|
||||
|
||||
IrBasicBlock *prev_block = irb->current_basic_block;
|
||||
if (peer_parent->peers.length > 0) {
|
||||
peer_parent->peers.last()->next_bb = else_block;
|
||||
}
|
||||
peer_parent->peers.append(this_peer_result_loc);
|
||||
ir_set_cursor_at_end_and_append_block(irb, else_block);
|
||||
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
|
||||
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
|
||||
&switch_else_var, LValNone, &this_peer_result_loc->base))
|
||||
{
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
ir_set_cursor_at_end(irb, prev_block);
|
||||
} else if (prong_node->data.switch_prong.any_items_are_range) {
|
||||
if (prong_node->data.switch_prong.any_items_are_range) {
|
||||
ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
|
||||
|
||||
IrInstruction *ok_bit = nullptr;
|
||||
@ -8195,6 +8174,56 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
}
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, range_block_no);
|
||||
} else {
|
||||
if (prong_item_count == 0) {
|
||||
if (else_prong) {
|
||||
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
|
||||
buf_sprintf("multiple else prongs in switch expression"));
|
||||
add_error_note(irb->codegen, msg, else_prong,
|
||||
buf_sprintf("previous else prong is here"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
else_prong = prong_node;
|
||||
} else if (prong_item_count == 1 &&
|
||||
prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol &&
|
||||
buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) {
|
||||
if (underscore_prong) {
|
||||
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
|
||||
buf_sprintf("multiple '_' prongs in switch expression"));
|
||||
add_error_note(irb->codegen, msg, underscore_prong,
|
||||
buf_sprintf("previous '_' prong is here"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
underscore_prong = prong_node;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (underscore_prong && else_prong) {
|
||||
ErrorMsg *msg = add_node_error(irb->codegen, prong_node,
|
||||
buf_sprintf("else and '_' prong in switch expression"));
|
||||
if (underscore_prong == prong_node)
|
||||
add_error_note(irb->codegen, msg, else_prong,
|
||||
buf_sprintf("else prong is here"));
|
||||
else
|
||||
add_error_note(irb->codegen, msg, underscore_prong,
|
||||
buf_sprintf("'_' prong is here"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
|
||||
|
||||
IrBasicBlock *prev_block = irb->current_basic_block;
|
||||
if (peer_parent->peers.length > 0) {
|
||||
peer_parent->peers.last()->next_bb = else_block;
|
||||
}
|
||||
peer_parent->peers.append(this_peer_result_loc);
|
||||
ir_set_cursor_at_end_and_append_block(irb, else_block);
|
||||
if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block,
|
||||
is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values,
|
||||
&switch_else_var, LValNone, &this_peer_result_loc->base))
|
||||
{
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
ir_set_cursor_at_end(irb, prev_block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8206,6 +8235,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
continue;
|
||||
if (prong_node->data.switch_prong.any_items_are_range)
|
||||
continue;
|
||||
if (underscore_prong == prong_node)
|
||||
continue;
|
||||
|
||||
ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
|
||||
|
||||
@ -8249,7 +8280,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
}
|
||||
|
||||
IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value,
|
||||
check_ranges.items, check_ranges.length, else_prong != nullptr);
|
||||
check_ranges.items, check_ranges.length, else_prong != nullptr, underscore_prong != nullptr);
|
||||
|
||||
IrInstruction *br_instruction;
|
||||
if (cases.length == 0) {
|
||||
@ -8269,7 +8300,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode *
|
||||
peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction;
|
||||
}
|
||||
|
||||
if (!else_prong) {
|
||||
if (!else_prong && !underscore_prong) {
|
||||
if (peer_parent->peers.length != 0) {
|
||||
peer_parent->peers.last()->next_bb = else_block;
|
||||
}
|
||||
@ -12790,7 +12821,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint);
|
||||
if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) {
|
||||
if (field == nullptr && !wanted_type->data.enumeration.non_exhaustive) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &val->data.x_bigint, 10);
|
||||
ErrorMsg *msg = ir_add_error(ira, source_instr,
|
||||
@ -21065,6 +21096,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi
|
||||
lazy_size_of->ira = ira; ira_ref(ira);
|
||||
result->value->data.x_lazy = &lazy_size_of->base;
|
||||
lazy_size_of->base.id = LazyValueIdSizeOf;
|
||||
lazy_size_of->bit_size = instruction->bit_size;
|
||||
|
||||
lazy_size_of->target_type = instruction->type_value->child;
|
||||
if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr)
|
||||
@ -21356,10 +21388,6 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source
|
||||
if (type_is_invalid(value->value->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (value->value->type->id == ZigTypeIdEnum) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value->value->type->id != ZigTypeIdUnion) {
|
||||
ir_add_error(ira, value,
|
||||
buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value->type->name)));
|
||||
@ -21427,12 +21455,6 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira,
|
||||
if (type_is_invalid(case_value->value->type))
|
||||
return ir_unreach_error(ira);
|
||||
|
||||
if (case_value->value->type->id == ZigTypeIdEnum) {
|
||||
case_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, case_value);
|
||||
if (type_is_invalid(case_value->value->type))
|
||||
return ir_unreach_error(ira);
|
||||
}
|
||||
|
||||
IrInstruction *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type);
|
||||
if (type_is_invalid(casted_case_value->value->type))
|
||||
return ir_unreach_error(ira);
|
||||
@ -21477,12 +21499,6 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira,
|
||||
if (type_is_invalid(new_value->value->type))
|
||||
continue;
|
||||
|
||||
if (new_value->value->type->id == ZigTypeIdEnum) {
|
||||
new_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, new_value);
|
||||
if (type_is_invalid(new_value->value->type))
|
||||
continue;
|
||||
}
|
||||
|
||||
IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type);
|
||||
if (type_is_invalid(casted_new_value->value->type))
|
||||
continue;
|
||||
@ -21598,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (target_type->data.enumeration.src_field_count < 2) {
|
||||
if (target_type->data.enumeration.src_field_count == 1) {
|
||||
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
|
||||
IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type);
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
@ -22319,11 +22335,39 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
|
||||
if (type_is_invalid(target->value->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (target->value->type->id == ZigTypeIdEnumLiteral) {
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
|
||||
Buf *field_name = target->value->data.x_enum_literal;
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee;
|
||||
init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(field_name), true);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (target->value->type->id == ZigTypeIdUnion) {
|
||||
target = ir_analyze_union_tag(ira, &instruction->base, target);
|
||||
if (type_is_invalid(target->value->type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
assert(target->value->type->id == ZigTypeIdEnum);
|
||||
|
||||
if (target->value->type->data.enumeration.src_field_count == 1 &&
|
||||
!target->value->type->data.enumeration.non_exhaustive) {
|
||||
TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0];
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee;
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
|
||||
init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (instr_is_comptime(target)) {
|
||||
if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (target->value->type->data.enumeration.non_exhaustive) {
|
||||
add_node_error(ira->codegen, instruction->base.source_node,
|
||||
buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
|
||||
@ -23074,7 +23118,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
||||
result->special = ConstValSpecialStatic;
|
||||
result->type = ir_type_info_get_type(ira, "Enum", nullptr);
|
||||
|
||||
ZigValue **fields = alloc_const_vals_ptrs(4);
|
||||
ZigValue **fields = alloc_const_vals_ptrs(5);
|
||||
result->data.x_struct.fields = fields;
|
||||
|
||||
// layout: ContainerLayout
|
||||
@ -23120,6 +23164,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
||||
{
|
||||
return err;
|
||||
}
|
||||
// is_exhaustive: bool
|
||||
ensure_field_index(result->type, "is_exhaustive", 4);
|
||||
fields[4]->special = ConstValSpecialStatic;
|
||||
fields[4]->type = ira->codegen->builtin_types.entry_bool;
|
||||
fields[4]->data.x_bool = !type_entry->data.enumeration.non_exhaustive;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -23335,7 +23384,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
||||
struct_field_val->special = ConstValSpecialStatic;
|
||||
struct_field_val->type = type_info_struct_field_type;
|
||||
|
||||
ZigValue **inner_fields = alloc_const_vals_ptrs(3);
|
||||
ZigValue **inner_fields = alloc_const_vals_ptrs(4);
|
||||
inner_fields[1]->special = ConstValSpecialStatic;
|
||||
inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int);
|
||||
|
||||
@ -23358,6 +23407,12 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
|
||||
inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
|
||||
inner_fields[2]->data.x_type = struct_field->type_entry;
|
||||
|
||||
// default_value: var
|
||||
inner_fields[3]->special = ConstValSpecialStatic;
|
||||
inner_fields[3]->type = get_optional_type(ira->codegen, struct_field->type_entry);
|
||||
memoize_field_init_val(ira->codegen, type_entry, struct_field);
|
||||
set_optional_payload(inner_fields[3], struct_field->init_val);
|
||||
|
||||
ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
|
||||
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
|
||||
|
||||
@ -26433,10 +26488,27 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
|
||||
bigint_incr(&field_index);
|
||||
}
|
||||
}
|
||||
if (!instruction->have_else_prong) {
|
||||
if (switch_type->data.enumeration.layout == ContainerLayoutExtern) {
|
||||
if (instruction->have_underscore_prong) {
|
||||
if (!switch_type->data.enumeration.non_exhaustive){
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("switch on an extern enum must have an else prong"));
|
||||
buf_sprintf("switch on non-exhaustive enum has `_` prong"));
|
||||
}
|
||||
for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
|
||||
TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
|
||||
if (buf_eql_str(enum_field->name, "_"))
|
||||
continue;
|
||||
|
||||
auto entry = field_prev_uses.maybe_get(enum_field->value);
|
||||
if (!entry) {
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name),
|
||||
buf_ptr(enum_field->name)));
|
||||
}
|
||||
}
|
||||
} else if (!instruction->have_else_prong) {
|
||||
if (switch_type->data.enumeration.non_exhaustive) {
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong"));
|
||||
}
|
||||
for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) {
|
||||
TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i];
|
||||
@ -29415,7 +29487,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
|
||||
|
||||
val->special = ConstValSpecialStatic;
|
||||
assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt);
|
||||
bigint_init_unsigned(&val->data.x_bigint, abi_size);
|
||||
if (lazy_size_of->bit_size)
|
||||
bigint_init_unsigned(&val->data.x_bigint, size_in_bits);
|
||||
else
|
||||
bigint_init_unsigned(&val->data.x_bigint, abi_size);
|
||||
|
||||
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
|
||||
return ErrorNone;
|
||||
|
@ -1039,7 +1039,10 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
|
||||
fprintf(irp->f, "@sizeOf(");
|
||||
if (instruction->bit_size)
|
||||
fprintf(irp->f, "@bitSizeOf(");
|
||||
else
|
||||
fprintf(irp->f, "@sizeOf(");
|
||||
ir_print_other_instruction(irp, instruction->type_value);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
@ -2,6 +2,56 @@ const tests = @import("tests.zig");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.addTest("non-exhaustive enums",
|
||||
\\const A = enum {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ _ = 1,
|
||||
\\};
|
||||
\\const B = enum(u1) {
|
||||
\\ a,
|
||||
\\ _,
|
||||
\\ b,
|
||||
\\};
|
||||
\\const C = enum(u1) {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub export fn entry() void {
|
||||
\\ _ = A;
|
||||
\\ _ = B;
|
||||
\\ _ = C;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:4:5: error: non-exhaustive enum must specify size",
|
||||
"error: value assigned to '_' field of non-exhaustive enum",
|
||||
"error: non-exhaustive enum specifies every value",
|
||||
"error: '_' field of non-exhaustive enum must be last",
|
||||
});
|
||||
|
||||
cases.addTest("switching with non-exhaustive enums",
|
||||
\\const E = enum(u8) {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub export fn entry() void {
|
||||
\\ var e: E = .b;
|
||||
\\ switch (e) { // error: switch not handling the tag `b`
|
||||
\\ .a => {},
|
||||
\\ _ => {},
|
||||
\\ }
|
||||
\\ switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong
|
||||
\\ .a => {},
|
||||
\\ .b => {},
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:8:5: error: enumeration value 'E.b' not handled in switch",
|
||||
"tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong",
|
||||
});
|
||||
|
||||
cases.addTest("@export with empty name string",
|
||||
\\pub export fn entry() void { }
|
||||
\\comptime {
|
||||
@ -139,25 +189,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
"tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
|
||||
});
|
||||
|
||||
cases.add("switch on extern enum missing else prong",
|
||||
\\const i = extern enum {
|
||||
\\ n = 0,
|
||||
\\ o = 2,
|
||||
\\ p = 4,
|
||||
\\ q = 4,
|
||||
\\};
|
||||
\\pub fn main() void {
|
||||
\\ var x = @intToEnum(i, 52);
|
||||
\\ switch (x) {
|
||||
\\ .n,
|
||||
\\ .o,
|
||||
\\ .p => unreachable,
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
"tmp.zig:9:5: error: switch on an extern enum must have an else prong",
|
||||
});
|
||||
|
||||
cases.add("invalid float literal",
|
||||
\\const std = @import("std");
|
||||
\\
|
||||
|
@ -618,7 +618,6 @@ test "peer resolution of string literals" {
|
||||
.b => "two",
|
||||
.c => "three",
|
||||
.d => "four",
|
||||
else => unreachable,
|
||||
};
|
||||
expect(mem.eql(u8, cmd, "two"));
|
||||
}
|
||||
|
@ -11,16 +11,9 @@ test "extern enum" {
|
||||
};
|
||||
fn doTheTest(y: c_int) void {
|
||||
var x = i.o;
|
||||
expect(@enumToInt(x) == 2);
|
||||
x = @intToEnum(i, 12);
|
||||
expect(@enumToInt(x) == 12);
|
||||
x = @intToEnum(i, y);
|
||||
expect(@enumToInt(x) == 52);
|
||||
switch (x) {
|
||||
.n,
|
||||
.o,
|
||||
.p => unreachable,
|
||||
else => {},
|
||||
.n, .p => unreachable,
|
||||
.o => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -28,6 +21,70 @@ test "extern enum" {
|
||||
comptime S.doTheTest(52);
|
||||
}
|
||||
|
||||
test "non-exhaustive enum" {
|
||||
const S = struct {
|
||||
const E = enum(u8) {
|
||||
a,
|
||||
b,
|
||||
_,
|
||||
};
|
||||
fn doTheTest(y: u8) void {
|
||||
var e: E = .b;
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
.b => true,
|
||||
_ => false,
|
||||
});
|
||||
e = @intToEnum(E, 12);
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
.b => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
.b => false,
|
||||
else => true,
|
||||
});
|
||||
e = .b;
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
else => true,
|
||||
});
|
||||
|
||||
expect(@typeInfo(E).Enum.fields.len == 2);
|
||||
e = @intToEnum(E, 12);
|
||||
expect(@enumToInt(e) == 12);
|
||||
e = @intToEnum(E, y);
|
||||
expect(@enumToInt(e) == 52);
|
||||
expect(@typeInfo(E).Enum.is_exhaustive == false);
|
||||
}
|
||||
};
|
||||
S.doTheTest(52);
|
||||
comptime S.doTheTest(52);
|
||||
}
|
||||
|
||||
test "empty non-exhaustive enum" {
|
||||
const S = struct {
|
||||
const E = enum(u8) {
|
||||
_,
|
||||
};
|
||||
fn doTheTest(y: u8) void {
|
||||
var e = @intToEnum(E, y);
|
||||
expect(switch (e) {
|
||||
_ => true,
|
||||
});
|
||||
expect(@enumToInt(e) == y);
|
||||
|
||||
expect(@typeInfo(E).Enum.fields.len == 0);
|
||||
expect(@typeInfo(E).Enum.is_exhaustive == false);
|
||||
}
|
||||
};
|
||||
S.doTheTest(42);
|
||||
comptime S.doTheTest(42);
|
||||
}
|
||||
|
||||
test "enum type" {
|
||||
const foo1 = Foo{ .One = 13 };
|
||||
const foo2 = Foo{
|
||||
@ -1057,3 +1114,8 @@ test "enum with one member default to u0 tag type" {
|
||||
};
|
||||
comptime expect(@TagType(E0) == u0);
|
||||
}
|
||||
|
||||
test "tagName on enum literals" {
|
||||
expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
|
||||
comptime expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
|
||||
}
|
||||
|
@ -124,3 +124,14 @@ fn fn1(alpha: bool) void {
|
||||
test "lazy @sizeOf result is checked for definedness" {
|
||||
const f = fn1;
|
||||
}
|
||||
|
||||
test "@bitSizeOf" {
|
||||
expect(@bitSizeOf(u2) == 2);
|
||||
expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
|
||||
expect(@bitSizeOf(struct {
|
||||
a: u2
|
||||
}) == 8);
|
||||
expect(@bitSizeOf(packed struct {
|
||||
a: u2
|
||||
}) == 2);
|
||||
}
|
||||
|
@ -237,9 +237,11 @@ fn testStruct() void {
|
||||
const struct_info = @typeInfo(TestStruct);
|
||||
expect(@as(TypeId, struct_info) == TypeId.Struct);
|
||||
expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
|
||||
expect(struct_info.Struct.fields.len == 3);
|
||||
expect(struct_info.Struct.fields.len == 4);
|
||||
expect(struct_info.Struct.fields[1].offset == null);
|
||||
expect(struct_info.Struct.fields[2].field_type == *TestStruct);
|
||||
expect(struct_info.Struct.fields[2].default_value == null);
|
||||
expect(struct_info.Struct.fields[3].default_value.? == 4);
|
||||
expect(struct_info.Struct.decls.len == 2);
|
||||
expect(struct_info.Struct.decls[0].is_pub);
|
||||
expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
|
||||
@ -254,6 +256,7 @@ const TestStruct = packed struct {
|
||||
fieldA: usize,
|
||||
fieldB: void,
|
||||
fieldC: *Self,
|
||||
fieldD: u32 = 4,
|
||||
|
||||
pub fn foo(self: *const Self) void {}
|
||||
};
|
||||
|
@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" {
|
||||
var v = U{ .A = 532 };
|
||||
expect(v.A == 532);
|
||||
}
|
||||
|
||||
test "runtime tag name with single field" {
|
||||
const U = union(enum) {
|
||||
A: i32,
|
||||
};
|
||||
|
||||
var v = U{ .A = 42 };
|
||||
expect(std.mem.eql(u8, @tagName(v), "A"));
|
||||
}
|
||||
|
@ -629,6 +629,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ VAL21 = 6917529027641081853,
|
||||
\\ VAL22 = 0,
|
||||
\\ VAL23 = -1,
|
||||
\\ _,
|
||||
\\};
|
||||
});
|
||||
}
|
||||
@ -988,8 +989,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\enum enum_ty { FOO };
|
||||
, &[_][]const u8{
|
||||
\\pub const FOO = @enumToInt(enum_enum_ty.FOO);
|
||||
\\pub const enum_enum_ty = extern enum {
|
||||
\\pub const enum_enum_ty = extern enum(c_int) {
|
||||
\\ FOO,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub extern var my_enum: enum_enum_ty;
|
||||
});
|
||||
@ -1102,28 +1104,31 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const a = @enumToInt(enum_unnamed_1.a);
|
||||
\\pub const b = @enumToInt(enum_unnamed_1.b);
|
||||
\\pub const c = @enumToInt(enum_unnamed_1.c);
|
||||
\\const enum_unnamed_1 = extern enum {
|
||||
\\const enum_unnamed_1 = extern enum(c_int) {
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ c,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub const d = enum_unnamed_1;
|
||||
\\pub const e = @enumToInt(enum_unnamed_2.e);
|
||||
\\pub const f = @enumToInt(enum_unnamed_2.f);
|
||||
\\pub const g = @enumToInt(enum_unnamed_2.g);
|
||||
\\const enum_unnamed_2 = extern enum {
|
||||
\\const enum_unnamed_2 = extern enum(c_int) {
|
||||
\\ e = 0,
|
||||
\\ f = 4,
|
||||
\\ g = 5,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);
|
||||
\\pub const i = @enumToInt(enum_unnamed_3.i);
|
||||
\\pub const j = @enumToInt(enum_unnamed_3.j);
|
||||
\\pub const k = @enumToInt(enum_unnamed_3.k);
|
||||
\\const enum_unnamed_3 = extern enum {
|
||||
\\const enum_unnamed_3 = extern enum(c_int) {
|
||||
\\ i,
|
||||
\\ j,
|
||||
\\ k,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub const struct_Baz = extern struct {
|
||||
\\ l: enum_unnamed_3,
|
||||
@ -1132,10 +1137,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const n = @enumToInt(enum_i.n);
|
||||
\\pub const o = @enumToInt(enum_i.o);
|
||||
\\pub const p = @enumToInt(enum_i.p);
|
||||
\\pub const enum_i = extern enum {
|
||||
\\pub const enum_i = extern enum(c_int) {
|
||||
\\ n,
|
||||
\\ o,
|
||||
\\ p,
|
||||
\\ _,
|
||||
\\};
|
||||
,
|
||||
\\pub const Baz = struct_Baz;
|
||||
@ -1563,9 +1569,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub const One = @enumToInt(enum_unnamed_1.One);
|
||||
\\pub const Two = @enumToInt(enum_unnamed_1.Two);
|
||||
\\const enum_unnamed_1 = extern enum {
|
||||
\\const enum_unnamed_1 = extern enum(c_int) {
|
||||
\\ One,
|
||||
\\ Two,
|
||||
\\ _,
|
||||
\\};
|
||||
});
|
||||
|
||||
@ -1665,10 +1672,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub const enum_Foo = extern enum {
|
||||
\\pub const enum_Foo = extern enum(c_int) {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub const SomeTypedef = c_int;
|
||||
\\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
|
||||
@ -1710,9 +1718,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ y: c_int,
|
||||
\\};
|
||||
,
|
||||
\\pub const enum_Bar = extern enum {
|
||||
\\pub const enum_Bar = extern enum(c_int) {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
|
||||
,
|
||||
@ -1973,10 +1982,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 4;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub const enum_SomeEnum = extern enum {
|
||||
\\pub const enum_SomeEnum = extern enum(c_int) {
|
||||
\\ A,
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\ _,
|
||||
\\};
|
||||
\\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
|
||||
\\ var a = arg_a;
|
||||
@ -2414,10 +2424,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const FooA = @enumToInt(enum_Foo.A);
|
||||
\\pub const FooB = @enumToInt(enum_Foo.B);
|
||||
\\pub const Foo1 = @enumToInt(enum_Foo.@"1");
|
||||
\\pub const enum_Foo = extern enum {
|
||||
\\pub const enum_Foo = extern enum(c_int) {
|
||||
\\ A = 2,
|
||||
\\ B = 5,
|
||||
\\ @"1" = 6,
|
||||
\\ _,
|
||||
\\};
|
||||
,
|
||||
\\pub const Foo = enum_Foo;
|
||||
|
Loading…
Reference in New Issue
Block a user