| author | |
| committer | |
| log | 97b2ac598b91194c09a96c9ed86e4f9b266d019c |
| tree | f8ddd18aaf3a52981f3a97faeac8ef7bd20e6908 |
| parent | 7e674d6761c057985003694f98861f589b6cf313 |
| parent | c522699f28c1df806865c527a7a68a875e606527 |
| signature |
43 files changed, 1432 insertions(+), 937 deletions(-)
CMakeLists.txt+29-12| ... | @@ -45,7 +45,6 @@ message("Configuring zig version ${ZIG_VERSION}") | ... | @@ -45,7 +45,6 @@ message("Configuring zig version ${ZIG_VERSION}") |
| 45 | 45 | ||
| 46 | set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)") | 46 | set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)") |
| 47 | set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries") | 47 | set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries") |
| 48 | set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix") | ||
| 49 | set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation") | 48 | set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation") |
| 50 | 49 | ||
| 51 | if(ZIG_STATIC) | 50 | if(ZIG_STATIC) |
| ... | @@ -414,19 +413,26 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") | ... | @@ -414,19 +413,26 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") |
| 414 | else() | 413 | else() |
| 415 | set(LIBUSERLAND_RELEASE_MODE "true") | 414 | set(LIBUSERLAND_RELEASE_MODE "true") |
| 416 | endif() | 415 | endif() |
| 417 | if(ZIG_SKIP_INSTALL_LIB_FILES) | 416 | |
| 418 | set(ZIG_BUILD_INSTALL_STEP "") | 417 | set(BUILD_LIBUSERLAND_ARGS "build" |
| 419 | else() | 418 | --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" |
| 420 | set(ZIG_BUILD_INSTALL_STEP "install") | 419 | "-Doutput-dir=${CMAKE_BINARY_DIR}" |
| 420 | "-Drelease=${LIBUSERLAND_RELEASE_MODE}" | ||
| 421 | "-Dlib-files-only" | ||
| 422 | --prefix "${CMAKE_INSTALL_PREFIX}" | ||
| 423 | libuserland | ||
| 424 | ) | ||
| 425 | |||
| 426 | # When using Visual Studio build system generator we default to libuserland install. | ||
| 427 | if(MSVC) | ||
| 428 | set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix") | ||
| 429 | if(NOT ZIG_SKIP_INSTALL_LIB_FILES) | ||
| 430 | set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install) | ||
| 431 | endif() | ||
| 421 | endif() | 432 | endif() |
| 433 | |||
| 422 | add_custom_target(zig_build_libuserland ALL | 434 | add_custom_target(zig_build_libuserland ALL |
| 423 | COMMAND zig0 build | 435 | COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} |
| 424 | --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" | ||
| 425 | libuserland ${ZIG_BUILD_INSTALL_STEP} | ||
| 426 | "-Doutput-dir=${CMAKE_BINARY_DIR}" | ||
| 427 | "-Drelease=${LIBUSERLAND_RELEASE_MODE}" | ||
| 428 | "-Dlib-files-only" | ||
| 429 | --prefix "${CMAKE_INSTALL_PREFIX}" | ||
| 430 | DEPENDS zig0 | 436 | DEPENDS zig0 |
| 431 | BYPRODUCTS "${LIBUSERLAND}" | 437 | BYPRODUCTS "${LIBUSERLAND}" |
| 432 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | 438 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" |
| ... | @@ -444,4 +450,15 @@ elseif(MINGW) | ... | @@ -444,4 +450,15 @@ elseif(MINGW) |
| 444 | target_link_libraries(zig ntdll) | 450 | target_link_libraries(zig ntdll) |
| 445 | endif() | 451 | endif() |
| 446 | add_dependencies(zig zig_build_libuserland) | 452 | add_dependencies(zig zig_build_libuserland) |
| 453 | |||
| 447 | install(TARGETS zig DESTINATION bin) | 454 | install(TARGETS zig DESTINATION bin) |
| 455 | |||
| 456 | # CODE has no effect with Visual Studio build system generator. | ||
| 457 | if(NOT MSVC) | ||
| 458 | get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR) | ||
| 459 | install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")") | ||
| 460 | install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)") | ||
| 461 | install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")") | ||
| 462 | install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")") | ||
| 463 | install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake) | ||
| 464 | endif() |
CONTRIBUTING.md+20-15| ... | @@ -51,23 +51,28 @@ knowledge of Zig internals.** | ... | @@ -51,23 +51,28 @@ knowledge of Zig internals.** |
| 51 | 51 | ||
| 52 | ### Editing Source Code | 52 | ### Editing Source Code |
| 53 | 53 | ||
| 54 | First, build the Stage 1 compiler as described in [the Building section](#building). | 54 | First, build the Stage 1 compiler as described in [Building from Source](README.md#Building-from-Source). |
| 55 | 55 | ||
| 56 | One modification you may want to make is adding `-DZIG_SKIP_INSTALL_LIB_FILES=ON` | 56 | Zig locates lib files relative to executable path by searching up the |
| 57 | to the cmake line. If you use the build directory as a working directory to run | 57 | filesystem tree for a sub-path of `lib/zig/std/std.zig` or `lib/std/std.zig`. |
| 58 | tests with, zig will find the lib files in the source directory, and they will not | 58 | Typically the former is an install and the latter a git working tree which |
| 59 | be "installed" every time you run `make`. This will allow you to make modifications | 59 | contains the build directory. |
| 60 | directly to the standard library, for example, and have them effective immediately. | 60 | |
| 61 | Note that if you already ran `make` or `make install` with the default cmake | 61 | During development it is not necessary to perform installs when modifying |
| 62 | settings, there will already be a `lib/` directory in your build directory. When | 62 | stage1 or userland sources and in fact it is faster and simpler to run, |
| 63 | executed from the build directory, zig will find this instead of the source lib/ | 63 | test and debug from a git working tree. |
| 64 | directory. Remove the unwanted directory so that the desired one can be found. | 64 | |
| 65 | - `make` is typically sufficient to build zig during development iterations. | ||
| 66 | - `make install` performs a build __and__ install. | ||
| 67 | - `msbuild -p:Configuration=Release INSTALL.vcxproj` on Windows performs a | ||
| 68 | build and install. To avoid install, pass cmake option `-DZIG_SKIP_INSTALL_LIB_FILES=ON`. | ||
| 65 | 69 | ||
| 66 | To test changes, do the following from the build directory: | 70 | To test changes, do the following from the build directory: |
| 67 | 71 | ||
| 68 | 1. Run `make install` (on POSIX) or | 72 | 1. Run `make` (on POSIX) or |
| 69 | `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows). | 73 | `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows). |
| 70 | 2. `bin/zig build test` (on POSIX) or `bin\zig.exe build test` (on Windows). | 74 | 2. `$BUILD_DIR/zig build test` (on POSIX) or |
| 75 | `$BUILD_DIR/Release\zig.exe build test` (on Windows). | ||
| 71 | 76 | ||
| 72 | That runs the whole test suite, which does a lot of extra testing that you | 77 | That runs the whole test suite, which does a lot of extra testing that you |
| 73 | likely won't always need, and can take upwards of 1 hour. This is what the | 78 | 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, | ... | @@ -85,8 +90,8 @@ Another example is choosing a different set of things to test. For example, |
| 85 | not the other ones. Combining this suggestion with the previous one, you could | 90 | not the other ones. Combining this suggestion with the previous one, you could |
| 86 | do this: | 91 | do this: |
| 87 | 92 | ||
| 88 | `bin/zig build test-std -Dskip-release` (on POSIX) or | 93 | `$BUILD_DIR/bin/zig build test-std -Dskip-release` (on POSIX) or |
| 89 | `bin\zig.exe build test-std -Dskip-release` (on Windows). | 94 | `$BUILD_DIR/Release\zig.exe build test-std -Dskip-release` (on Windows). |
| 90 | 95 | ||
| 91 | This will run only the standard library tests, in debug mode only, for all | 96 | This will run only the standard library tests, in debug mode only, for all |
| 92 | targets (it will cross-compile the tests for non-native targets but not run | 97 | targets (it will cross-compile the tests for non-native targets but not run |
cmake/install.cmake created+37| ... | @@ -0,0 +1,37 @@ | ||
| 1 | message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib") | ||
| 2 | |||
| 3 | if(NOT EXISTS ${zig0_EXE}) | ||
| 4 | message("::") | ||
| 5 | message(":: ERROR: Executable not found") | ||
| 6 | message(":: (execute_process)") | ||
| 7 | message("::") | ||
| 8 | message(":: executable: ${zig0_EXE}") | ||
| 9 | message("::") | ||
| 10 | message(FATAL_ERROR) | ||
| 11 | endif() | ||
| 12 | |||
| 13 | execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS} | ||
| 14 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | ||
| 15 | RESULT_VARIABLE _result | ||
| 16 | ) | ||
| 17 | if(_result) | ||
| 18 | message("::") | ||
| 19 | message(":: ERROR: ${_result}") | ||
| 20 | message(":: (execute_process)") | ||
| 21 | |||
| 22 | string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}") | ||
| 23 | message("::") | ||
| 24 | message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install") | ||
| 25 | |||
| 26 | set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}) | ||
| 27 | list(LENGTH _args _len) | ||
| 28 | math(EXPR _len "${_len} - 1") | ||
| 29 | message("::") | ||
| 30 | foreach(_i RANGE 0 ${_len}) | ||
| 31 | list(GET _args ${_i} _arg) | ||
| 32 | message(":: argv[${_i}]: ${_arg}") | ||
| 33 | endforeach() | ||
| 34 | |||
| 35 | message("::") | ||
| 36 | message(FATAL_ERROR) | ||
| 37 | endif() | ||
doc/langref.html.in+55-1| ... | @@ -2893,6 +2893,47 @@ test "switch using enum literals" { | ... | @@ -2893,6 +2893,47 @@ test "switch using enum literals" { |
| 2893 | } | 2893 | } |
| 2894 | {#code_end#} | 2894 | {#code_end#} |
| 2895 | {#header_close#} | 2895 | {#header_close#} |
| 2896 | |||
| 2897 | {#header_open|Non-exhaustive enum#} | ||
| 2898 | <p> | ||
| 2899 | A Non-exhaustive enum can be created by adding a trailing '_' field. | ||
| 2900 | It must specify a tag type and cannot consume every enumeration value. | ||
| 2901 | </p> | ||
| 2902 | <p> | ||
| 2903 | {#link|@intToEnum#} on a non-exhaustive enum cannot fail. | ||
| 2904 | </p> | ||
| 2905 | <p> | ||
| 2906 | A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong | ||
| 2907 | with the difference being that it makes it a compile error if all the known tag names are not handled by the switch. | ||
| 2908 | </p> | ||
| 2909 | {#code_begin|test#} | ||
| 2910 | const std = @import("std"); | ||
| 2911 | const assert = std.debug.assert; | ||
| 2912 | |||
| 2913 | const Number = enum(u8) { | ||
| 2914 | One, | ||
| 2915 | Two, | ||
| 2916 | Three, | ||
| 2917 | _, | ||
| 2918 | }; | ||
| 2919 | |||
| 2920 | test "switch on non-exhaustive enum" { | ||
| 2921 | const number = Number.One; | ||
| 2922 | const result = switch (number) { | ||
| 2923 | .One => true, | ||
| 2924 | .Two, | ||
| 2925 | .Three => false, | ||
| 2926 | _ => false, | ||
| 2927 | }; | ||
| 2928 | assert(result); | ||
| 2929 | const is_one = switch (number) { | ||
| 2930 | .One => true, | ||
| 2931 | else => false, | ||
| 2932 | }; | ||
| 2933 | assert(is_one); | ||
| 2934 | } | ||
| 2935 | {#code_end#} | ||
| 2936 | {#header_close#} | ||
| 2896 | {#header_close#} | 2937 | {#header_close#} |
| 2897 | 2938 | ||
| 2898 | {#header_open|union#} | 2939 | {#header_open|union#} |
| ... | @@ -6815,6 +6856,19 @@ async fn func(y: *i32) void { | ... | @@ -6815,6 +6856,19 @@ async fn func(y: *i32) void { |
| 6815 | </p> | 6856 | </p> |
| 6816 | {#header_close#} | 6857 | {#header_close#} |
| 6817 | 6858 | ||
| 6859 | {#header_open|@bitSizeOf#} | ||
| 6860 | <pre>{#syntax#}@bitSizeOf(comptime T: type) comptime_int{#endsyntax#}</pre> | ||
| 6861 | <p> | ||
| 6862 | This function returns the number of bits it takes to store {#syntax#}T{#endsyntax#} in memory. | ||
| 6863 | The result is a target-specific compile time constant. | ||
| 6864 | </p> | ||
| 6865 | <p> | ||
| 6866 | This function measures the size at runtime. For types that are disallowed at runtime, such as | ||
| 6867 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. | ||
| 6868 | </p> | ||
| 6869 | {#see_also|@sizeOf|@typeInfo#} | ||
| 6870 | {#header_close#} | ||
| 6871 | |||
| 6818 | {#header_open|@breakpoint#} | 6872 | {#header_open|@breakpoint#} |
| 6819 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> | 6873 | <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre> |
| 6820 | <p> | 6874 | <p> |
| ... | @@ -8044,7 +8098,7 @@ test "@setRuntimeSafety" { | ... | @@ -8044,7 +8098,7 @@ test "@setRuntimeSafety" { |
| 8044 | This function measures the size at runtime. For types that are disallowed at runtime, such as | 8098 | This function measures the size at runtime. For types that are disallowed at runtime, such as |
| 8045 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. | 8099 | {#syntax#}comptime_int{#endsyntax#} and {#syntax#}type{#endsyntax#}, the result is {#syntax#}0{#endsyntax#}. |
| 8046 | </p> | 8100 | </p> |
| 8047 | {#see_also|@typeInfo#} | 8101 | {#see_also|@bitSizeOf|@typeInfo#} |
| 8048 | {#header_close#} | 8102 | {#header_close#} |
| 8049 | 8103 | ||
| 8050 | {#header_open|@sliceToBytes#} | 8104 | {#header_open|@sliceToBytes#} |
lib/std/build.zig+3-1| ... | @@ -1687,7 +1687,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1687,7 +1687,9 @@ pub const LibExeObjStep = struct { |
| 1687 | } | 1687 | } |
| 1688 | 1688 | ||
| 1689 | pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { | 1689 | pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { |
| 1690 | self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable; | 1690 | self.link_objects.append(LinkObject{ |
| 1691 | .AssemblyFile = .{ .path = self.builder.dupe(path) }, | ||
| 1692 | }) catch unreachable; | ||
| 1691 | } | 1693 | } |
| 1692 | 1694 | ||
| 1693 | pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void { | 1695 | pub fn addAssemblyFileFromWriteFileStep(self: *LibExeObjStep, wfs: *WriteFileStep, basename: []const u8) void { |
lib/std/builtin.zig+2| ... | @@ -205,6 +205,7 @@ pub const TypeInfo = union(enum) { | ... | @@ -205,6 +205,7 @@ pub const TypeInfo = union(enum) { |
| 205 | name: []const u8, | 205 | name: []const u8, |
| 206 | offset: ?comptime_int, | 206 | offset: ?comptime_int, |
| 207 | field_type: type, | 207 | field_type: type, |
| 208 | default_value: var, | ||
| 208 | }; | 209 | }; |
| 209 | 210 | ||
| 210 | /// This data structure is used by the Zig language code generation and | 211 | /// This data structure is used by the Zig language code generation and |
| ... | @@ -253,6 +254,7 @@ pub const TypeInfo = union(enum) { | ... | @@ -253,6 +254,7 @@ pub const TypeInfo = union(enum) { |
| 253 | tag_type: type, | 254 | tag_type: type, |
| 254 | fields: []EnumField, | 255 | fields: []EnumField, |
| 255 | decls: []Declaration, | 256 | decls: []Declaration, |
| 257 | is_exhaustive: bool, | ||
| 256 | }; | 258 | }; |
| 257 | 259 | ||
| 258 | /// This data structure is used by the Zig language code generation and | 260 | /// This data structure is used by the Zig language code generation and |
lib/std/c.zig+3-3| ... | @@ -185,7 +185,7 @@ pub extern "c" fn getaddrinfo( | ... | @@ -185,7 +185,7 @@ pub extern "c" fn getaddrinfo( |
| 185 | noalias service: [*:0]const u8, | 185 | noalias service: [*:0]const u8, |
| 186 | noalias hints: *const addrinfo, | 186 | noalias hints: *const addrinfo, |
| 187 | noalias res: **addrinfo, | 187 | noalias res: **addrinfo, |
| 188 | ) c_int; | 188 | ) EAI; |
| 189 | 189 | ||
| 190 | pub extern "c" fn freeaddrinfo(res: *addrinfo) void; | 190 | pub extern "c" fn freeaddrinfo(res: *addrinfo) void; |
| 191 | 191 | ||
| ... | @@ -197,9 +197,9 @@ pub extern "c" fn getnameinfo( | ... | @@ -197,9 +197,9 @@ pub extern "c" fn getnameinfo( |
| 197 | noalias serv: [*]u8, | 197 | noalias serv: [*]u8, |
| 198 | servlen: socklen_t, | 198 | servlen: socklen_t, |
| 199 | flags: u32, | 199 | flags: u32, |
| 200 | ) c_int; | 200 | ) EAI; |
| 201 | 201 | ||
| 202 | pub extern "c" fn gai_strerror(errcode: c_int) [*:0]const u8; | 202 | pub extern "c" fn gai_strerror(errcode: EAI) [*:0]const u8; |
| 203 | 203 | ||
| 204 | pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int; | 204 | pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int; |
| 205 | 205 |
lib/std/c/darwin.zig+33-28| ... | @@ -70,47 +70,52 @@ pub const AI_NUMERICHOST = 0x00000004; | ... | @@ -70,47 +70,52 @@ pub const AI_NUMERICHOST = 0x00000004; |
| 70 | /// prevent service name resolution | 70 | /// prevent service name resolution |
| 71 | pub const AI_NUMERICSERV = 0x00001000; | 71 | pub const AI_NUMERICSERV = 0x00001000; |
| 72 | 72 | ||
| 73 | /// address family for hostname not supported | 73 | pub const EAI = extern enum(c_int) { |
| 74 | pub const EAI_ADDRFAMILY = 1; | 74 | /// address family for hostname not supported |
| 75 | ADDRFAMILY = 1, | ||
| 75 | 76 | ||
| 76 | /// temporary failure in name resolution | 77 | /// temporary failure in name resolution |
| 77 | pub const EAI_AGAIN = 2; | 78 | AGAIN = 2, |
| 78 | 79 | ||
| 79 | /// invalid value for ai_flags | 80 | /// invalid value for ai_flags |
| 80 | pub const EAI_BADFLAGS = 3; | 81 | BADFLAGS = 3, |
| 81 | 82 | ||
| 82 | /// non-recoverable failure in name resolution | 83 | /// non-recoverable failure in name resolution |
| 83 | pub const EAI_FAIL = 4; | 84 | FAIL = 4, |
| 84 | 85 | ||
| 85 | /// ai_family not supported | 86 | /// ai_family not supported |
| 86 | pub const EAI_FAMILY = 5; | 87 | FAMILY = 5, |
| 87 | 88 | ||
| 88 | /// memory allocation failure | 89 | /// memory allocation failure |
| 89 | pub const EAI_MEMORY = 6; | 90 | MEMORY = 6, |
| 90 | 91 | ||
| 91 | /// no address associated with hostname | 92 | /// no address associated with hostname |
| 92 | pub const EAI_NODATA = 7; | 93 | NODATA = 7, |
| 93 | 94 | ||
| 94 | /// hostname nor servname provided, or not known | 95 | /// hostname nor servname provided, or not known |
| 95 | pub const EAI_NONAME = 8; | 96 | NONAME = 8, |
| 96 | 97 | ||
| 97 | /// servname not supported for ai_socktype | 98 | /// servname not supported for ai_socktype |
| 98 | pub const EAI_SERVICE = 9; | 99 | SERVICE = 9, |
| 99 | 100 | ||
| 100 | /// ai_socktype not supported | 101 | /// ai_socktype not supported |
| 101 | pub const EAI_SOCKTYPE = 10; | 102 | SOCKTYPE = 10, |
| 102 | 103 | ||
| 103 | /// system error returned in errno | 104 | /// system error returned in errno |
| 104 | pub const EAI_SYSTEM = 11; | 105 | SYSTEM = 11, |
| 105 | 106 | ||
| 106 | /// invalid value for hints | 107 | /// invalid value for hints |
| 107 | pub const EAI_BADHINTS = 12; | 108 | BADHINTS = 12, |
| 108 | 109 | ||
| 109 | /// resolved protocol is unknown | 110 | /// resolved protocol is unknown |
| 110 | pub const EAI_PROTOCOL = 13; | 111 | PROTOCOL = 13, |
| 112 | |||
| 113 | /// argument buffer overflow | ||
| 114 | OVERFLOW = 14, | ||
| 115 | |||
| 116 | _, | ||
| 117 | }; | ||
| 111 | 118 | ||
| 112 | /// argument buffer overflow | ||
| 113 | pub const EAI_OVERFLOW = 14; | ||
| 114 | pub const EAI_MAX = 15; | 119 | pub const EAI_MAX = 15; |
| 115 | 120 | ||
| 116 | pub const pthread_mutex_t = extern struct { | 121 | pub const pthread_mutex_t = extern struct { |
lib/std/c/freebsd.zig+32-28| ... | @@ -23,47 +23,51 @@ pub const pthread_attr_t = extern struct { | ... | @@ -23,47 +23,51 @@ pub const pthread_attr_t = extern struct { |
| 23 | __align: c_long, | 23 | __align: c_long, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | /// address family for hostname not supported | 26 | pub const EAI = extern enum(c_int) { |
| 27 | pub const EAI_ADDRFAMILY = 1; | 27 | /// address family for hostname not supported |
| 28 | ADDRFAMILY = 1, | ||
| 28 | 29 | ||
| 29 | /// name could not be resolved at this time | 30 | /// name could not be resolved at this time |
| 30 | pub const EAI_AGAIN = 2; | 31 | AGAIN = 2, |
| 31 | 32 | ||
| 32 | /// flags parameter had an invalid value | 33 | /// flags parameter had an invalid value |
| 33 | pub const EAI_BADFLAGS = 3; | 34 | BADFLAGS = 3, |
| 34 | 35 | ||
| 35 | /// non-recoverable failure in name resolution | 36 | /// non-recoverable failure in name resolution |
| 36 | pub const EAI_FAIL = 4; | 37 | FAIL = 4, |
| 37 | 38 | ||
| 38 | /// address family not recognized | 39 | /// address family not recognized |
| 39 | pub const EAI_FAMILY = 5; | 40 | FAMILY = 5, |
| 40 | 41 | ||
| 41 | /// memory allocation failure | 42 | /// memory allocation failure |
| 42 | pub const EAI_MEMORY = 6; | 43 | MEMORY = 6, |
| 43 | 44 | ||
| 44 | /// no address associated with hostname | 45 | /// no address associated with hostname |
| 45 | pub const EAI_NODATA = 7; | 46 | NODATA = 7, |
| 46 | 47 | ||
| 47 | /// name does not resolve | 48 | /// name does not resolve |
| 48 | pub const EAI_NONAME = 8; | 49 | NONAME = 8, |
| 49 | 50 | ||
| 50 | /// service not recognized for socket type | 51 | /// service not recognized for socket type |
| 51 | pub const EAI_SERVICE = 9; | 52 | SERVICE = 9, |
| 52 | 53 | ||
| 53 | /// intended socket type was not recognized | 54 | /// intended socket type was not recognized |
| 54 | pub const EAI_SOCKTYPE = 10; | 55 | SOCKTYPE = 10, |
| 55 | 56 | ||
| 56 | /// system error returned in errno | 57 | /// system error returned in errno |
| 57 | pub const EAI_SYSTEM = 11; | 58 | SYSTEM = 11, |
| 58 | 59 | ||
| 59 | /// invalid value for hints | 60 | /// invalid value for hints |
| 60 | pub const EAI_BADHINTS = 12; | 61 | BADHINTS = 12, |
| 61 | 62 | ||
| 62 | /// resolved protocol is unknown | 63 | /// resolved protocol is unknown |
| 63 | pub const EAI_PROTOCOL = 13; | 64 | PROTOCOL = 13, |
| 64 | 65 | ||
| 65 | /// argument buffer overflow | 66 | /// argument buffer overflow |
| 66 | pub const EAI_OVERFLOW = 14; | 67 | OVERFLOW = 14, |
| 68 | |||
| 69 | _, | ||
| 70 | }; | ||
| 67 | 71 | ||
| 68 | pub const EAI_MAX = 15; | 72 | pub const EAI_MAX = 15; |
| 69 | 73 |
lib/std/c/linux.zig+22-18| ... | @@ -32,25 +32,29 @@ pub const NI_NAMEREQD = 0x08; | ... | @@ -32,25 +32,29 @@ pub const NI_NAMEREQD = 0x08; |
| 32 | pub const NI_DGRAM = 0x10; | 32 | pub const NI_DGRAM = 0x10; |
| 33 | pub const NI_NUMERICSCOPE = 0x100; | 33 | pub const NI_NUMERICSCOPE = 0x100; |
| 34 | 34 | ||
| 35 | pub const EAI_BADFLAGS = -1; | 35 | pub const EAI = extern enum(c_int) { |
| 36 | pub const EAI_NONAME = -2; | 36 | BADFLAGS = -1, |
| 37 | pub const EAI_AGAIN = -3; | 37 | NONAME = -2, |
| 38 | pub const EAI_FAIL = -4; | 38 | AGAIN = -3, |
| 39 | pub const EAI_FAMILY = -6; | 39 | FAIL = -4, |
| 40 | pub const EAI_SOCKTYPE = -7; | 40 | FAMILY = -6, |
| 41 | pub const EAI_SERVICE = -8; | 41 | SOCKTYPE = -7, |
| 42 | pub const EAI_MEMORY = -10; | 42 | SERVICE = -8, |
| 43 | pub const EAI_SYSTEM = -11; | 43 | MEMORY = -10, |
| 44 | pub const EAI_OVERFLOW = -12; | 44 | SYSTEM = -11, |
| 45 | OVERFLOW = -12, | ||
| 45 | 46 | ||
| 46 | pub const EAI_NODATA = -5; | 47 | NODATA = -5, |
| 47 | pub const EAI_ADDRFAMILY = -9; | 48 | ADDRFAMILY = -9, |
| 48 | pub const EAI_INPROGRESS = -100; | 49 | INPROGRESS = -100, |
| 49 | pub const EAI_CANCELED = -101; | 50 | CANCELED = -101, |
| 50 | pub const EAI_NOTCANCELED = -102; | 51 | NOTCANCELED = -102, |
| 51 | pub const EAI_ALLDONE = -103; | 52 | ALLDONE = -103, |
| 52 | pub const EAI_INTR = -104; | 53 | INTR = -104, |
| 53 | pub const EAI_IDN_ENCODE = -105; | 54 | IDN_ENCODE = -105, |
| 55 | |||
| 56 | _, | ||
| 57 | }; | ||
| 54 | 58 | ||
| 55 | pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; | 59 | pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; |
| 56 | pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; | 60 | pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; |
lib/std/dynamic_library.zig+1-1| ... | @@ -277,7 +277,7 @@ pub const WindowsDynLib = struct { | ... | @@ -277,7 +277,7 @@ pub const WindowsDynLib = struct { |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | pub fn openC(path_c: [*:0]const u8) !WindowsDynLib { | 279 | pub fn openC(path_c: [*:0]const u8) !WindowsDynLib { |
| 280 | const path_w = try windows.cStrToPrefixedFileW(path); | 280 | const path_w = try windows.cStrToPrefixedFileW(path_c); |
| 281 | return openW(&path_w); | 281 | return openW(&path_w); |
| 282 | } | 282 | } |
| 283 | 283 |
lib/std/fmt.zig+11-6| ... | @@ -431,7 +431,7 @@ pub fn formatType( | ... | @@ -431,7 +431,7 @@ pub fn formatType( |
| 431 | }, | 431 | }, |
| 432 | else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), | 432 | else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }), |
| 433 | }, | 433 | }, |
| 434 | .Many => { | 434 | .Many, .C => { |
| 435 | if (ptr_info.child == u8) { | 435 | if (ptr_info.child == u8) { |
| 436 | if (fmt.len > 0 and fmt[0] == 's') { | 436 | if (fmt.len > 0 and fmt[0] == 's') { |
| 437 | const len = mem.len(u8, value); | 437 | const len = mem.len(u8, value); |
| ... | @@ -449,9 +449,6 @@ pub fn formatType( | ... | @@ -449,9 +449,6 @@ pub fn formatType( |
| 449 | } | 449 | } |
| 450 | return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); | 450 | return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) }); |
| 451 | }, | 451 | }, |
| 452 | .C => { | ||
| 453 | return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }); | ||
| 454 | }, | ||
| 455 | }, | 452 | }, |
| 456 | .Array => |info| { | 453 | .Array => |info| { |
| 457 | const Slice = @Type(builtin.TypeInfo{ | 454 | const Slice = @Type(builtin.TypeInfo{ |
| ... | @@ -1285,8 +1282,16 @@ test "pointer" { | ... | @@ -1285,8 +1282,16 @@ test "pointer" { |
| 1285 | } | 1282 | } |
| 1286 | 1283 | ||
| 1287 | test "cstr" { | 1284 | test "cstr" { |
| 1288 | try testFmt("cstr: Test C\n", "cstr: {s}\n", .{"Test C"}); | 1285 | try testFmt( |
| 1289 | try testFmt("cstr: Test C \n", "cstr: {s:10}\n", .{"Test C"}); | 1286 | "cstr: Test C\n", |
| 1287 | "cstr: {s}\n", | ||
| 1288 | .{@ptrCast([*c]const u8, "Test C")}, | ||
| 1289 | ); | ||
| 1290 | try testFmt( | ||
| 1291 | "cstr: Test C \n", | ||
| 1292 | "cstr: {s:10}\n", | ||
| 1293 | .{@ptrCast([*c]const u8, "Test C")}, | ||
| 1294 | ); | ||
| 1290 | } | 1295 | } |
| 1291 | 1296 | ||
| 1292 | test "filesize" { | 1297 | test "filesize" { |
lib/std/hash/benchmark.zig+2-2| ... | @@ -47,11 +47,11 @@ const hashes = [_]Hash{ | ... | @@ -47,11 +47,11 @@ const hashes = [_]Hash{ |
| 47 | .name = "adler32", | 47 | .name = "adler32", |
| 48 | }, | 48 | }, |
| 49 | Hash{ | 49 | Hash{ |
| 50 | .ty = hash.crc.Crc32WithPoly(hash.crc.Polynomial.IEEE), | 50 | .ty = hash.crc.Crc32WithPoly(.IEEE), |
| 51 | .name = "crc32-slicing-by-8", | 51 | .name = "crc32-slicing-by-8", |
| 52 | }, | 52 | }, |
| 53 | Hash{ | 53 | Hash{ |
| 54 | .ty = hash.crc.Crc32SmallWithPoly(hash.crc.Polynomial.IEEE), | 54 | .ty = hash.crc.Crc32SmallWithPoly(.IEEE), |
| 55 | .name = "crc32-half-byte-lookup", | 55 | .name = "crc32-half-byte-lookup", |
| 56 | }, | 56 | }, |
| 57 | Hash{ | 57 | Hash{ |
lib/std/hash/crc.zig+14-13| ... | @@ -9,17 +9,18 @@ const std = @import("../std.zig"); | ... | @@ -9,17 +9,18 @@ const std = @import("../std.zig"); |
| 9 | const debug = std.debug; | 9 | const debug = std.debug; |
| 10 | const testing = std.testing; | 10 | const testing = std.testing; |
| 11 | 11 | ||
| 12 | pub const Polynomial = struct { | 12 | pub const Polynomial = enum(u32) { |
| 13 | pub const IEEE = 0xedb88320; | 13 | IEEE = 0xedb88320, |
| 14 | pub const Castagnoli = 0x82f63b78; | 14 | Castagnoli = 0x82f63b78, |
| 15 | pub const Koopman = 0xeb31d82e; | 15 | Koopman = 0xeb31d82e, |
| 16 | _, | ||
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | // IEEE is by far the most common CRC and so is aliased by default. | 19 | // IEEE is by far the most common CRC and so is aliased by default. |
| 19 | pub const Crc32 = Crc32WithPoly(Polynomial.IEEE); | 20 | pub const Crc32 = Crc32WithPoly(.IEEE); |
| 20 | 21 | ||
| 21 | // slicing-by-8 crc32 implementation. | 22 | // slicing-by-8 crc32 implementation. |
| 22 | pub fn Crc32WithPoly(comptime poly: u32) type { | 23 | pub fn Crc32WithPoly(comptime poly: Polynomial) type { |
| 23 | return struct { | 24 | return struct { |
| 24 | const Self = @This(); | 25 | const Self = @This(); |
| 25 | const lookup_tables = comptime block: { | 26 | const lookup_tables = comptime block: { |
| ... | @@ -31,7 +32,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { | ... | @@ -31,7 +32,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 31 | var j: usize = 0; | 32 | var j: usize = 0; |
| 32 | while (j < 8) : (j += 1) { | 33 | while (j < 8) : (j += 1) { |
| 33 | if (crc & 1 == 1) { | 34 | if (crc & 1 == 1) { |
| 34 | crc = (crc >> 1) ^ poly; | 35 | crc = (crc >> 1) ^ @enumToInt(poly); |
| 35 | } else { | 36 | } else { |
| 36 | crc = (crc >> 1); | 37 | crc = (crc >> 1); |
| 37 | } | 38 | } |
| ... | @@ -100,7 +101,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { | ... | @@ -100,7 +101,7 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | test "crc32 ieee" { | 103 | test "crc32 ieee" { |
| 103 | const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE); | 104 | const Crc32Ieee = Crc32WithPoly(.IEEE); |
| 104 | 105 | ||
| 105 | testing.expect(Crc32Ieee.hash("") == 0x00000000); | 106 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 106 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); | 107 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | @@ -108,7 +109,7 @@ test "crc32 ieee" { | ... | @@ -108,7 +109,7 @@ test "crc32 ieee" { |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | test "crc32 castagnoli" { | 111 | test "crc32 castagnoli" { |
| 111 | const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli); | 112 | const Crc32Castagnoli = Crc32WithPoly(.Castagnoli); |
| 112 | 113 | ||
| 113 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); | 114 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 114 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); | 115 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
| ... | @@ -116,7 +117,7 @@ test "crc32 castagnoli" { | ... | @@ -116,7 +117,7 @@ test "crc32 castagnoli" { |
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | // half-byte lookup table implementation. | 119 | // half-byte lookup table implementation. |
| 119 | pub fn Crc32SmallWithPoly(comptime poly: u32) type { | 120 | pub fn Crc32SmallWithPoly(comptime poly: Polynomial) type { |
| 120 | return struct { | 121 | return struct { |
| 121 | const Self = @This(); | 122 | const Self = @This(); |
| 122 | const lookup_table = comptime block: { | 123 | const lookup_table = comptime block: { |
| ... | @@ -127,7 +128,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { | ... | @@ -127,7 +128,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 127 | var j: usize = 0; | 128 | var j: usize = 0; |
| 128 | while (j < 8) : (j += 1) { | 129 | while (j < 8) : (j += 1) { |
| 129 | if (crc & 1 == 1) { | 130 | if (crc & 1 == 1) { |
| 130 | crc = (crc >> 1) ^ poly; | 131 | crc = (crc >> 1) ^ @enumToInt(poly); |
| 131 | } else { | 132 | } else { |
| 132 | crc = (crc >> 1); | 133 | crc = (crc >> 1); |
| 133 | } | 134 | } |
| ... | @@ -164,7 +165,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { | ... | @@ -164,7 +165,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | test "small crc32 ieee" { | 167 | test "small crc32 ieee" { |
| 167 | const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE); | 168 | const Crc32Ieee = Crc32SmallWithPoly(.IEEE); |
| 168 | 169 | ||
| 169 | testing.expect(Crc32Ieee.hash("") == 0x00000000); | 170 | testing.expect(Crc32Ieee.hash("") == 0x00000000); |
| 170 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); | 171 | testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43); |
| ... | @@ -172,7 +173,7 @@ test "small crc32 ieee" { | ... | @@ -172,7 +173,7 @@ test "small crc32 ieee" { |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | test "small crc32 castagnoli" { | 175 | test "small crc32 castagnoli" { |
| 175 | const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli); | 176 | const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli); |
| 176 | 177 | ||
| 177 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); | 178 | testing.expect(Crc32Castagnoli.hash("") == 0x00000000); |
| 178 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); | 179 | testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330); |
lib/std/net.zig+12-12| ... | @@ -452,18 +452,18 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* | ... | @@ -452,18 +452,18 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* |
| 452 | }; | 452 | }; |
| 453 | var res: *os.addrinfo = undefined; | 453 | var res: *os.addrinfo = undefined; |
| 454 | switch (os.system.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res)) { | 454 | switch (os.system.getaddrinfo(name_c.ptr, @ptrCast([*:0]const u8, port_c.ptr), &hints, &res)) { |
| 455 | 0 => {}, | 455 | @intToEnum(os.system.EAI, 0) => {}, |
| 456 | c.EAI_ADDRFAMILY => return error.HostLacksNetworkAddresses, | 456 | .ADDRFAMILY => return error.HostLacksNetworkAddresses, |
| 457 | c.EAI_AGAIN => return error.TemporaryNameServerFailure, | 457 | .AGAIN => return error.TemporaryNameServerFailure, |
| 458 | c.EAI_BADFLAGS => unreachable, // Invalid hints | 458 | .BADFLAGS => unreachable, // Invalid hints |
| 459 | c.EAI_FAIL => return error.NameServerFailure, | 459 | .FAIL => return error.NameServerFailure, |
| 460 | c.EAI_FAMILY => return error.AddressFamilyNotSupported, | 460 | .FAMILY => return error.AddressFamilyNotSupported, |
| 461 | c.EAI_MEMORY => return error.OutOfMemory, | 461 | .MEMORY => return error.OutOfMemory, |
| 462 | c.EAI_NODATA => return error.HostLacksNetworkAddresses, | 462 | .NODATA => return error.HostLacksNetworkAddresses, |
| 463 | c.EAI_NONAME => return error.UnknownHostName, | 463 | .NONAME => return error.UnknownHostName, |
| 464 | c.EAI_SERVICE => return error.ServiceUnavailable, | 464 | .SERVICE => return error.ServiceUnavailable, |
| 465 | c.EAI_SOCKTYPE => unreachable, // Invalid socket type requested in hints | 465 | .SOCKTYPE => unreachable, // Invalid socket type requested in hints |
| 466 | c.EAI_SYSTEM => switch (os.errno(-1)) { | 466 | .SYSTEM => switch (os.errno(-1)) { |
| 467 | else => |e| return os.unexpectedErrno(e), | 467 | else => |e| return os.unexpectedErrno(e), |
| 468 | }, | 468 | }, |
| 469 | else => unreachable, | 469 | else => unreachable, |
lib/std/os/bits/linux.zig+1-1| ... | @@ -18,7 +18,7 @@ pub usingnamespace switch (builtin.arch) { | ... | @@ -18,7 +18,7 @@ pub usingnamespace switch (builtin.arch) { |
| 18 | else => struct {}, | 18 | else => struct {}, |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | const is_mips = builtin.arch == .mipsel; | 21 | const is_mips = builtin.arch.isMIPS(); |
| 22 | 22 | ||
| 23 | pub const pid_t = i32; | 23 | pub const pid_t = i32; |
| 24 | pub const fd_t = i32; | 24 | pub const fd_t = i32; |
lib/std/special/compiler_rt.zig+54-72| ... | @@ -16,42 +16,42 @@ comptime { | ... | @@ -16,42 +16,42 @@ comptime { |
| 16 | else => {}, | 16 | else => {}, |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | @export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage }); | 19 | @export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__lesf2", .linkage = linkage }); |
| 20 | @export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage }); | 20 | @export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__ledf2", .linkage = linkage }); |
| 21 | @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage }); | 21 | @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__letf2", .linkage = linkage }); |
| 22 | 22 | ||
| 23 | @export(@import("compiler_rt/comparesf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage }); | 23 | @export(@import("compiler_rt/compareXf2.zig").__gesf2, .{ .name = "__gesf2", .linkage = linkage }); |
| 24 | @export(@import("compiler_rt/comparedf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage }); | 24 | @export(@import("compiler_rt/compareXf2.zig").__gedf2, .{ .name = "__gedf2", .linkage = linkage }); |
| 25 | @export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage }); | 25 | @export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__getf2", .linkage = linkage }); |
| 26 | 26 | ||
| 27 | if (!is_test) { | 27 | if (!is_test) { |
| 28 | @export(@import("compiler_rt/comparesf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); | 28 | @export(@import("compiler_rt/compareXf2.zig").__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); |
| 29 | @export(@import("compiler_rt/comparedf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); | 29 | @export(@import("compiler_rt/compareXf2.zig").__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); |
| 30 | @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage }); | 30 | @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__cmptf2", .linkage = linkage }); |
| 31 | 31 | ||
| 32 | @export(@import("compiler_rt/comparesf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); | 32 | @export(@import("compiler_rt/compareXf2.zig").__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); |
| 33 | @export(@import("compiler_rt/comparedf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); | 33 | @export(@import("compiler_rt/compareXf2.zig").__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); |
| 34 | @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage }); | 34 | @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__eqtf2", .linkage = linkage }); |
| 35 | 35 | ||
| 36 | @export(@import("compiler_rt/comparesf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); | 36 | @export(@import("compiler_rt/compareXf2.zig").__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); |
| 37 | @export(@import("compiler_rt/comparedf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); | 37 | @export(@import("compiler_rt/compareXf2.zig").__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); |
| 38 | @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage }); | 38 | @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__lttf2", .linkage = linkage }); |
| 39 | 39 | ||
| 40 | @export(@import("compiler_rt/comparesf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage }); | 40 | @export(@import("compiler_rt/compareXf2.zig").__nesf2, .{ .name = "__nesf2", .linkage = linkage }); |
| 41 | @export(@import("compiler_rt/comparedf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage }); | 41 | @export(@import("compiler_rt/compareXf2.zig").__nedf2, .{ .name = "__nedf2", .linkage = linkage }); |
| 42 | @export(@import("compiler_rt/comparetf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage }); | 42 | @export(@import("compiler_rt/compareXf2.zig").__letf2, .{ .name = "__netf2", .linkage = linkage }); |
| 43 | 43 | ||
| 44 | @export(@import("compiler_rt/comparesf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); | 44 | @export(@import("compiler_rt/compareXf2.zig").__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); |
| 45 | @export(@import("compiler_rt/comparedf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); | 45 | @export(@import("compiler_rt/compareXf2.zig").__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); |
| 46 | @export(@import("compiler_rt/comparetf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage }); | 46 | @export(@import("compiler_rt/compareXf2.zig").__getf2, .{ .name = "__gttf2", .linkage = linkage }); |
| 47 | 47 | ||
| 48 | @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); | 48 | @export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); |
| 49 | @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage }); | 49 | @export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage }); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | @export(@import("compiler_rt/comparesf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); | 52 | @export(@import("compiler_rt/compareXf2.zig").__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); |
| 53 | @export(@import("compiler_rt/comparedf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); | 53 | @export(@import("compiler_rt/compareXf2.zig").__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); |
| 54 | @export(@import("compiler_rt/comparetf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); | 54 | @export(@import("compiler_rt/compareXf2.zig").__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); |
| 55 | 55 | ||
| 56 | @export(@import("compiler_rt/addXf3.zig").__addsf3, .{ .name = "__addsf3", .linkage = linkage }); | 56 | @export(@import("compiler_rt/addXf3.zig").__addsf3, .{ .name = "__addsf3", .linkage = linkage }); |
| 57 | @export(@import("compiler_rt/addXf3.zig").__adddf3, .{ .name = "__adddf3", .linkage = linkage }); | 57 | @export(@import("compiler_rt/addXf3.zig").__adddf3, .{ .name = "__adddf3", .linkage = linkage }); |
| ... | @@ -146,8 +146,10 @@ comptime { | ... | @@ -146,8 +146,10 @@ comptime { |
| 146 | @export(@import("compiler_rt/negXf2.zig").__negsf2, .{ .name = "__negsf2", .linkage = linkage }); | 146 | @export(@import("compiler_rt/negXf2.zig").__negsf2, .{ .name = "__negsf2", .linkage = linkage }); |
| 147 | @export(@import("compiler_rt/negXf2.zig").__negdf2, .{ .name = "__negdf2", .linkage = linkage }); | 147 | @export(@import("compiler_rt/negXf2.zig").__negdf2, .{ .name = "__negdf2", .linkage = linkage }); |
| 148 | 148 | ||
| 149 | if (is_arm_arch and !is_arm_64 and !is_test) { | 149 | @export(@import("compiler_rt/clzsi2.zig").__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); |
| 150 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = strong_linkage }); | 150 | |
| 151 | if (builtin.arch.isARM() and !is_test) { | ||
| 152 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); | ||
| 151 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); | 153 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); |
| 152 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); | 154 | @export(@import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); |
| 153 | 155 | ||
| ... | @@ -177,7 +179,9 @@ comptime { | ... | @@ -177,7 +179,9 @@ comptime { |
| 177 | @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); | 179 | @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); |
| 178 | @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); | 180 | @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); |
| 179 | 181 | ||
| 180 | @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); | 182 | if (builtin.os == .linux) { |
| 183 | @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); | ||
| 184 | } | ||
| 181 | 185 | ||
| 182 | @export(@import("compiler_rt/extendXfYf2.zig").__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); | 186 | @export(@import("compiler_rt/extendXfYf2.zig").__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); |
| 183 | @export(@import("compiler_rt/floatsiXf.zig").__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); | 187 | @export(@import("compiler_rt/floatsiXf.zig").__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); |
| ... | @@ -222,20 +226,29 @@ comptime { | ... | @@ -222,20 +226,29 @@ comptime { |
| 222 | @export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); | 226 | @export(@import("compiler_rt/divsf3.zig").__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); |
| 223 | @export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); | 227 | @export(@import("compiler_rt/divdf3.zig").__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); |
| 224 | 228 | ||
| 225 | @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); | 229 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); |
| 226 | @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); | 230 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); |
| 227 | @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); | 231 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); |
| 228 | @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); | 232 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); |
| 229 | @export(@import("compiler_rt/arm/aeabi_fcmp.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); | 233 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); |
| 230 | @export(@import("compiler_rt/comparesf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); | 234 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); |
| 231 | 235 | ||
| 232 | @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); | 236 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); |
| 233 | @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); | 237 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); |
| 234 | @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); | 238 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); |
| 235 | @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); | 239 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); |
| 236 | @export(@import("compiler_rt/arm/aeabi_dcmp.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); | 240 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); |
| 237 | @export(@import("compiler_rt/comparedf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); | 241 | @export(@import("compiler_rt/compareXf2.zig").__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); |
| 242 | } | ||
| 243 | |||
| 244 | if (builtin.arch == .i386 and builtin.abi == .msvc) { | ||
| 245 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins | ||
| 246 | @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); | ||
| 247 | @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); | ||
| 248 | @export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); | ||
| 249 | @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); | ||
| 238 | } | 250 | } |
| 251 | |||
| 239 | if (builtin.os == .windows) { | 252 | if (builtin.os == .windows) { |
| 240 | // Default stack-probe functions emitted by LLVM | 253 | // Default stack-probe functions emitted by LLVM |
| 241 | if (is_mingw) { | 254 | if (is_mingw) { |
| ... | @@ -254,13 +267,6 @@ comptime { | ... | @@ -254,13 +267,6 @@ comptime { |
| 254 | 267 | ||
| 255 | switch (builtin.arch) { | 268 | switch (builtin.arch) { |
| 256 | .i386 => { | 269 | .i386 => { |
| 257 | // Don't let LLVM apply the stdcall name mangling on those MSVC | ||
| 258 | // builtin functions | ||
| 259 | @export(@import("compiler_rt/aulldiv.zig")._alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); | ||
| 260 | @export(@import("compiler_rt/aulldiv.zig")._aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); | ||
| 261 | @export(@import("compiler_rt/aullrem.zig")._allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); | ||
| 262 | @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); | ||
| 263 | |||
| 264 | @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage }); | 270 | @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage }); |
| 265 | @export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage }); | 271 | @export(@import("compiler_rt/modti3.zig").__modti3, .{ .name = "__modti3", .linkage = linkage }); |
| 266 | @export(@import("compiler_rt/multi3.zig").__multi3, .{ .name = "__multi3", .linkage = linkage }); | 272 | @export(@import("compiler_rt/multi3.zig").__multi3, .{ .name = "__multi3", .linkage = linkage }); |
| ... | @@ -295,16 +301,12 @@ comptime { | ... | @@ -295,16 +301,12 @@ comptime { |
| 295 | @export(@import("compiler_rt/mulodi4.zig").__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | 301 | @export(@import("compiler_rt/mulodi4.zig").__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); |
| 296 | } | 302 | } |
| 297 | 303 | ||
| 298 | const std = @import("std"); | ||
| 299 | const assert = std.debug.assert; | ||
| 300 | const testing = std.testing; | ||
| 301 | |||
| 302 | // Avoid dragging in the runtime safety mechanisms into this .o file, | 304 | // Avoid dragging in the runtime safety mechanisms into this .o file, |
| 303 | // unless we're trying to test this file. | 305 | // unless we're trying to test this file. |
| 304 | pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { | 306 | pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { |
| 305 | @setCold(true); | 307 | @setCold(true); |
| 306 | if (is_test) { | 308 | if (is_test) { |
| 307 | std.debug.panic("{}", .{msg}); | 309 | @import("std").debug.panic("{}", .{msg}); |
| 308 | } else { | 310 | } else { |
| 309 | unreachable; | 311 | unreachable; |
| 310 | } | 312 | } |
| ... | @@ -320,23 +322,3 @@ extern var __stack_chk_guard: usize = blk: { | ... | @@ -320,23 +322,3 @@ extern var __stack_chk_guard: usize = blk: { |
| 320 | buf[@sizeOf(usize) - 2] = '\n'; | 322 | buf[@sizeOf(usize) - 2] = '\n'; |
| 321 | break :blk @bitCast(usize, buf); | 323 | break :blk @bitCast(usize, buf); |
| 322 | }; | 324 | }; |
| 323 | |||
| 324 | const is_arm_64 = switch (builtin.arch) { | ||
| 325 | builtin.Arch.aarch64, | ||
| 326 | builtin.Arch.aarch64_be, | ||
| 327 | => true, | ||
| 328 | else => false, | ||
| 329 | }; | ||
| 330 | |||
| 331 | const is_arm_arch = switch (builtin.arch) { | ||
| 332 | builtin.Arch.arm, | ||
| 333 | builtin.Arch.armeb, | ||
| 334 | builtin.Arch.aarch64, | ||
| 335 | builtin.Arch.aarch64_be, | ||
| 336 | builtin.Arch.thumb, | ||
| 337 | builtin.Arch.thumbeb, | ||
| 338 | => true, | ||
| 339 | else => false, | ||
| 340 | }; | ||
| 341 | |||
| 342 | const is_arm_32 = is_arm_arch and !is_arm_64; |
lib/std/special/compiler_rt/arm.zig+9-10| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | // ARM specific builtins | 1 | // ARM specific builtins |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | ||
| 4 | 3 | ||
| 5 | const __divmodsi4 = @import("int.zig").__divmodsi4; | 4 | const __divmodsi4 = @import("int.zig").__divmodsi4; |
| 6 | const __udivmodsi4 = @import("int.zig").__udivmodsi4; | 5 | const __udivmodsi4 = @import("int.zig").__udivmodsi4; |
| ... | @@ -33,18 +32,14 @@ pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void { | ... | @@ -33,18 +32,14 @@ pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void { |
| 33 | _ = memset(dest, 0, n); | 32 | _ = memset(dest, 0, n); |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void { | 35 | // Dummy functions to avoid errors during the linking phase |
| 37 | unreachable; | 36 | pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {} |
| 38 | } | 37 | pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {} |
| 39 | pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void { | 38 | pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {} |
| 40 | unreachable; | ||
| 41 | } | ||
| 42 | pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void { | ||
| 43 | unreachable; | ||
| 44 | } | ||
| 45 | 39 | ||
| 46 | // This function can only clobber r0 according to the ABI | 40 | // This function can only clobber r0 according to the ABI |
| 47 | pub fn __aeabi_read_tp() callconv(.Naked) void { | 41 | pub fn __aeabi_read_tp() callconv(.Naked) void { |
| 42 | @setRuntimeSafety(false); | ||
| 48 | asm volatile ( | 43 | asm volatile ( |
| 49 | \\ mrc p15, 0, r0, c13, c0, 3 | 44 | \\ mrc p15, 0, r0, c13, c0, 3 |
| 50 | \\ bx lr | 45 | \\ bx lr |
| ... | @@ -56,6 +51,7 @@ pub fn __aeabi_read_tp() callconv(.Naked) void { | ... | @@ -56,6 +51,7 @@ pub fn __aeabi_read_tp() callconv(.Naked) void { |
| 56 | // calling convention is always respected | 51 | // calling convention is always respected |
| 57 | 52 | ||
| 58 | pub fn __aeabi_uidivmod() callconv(.Naked) void { | 53 | pub fn __aeabi_uidivmod() callconv(.Naked) void { |
| 54 | @setRuntimeSafety(false); | ||
| 59 | // Divide r0 by r1; the quotient goes in r0, the remainder in r1 | 55 | // Divide r0 by r1; the quotient goes in r0, the remainder in r1 |
| 60 | asm volatile ( | 56 | asm volatile ( |
| 61 | \\ push {lr} | 57 | \\ push {lr} |
| ... | @@ -73,6 +69,7 @@ pub fn __aeabi_uidivmod() callconv(.Naked) void { | ... | @@ -73,6 +69,7 @@ pub fn __aeabi_uidivmod() callconv(.Naked) void { |
| 73 | } | 69 | } |
| 74 | 70 | ||
| 75 | pub fn __aeabi_uldivmod() callconv(.Naked) void { | 71 | pub fn __aeabi_uldivmod() callconv(.Naked) void { |
| 72 | @setRuntimeSafety(false); | ||
| 76 | // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 | 73 | // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 |
| 77 | asm volatile ( | 74 | asm volatile ( |
| 78 | \\ push {r4, lr} | 75 | \\ push {r4, lr} |
| ... | @@ -92,6 +89,7 @@ pub fn __aeabi_uldivmod() callconv(.Naked) void { | ... | @@ -92,6 +89,7 @@ pub fn __aeabi_uldivmod() callconv(.Naked) void { |
| 92 | } | 89 | } |
| 93 | 90 | ||
| 94 | pub fn __aeabi_idivmod() callconv(.Naked) void { | 91 | pub fn __aeabi_idivmod() callconv(.Naked) void { |
| 92 | @setRuntimeSafety(false); | ||
| 95 | // Divide r0 by r1; the quotient goes in r0, the remainder in r1 | 93 | // Divide r0 by r1; the quotient goes in r0, the remainder in r1 |
| 96 | asm volatile ( | 94 | asm volatile ( |
| 97 | \\ push {lr} | 95 | \\ push {lr} |
| ... | @@ -109,6 +107,7 @@ pub fn __aeabi_idivmod() callconv(.Naked) void { | ... | @@ -109,6 +107,7 @@ pub fn __aeabi_idivmod() callconv(.Naked) void { |
| 109 | } | 107 | } |
| 110 | 108 | ||
| 111 | pub fn __aeabi_ldivmod() callconv(.Naked) void { | 109 | pub fn __aeabi_ldivmod() callconv(.Naked) void { |
| 110 | @setRuntimeSafety(false); | ||
| 112 | // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 | 111 | // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 |
| 113 | asm volatile ( | 112 | asm volatile ( |
| 114 | \\ push {r4, lr} | 113 | \\ push {r4, lr} |
lib/std/special/compiler_rt/arm/aeabi_dcmp.zig deleted-95| ... | @@ -1,95 +0,0 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_dcmp.S | ||
| 4 | |||
| 5 | const ConditionalOperator = enum { | ||
| 6 | Eq, | ||
| 7 | Lt, | ||
| 8 | Le, | ||
| 9 | Ge, | ||
| 10 | Gt, | ||
| 11 | }; | ||
| 12 | |||
| 13 | pub fn __aeabi_dcmpeq() callconv(.Naked) noreturn { | ||
| 14 | @setRuntimeSafety(false); | ||
| 15 | @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq}); | ||
| 16 | unreachable; | ||
| 17 | } | ||
| 18 | |||
| 19 | pub fn __aeabi_dcmplt() callconv(.Naked) noreturn { | ||
| 20 | @setRuntimeSafety(false); | ||
| 21 | @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt}); | ||
| 22 | unreachable; | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn __aeabi_dcmple() callconv(.Naked) noreturn { | ||
| 26 | @setRuntimeSafety(false); | ||
| 27 | @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le}); | ||
| 28 | unreachable; | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn __aeabi_dcmpge() callconv(.Naked) noreturn { | ||
| 32 | @setRuntimeSafety(false); | ||
| 33 | @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge}); | ||
| 34 | unreachable; | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn __aeabi_dcmpgt() callconv(.Naked) noreturn { | ||
| 38 | @setRuntimeSafety(false); | ||
| 39 | @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt}); | ||
| 40 | unreachable; | ||
| 41 | } | ||
| 42 | |||
| 43 | fn aeabi_dcmp(comptime cond: ConditionalOperator) void { | ||
| 44 | @setRuntimeSafety(false); | ||
| 45 | asm volatile ( | ||
| 46 | \\ push { r4, lr } | ||
| 47 | ); | ||
| 48 | |||
| 49 | switch (cond) { | ||
| 50 | .Eq => asm volatile ( | ||
| 51 | \\ bl __eqdf2 | ||
| 52 | \\ cmp r0, #0 | ||
| 53 | \\ beq 1f | ||
| 54 | \\ movs r0, #0 | ||
| 55 | \\ pop { r4, pc } | ||
| 56 | \\ 1: | ||
| 57 | ), | ||
| 58 | .Lt => asm volatile ( | ||
| 59 | \\ bl __ltdf2 | ||
| 60 | \\ cmp r0, #0 | ||
| 61 | \\ blt 1f | ||
| 62 | \\ movs r0, #0 | ||
| 63 | \\ pop { r4, pc } | ||
| 64 | \\ 1: | ||
| 65 | ), | ||
| 66 | .Le => asm volatile ( | ||
| 67 | \\ bl __ledf2 | ||
| 68 | \\ cmp r0, #0 | ||
| 69 | \\ ble 1f | ||
| 70 | \\ movs r0, #0 | ||
| 71 | \\ pop { r4, pc } | ||
| 72 | \\ 1: | ||
| 73 | ), | ||
| 74 | .Ge => asm volatile ( | ||
| 75 | \\ bl __ltdf2 | ||
| 76 | \\ cmp r0, #0 | ||
| 77 | \\ bge 1f | ||
| 78 | \\ movs r0, #0 | ||
| 79 | \\ pop { r4, pc } | ||
| 80 | \\ 1: | ||
| 81 | ), | ||
| 82 | .Gt => asm volatile ( | ||
| 83 | \\ bl __gtdf2 | ||
| 84 | \\ cmp r0, #0 | ||
| 85 | \\ bgt 1f | ||
| 86 | \\ movs r0, #0 | ||
| 87 | \\ pop { r4, pc } | ||
| 88 | \\ 1: | ||
| 89 | ), | ||
| 90 | } | ||
| 91 | asm volatile ( | ||
| 92 | \\ movs r0, #1 | ||
| 93 | \\ pop { r4, pc } | ||
| 94 | ); | ||
| 95 | } | ||
lib/std/special/compiler_rt/arm/aeabi_fcmp.zig deleted-95| ... | @@ -1,95 +0,0 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/arm/aeabi_fcmp.S | ||
| 4 | |||
| 5 | const ConditionalOperator = enum { | ||
| 6 | Eq, | ||
| 7 | Lt, | ||
| 8 | Le, | ||
| 9 | Ge, | ||
| 10 | Gt, | ||
| 11 | }; | ||
| 12 | |||
| 13 | pub fn __aeabi_fcmpeq() callconv(.Naked) noreturn { | ||
| 14 | @setRuntimeSafety(false); | ||
| 15 | @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq}); | ||
| 16 | unreachable; | ||
| 17 | } | ||
| 18 | |||
| 19 | pub fn __aeabi_fcmplt() callconv(.Naked) noreturn { | ||
| 20 | @setRuntimeSafety(false); | ||
| 21 | @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt}); | ||
| 22 | unreachable; | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn __aeabi_fcmple() callconv(.Naked) noreturn { | ||
| 26 | @setRuntimeSafety(false); | ||
| 27 | @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le}); | ||
| 28 | unreachable; | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn __aeabi_fcmpge() callconv(.Naked) noreturn { | ||
| 32 | @setRuntimeSafety(false); | ||
| 33 | @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge}); | ||
| 34 | unreachable; | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn __aeabi_fcmpgt() callconv(.Naked) noreturn { | ||
| 38 | @setRuntimeSafety(false); | ||
| 39 | @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt}); | ||
| 40 | unreachable; | ||
| 41 | } | ||
| 42 | |||
| 43 | fn aeabi_fcmp(comptime cond: ConditionalOperator) void { | ||
| 44 | @setRuntimeSafety(false); | ||
| 45 | asm volatile ( | ||
| 46 | \\ push { r4, lr } | ||
| 47 | ); | ||
| 48 | |||
| 49 | switch (cond) { | ||
| 50 | .Eq => asm volatile ( | ||
| 51 | \\ bl __eqsf2 | ||
| 52 | \\ cmp r0, #0 | ||
| 53 | \\ beq 1f | ||
| 54 | \\ movs r0, #0 | ||
| 55 | \\ pop { r4, pc } | ||
| 56 | \\ 1: | ||
| 57 | ), | ||
| 58 | .Lt => asm volatile ( | ||
| 59 | \\ bl __ltsf2 | ||
| 60 | \\ cmp r0, #0 | ||
| 61 | \\ blt 1f | ||
| 62 | \\ movs r0, #0 | ||
| 63 | \\ pop { r4, pc } | ||
| 64 | \\ 1: | ||
| 65 | ), | ||
| 66 | .Le => asm volatile ( | ||
| 67 | \\ bl __lesf2 | ||
| 68 | \\ cmp r0, #0 | ||
| 69 | \\ ble 1f | ||
| 70 | \\ movs r0, #0 | ||
| 71 | \\ pop { r4, pc } | ||
| 72 | \\ 1: | ||
| 73 | ), | ||
| 74 | .Ge => asm volatile ( | ||
| 75 | \\ bl __ltsf2 | ||
| 76 | \\ cmp r0, #0 | ||
| 77 | \\ bge 1f | ||
| 78 | \\ movs r0, #0 | ||
| 79 | \\ pop { r4, pc } | ||
| 80 | \\ 1: | ||
| 81 | ), | ||
| 82 | .Gt => asm volatile ( | ||
| 83 | \\ bl __gtsf2 | ||
| 84 | \\ cmp r0, #0 | ||
| 85 | \\ bgt 1f | ||
| 86 | \\ movs r0, #0 | ||
| 87 | \\ pop { r4, pc } | ||
| 88 | \\ 1: | ||
| 89 | ), | ||
| 90 | } | ||
| 91 | asm volatile ( | ||
| 92 | \\ movs r0, #1 | ||
| 93 | \\ pop { r4, pc } | ||
| 94 | ); | ||
| 95 | } | ||
lib/std/special/compiler_rt/clzsi2.zig created+116| ... | @@ -0,0 +1,116 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | |||
| 3 | fn __clzsi2_generic(a: i32) callconv(.C) i32 { | ||
| 4 | @setRuntimeSafety(builtin.is_test); | ||
| 5 | |||
| 6 | var x = @bitCast(u32, a); | ||
| 7 | var n: i32 = 32; | ||
| 8 | |||
| 9 | // Count first bit set using binary search, from Hacker's Delight | ||
| 10 | var y: u32 = 0; | ||
| 11 | inline for ([_]i32{ 16, 8, 4, 2, 1 }) |shift| { | ||
| 12 | y = x >> shift; | ||
| 13 | if (y != 0) { | ||
| 14 | n = n - shift; | ||
| 15 | x = y; | ||
| 16 | } | ||
| 17 | } | ||
| 18 | |||
| 19 | return n - @bitCast(i32, x); | ||
| 20 | } | ||
| 21 | |||
| 22 | fn __clzsi2_thumb1() callconv(.Naked) void { | ||
| 23 | @setRuntimeSafety(builtin.is_test); | ||
| 24 | |||
| 25 | // Similar to the generic version with the last two rounds replaced by a LUT | ||
| 26 | asm volatile ( | ||
| 27 | \\ movs r1, #32 | ||
| 28 | \\ lsrs r2, r0, #16 | ||
| 29 | \\ beq 1f | ||
| 30 | \\ subs r1, #16 | ||
| 31 | \\ movs r0, r2 | ||
| 32 | \\ 1: | ||
| 33 | \\ lsrs r2, r0, #8 | ||
| 34 | \\ beq 1f | ||
| 35 | \\ subs r1, #8 | ||
| 36 | \\ movs r0, r2 | ||
| 37 | \\ 1: | ||
| 38 | \\ lsrs r2, r0, #4 | ||
| 39 | \\ beq 1f | ||
| 40 | \\ subs r1, #4 | ||
| 41 | \\ movs r0, r2 | ||
| 42 | \\ 1: | ||
| 43 | \\ ldr r3, =LUT | ||
| 44 | \\ ldrb r0, [r3, r0] | ||
| 45 | \\ subs r0, r1, r0 | ||
| 46 | \\ bx lr | ||
| 47 | \\ .p2align 2 | ||
| 48 | \\ LUT: | ||
| 49 | \\ .byte 4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0 | ||
| 50 | ); | ||
| 51 | |||
| 52 | unreachable; | ||
| 53 | } | ||
| 54 | |||
| 55 | fn __clzsi2_arm32() callconv(.Naked) void { | ||
| 56 | @setRuntimeSafety(builtin.is_test); | ||
| 57 | |||
| 58 | asm volatile ( | ||
| 59 | \\ // Assumption: n != 0 | ||
| 60 | \\ // r0: n | ||
| 61 | \\ // r1: count of leading zeros in n + 1 | ||
| 62 | \\ // r2: scratch register for shifted r0 | ||
| 63 | \\ mov r1, #1 | ||
| 64 | \\ | ||
| 65 | \\ // Basic block: | ||
| 66 | \\ // if ((r0 >> SHIFT) == 0) | ||
| 67 | \\ // r1 += SHIFT; | ||
| 68 | \\ // else | ||
| 69 | \\ // r0 >>= SHIFT; | ||
| 70 | \\ // for descending powers of two as SHIFT. | ||
| 71 | \\ lsrs r2, r0, #16 | ||
| 72 | \\ movne r0, r2 | ||
| 73 | \\ addeq r1, #16 | ||
| 74 | \\ | ||
| 75 | \\ lsrs r2, r0, #8 | ||
| 76 | \\ movne r0, r2 | ||
| 77 | \\ addeq r1, #8 | ||
| 78 | \\ | ||
| 79 | \\ lsrs r2, r0, #4 | ||
| 80 | \\ movne r0, r2 | ||
| 81 | \\ addeq r1, #4 | ||
| 82 | \\ | ||
| 83 | \\ lsrs r2, r0, #2 | ||
| 84 | \\ movne r0, r2 | ||
| 85 | \\ addeq r1, #2 | ||
| 86 | \\ | ||
| 87 | \\ // The basic block invariants at this point are (r0 >> 2) == 0 and | ||
| 88 | \\ // r0 != 0. This means 1 <= r0 <= 3 and 0 <= (r0 >> 1) <= 1. | ||
| 89 | \\ // | ||
| 90 | \\ // r0 | (r0 >> 1) == 0 | (r0 >> 1) == 1 | -(r0 >> 1) | 1 - (r0 >> 1)f | ||
| 91 | \\ // ---+----------------+----------------+------------+-------------- | ||
| 92 | \\ // 1 | 1 | 0 | 0 | 1 | ||
| 93 | \\ // 2 | 0 | 1 | -1 | 0 | ||
| 94 | \\ // 3 | 0 | 1 | -1 | 0 | ||
| 95 | \\ // | ||
| 96 | \\ // The r1's initial value of 1 compensates for the 1 here. | ||
| 97 | \\ sub r0, r1, r0, lsr #1 | ||
| 98 | \\ bx lr | ||
| 99 | ); | ||
| 100 | |||
| 101 | unreachable; | ||
| 102 | } | ||
| 103 | |||
| 104 | pub const __clzsi2 = blk: { | ||
| 105 | if (builtin.arch.isARM()) { | ||
| 106 | break :blk __clzsi2_arm32; | ||
| 107 | } else if (builtin.arch.isThumb()) { | ||
| 108 | break :blk __clzsi2_thumb1; | ||
| 109 | } else { | ||
| 110 | break :blk __clzsi2_generic; | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | |||
| 114 | test "test clzsi2" { | ||
| 115 | _ = @import("clzsi2_test.zig"); | ||
| 116 | } | ||
lib/std/special/compiler_rt/clzsi2_test.zig created+292| ... | @@ -0,0 +1,292 @@ | ||
| 1 | const clzsi2 = @import("clzsi2.zig"); | ||
| 2 | const testing = @import("std").testing; | ||
| 3 | |||
| 4 | fn test__clzsi2(a: u32, expected: i32) void { | ||
| 5 | var nakedClzsi2 = clzsi2.__clzsi2; | ||
| 6 | var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2); | ||
| 7 | var x = @intCast(i32, a); | ||
| 8 | var result = actualClzsi2(x); | ||
| 9 | testing.expectEqual(expected, result); | ||
| 10 | } | ||
| 11 | |||
| 12 | test "clzsi2" { | ||
| 13 | test__clzsi2(0x00800000, 8); | ||
| 14 | test__clzsi2(0x01000000, 7); | ||
| 15 | test__clzsi2(0x02000000, 6); | ||
| 16 | test__clzsi2(0x03000000, 6); | ||
| 17 | test__clzsi2(0x04000000, 5); | ||
| 18 | test__clzsi2(0x05000000, 5); | ||
| 19 | test__clzsi2(0x06000000, 5); | ||
| 20 | test__clzsi2(0x07000000, 5); | ||
| 21 | test__clzsi2(0x08000000, 4); | ||
| 22 | test__clzsi2(0x09000000, 4); | ||
| 23 | test__clzsi2(0x0A000000, 4); | ||
| 24 | test__clzsi2(0x0B000000, 4); | ||
| 25 | test__clzsi2(0x0C000000, 4); | ||
| 26 | test__clzsi2(0x0D000000, 4); | ||
| 27 | test__clzsi2(0x0E000000, 4); | ||
| 28 | test__clzsi2(0x0F000000, 4); | ||
| 29 | test__clzsi2(0x10000000, 3); | ||
| 30 | test__clzsi2(0x11000000, 3); | ||
| 31 | test__clzsi2(0x12000000, 3); | ||
| 32 | test__clzsi2(0x13000000, 3); | ||
| 33 | test__clzsi2(0x14000000, 3); | ||
| 34 | test__clzsi2(0x15000000, 3); | ||
| 35 | test__clzsi2(0x16000000, 3); | ||
| 36 | test__clzsi2(0x17000000, 3); | ||
| 37 | test__clzsi2(0x18000000, 3); | ||
| 38 | test__clzsi2(0x19000000, 3); | ||
| 39 | test__clzsi2(0x1A000000, 3); | ||
| 40 | test__clzsi2(0x1B000000, 3); | ||
| 41 | test__clzsi2(0x1C000000, 3); | ||
| 42 | test__clzsi2(0x1D000000, 3); | ||
| 43 | test__clzsi2(0x1E000000, 3); | ||
| 44 | test__clzsi2(0x1F000000, 3); | ||
| 45 | test__clzsi2(0x20000000, 2); | ||
| 46 | test__clzsi2(0x21000000, 2); | ||
| 47 | test__clzsi2(0x22000000, 2); | ||
| 48 | test__clzsi2(0x23000000, 2); | ||
| 49 | test__clzsi2(0x24000000, 2); | ||
| 50 | test__clzsi2(0x25000000, 2); | ||
| 51 | test__clzsi2(0x26000000, 2); | ||
| 52 | test__clzsi2(0x27000000, 2); | ||
| 53 | test__clzsi2(0x28000000, 2); | ||
| 54 | test__clzsi2(0x29000000, 2); | ||
| 55 | test__clzsi2(0x2A000000, 2); | ||
| 56 | test__clzsi2(0x2B000000, 2); | ||
| 57 | test__clzsi2(0x2C000000, 2); | ||
| 58 | test__clzsi2(0x2D000000, 2); | ||
| 59 | test__clzsi2(0x2E000000, 2); | ||
| 60 | test__clzsi2(0x2F000000, 2); | ||
| 61 | test__clzsi2(0x30000000, 2); | ||
| 62 | test__clzsi2(0x31000000, 2); | ||
| 63 | test__clzsi2(0x32000000, 2); | ||
| 64 | test__clzsi2(0x33000000, 2); | ||
| 65 | test__clzsi2(0x34000000, 2); | ||
| 66 | test__clzsi2(0x35000000, 2); | ||
| 67 | test__clzsi2(0x36000000, 2); | ||
| 68 | test__clzsi2(0x37000000, 2); | ||
| 69 | test__clzsi2(0x38000000, 2); | ||
| 70 | test__clzsi2(0x39000000, 2); | ||
| 71 | test__clzsi2(0x3A000000, 2); | ||
| 72 | test__clzsi2(0x3B000000, 2); | ||
| 73 | test__clzsi2(0x3C000000, 2); | ||
| 74 | test__clzsi2(0x3D000000, 2); | ||
| 75 | test__clzsi2(0x3E000000, 2); | ||
| 76 | test__clzsi2(0x3F000000, 2); | ||
| 77 | test__clzsi2(0x40000000, 1); | ||
| 78 | test__clzsi2(0x41000000, 1); | ||
| 79 | test__clzsi2(0x42000000, 1); | ||
| 80 | test__clzsi2(0x43000000, 1); | ||
| 81 | test__clzsi2(0x44000000, 1); | ||
| 82 | test__clzsi2(0x45000000, 1); | ||
| 83 | test__clzsi2(0x46000000, 1); | ||
| 84 | test__clzsi2(0x47000000, 1); | ||
| 85 | test__clzsi2(0x48000000, 1); | ||
| 86 | test__clzsi2(0x49000000, 1); | ||
| 87 | test__clzsi2(0x4A000000, 1); | ||
| 88 | test__clzsi2(0x4B000000, 1); | ||
| 89 | test__clzsi2(0x4C000000, 1); | ||
| 90 | test__clzsi2(0x4D000000, 1); | ||
| 91 | test__clzsi2(0x4E000000, 1); | ||
| 92 | test__clzsi2(0x4F000000, 1); | ||
| 93 | test__clzsi2(0x50000000, 1); | ||
| 94 | test__clzsi2(0x51000000, 1); | ||
| 95 | test__clzsi2(0x52000000, 1); | ||
| 96 | test__clzsi2(0x53000000, 1); | ||
| 97 | test__clzsi2(0x54000000, 1); | ||
| 98 | test__clzsi2(0x55000000, 1); | ||
| 99 | test__clzsi2(0x56000000, 1); | ||
| 100 | test__clzsi2(0x57000000, 1); | ||
| 101 | test__clzsi2(0x58000000, 1); | ||
| 102 | test__clzsi2(0x59000000, 1); | ||
| 103 | test__clzsi2(0x5A000000, 1); | ||
| 104 | test__clzsi2(0x5B000000, 1); | ||
| 105 | test__clzsi2(0x5C000000, 1); | ||
| 106 | test__clzsi2(0x5D000000, 1); | ||
| 107 | test__clzsi2(0x5E000000, 1); | ||
| 108 | test__clzsi2(0x5F000000, 1); | ||
| 109 | test__clzsi2(0x60000000, 1); | ||
| 110 | test__clzsi2(0x61000000, 1); | ||
| 111 | test__clzsi2(0x62000000, 1); | ||
| 112 | test__clzsi2(0x63000000, 1); | ||
| 113 | test__clzsi2(0x64000000, 1); | ||
| 114 | test__clzsi2(0x65000000, 1); | ||
| 115 | test__clzsi2(0x66000000, 1); | ||
| 116 | test__clzsi2(0x67000000, 1); | ||
| 117 | test__clzsi2(0x68000000, 1); | ||
| 118 | test__clzsi2(0x69000000, 1); | ||
| 119 | test__clzsi2(0x6A000000, 1); | ||
| 120 | test__clzsi2(0x6B000000, 1); | ||
| 121 | test__clzsi2(0x6C000000, 1); | ||
| 122 | test__clzsi2(0x6D000000, 1); | ||
| 123 | test__clzsi2(0x6E000000, 1); | ||
| 124 | test__clzsi2(0x6F000000, 1); | ||
| 125 | test__clzsi2(0x70000000, 1); | ||
| 126 | test__clzsi2(0x71000000, 1); | ||
| 127 | test__clzsi2(0x72000000, 1); | ||
| 128 | test__clzsi2(0x73000000, 1); | ||
| 129 | test__clzsi2(0x74000000, 1); | ||
| 130 | test__clzsi2(0x75000000, 1); | ||
| 131 | test__clzsi2(0x76000000, 1); | ||
| 132 | test__clzsi2(0x77000000, 1); | ||
| 133 | test__clzsi2(0x78000000, 1); | ||
| 134 | test__clzsi2(0x79000000, 1); | ||
| 135 | test__clzsi2(0x7A000000, 1); | ||
| 136 | test__clzsi2(0x7B000000, 1); | ||
| 137 | test__clzsi2(0x7C000000, 1); | ||
| 138 | test__clzsi2(0x7D000000, 1); | ||
| 139 | test__clzsi2(0x7E000000, 1); | ||
| 140 | test__clzsi2(0x7F000000, 1); | ||
| 141 | test__clzsi2(0x80000000, 0); | ||
| 142 | test__clzsi2(0x81000000, 0); | ||
| 143 | test__clzsi2(0x82000000, 0); | ||
| 144 | test__clzsi2(0x83000000, 0); | ||
| 145 | test__clzsi2(0x84000000, 0); | ||
| 146 | test__clzsi2(0x85000000, 0); | ||
| 147 | test__clzsi2(0x86000000, 0); | ||
| 148 | test__clzsi2(0x87000000, 0); | ||
| 149 | test__clzsi2(0x88000000, 0); | ||
| 150 | test__clzsi2(0x89000000, 0); | ||
| 151 | test__clzsi2(0x8A000000, 0); | ||
| 152 | test__clzsi2(0x8B000000, 0); | ||
| 153 | test__clzsi2(0x8C000000, 0); | ||
| 154 | test__clzsi2(0x8D000000, 0); | ||
| 155 | test__clzsi2(0x8E000000, 0); | ||
| 156 | test__clzsi2(0x8F000000, 0); | ||
| 157 | test__clzsi2(0x90000000, 0); | ||
| 158 | test__clzsi2(0x91000000, 0); | ||
| 159 | test__clzsi2(0x92000000, 0); | ||
| 160 | test__clzsi2(0x93000000, 0); | ||
| 161 | test__clzsi2(0x94000000, 0); | ||
| 162 | test__clzsi2(0x95000000, 0); | ||
| 163 | test__clzsi2(0x96000000, 0); | ||
| 164 | test__clzsi2(0x97000000, 0); | ||
| 165 | test__clzsi2(0x98000000, 0); | ||
| 166 | test__clzsi2(0x99000000, 0); | ||
| 167 | test__clzsi2(0x9A000000, 0); | ||
| 168 | test__clzsi2(0x9B000000, 0); | ||
| 169 | test__clzsi2(0x9C000000, 0); | ||
| 170 | test__clzsi2(0x9D000000, 0); | ||
| 171 | test__clzsi2(0x9E000000, 0); | ||
| 172 | test__clzsi2(0x9F000000, 0); | ||
| 173 | test__clzsi2(0xA0000000, 0); | ||
| 174 | test__clzsi2(0xA1000000, 0); | ||
| 175 | test__clzsi2(0xA2000000, 0); | ||
| 176 | test__clzsi2(0xA3000000, 0); | ||
| 177 | test__clzsi2(0xA4000000, 0); | ||
| 178 | test__clzsi2(0xA5000000, 0); | ||
| 179 | test__clzsi2(0xA6000000, 0); | ||
| 180 | test__clzsi2(0xA7000000, 0); | ||
| 181 | test__clzsi2(0xA8000000, 0); | ||
| 182 | test__clzsi2(0xA9000000, 0); | ||
| 183 | test__clzsi2(0xAA000000, 0); | ||
| 184 | test__clzsi2(0xAB000000, 0); | ||
| 185 | test__clzsi2(0xAC000000, 0); | ||
| 186 | test__clzsi2(0xAD000000, 0); | ||
| 187 | test__clzsi2(0xAE000000, 0); | ||
| 188 | test__clzsi2(0xAF000000, 0); | ||
| 189 | test__clzsi2(0xB0000000, 0); | ||
| 190 | test__clzsi2(0xB1000000, 0); | ||
| 191 | test__clzsi2(0xB2000000, 0); | ||
| 192 | test__clzsi2(0xB3000000, 0); | ||
| 193 | test__clzsi2(0xB4000000, 0); | ||
| 194 | test__clzsi2(0xB5000000, 0); | ||
| 195 | test__clzsi2(0xB6000000, 0); | ||
| 196 | test__clzsi2(0xB7000000, 0); | ||
| 197 | test__clzsi2(0xB8000000, 0); | ||
| 198 | test__clzsi2(0xB9000000, 0); | ||
| 199 | test__clzsi2(0xBA000000, 0); | ||
| 200 | test__clzsi2(0xBB000000, 0); | ||
| 201 | test__clzsi2(0xBC000000, 0); | ||
| 202 | test__clzsi2(0xBD000000, 0); | ||
| 203 | test__clzsi2(0xBE000000, 0); | ||
| 204 | test__clzsi2(0xBF000000, 0); | ||
| 205 | test__clzsi2(0xC0000000, 0); | ||
| 206 | test__clzsi2(0xC1000000, 0); | ||
| 207 | test__clzsi2(0xC2000000, 0); | ||
| 208 | test__clzsi2(0xC3000000, 0); | ||
| 209 | test__clzsi2(0xC4000000, 0); | ||
| 210 | test__clzsi2(0xC5000000, 0); | ||
| 211 | test__clzsi2(0xC6000000, 0); | ||
| 212 | test__clzsi2(0xC7000000, 0); | ||
| 213 | test__clzsi2(0xC8000000, 0); | ||
| 214 | test__clzsi2(0xC9000000, 0); | ||
| 215 | test__clzsi2(0xCA000000, 0); | ||
| 216 | test__clzsi2(0xCB000000, 0); | ||
| 217 | test__clzsi2(0xCC000000, 0); | ||
| 218 | test__clzsi2(0xCD000000, 0); | ||
| 219 | test__clzsi2(0xCE000000, 0); | ||
| 220 | test__clzsi2(0xCF000000, 0); | ||
| 221 | test__clzsi2(0xD0000000, 0); | ||
| 222 | test__clzsi2(0xD1000000, 0); | ||
| 223 | test__clzsi2(0xD2000000, 0); | ||
| 224 | test__clzsi2(0xD3000000, 0); | ||
| 225 | test__clzsi2(0xD4000000, 0); | ||
| 226 | test__clzsi2(0xD5000000, 0); | ||
| 227 | test__clzsi2(0xD6000000, 0); | ||
| 228 | test__clzsi2(0xD7000000, 0); | ||
| 229 | test__clzsi2(0xD8000000, 0); | ||
| 230 | test__clzsi2(0xD9000000, 0); | ||
| 231 | test__clzsi2(0xDA000000, 0); | ||
| 232 | test__clzsi2(0xDB000000, 0); | ||
| 233 | test__clzsi2(0xDC000000, 0); | ||
| 234 | test__clzsi2(0xDD000000, 0); | ||
| 235 | test__clzsi2(0xDE000000, 0); | ||
| 236 | test__clzsi2(0xDF000000, 0); | ||
| 237 | test__clzsi2(0xE0000000, 0); | ||
| 238 | test__clzsi2(0xE1000000, 0); | ||
| 239 | test__clzsi2(0xE2000000, 0); | ||
| 240 | test__clzsi2(0xE3000000, 0); | ||
| 241 | test__clzsi2(0xE4000000, 0); | ||
| 242 | test__clzsi2(0xE5000000, 0); | ||
| 243 | test__clzsi2(0xE6000000, 0); | ||
| 244 | test__clzsi2(0xE7000000, 0); | ||
| 245 | test__clzsi2(0xE8000000, 0); | ||
| 246 | test__clzsi2(0xE9000000, 0); | ||
| 247 | test__clzsi2(0xEA000000, 0); | ||
| 248 | test__clzsi2(0xEB000000, 0); | ||
| 249 | test__clzsi2(0xEC000000, 0); | ||
| 250 | test__clzsi2(0xED000000, 0); | ||
| 251 | test__clzsi2(0xEE000000, 0); | ||
| 252 | test__clzsi2(0xEF000000, 0); | ||
| 253 | test__clzsi2(0xF0000000, 0); | ||
| 254 | test__clzsi2(0xF1000000, 0); | ||
| 255 | test__clzsi2(0xF2000000, 0); | ||
| 256 | test__clzsi2(0xF3000000, 0); | ||
| 257 | test__clzsi2(0xF4000000, 0); | ||
| 258 | test__clzsi2(0xF5000000, 0); | ||
| 259 | test__clzsi2(0xF6000000, 0); | ||
| 260 | test__clzsi2(0xF7000000, 0); | ||
| 261 | test__clzsi2(0xF8000000, 0); | ||
| 262 | test__clzsi2(0xF9000000, 0); | ||
| 263 | test__clzsi2(0xFA000000, 0); | ||
| 264 | test__clzsi2(0xFB000000, 0); | ||
| 265 | test__clzsi2(0xFC000000, 0); | ||
| 266 | test__clzsi2(0xFD000000, 0); | ||
| 267 | test__clzsi2(0xFE000000, 0); | ||
| 268 | test__clzsi2(0xFF000000, 0); | ||
| 269 | test__clzsi2(0x00000001, 31); | ||
| 270 | test__clzsi2(0x00000002, 30); | ||
| 271 | test__clzsi2(0x00000004, 29); | ||
| 272 | test__clzsi2(0x00000008, 28); | ||
| 273 | test__clzsi2(0x00000010, 27); | ||
| 274 | test__clzsi2(0x00000020, 26); | ||
| 275 | test__clzsi2(0x00000040, 25); | ||
| 276 | test__clzsi2(0x00000080, 24); | ||
| 277 | test__clzsi2(0x00000100, 23); | ||
| 278 | test__clzsi2(0x00000200, 22); | ||
| 279 | test__clzsi2(0x00000400, 21); | ||
| 280 | test__clzsi2(0x00000800, 20); | ||
| 281 | test__clzsi2(0x00001000, 19); | ||
| 282 | test__clzsi2(0x00002000, 18); | ||
| 283 | test__clzsi2(0x00004000, 17); | ||
| 284 | test__clzsi2(0x00008000, 16); | ||
| 285 | test__clzsi2(0x00010000, 15); | ||
| 286 | test__clzsi2(0x00020000, 14); | ||
| 287 | test__clzsi2(0x00040000, 13); | ||
| 288 | test__clzsi2(0x00080000, 12); | ||
| 289 | test__clzsi2(0x00100000, 11); | ||
| 290 | test__clzsi2(0x00200000, 10); | ||
| 291 | test__clzsi2(0x00400000, 9); | ||
| 292 | } | ||
lib/std/special/compiler_rt/compareXf2.zig created+253| ... | @@ -0,0 +1,253 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | const builtin = @import("builtin"); | ||
| 7 | |||
| 8 | const LE = extern enum(i32) { | ||
| 9 | Less = -1, | ||
| 10 | Equal = 0, | ||
| 11 | Greater = 1, | ||
| 12 | Unordered = 1, | ||
| 13 | }; | ||
| 14 | |||
| 15 | const GE = extern enum(i32) { | ||
| 16 | Less = -1, | ||
| 17 | Equal = 0, | ||
| 18 | Greater = 1, | ||
| 19 | Unordered = -1, | ||
| 20 | }; | ||
| 21 | |||
| 22 | pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT { | ||
| 23 | @setRuntimeSafety(builtin.is_test); | ||
| 24 | |||
| 25 | const srep_t = @IntType(true, T.bit_count); | ||
| 26 | const rep_t = @IntType(false, T.bit_count); | ||
| 27 | |||
| 28 | const significandBits = std.math.floatMantissaBits(T); | ||
| 29 | const exponentBits = std.math.floatExponentBits(T); | ||
| 30 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | ||
| 31 | const absMask = signBit - 1; | ||
| 32 | const infRep = @bitCast(rep_t, std.math.inf(T)); | ||
| 33 | |||
| 34 | const aInt = @bitCast(srep_t, a); | ||
| 35 | const bInt = @bitCast(srep_t, b); | ||
| 36 | const aAbs = @bitCast(rep_t, aInt) & absMask; | ||
| 37 | const bAbs = @bitCast(rep_t, bInt) & absMask; | ||
| 38 | |||
| 39 | // If either a or b is NaN, they are unordered. | ||
| 40 | if (aAbs > infRep or bAbs > infRep) return .Unordered; | ||
| 41 | |||
| 42 | // If a and b are both zeros, they are equal. | ||
| 43 | if ((aAbs | bAbs) == 0) return .Equal; | ||
| 44 | |||
| 45 | // If at least one of a and b is positive, we get the same result comparing | ||
| 46 | // a and b as signed integers as we would with a fp_ting-point compare. | ||
| 47 | if ((aInt & bInt) >= 0) { | ||
| 48 | if (aInt < bInt) { | ||
| 49 | return .Less; | ||
| 50 | } else if (aInt == bInt) { | ||
| 51 | return .Equal; | ||
| 52 | } else return .Greater; | ||
| 53 | } | ||
| 54 | |||
| 55 | // Otherwise, both are negative, so we need to flip the sense of the | ||
| 56 | // comparison to get the correct result. (This assumes a twos- or ones- | ||
| 57 | // complement integer representation; if integers are represented in a | ||
| 58 | // sign-magnitude representation, then this flip is incorrect). | ||
| 59 | else { | ||
| 60 | if (aInt > bInt) { | ||
| 61 | return .Less; | ||
| 62 | } else if (aInt == bInt) { | ||
| 63 | return .Equal; | ||
| 64 | } else return .Greater; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | pub fn unordcmp(comptime T: type, a: T, b: T) i32 { | ||
| 69 | @setRuntimeSafety(builtin.is_test); | ||
| 70 | |||
| 71 | const rep_t = @IntType(false, T.bit_count); | ||
| 72 | |||
| 73 | const significandBits = std.math.floatMantissaBits(T); | ||
| 74 | const exponentBits = std.math.floatExponentBits(T); | ||
| 75 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | ||
| 76 | const absMask = signBit - 1; | ||
| 77 | const infRep = @bitCast(rep_t, std.math.inf(T)); | ||
| 78 | |||
| 79 | const aAbs: rep_t = @bitCast(rep_t, a) & absMask; | ||
| 80 | const bAbs: rep_t = @bitCast(rep_t, b) & absMask; | ||
| 81 | |||
| 82 | return @boolToInt(aAbs > infRep or bAbs > infRep); | ||
| 83 | } | ||
| 84 | |||
| 85 | // Comparison between f32 | ||
| 86 | |||
| 87 | pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 88 | @setRuntimeSafety(builtin.is_test); | ||
| 89 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, LE, a, b })); | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 93 | @setRuntimeSafety(builtin.is_test); | ||
| 94 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f32, GE, a, b })); | ||
| 95 | } | ||
| 96 | |||
| 97 | pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 98 | return __lesf2(a, b); | ||
| 99 | } | ||
| 100 | |||
| 101 | pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 102 | return __lesf2(a, b); | ||
| 103 | } | ||
| 104 | |||
| 105 | pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 106 | return __lesf2(a, b); | ||
| 107 | } | ||
| 108 | |||
| 109 | pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 110 | return __gesf2(a, b); | ||
| 111 | } | ||
| 112 | |||
| 113 | // Comparison between f64 | ||
| 114 | |||
| 115 | pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 116 | @setRuntimeSafety(builtin.is_test); | ||
| 117 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, LE, a, b })); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 121 | @setRuntimeSafety(builtin.is_test); | ||
| 122 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f64, GE, a, b })); | ||
| 123 | } | ||
| 124 | |||
| 125 | pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 126 | return __ledf2(a, b); | ||
| 127 | } | ||
| 128 | |||
| 129 | pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 130 | return __ledf2(a, b); | ||
| 131 | } | ||
| 132 | |||
| 133 | pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 134 | return __ledf2(a, b); | ||
| 135 | } | ||
| 136 | |||
| 137 | pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 138 | return __gedf2(a, b); | ||
| 139 | } | ||
| 140 | |||
| 141 | // Comparison between f128 | ||
| 142 | |||
| 143 | pub fn __letf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 144 | @setRuntimeSafety(builtin.is_test); | ||
| 145 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, LE, a, b })); | ||
| 146 | } | ||
| 147 | |||
| 148 | pub fn __getf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 149 | @setRuntimeSafety(builtin.is_test); | ||
| 150 | return @bitCast(i32, @call(.{ .modifier = .always_inline }, cmp, .{ f128, GE, a, b })); | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 154 | return __letf2(a, b); | ||
| 155 | } | ||
| 156 | |||
| 157 | pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 158 | return __letf2(a, b); | ||
| 159 | } | ||
| 160 | |||
| 161 | pub fn __netf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 162 | return __letf2(a, b); | ||
| 163 | } | ||
| 164 | |||
| 165 | pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 166 | return __getf2(a, b); | ||
| 167 | } | ||
| 168 | |||
| 169 | // Unordered comparison between f32/f64/f128 | ||
| 170 | |||
| 171 | pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 { | ||
| 172 | @setRuntimeSafety(builtin.is_test); | ||
| 173 | return @call(.{ .modifier = .always_inline }, unordcmp, .{ f32, a, b }); | ||
| 174 | } | ||
| 175 | |||
| 176 | pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 { | ||
| 177 | @setRuntimeSafety(builtin.is_test); | ||
| 178 | return @call(.{ .modifier = .always_inline }, unordcmp, .{ f64, a, b }); | ||
| 179 | } | ||
| 180 | |||
| 181 | pub fn __unordtf2(a: f128, b: f128) callconv(.C) i32 { | ||
| 182 | @setRuntimeSafety(builtin.is_test); | ||
| 183 | return @call(.{ .modifier = .always_inline }, unordcmp, .{ f128, a, b }); | ||
| 184 | } | ||
| 185 | |||
| 186 | // ARM EABI intrinsics | ||
| 187 | |||
| 188 | pub fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 189 | @setRuntimeSafety(false); | ||
| 190 | return @boolToInt(@call(.{ .modifier = .always_inline }, __eqsf2, .{ a, b }) == 0); | ||
| 191 | } | ||
| 192 | |||
| 193 | pub fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 194 | @setRuntimeSafety(false); | ||
| 195 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ltsf2, .{ a, b }) < 0); | ||
| 196 | } | ||
| 197 | |||
| 198 | pub fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 199 | @setRuntimeSafety(false); | ||
| 200 | return @boolToInt(@call(.{ .modifier = .always_inline }, __lesf2, .{ a, b }) <= 0); | ||
| 201 | } | ||
| 202 | |||
| 203 | pub fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 204 | @setRuntimeSafety(false); | ||
| 205 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gesf2, .{ a, b }) >= 0); | ||
| 206 | } | ||
| 207 | |||
| 208 | pub fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 209 | @setRuntimeSafety(false); | ||
| 210 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gtsf2, .{ a, b }) > 0); | ||
| 211 | } | ||
| 212 | |||
| 213 | pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 { | ||
| 214 | @setRuntimeSafety(false); | ||
| 215 | return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b }); | ||
| 216 | } | ||
| 217 | |||
| 218 | pub fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 219 | @setRuntimeSafety(false); | ||
| 220 | return @boolToInt(@call(.{ .modifier = .always_inline }, __eqdf2, .{ a, b }) == 0); | ||
| 221 | } | ||
| 222 | |||
| 223 | pub fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 224 | @setRuntimeSafety(false); | ||
| 225 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ltdf2, .{ a, b }) < 0); | ||
| 226 | } | ||
| 227 | |||
| 228 | pub fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 229 | @setRuntimeSafety(false); | ||
| 230 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ledf2, .{ a, b }) <= 0); | ||
| 231 | } | ||
| 232 | |||
| 233 | pub fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 234 | @setRuntimeSafety(false); | ||
| 235 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gedf2, .{ a, b }) >= 0); | ||
| 236 | } | ||
| 237 | |||
| 238 | pub fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 239 | @setRuntimeSafety(false); | ||
| 240 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gtdf2, .{ a, b }) > 0); | ||
| 241 | } | ||
| 242 | |||
| 243 | pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 { | ||
| 244 | @setRuntimeSafety(false); | ||
| 245 | return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b }); | ||
| 246 | } | ||
| 247 | |||
| 248 | test "comparesf2" { | ||
| 249 | _ = @import("comparesf2_test.zig"); | ||
| 250 | } | ||
| 251 | test "comparedf2" { | ||
| 252 | _ = @import("comparedf2_test.zig"); | ||
| 253 | } | ||
lib/std/special/compiler_rt/comparedf2.zig deleted-127| ... | @@ -1,127 +0,0 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparedf2.c | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | const builtin = @import("builtin"); | ||
| 7 | const is_test = builtin.is_test; | ||
| 8 | |||
| 9 | const fp_t = f64; | ||
| 10 | const rep_t = u64; | ||
| 11 | const srep_t = i64; | ||
| 12 | |||
| 13 | const typeWidth = rep_t.bit_count; | ||
| 14 | const significandBits = std.math.floatMantissaBits(fp_t); | ||
| 15 | const exponentBits = std.math.floatExponentBits(fp_t); | ||
| 16 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | ||
| 17 | const absMask = signBit - 1; | ||
| 18 | const implicitBit = @as(rep_t, 1) << significandBits; | ||
| 19 | const significandMask = implicitBit - 1; | ||
| 20 | const exponentMask = absMask ^ significandMask; | ||
| 21 | const infRep = @bitCast(rep_t, std.math.inf(fp_t)); | ||
| 22 | |||
| 23 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 24 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 25 | const LE_LESS = @as(c_int, -1); | ||
| 26 | const LE_EQUAL = @as(c_int, 0); | ||
| 27 | const LE_GREATER = @as(c_int, 1); | ||
| 28 | const LE_UNORDERED = @as(c_int, 1); | ||
| 29 | |||
| 30 | pub fn __ledf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 31 | @setRuntimeSafety(is_test); | ||
| 32 | const aInt: srep_t = @bitCast(srep_t, a); | ||
| 33 | const bInt: srep_t = @bitCast(srep_t, b); | ||
| 34 | const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; | ||
| 35 | const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; | ||
| 36 | |||
| 37 | // If either a or b is NaN, they are unordered. | ||
| 38 | if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; | ||
| 39 | |||
| 40 | // If a and b are both zeros, they are equal. | ||
| 41 | if ((aAbs | bAbs) == 0) return LE_EQUAL; | ||
| 42 | |||
| 43 | // If at least one of a and b is positive, we get the same result comparing | ||
| 44 | // a and b as signed integers as we would with a fp_ting-point compare. | ||
| 45 | if ((aInt & bInt) >= 0) { | ||
| 46 | if (aInt < bInt) { | ||
| 47 | return LE_LESS; | ||
| 48 | } else if (aInt == bInt) { | ||
| 49 | return LE_EQUAL; | ||
| 50 | } else return LE_GREATER; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Otherwise, both are negative, so we need to flip the sense of the | ||
| 54 | // comparison to get the correct result. (This assumes a twos- or ones- | ||
| 55 | // complement integer representation; if integers are represented in a | ||
| 56 | // sign-magnitude representation, then this flip is incorrect). | ||
| 57 | else { | ||
| 58 | if (aInt > bInt) { | ||
| 59 | return LE_LESS; | ||
| 60 | } else if (aInt == bInt) { | ||
| 61 | return LE_EQUAL; | ||
| 62 | } else return LE_GREATER; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 67 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 68 | const GE_LESS = @as(c_int, -1); | ||
| 69 | const GE_EQUAL = @as(c_int, 0); | ||
| 70 | const GE_GREATER = @as(c_int, 1); | ||
| 71 | const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED | ||
| 72 | |||
| 73 | pub fn __gedf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 74 | @setRuntimeSafety(is_test); | ||
| 75 | const aInt: srep_t = @bitCast(srep_t, a); | ||
| 76 | const bInt: srep_t = @bitCast(srep_t, b); | ||
| 77 | const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; | ||
| 78 | const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; | ||
| 79 | |||
| 80 | if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; | ||
| 81 | if ((aAbs | bAbs) == 0) return GE_EQUAL; | ||
| 82 | if ((aInt & bInt) >= 0) { | ||
| 83 | if (aInt < bInt) { | ||
| 84 | return GE_LESS; | ||
| 85 | } else if (aInt == bInt) { | ||
| 86 | return GE_EQUAL; | ||
| 87 | } else return GE_GREATER; | ||
| 88 | } else { | ||
| 89 | if (aInt > bInt) { | ||
| 90 | return GE_LESS; | ||
| 91 | } else if (aInt == bInt) { | ||
| 92 | return GE_EQUAL; | ||
| 93 | } else return GE_GREATER; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | pub fn __unorddf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 98 | @setRuntimeSafety(is_test); | ||
| 99 | const aAbs: rep_t = @bitCast(rep_t, a) & absMask; | ||
| 100 | const bAbs: rep_t = @bitCast(rep_t, b) & absMask; | ||
| 101 | return @boolToInt(aAbs > infRep or bAbs > infRep); | ||
| 102 | } | ||
| 103 | |||
| 104 | pub fn __eqdf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 105 | return __ledf2(a, b); | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn __ltdf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 109 | return __ledf2(a, b); | ||
| 110 | } | ||
| 111 | |||
| 112 | pub fn __nedf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 113 | return __ledf2(a, b); | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn __gtdf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 117 | return __gedf2(a, b); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn __aeabi_dcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int { | ||
| 121 | @setRuntimeSafety(false); | ||
| 122 | return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b }); | ||
| 123 | } | ||
| 124 | |||
| 125 | test "import comparedf2" { | ||
| 126 | _ = @import("comparedf2_test.zig"); | ||
| 127 | } | ||
lib/std/special/compiler_rt/comparedf2_test.zig+1-1| ... | @@ -6,7 +6,7 @@ const std = @import("std"); | ... | @@ -6,7 +6,7 @@ const std = @import("std"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 8 | 8 | ||
| 9 | const comparedf2 = @import("comparedf2.zig"); | 9 | const comparedf2 = @import("compareXf2.zig"); |
| 10 | 10 | ||
| 11 | const TestVector = struct { | 11 | const TestVector = struct { |
| 12 | a: f64, | 12 | a: f64, |
lib/std/special/compiler_rt/comparesf2.zig deleted-127| ... | @@ -1,127 +0,0 @@ | ||
| 1 | // Ported from: | ||
| 2 | // | ||
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c | ||
| 4 | |||
| 5 | const std = @import("std"); | ||
| 6 | const builtin = @import("builtin"); | ||
| 7 | const is_test = builtin.is_test; | ||
| 8 | |||
| 9 | const fp_t = f32; | ||
| 10 | const rep_t = u32; | ||
| 11 | const srep_t = i32; | ||
| 12 | |||
| 13 | const typeWidth = rep_t.bit_count; | ||
| 14 | const significandBits = std.math.floatMantissaBits(fp_t); | ||
| 15 | const exponentBits = std.math.floatExponentBits(fp_t); | ||
| 16 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | ||
| 17 | const absMask = signBit - 1; | ||
| 18 | const implicitBit = @as(rep_t, 1) << significandBits; | ||
| 19 | const significandMask = implicitBit - 1; | ||
| 20 | const exponentMask = absMask ^ significandMask; | ||
| 21 | const infRep = @bitCast(rep_t, std.math.inf(fp_t)); | ||
| 22 | |||
| 23 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 24 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 25 | const LE_LESS = @as(c_int, -1); | ||
| 26 | const LE_EQUAL = @as(c_int, 0); | ||
| 27 | const LE_GREATER = @as(c_int, 1); | ||
| 28 | const LE_UNORDERED = @as(c_int, 1); | ||
| 29 | |||
| 30 | pub fn __lesf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 31 | @setRuntimeSafety(is_test); | ||
| 32 | const aInt: srep_t = @bitCast(srep_t, a); | ||
| 33 | const bInt: srep_t = @bitCast(srep_t, b); | ||
| 34 | const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; | ||
| 35 | const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; | ||
| 36 | |||
| 37 | // If either a or b is NaN, they are unordered. | ||
| 38 | if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; | ||
| 39 | |||
| 40 | // If a and b are both zeros, they are equal. | ||
| 41 | if ((aAbs | bAbs) == 0) return LE_EQUAL; | ||
| 42 | |||
| 43 | // If at least one of a and b is positive, we get the same result comparing | ||
| 44 | // a and b as signed integers as we would with a fp_ting-point compare. | ||
| 45 | if ((aInt & bInt) >= 0) { | ||
| 46 | if (aInt < bInt) { | ||
| 47 | return LE_LESS; | ||
| 48 | } else if (aInt == bInt) { | ||
| 49 | return LE_EQUAL; | ||
| 50 | } else return LE_GREATER; | ||
| 51 | } | ||
| 52 | |||
| 53 | // Otherwise, both are negative, so we need to flip the sense of the | ||
| 54 | // comparison to get the correct result. (This assumes a twos- or ones- | ||
| 55 | // complement integer representation; if integers are represented in a | ||
| 56 | // sign-magnitude representation, then this flip is incorrect). | ||
| 57 | else { | ||
| 58 | if (aInt > bInt) { | ||
| 59 | return LE_LESS; | ||
| 60 | } else if (aInt == bInt) { | ||
| 61 | return LE_EQUAL; | ||
| 62 | } else return LE_GREATER; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 67 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 68 | const GE_LESS = @as(c_int, -1); | ||
| 69 | const GE_EQUAL = @as(c_int, 0); | ||
| 70 | const GE_GREATER = @as(c_int, 1); | ||
| 71 | const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED | ||
| 72 | |||
| 73 | pub fn __gesf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 74 | @setRuntimeSafety(is_test); | ||
| 75 | const aInt: srep_t = @bitCast(srep_t, a); | ||
| 76 | const bInt: srep_t = @bitCast(srep_t, b); | ||
| 77 | const aAbs: rep_t = @bitCast(rep_t, aInt) & absMask; | ||
| 78 | const bAbs: rep_t = @bitCast(rep_t, bInt) & absMask; | ||
| 79 | |||
| 80 | if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; | ||
| 81 | if ((aAbs | bAbs) == 0) return GE_EQUAL; | ||
| 82 | if ((aInt & bInt) >= 0) { | ||
| 83 | if (aInt < bInt) { | ||
| 84 | return GE_LESS; | ||
| 85 | } else if (aInt == bInt) { | ||
| 86 | return GE_EQUAL; | ||
| 87 | } else return GE_GREATER; | ||
| 88 | } else { | ||
| 89 | if (aInt > bInt) { | ||
| 90 | return GE_LESS; | ||
| 91 | } else if (aInt == bInt) { | ||
| 92 | return GE_EQUAL; | ||
| 93 | } else return GE_GREATER; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | pub fn __unordsf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 98 | @setRuntimeSafety(is_test); | ||
| 99 | const aAbs: rep_t = @bitCast(rep_t, a) & absMask; | ||
| 100 | const bAbs: rep_t = @bitCast(rep_t, b) & absMask; | ||
| 101 | return @boolToInt(aAbs > infRep or bAbs > infRep); | ||
| 102 | } | ||
| 103 | |||
| 104 | pub fn __eqsf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 105 | return __lesf2(a, b); | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn __ltsf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 109 | return __lesf2(a, b); | ||
| 110 | } | ||
| 111 | |||
| 112 | pub fn __nesf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 113 | return __lesf2(a, b); | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn __gtsf2(a: fp_t, b: fp_t) callconv(.C) c_int { | ||
| 117 | return __gesf2(a, b); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn __aeabi_fcmpun(a: fp_t, b: fp_t) callconv(.AAPCS) c_int { | ||
| 121 | @setRuntimeSafety(false); | ||
| 122 | return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b }); | ||
| 123 | } | ||
| 124 | |||
| 125 | test "import comparesf2" { | ||
| 126 | _ = @import("comparesf2_test.zig"); | ||
| 127 | } | ||
lib/std/special/compiler_rt/comparesf2_test.zig+1-1| ... | @@ -6,7 +6,7 @@ const std = @import("std"); | ... | @@ -6,7 +6,7 @@ const std = @import("std"); |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const is_test = builtin.is_test; | 7 | const is_test = builtin.is_test; |
| 8 | 8 | ||
| 9 | const comparesf2 = @import("comparesf2.zig"); | 9 | const comparesf2 = @import("compareXf2.zig"); |
| 10 | 10 | ||
| 11 | const TestVector = struct { | 11 | const TestVector = struct { |
| 12 | a: f32, | 12 | a: f32, |
lib/std/special/compiler_rt/comparetf2.zig deleted-99| ... | @@ -1,99 +0,0 @@ | ||
| 1 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 2 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 3 | const LE_LESS = @as(c_int, -1); | ||
| 4 | const LE_EQUAL = @as(c_int, 0); | ||
| 5 | const LE_GREATER = @as(c_int, 1); | ||
| 6 | const LE_UNORDERED = @as(c_int, 1); | ||
| 7 | |||
| 8 | const rep_t = u128; | ||
| 9 | const srep_t = i128; | ||
| 10 | |||
| 11 | const typeWidth = rep_t.bit_count; | ||
| 12 | const significandBits = 112; | ||
| 13 | const exponentBits = (typeWidth - significandBits - 1); | ||
| 14 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | ||
| 15 | const absMask = signBit - 1; | ||
| 16 | const implicitBit = @as(rep_t, 1) << significandBits; | ||
| 17 | const significandMask = implicitBit - 1; | ||
| 18 | const exponentMask = absMask ^ significandMask; | ||
| 19 | const infRep = exponentMask; | ||
| 20 | |||
| 21 | const builtin = @import("builtin"); | ||
| 22 | const is_test = builtin.is_test; | ||
| 23 | |||
| 24 | pub fn __letf2(a: f128, b: f128) callconv(.C) c_int { | ||
| 25 | @setRuntimeSafety(is_test); | ||
| 26 | |||
| 27 | const aInt = @bitCast(rep_t, a); | ||
| 28 | const bInt = @bitCast(rep_t, b); | ||
| 29 | |||
| 30 | const aAbs: rep_t = aInt & absMask; | ||
| 31 | const bAbs: rep_t = bInt & absMask; | ||
| 32 | |||
| 33 | // If either a or b is NaN, they are unordered. | ||
| 34 | if (aAbs > infRep or bAbs > infRep) return LE_UNORDERED; | ||
| 35 | |||
| 36 | // If a and b are both zeros, they are equal. | ||
| 37 | if ((aAbs | bAbs) == 0) return LE_EQUAL; | ||
| 38 | |||
| 39 | // If at least one of a and b is positive, we get the same result comparing | ||
| 40 | // a and b as signed integers as we would with a floating-point compare. | ||
| 41 | return if ((aInt & bInt) >= 0) | ||
| 42 | if (aInt < bInt) | ||
| 43 | LE_LESS | ||
| 44 | else if (aInt == bInt) | ||
| 45 | LE_EQUAL | ||
| 46 | else | ||
| 47 | LE_GREATER | ||
| 48 | else | ||
| 49 | // Otherwise, both are negative, so we need to flip the sense of the | ||
| 50 | // comparison to get the correct result. (This assumes a twos- or ones- | ||
| 51 | // complement integer representation; if integers are represented in a | ||
| 52 | // sign-magnitude representation, then this flip is incorrect). | ||
| 53 | if (aInt > bInt) | ||
| 54 | LE_LESS | ||
| 55 | else if (aInt == bInt) | ||
| 56 | LE_EQUAL | ||
| 57 | else | ||
| 58 | LE_GREATER; | ||
| 59 | } | ||
| 60 | |||
| 61 | // TODO https://github.com/ziglang/zig/issues/641 | ||
| 62 | // and then make the return types of some of these functions the enum instead of c_int | ||
| 63 | const GE_LESS = @as(c_int, -1); | ||
| 64 | const GE_EQUAL = @as(c_int, 0); | ||
| 65 | const GE_GREATER = @as(c_int, 1); | ||
| 66 | const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED | ||
| 67 | |||
| 68 | pub fn __getf2(a: f128, b: f128) callconv(.C) c_int { | ||
| 69 | @setRuntimeSafety(is_test); | ||
| 70 | |||
| 71 | const aInt = @bitCast(srep_t, a); | ||
| 72 | const bInt = @bitCast(srep_t, b); | ||
| 73 | const aAbs = @bitCast(rep_t, aInt) & absMask; | ||
| 74 | const bAbs = @bitCast(rep_t, bInt) & absMask; | ||
| 75 | |||
| 76 | if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED; | ||
| 77 | if ((aAbs | bAbs) == 0) return GE_EQUAL; | ||
| 78 | return if ((aInt & bInt) >= 0) | ||
| 79 | if (aInt < bInt) | ||
| 80 | GE_LESS | ||
| 81 | else if (aInt == bInt) | ||
| 82 | GE_EQUAL | ||
| 83 | else | ||
| 84 | GE_GREATER | ||
| 85 | else if (aInt > bInt) | ||
| 86 | GE_LESS | ||
| 87 | else if (aInt == bInt) | ||
| 88 | GE_EQUAL | ||
| 89 | else | ||
| 90 | GE_GREATER; | ||
| 91 | } | ||
| 92 | |||
| 93 | pub fn __unordtf2(a: f128, b: f128) callconv(.C) c_int { | ||
| 94 | @setRuntimeSafety(is_test); | ||
| 95 | |||
| 96 | const aAbs = @bitCast(rep_t, a) & absMask; | ||
| 97 | const bAbs = @bitCast(rep_t, b) & absMask; | ||
| 98 | return @boolToInt(aAbs > infRep or bAbs > infRep); | ||
| 99 | } | ||
lib/std/start.zig+2-11| ... | @@ -8,16 +8,7 @@ const uefi = std.os.uefi; | ... | @@ -8,16 +8,7 @@ const uefi = std.os.uefi; |
| 8 | 8 | ||
| 9 | var starting_stack_ptr: [*]usize = undefined; | 9 | var starting_stack_ptr: [*]usize = undefined; |
| 10 | 10 | ||
| 11 | const is_wasm = switch (builtin.arch) { | 11 | const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start"; |
| 12 | .wasm32, .wasm64 => true, | ||
| 13 | else => false, | ||
| 14 | }; | ||
| 15 | |||
| 16 | const is_mips = switch (builtin.arch) { | ||
| 17 | .mips, .mipsel, .mips64, .mips64el => true, | ||
| 18 | else => false, | ||
| 19 | }; | ||
| 20 | const start_sym_name = if (is_mips) "__start" else "_start"; | ||
| 21 | 12 | ||
| 22 | comptime { | 13 | comptime { |
| 23 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { | 14 | if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { |
| ... | @@ -35,7 +26,7 @@ comptime { | ... | @@ -35,7 +26,7 @@ comptime { |
| 35 | } | 26 | } |
| 36 | } else if (builtin.os == .uefi) { | 27 | } else if (builtin.os == .uefi) { |
| 37 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); | 28 | if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" }); |
| 38 | } else if (is_wasm and builtin.os == .freestanding) { | 29 | } else if (builtin.arch.isWasm() and builtin.os == .freestanding) { |
| 39 | if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); | 30 | if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); |
| 40 | } else if (builtin.os != .other and builtin.os != .freestanding) { | 31 | } else if (builtin.os != .other and builtin.os != .freestanding) { |
| 41 | if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); | 32 | if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); |
lib/std/target.zig+38| ... | @@ -125,6 +125,16 @@ pub const Target = union(enum) { | ... | @@ -125,6 +125,16 @@ pub const Target = union(enum) { |
| 125 | v5, | 125 | v5, |
| 126 | v5te, | 126 | v5te, |
| 127 | v4t, | 127 | v4t, |
| 128 | |||
| 129 | pub fn version(version: Arm32) comptime_int { | ||
| 130 | return switch (version) { | ||
| 131 | .v8_5a, .v8_4a, .v8_3a, .v8_2a, .v8_1a, .v8, .v8r, .v8m_baseline, .v8m_mainline, .v8_1m_mainline => 8, | ||
| 132 | .v7, .v7em, .v7m, .v7s, .v7k, .v7ve => 7, | ||
| 133 | .v6, .v6m, .v6k, .v6t2 => 6, | ||
| 134 | .v5, .v5te => 5, | ||
| 135 | .v4t => 4, | ||
| 136 | }; | ||
| 137 | } | ||
| 128 | }; | 138 | }; |
| 129 | pub const Arm64 = enum { | 139 | pub const Arm64 = enum { |
| 130 | v8_5a, | 140 | v8_5a, |
| ... | @@ -146,6 +156,34 @@ pub const Target = union(enum) { | ... | @@ -146,6 +156,34 @@ pub const Target = union(enum) { |
| 146 | r6, | 156 | r6, |
| 147 | }; | 157 | }; |
| 148 | 158 | ||
| 159 | pub fn isARM(arch: Arch) bool { | ||
| 160 | return switch (arch) { | ||
| 161 | .arm, .armeb => true, | ||
| 162 | else => false, | ||
| 163 | }; | ||
| 164 | } | ||
| 165 | |||
| 166 | pub fn isThumb(arch: Arch) bool { | ||
| 167 | return switch (arch) { | ||
| 168 | .thumb, .thumbeb => true, | ||
| 169 | else => false, | ||
| 170 | }; | ||
| 171 | } | ||
| 172 | |||
| 173 | pub fn isWasm(arch: Arch) bool { | ||
| 174 | return switch (arch) { | ||
| 175 | .wasm32, .wasm64 => true, | ||
| 176 | else => false, | ||
| 177 | }; | ||
| 178 | } | ||
| 179 | |||
| 180 | pub fn isMIPS(arch: Arch) bool { | ||
| 181 | return switch (arch) { | ||
| 182 | .mips, .mipsel, .mips64, .mips64el => true, | ||
| 183 | else => false, | ||
| 184 | }; | ||
| 185 | } | ||
| 186 | |||
| 149 | pub fn toElfMachine(arch: Arch) std.elf.EM { | 187 | pub fn toElfMachine(arch: Arch) std.elf.EM { |
| 150 | return switch (arch) { | 188 | return switch (arch) { |
| 151 | .avr => ._AVR, | 189 | .avr => ._AVR, |
src-self-hosted/translate_c.zig+42-51| ... | @@ -289,8 +289,7 @@ pub fn translate( | ... | @@ -289,8 +289,7 @@ pub fn translate( |
| 289 | tree.errors = ast.Tree.ErrorList.init(arena); | 289 | tree.errors = ast.Tree.ErrorList.init(arena); |
| 290 | 290 | ||
| 291 | tree.root_node = try arena.create(ast.Node.Root); | 291 | tree.root_node = try arena.create(ast.Node.Root); |
| 292 | tree.root_node.* = ast.Node.Root{ | 292 | tree.root_node.* = .{ |
| 293 | .base = ast.Node{ .id = ast.Node.Id.Root }, | ||
| 294 | .decls = ast.Node.Root.DeclList.init(arena), | 293 | .decls = ast.Node.Root.DeclList.init(arena), |
| 295 | // initialized with the eof token at the end | 294 | // initialized with the eof token at the end |
| 296 | .eof_token = undefined, | 295 | .eof_token = undefined, |
| ... | @@ -440,7 +439,6 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { | ... | @@ -440,7 +439,6 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void { |
| 440 | .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), | 439 | .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}), |
| 441 | .Auto => unreachable, // Not legal on functions | 440 | .Auto => unreachable, // Not legal on functions |
| 442 | .Register => unreachable, // Not legal on functions | 441 | .Register => unreachable, // Not legal on functions |
| 443 | else => unreachable, | ||
| 444 | }, | 442 | }, |
| 445 | }; | 443 | }; |
| 446 | 444 | ||
| ... | @@ -877,25 +875,23 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -877,25 +875,23 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 877 | // types, while that's not ISO-C compliant many compilers allow this and | 875 | // types, while that's not ISO-C compliant many compilers allow this and |
| 878 | // default to the usual integer type used for all the enums. | 876 | // default to the usual integer type used for all the enums. |
| 879 | 877 | ||
| 880 | // TODO only emit this tag type if the enum tag type is not the default. | 878 | // default to c_int since msvc and gcc default to different types |
| 881 | // I don't know what the default is, need to figure out how clang is deciding. | 879 | _ = try appendToken(c, .LParen, "("); |
| 882 | // it appears to at least be different across gcc/msvc | 880 | container_node.init_arg_expr = .{ |
| 883 | if (int_type.ptr != null and | 881 | .Type = if (int_type.ptr != null and |
| 884 | !isCBuiltinType(int_type, .UInt) and | 882 | !isCBuiltinType(int_type, .UInt) and |
| 885 | !isCBuiltinType(int_type, .Int)) | 883 | !isCBuiltinType(int_type, .Int)) |
| 886 | { | 884 | transQualType(rp, int_type, enum_loc) catch |err| switch (err) { |
| 887 | _ = try appendToken(c, .LParen, "("); | ||
| 888 | container_node.init_arg_expr = .{ | ||
| 889 | .Type = transQualType(rp, int_type, enum_loc) catch |err| switch (err) { | ||
| 890 | error.UnsupportedType => { | 885 | error.UnsupportedType => { |
| 891 | try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{}); | 886 | try failDecl(c, enum_loc, name, "unable to translate enum tag type", .{}); |
| 892 | return null; | 887 | return null; |
| 893 | }, | 888 | }, |
| 894 | else => |e| return e, | 889 | else => |e| return e, |
| 895 | }, | 890 | } |
| 896 | }; | 891 | else |
| 897 | _ = try appendToken(c, .RParen, ")"); | 892 | try transCreateNodeIdentifier(c, "c_int"), |
| 898 | } | 893 | }; |
| 894 | _ = try appendToken(c, .RParen, ")"); | ||
| 899 | 895 | ||
| 900 | container_node.lbrace_token = try appendToken(c, .LBrace, "{"); | 896 | container_node.lbrace_token = try appendToken(c, .LBrace, "{"); |
| 901 | 897 | ||
| ... | @@ -953,6 +949,19 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -953,6 +949,19 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 953 | tld_node.semicolon_token = try appendToken(c, .Semicolon, ";"); | 949 | tld_node.semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 954 | try addTopLevelDecl(c, field_name, &tld_node.base); | 950 | try addTopLevelDecl(c, field_name, &tld_node.base); |
| 955 | } | 951 | } |
| 952 | // make non exhaustive | ||
| 953 | const field_node = try c.a().create(ast.Node.ContainerField); | ||
| 954 | field_node.* = .{ | ||
| 955 | .doc_comments = null, | ||
| 956 | .comptime_token = null, | ||
| 957 | .name_token = try appendIdentifier(c, "_"), | ||
| 958 | .type_expr = null, | ||
| 959 | .value_expr = null, | ||
| 960 | .align_expr = null, | ||
| 961 | }; | ||
| 962 | |||
| 963 | try container_node.fields_and_decls.push(&field_node.base); | ||
| 964 | _ = try appendToken(c, .Comma, ","); | ||
| 956 | container_node.rbrace_token = try appendToken(c, .RBrace, "}"); | 965 | container_node.rbrace_token = try appendToken(c, .RBrace, "}"); |
| 957 | 966 | ||
| 958 | break :blk &container_node.base; | 967 | break :blk &container_node.base; |
| ... | @@ -1231,18 +1240,6 @@ fn transBinaryOperator( | ... | @@ -1231,18 +1240,6 @@ fn transBinaryOperator( |
| 1231 | op_id = .BitOr; | 1240 | op_id = .BitOr; |
| 1232 | op_token = try appendToken(rp.c, .Pipe, "|"); | 1241 | op_token = try appendToken(rp.c, .Pipe, "|"); |
| 1233 | }, | 1242 | }, |
| 1234 | .Assign, | ||
| 1235 | .MulAssign, | ||
| 1236 | .DivAssign, | ||
| 1237 | .RemAssign, | ||
| 1238 | .AddAssign, | ||
| 1239 | .SubAssign, | ||
| 1240 | .ShlAssign, | ||
| 1241 | .ShrAssign, | ||
| 1242 | .AndAssign, | ||
| 1243 | .XorAssign, | ||
| 1244 | .OrAssign, | ||
| 1245 | => unreachable, | ||
| 1246 | else => unreachable, | 1243 | else => unreachable, |
| 1247 | } | 1244 | } |
| 1248 | 1245 | ||
| ... | @@ -1678,7 +1675,6 @@ fn transStringLiteral( | ... | @@ -1678,7 +1675,6 @@ fn transStringLiteral( |
| 1678 | "TODO: support string literal kind {}", | 1675 | "TODO: support string literal kind {}", |
| 1679 | .{kind}, | 1676 | .{kind}, |
| 1680 | ), | 1677 | ), |
| 1681 | else => unreachable, | ||
| 1682 | } | 1678 | } |
| 1683 | } | 1679 | } |
| 1684 | 1680 | ||
| ... | @@ -2206,6 +2202,19 @@ fn transDoWhileLoop( | ... | @@ -2206,6 +2202,19 @@ fn transDoWhileLoop( |
| 2206 | .id = .Loop, | 2202 | .id = .Loop, |
| 2207 | }; | 2203 | }; |
| 2208 | 2204 | ||
| 2205 | // if (!cond) break; | ||
| 2206 | const if_node = try transCreateNodeIf(rp.c); | ||
| 2207 | var cond_scope = Scope{ | ||
| 2208 | .parent = scope, | ||
| 2209 | .id = .Condition, | ||
| 2210 | }; | ||
| 2211 | const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); | ||
| 2212 | prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true); | ||
| 2213 | _ = try appendToken(rp.c, .RParen, ")"); | ||
| 2214 | if_node.condition = &prefix_op.base; | ||
| 2215 | if_node.body = &(try transCreateNodeBreak(rp.c, null)).base; | ||
| 2216 | _ = try appendToken(rp.c, .Semicolon, ";"); | ||
| 2217 | |||
| 2209 | const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: { | 2218 | const body_node = if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == .CompoundStmtClass) blk: { |
| 2210 | // there's already a block in C, so we'll append our condition to it. | 2219 | // there's already a block in C, so we'll append our condition to it. |
| 2211 | // c: do { | 2220 | // c: do { |
| ... | @@ -2217,10 +2226,7 @@ fn transDoWhileLoop( | ... | @@ -2217,10 +2226,7 @@ fn transDoWhileLoop( |
| 2217 | // zig: b; | 2226 | // zig: b; |
| 2218 | // zig: if (!cond) break; | 2227 | // zig: if (!cond) break; |
| 2219 | // zig: } | 2228 | // zig: } |
| 2220 | const body = (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?; | 2229 | break :blk (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?; |
| 2221 | // if this is used as an expression in Zig it needs to be immediately followed by a semicolon | ||
| 2222 | _ = try appendToken(rp.c, .Semicolon, ";"); | ||
| 2223 | break :blk body; | ||
| 2224 | } else blk: { | 2230 | } else blk: { |
| 2225 | // the C statement is without a block, so we need to create a block to contain it. | 2231 | // the C statement is without a block, so we need to create a block to contain it. |
| 2226 | // c: do | 2232 | // c: do |
| ... | @@ -2236,19 +2242,6 @@ fn transDoWhileLoop( | ... | @@ -2236,19 +2242,6 @@ fn transDoWhileLoop( |
| 2236 | break :blk block; | 2242 | break :blk block; |
| 2237 | }; | 2243 | }; |
| 2238 | 2244 | ||
| 2239 | // if (!cond) break; | ||
| 2240 | const if_node = try transCreateNodeIf(rp.c); | ||
| 2241 | var cond_scope = Scope{ | ||
| 2242 | .parent = scope, | ||
| 2243 | .id = .Condition, | ||
| 2244 | }; | ||
| 2245 | const prefix_op = try transCreateNodePrefixOp(rp.c, .BoolNot, .Bang, "!"); | ||
| 2246 | prefix_op.rhs = try transBoolExpr(rp, &cond_scope, @ptrCast(*const ZigClangExpr, ZigClangDoStmt_getCond(stmt)), .used, .r_value, true); | ||
| 2247 | _ = try appendToken(rp.c, .RParen, ")"); | ||
| 2248 | if_node.condition = &prefix_op.base; | ||
| 2249 | if_node.body = &(try transCreateNodeBreak(rp.c, null)).base; | ||
| 2250 | _ = try appendToken(rp.c, .Semicolon, ";"); | ||
| 2251 | |||
| 2252 | try body_node.statements.push(&if_node.base); | 2245 | try body_node.statements.push(&if_node.base); |
| 2253 | if (new) | 2246 | if (new) |
| 2254 | body_node.rbrace = try appendToken(rp.c, .RBrace, "}"); | 2247 | body_node.rbrace = try appendToken(rp.c, .RBrace, "}"); |
| ... | @@ -4783,8 +4776,7 @@ fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex { | ... | @@ -4783,8 +4776,7 @@ fn appendIdentifier(c: *Context, name: []const u8) !ast.TokenIndex { |
| 4783 | fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node { | 4776 | fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node { |
| 4784 | const token_index = try appendIdentifier(c, name); | 4777 | const token_index = try appendIdentifier(c, name); |
| 4785 | const identifier = try c.a().create(ast.Node.Identifier); | 4778 | const identifier = try c.a().create(ast.Node.Identifier); |
| 4786 | identifier.* = ast.Node.Identifier{ | 4779 | identifier.* = .{ |
| 4787 | .base = ast.Node{ .id = ast.Node.Id.Identifier }, | ||
| 4788 | .token = token_index, | 4780 | .token = token_index, |
| 4789 | }; | 4781 | }; |
| 4790 | return &identifier.base; | 4782 | return &identifier.base; |
| ... | @@ -4923,8 +4915,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u | ... | @@ -4923,8 +4915,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u |
| 4923 | 4915 | ||
| 4924 | const token_index = try appendToken(c, .Keyword_var, "var"); | 4916 | const token_index = try appendToken(c, .Keyword_var, "var"); |
| 4925 | const identifier = try c.a().create(ast.Node.Identifier); | 4917 | const identifier = try c.a().create(ast.Node.Identifier); |
| 4926 | identifier.* = ast.Node.Identifier{ | 4918 | identifier.* = .{ |
| 4927 | .base = ast.Node{ .id = ast.Node.Id.Identifier }, | ||
| 4928 | .token = token_index, | 4919 | .token = token_index, |
| 4929 | }; | 4920 | }; |
| 4930 | 4921 |
src/all_types.hpp+6| ... | @@ -358,6 +358,8 @@ struct LazyValueSizeOf { | ... | @@ -358,6 +358,8 @@ struct LazyValueSizeOf { |
| 358 | 358 | ||
| 359 | IrAnalyze *ira; | 359 | IrAnalyze *ira; |
| 360 | IrInstruction *target_type; | 360 | IrInstruction *target_type; |
| 361 | |||
| 362 | bool bit_size; | ||
| 361 | }; | 363 | }; |
| 362 | 364 | ||
| 363 | struct LazyValueSliceType { | 365 | struct LazyValueSliceType { |
| ... | @@ -1383,6 +1385,7 @@ struct ZigTypeEnum { | ... | @@ -1383,6 +1385,7 @@ struct ZigTypeEnum { |
| 1383 | ContainerLayout layout; | 1385 | ContainerLayout layout; |
| 1384 | ResolveStatus resolve_status; | 1386 | ResolveStatus resolve_status; |
| 1385 | 1387 | ||
| 1388 | bool non_exhaustive; | ||
| 1386 | bool resolve_loop_flag; | 1389 | bool resolve_loop_flag; |
| 1387 | }; | 1390 | }; |
| 1388 | 1391 | ||
| ... | @@ -1754,6 +1757,7 @@ enum BuiltinFnId { | ... | @@ -1754,6 +1757,7 @@ enum BuiltinFnId { |
| 1754 | BuiltinFnIdFrameSize, | 1757 | BuiltinFnIdFrameSize, |
| 1755 | BuiltinFnIdAs, | 1758 | BuiltinFnIdAs, |
| 1756 | BuiltinFnIdCall, | 1759 | BuiltinFnIdCall, |
| 1760 | BuiltinFnIdBitSizeof, | ||
| 1757 | }; | 1761 | }; |
| 1758 | 1762 | ||
| 1759 | struct BuiltinFnEntry { | 1763 | struct BuiltinFnEntry { |
| ... | @@ -3146,6 +3150,7 @@ struct IrInstructionAsmGen { | ... | @@ -3146,6 +3150,7 @@ struct IrInstructionAsmGen { |
| 3146 | struct IrInstructionSizeOf { | 3150 | struct IrInstructionSizeOf { |
| 3147 | IrInstruction base; | 3151 | IrInstruction base; |
| 3148 | 3152 | ||
| 3153 | bool bit_size; | ||
| 3149 | IrInstruction *type_value; | 3154 | IrInstruction *type_value; |
| 3150 | }; | 3155 | }; |
| 3151 | 3156 | ||
| ... | @@ -3665,6 +3670,7 @@ struct IrInstructionCheckSwitchProngs { | ... | @@ -3665,6 +3670,7 @@ struct IrInstructionCheckSwitchProngs { |
| 3665 | IrInstructionCheckSwitchProngsRange *ranges; | 3670 | IrInstructionCheckSwitchProngsRange *ranges; |
| 3666 | size_t range_count; | 3671 | size_t range_count; |
| 3667 | bool have_else_prong; | 3672 | bool have_else_prong; |
| 3673 | bool have_underscore_prong; | ||
| 3668 | }; | 3674 | }; |
| 3669 | 3675 | ||
| 3670 | struct IrInstructionCheckStatementIsVoid { | 3676 | struct IrInstructionCheckStatementIsVoid { |
src/analyze.cpp+33-9| ... | @@ -2569,15 +2569,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2569,15 +2569,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2569 | return ErrorSemanticAnalyzeFail; | 2569 | return ErrorSemanticAnalyzeFail; |
| 2570 | } | 2570 | } |
| 2571 | 2571 | ||
| 2572 | enum_type->data.enumeration.src_field_count = field_count; | ||
| 2573 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | ||
| 2574 | enum_type->data.enumeration.fields_by_name.init(field_count); | ||
| 2575 | |||
| 2576 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; | 2572 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 2577 | 2573 | ||
| 2578 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | ||
| 2579 | occupied_tag_values.init(field_count); | ||
| 2580 | |||
| 2581 | ZigType *tag_int_type; | 2574 | ZigType *tag_int_type; |
| 2582 | if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { | 2575 | if (enum_type->data.enumeration.layout == ContainerLayoutExtern) { |
| 2583 | tag_int_type = get_c_int_type(g, CIntTypeInt); | 2576 | tag_int_type = get_c_int_type(g, CIntTypeInt); |
| ... | @@ -2612,13 +2605,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2612,13 +2605,14 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2612 | buf_ptr(&wanted_tag_int_type->name))); | 2605 | buf_ptr(&wanted_tag_int_type->name))); |
| 2613 | add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr, | 2606 | add_error_note(g, msg, decl_node->data.container_decl.init_arg_expr, |
| 2614 | buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid")); | 2607 | buf_sprintf("any integral type of size 8, 16, 32, 64 or 128 bit is valid")); |
| 2615 | return ErrorNone; | 2608 | return ErrorSemanticAnalyzeFail; |
| 2616 | } | 2609 | } |
| 2617 | } | 2610 | } |
| 2618 | tag_int_type = wanted_tag_int_type; | 2611 | tag_int_type = wanted_tag_int_type; |
| 2619 | } | 2612 | } |
| 2620 | } | 2613 | } |
| 2621 | 2614 | ||
| 2615 | enum_type->data.enumeration.non_exhaustive = false; | ||
| 2622 | enum_type->data.enumeration.tag_int_type = tag_int_type; | 2616 | enum_type->data.enumeration.tag_int_type = tag_int_type; |
| 2623 | enum_type->size_in_bits = tag_int_type->size_in_bits; | 2617 | enum_type->size_in_bits = tag_int_type->size_in_bits; |
| 2624 | enum_type->abi_size = tag_int_type->abi_size; | 2618 | enum_type->abi_size = tag_int_type->abi_size; |
| ... | @@ -2627,6 +2621,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { | ... | @@ -2627,6 +2621,31 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2627 | BigInt bi_one; | 2621 | BigInt bi_one; |
| 2628 | bigint_init_unsigned(&bi_one, 1); | 2622 | bigint_init_unsigned(&bi_one, 1); |
| 2629 | 2623 | ||
| 2624 | AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1); | ||
| 2625 | if (buf_eql_str(last_field_node->data.struct_field.name, "_")) { | ||
| 2626 | field_count -= 1; | ||
| 2627 | if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) { | ||
| 2628 | add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value")); | ||
| 2629 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | ||
| 2630 | } | ||
| 2631 | if (decl_node->data.container_decl.init_arg_expr == nullptr) { | ||
| 2632 | add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size")); | ||
| 2633 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | ||
| 2634 | } | ||
| 2635 | if (last_field_node->data.struct_field.value != nullptr) { | ||
| 2636 | add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum")); | ||
| 2637 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | ||
| 2638 | } | ||
| 2639 | enum_type->data.enumeration.non_exhaustive = true; | ||
| 2640 | } | ||
| 2641 | |||
| 2642 | enum_type->data.enumeration.src_field_count = field_count; | ||
| 2643 | enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); | ||
| 2644 | enum_type->data.enumeration.fields_by_name.init(field_count); | ||
| 2645 | |||
| 2646 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {}; | ||
| 2647 | occupied_tag_values.init(field_count); | ||
| 2648 | |||
| 2630 | TypeEnumField *last_enum_field = nullptr; | 2649 | TypeEnumField *last_enum_field = nullptr; |
| 2631 | 2650 | ||
| 2632 | for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { | 2651 | 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) { | ... | @@ -2648,6 +2667,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2648 | buf_sprintf("consider 'union(enum)' here")); | 2667 | buf_sprintf("consider 'union(enum)' here")); |
| 2649 | } | 2668 | } |
| 2650 | 2669 | ||
| 2670 | if (buf_eql_str(type_enum_field->name, "_")) { | ||
| 2671 | add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last")); | ||
| 2672 | enum_type->data.enumeration.resolve_status = ResolveStatusInvalid; | ||
| 2673 | } | ||
| 2674 | |||
| 2651 | auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); | 2675 | auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field); |
| 2652 | if (field_entry != nullptr) { | 2676 | if (field_entry != nullptr) { |
| 2653 | ErrorMsg *msg = add_node_error(g, field_node, | 2677 | ErrorMsg *msg = add_node_error(g, field_node, |
| ... | @@ -8288,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu | ... | @@ -8288,7 +8312,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatu |
| 8288 | 8312 | ||
| 8289 | uint32_t field_count = enum_type->data.enumeration.src_field_count; | 8313 | uint32_t field_count = enum_type->data.enumeration.src_field_count; |
| 8290 | 8314 | ||
| 8291 | assert(enum_type->data.enumeration.fields); | 8315 | assert(field_count == 0 || enum_type->data.enumeration.fields != nullptr); |
| 8292 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); | 8316 | ZigLLVMDIEnumerator **di_enumerators = allocate<ZigLLVMDIEnumerator*>(field_count); |
| 8293 | 8317 | ||
| 8294 | for (uint32_t i = 0; i < field_count; i += 1) { | 8318 | for (uint32_t i = 0; i < field_count; i += 1) { |
src/codegen.cpp+7-1| ... | @@ -3356,7 +3356,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, | ... | @@ -3356,7 +3356,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, |
| 3356 | LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | 3356 | LLVMValueRef tag_int_value = gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), |
| 3357 | instruction->target->value->type, tag_int_type, target_val); | 3357 | instruction->target->value->type, tag_int_type, target_val); |
| 3358 | 3358 | ||
| 3359 | if (ir_want_runtime_safety(g, &instruction->base) && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { | 3359 | if (ir_want_runtime_safety(g, &instruction->base) && !wanted_type->data.enumeration.non_exhaustive) { |
| 3360 | LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue"); | 3360 | LLVMBasicBlockRef bad_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadValue"); |
| 3361 | LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue"); | 3361 | LLVMBasicBlockRef ok_value_block = LLVMAppendBasicBlock(g->cur_fn_val, "OkValue"); |
| 3362 | size_t field_count = wanted_type->data.enumeration.src_field_count; | 3362 | 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 | ... | @@ -5065,6 +5065,11 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable |
| 5065 | { | 5065 | { |
| 5066 | ZigType *enum_type = instruction->target->value->type; | 5066 | ZigType *enum_type = instruction->target->value->type; |
| 5067 | assert(enum_type->id == ZigTypeIdEnum); | 5067 | assert(enum_type->id == ZigTypeIdEnum); |
| 5068 | if (enum_type->data.enumeration.non_exhaustive) { | ||
| 5069 | add_node_error(g, instruction->base.source_node, | ||
| 5070 | buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991")); | ||
| 5071 | codegen_report_errors_and_exit(g); | ||
| 5072 | } | ||
| 5068 | 5073 | ||
| 5069 | LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); | 5074 | LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); |
| 5070 | 5075 | ||
| ... | @@ -8299,6 +8304,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -8299,6 +8304,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 8299 | create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); | 8304 | create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); |
| 8300 | create_builtin_fn(g, BuiltinFnIdAs, "as", 2); | 8305 | create_builtin_fn(g, BuiltinFnIdAs, "as", 2); |
| 8301 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); | 8306 | create_builtin_fn(g, BuiltinFnIdCall, "call", 3); |
| 8307 | create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1); | ||
| 8302 | } | 8308 | } |
| 8303 | 8309 | ||
| 8304 | static const char *bool_to_str(bool b) { | 8310 | static const char *bool_to_str(bool b) { |
src/ir.cpp+131-56| ... | @@ -2392,9 +2392,10 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so | ... | @@ -2392,9 +2392,10 @@ static IrInstruction *ir_build_asm_gen(IrAnalyze *ira, Scope *scope, AstNode *so |
| 2392 | return &instruction->base; | 2392 | return &instruction->base; |
| 2393 | } | 2393 | } |
| 2394 | 2394 | ||
| 2395 | static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { | 2395 | static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, bool bit_size) { |
| 2396 | IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, scope, source_node); | 2396 | IrInstructionSizeOf *instruction = ir_build_instruction<IrInstructionSizeOf>(irb, scope, source_node); |
| 2397 | instruction->type_value = type_value; | 2397 | instruction->type_value = type_value; |
| 2398 | instruction->bit_size = bit_size; | ||
| 2398 | 2399 | ||
| 2399 | ir_ref_instruction(type_value, irb->current_basic_block); | 2400 | ir_ref_instruction(type_value, irb->current_basic_block); |
| 2400 | 2401 | ||
| ... | @@ -3451,7 +3452,7 @@ static IrInstruction *ir_build_err_to_int(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -3451,7 +3452,7 @@ static IrInstruction *ir_build_err_to_int(IrBuilder *irb, Scope *scope, AstNode |
| 3451 | 3452 | ||
| 3452 | static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node, | 3453 | static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 3453 | IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count, | 3454 | IrInstruction *target_value, IrInstructionCheckSwitchProngsRange *ranges, size_t range_count, |
| 3454 | bool have_else_prong) | 3455 | bool have_else_prong, bool have_underscore_prong) |
| 3455 | { | 3456 | { |
| 3456 | IrInstructionCheckSwitchProngs *instruction = ir_build_instruction<IrInstructionCheckSwitchProngs>( | 3457 | IrInstructionCheckSwitchProngs *instruction = ir_build_instruction<IrInstructionCheckSwitchProngs>( |
| 3457 | irb, scope, source_node); | 3458 | irb, scope, source_node); |
| ... | @@ -3459,6 +3460,7 @@ static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, | ... | @@ -3459,6 +3460,7 @@ static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, |
| 3459 | instruction->ranges = ranges; | 3460 | instruction->ranges = ranges; |
| 3460 | instruction->range_count = range_count; | 3461 | instruction->range_count = range_count; |
| 3461 | instruction->have_else_prong = have_else_prong; | 3462 | instruction->have_else_prong = have_else_prong; |
| 3463 | instruction->have_underscore_prong = have_underscore_prong; | ||
| 3462 | 3464 | ||
| 3463 | ir_ref_instruction(target_value, irb->current_basic_block); | 3465 | ir_ref_instruction(target_value, irb->current_basic_block); |
| 3464 | for (size_t i = 0; i < range_count; i += 1) { | 3466 | 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 | ... | @@ -5249,13 +5251,14 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 5249 | return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); | 5251 | return ir_lval_wrap(irb, scope, set_float_mode, lval, result_loc); |
| 5250 | } | 5252 | } |
| 5251 | case BuiltinFnIdSizeof: | 5253 | case BuiltinFnIdSizeof: |
| 5254 | case BuiltinFnIdBitSizeof: | ||
| 5252 | { | 5255 | { |
| 5253 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | 5256 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 5254 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | 5257 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 5255 | if (arg0_value == irb->codegen->invalid_instruction) | 5258 | if (arg0_value == irb->codegen->invalid_instruction) |
| 5256 | return arg0_value; | 5259 | return arg0_value; |
| 5257 | 5260 | ||
| 5258 | IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value); | 5261 | IrInstruction *size_of = ir_build_size_of(irb, scope, node, arg0_value, builtin_fn->id == BuiltinFnIdBitSizeof); |
| 5259 | return ir_lval_wrap(irb, scope, size_of, lval, result_loc); | 5262 | return ir_lval_wrap(irb, scope, size_of, lval, result_loc); |
| 5260 | } | 5263 | } |
| 5261 | case BuiltinFnIdImport: | 5264 | case BuiltinFnIdImport: |
| ... | @@ -6027,8 +6030,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -6027,8 +6030,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 6027 | if (arg0_value == irb->codegen->invalid_instruction) | 6030 | if (arg0_value == irb->codegen->invalid_instruction) |
| 6028 | return arg0_value; | 6031 | return arg0_value; |
| 6029 | 6032 | ||
| 6030 | IrInstruction *actual_tag = ir_build_union_tag(irb, scope, node, arg0_value); | 6033 | IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, arg0_value); |
| 6031 | IrInstruction *tag_name = ir_build_tag_name(irb, scope, node, actual_tag); | ||
| 6032 | return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); | 6034 | return ir_lval_wrap(irb, scope, tag_name, lval, result_loc); |
| 6033 | } | 6035 | } |
| 6034 | case BuiltinFnIdTagType: | 6036 | case BuiltinFnIdTagType: |
| ... | @@ -8090,34 +8092,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -8090,34 +8092,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 8090 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); | 8092 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 8091 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); | 8093 | Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope); |
| 8092 | AstNode *else_prong = nullptr; | 8094 | AstNode *else_prong = nullptr; |
| 8095 | AstNode *underscore_prong = nullptr; | ||
| 8093 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { | 8096 | for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) { |
| 8094 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); | 8097 | AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i); |
| 8095 | size_t prong_item_count = prong_node->data.switch_prong.items.length; | 8098 | size_t prong_item_count = prong_node->data.switch_prong.items.length; |
| 8096 | if (prong_item_count == 0) { | 8099 | if (prong_node->data.switch_prong.any_items_are_range) { |
| 8097 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 8098 | if (else_prong) { | ||
| 8099 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 8100 | buf_sprintf("multiple else prongs in switch expression")); | ||
| 8101 | add_error_note(irb->codegen, msg, else_prong, | ||
| 8102 | buf_sprintf("previous else prong is here")); | ||
| 8103 | return irb->codegen->invalid_instruction; | ||
| 8104 | } | ||
| 8105 | else_prong = prong_node; | ||
| 8106 | |||
| 8107 | IrBasicBlock *prev_block = irb->current_basic_block; | ||
| 8108 | if (peer_parent->peers.length > 0) { | ||
| 8109 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8110 | } | ||
| 8111 | peer_parent->peers.append(this_peer_result_loc); | ||
| 8112 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8113 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, | ||
| 8114 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, | ||
| 8115 | &switch_else_var, LValNone, &this_peer_result_loc->base)) | ||
| 8116 | { | ||
| 8117 | return irb->codegen->invalid_instruction; | ||
| 8118 | } | ||
| 8119 | ir_set_cursor_at_end(irb, prev_block); | ||
| 8120 | } else if (prong_node->data.switch_prong.any_items_are_range) { | ||
| 8121 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | 8100 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); |
| 8122 | 8101 | ||
| 8123 | IrInstruction *ok_bit = nullptr; | 8102 | IrInstruction *ok_bit = nullptr; |
| ... | @@ -8195,6 +8174,56 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -8195,6 +8174,56 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 8195 | } | 8174 | } |
| 8196 | 8175 | ||
| 8197 | ir_set_cursor_at_end_and_append_block(irb, range_block_no); | 8176 | ir_set_cursor_at_end_and_append_block(irb, range_block_no); |
| 8177 | } else { | ||
| 8178 | if (prong_item_count == 0) { | ||
| 8179 | if (else_prong) { | ||
| 8180 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 8181 | buf_sprintf("multiple else prongs in switch expression")); | ||
| 8182 | add_error_note(irb->codegen, msg, else_prong, | ||
| 8183 | buf_sprintf("previous else prong is here")); | ||
| 8184 | return irb->codegen->invalid_instruction; | ||
| 8185 | } | ||
| 8186 | else_prong = prong_node; | ||
| 8187 | } else if (prong_item_count == 1 && | ||
| 8188 | prong_node->data.switch_prong.items.at(0)->type == NodeTypeSymbol && | ||
| 8189 | buf_eql_str(prong_node->data.switch_prong.items.at(0)->data.symbol_expr.symbol, "_")) { | ||
| 8190 | if (underscore_prong) { | ||
| 8191 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 8192 | buf_sprintf("multiple '_' prongs in switch expression")); | ||
| 8193 | add_error_note(irb->codegen, msg, underscore_prong, | ||
| 8194 | buf_sprintf("previous '_' prong is here")); | ||
| 8195 | return irb->codegen->invalid_instruction; | ||
| 8196 | } | ||
| 8197 | underscore_prong = prong_node; | ||
| 8198 | } else { | ||
| 8199 | continue; | ||
| 8200 | } | ||
| 8201 | if (underscore_prong && else_prong) { | ||
| 8202 | ErrorMsg *msg = add_node_error(irb->codegen, prong_node, | ||
| 8203 | buf_sprintf("else and '_' prong in switch expression")); | ||
| 8204 | if (underscore_prong == prong_node) | ||
| 8205 | add_error_note(irb->codegen, msg, else_prong, | ||
| 8206 | buf_sprintf("else prong is here")); | ||
| 8207 | else | ||
| 8208 | add_error_note(irb->codegen, msg, underscore_prong, | ||
| 8209 | buf_sprintf("'_' prong is here")); | ||
| 8210 | return irb->codegen->invalid_instruction; | ||
| 8211 | } | ||
| 8212 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | ||
| 8213 | |||
| 8214 | IrBasicBlock *prev_block = irb->current_basic_block; | ||
| 8215 | if (peer_parent->peers.length > 0) { | ||
| 8216 | peer_parent->peers.last()->next_bb = else_block; | ||
| 8217 | } | ||
| 8218 | peer_parent->peers.append(this_peer_result_loc); | ||
| 8219 | ir_set_cursor_at_end_and_append_block(irb, else_block); | ||
| 8220 | if (!ir_gen_switch_prong_expr(irb, subexpr_scope, node, prong_node, end_block, | ||
| 8221 | is_comptime, var_is_comptime, target_value_ptr, nullptr, 0, &incoming_blocks, &incoming_values, | ||
| 8222 | &switch_else_var, LValNone, &this_peer_result_loc->base)) | ||
| 8223 | { | ||
| 8224 | return irb->codegen->invalid_instruction; | ||
| 8225 | } | ||
| 8226 | ir_set_cursor_at_end(irb, prev_block); | ||
| 8198 | } | 8227 | } |
| 8199 | } | 8228 | } |
| 8200 | 8229 | ||
| ... | @@ -8206,6 +8235,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -8206,6 +8235,8 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 8206 | continue; | 8235 | continue; |
| 8207 | if (prong_node->data.switch_prong.any_items_are_range) | 8236 | if (prong_node->data.switch_prong.any_items_are_range) |
| 8208 | continue; | 8237 | continue; |
| 8238 | if (underscore_prong == prong_node) | ||
| 8239 | continue; | ||
| 8209 | 8240 | ||
| 8210 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); | 8241 | ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent); |
| 8211 | 8242 | ||
| ... | @@ -8249,7 +8280,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -8249,7 +8280,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 8249 | } | 8280 | } |
| 8250 | 8281 | ||
| 8251 | IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, | 8282 | IrInstruction *switch_prongs_void = ir_build_check_switch_prongs(irb, scope, node, target_value, |
| 8252 | check_ranges.items, check_ranges.length, else_prong != nullptr); | 8283 | check_ranges.items, check_ranges.length, else_prong != nullptr, underscore_prong != nullptr); |
| 8253 | 8284 | ||
| 8254 | IrInstruction *br_instruction; | 8285 | IrInstruction *br_instruction; |
| 8255 | if (cases.length == 0) { | 8286 | if (cases.length == 0) { |
| ... | @@ -8269,7 +8300,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -8269,7 +8300,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 8269 | peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; | 8300 | peer_parent->peers.at(i)->base.source_instruction = peer_parent->base.source_instruction; |
| 8270 | } | 8301 | } |
| 8271 | 8302 | ||
| 8272 | if (!else_prong) { | 8303 | if (!else_prong && !underscore_prong) { |
| 8273 | if (peer_parent->peers.length != 0) { | 8304 | if (peer_parent->peers.length != 0) { |
| 8274 | peer_parent->peers.last()->next_bb = else_block; | 8305 | peer_parent->peers.last()->next_bb = else_block; |
| 8275 | } | 8306 | } |
| ... | @@ -12790,7 +12821,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour | ... | @@ -12790,7 +12821,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 12790 | return ira->codegen->invalid_instruction; | 12821 | return ira->codegen->invalid_instruction; |
| 12791 | 12822 | ||
| 12792 | TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint); | 12823 | TypeEnumField *field = find_enum_field_by_tag(wanted_type, &val->data.x_bigint); |
| 12793 | if (field == nullptr && wanted_type->data.enumeration.layout != ContainerLayoutExtern) { | 12824 | if (field == nullptr && !wanted_type->data.enumeration.non_exhaustive) { |
| 12794 | Buf *val_buf = buf_alloc(); | 12825 | Buf *val_buf = buf_alloc(); |
| 12795 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); | 12826 | bigint_append_buf(val_buf, &val->data.x_bigint, 10); |
| 12796 | ErrorMsg *msg = ir_add_error(ira, source_instr, | 12827 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| ... | @@ -21065,6 +21096,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi | ... | @@ -21065,6 +21096,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructi |
| 21065 | lazy_size_of->ira = ira; ira_ref(ira); | 21096 | lazy_size_of->ira = ira; ira_ref(ira); |
| 21066 | result->value->data.x_lazy = &lazy_size_of->base; | 21097 | result->value->data.x_lazy = &lazy_size_of->base; |
| 21067 | lazy_size_of->base.id = LazyValueIdSizeOf; | 21098 | lazy_size_of->base.id = LazyValueIdSizeOf; |
| 21099 | lazy_size_of->bit_size = instruction->bit_size; | ||
| 21068 | 21100 | ||
| 21069 | lazy_size_of->target_type = instruction->type_value->child; | 21101 | lazy_size_of->target_type = instruction->type_value->child; |
| 21070 | if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr) | 21102 | 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 | ... | @@ -21356,10 +21388,6 @@ static IrInstruction *ir_analyze_union_tag(IrAnalyze *ira, IrInstruction *source |
| 21356 | if (type_is_invalid(value->value->type)) | 21388 | if (type_is_invalid(value->value->type)) |
| 21357 | return ira->codegen->invalid_instruction; | 21389 | return ira->codegen->invalid_instruction; |
| 21358 | 21390 | ||
| 21359 | if (value->value->type->id == ZigTypeIdEnum) { | ||
| 21360 | return value; | ||
| 21361 | } | ||
| 21362 | |||
| 21363 | if (value->value->type->id != ZigTypeIdUnion) { | 21391 | if (value->value->type->id != ZigTypeIdUnion) { |
| 21364 | ir_add_error(ira, value, | 21392 | ir_add_error(ira, value, |
| 21365 | buf_sprintf("expected enum or union type, found '%s'", buf_ptr(&value->value->type->name))); | 21393 | 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, | ... | @@ -21427,12 +21455,6 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 21427 | if (type_is_invalid(case_value->value->type)) | 21455 | if (type_is_invalid(case_value->value->type)) |
| 21428 | return ir_unreach_error(ira); | 21456 | return ir_unreach_error(ira); |
| 21429 | 21457 | ||
| 21430 | if (case_value->value->type->id == ZigTypeIdEnum) { | ||
| 21431 | case_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, case_value); | ||
| 21432 | if (type_is_invalid(case_value->value->type)) | ||
| 21433 | return ir_unreach_error(ira); | ||
| 21434 | } | ||
| 21435 | |||
| 21436 | IrInstruction *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type); | 21458 | IrInstruction *casted_case_value = ir_implicit_cast(ira, case_value, target_value->value->type); |
| 21437 | if (type_is_invalid(casted_case_value->value->type)) | 21459 | if (type_is_invalid(casted_case_value->value->type)) |
| 21438 | return ir_unreach_error(ira); | 21460 | return ir_unreach_error(ira); |
| ... | @@ -21477,12 +21499,6 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, | ... | @@ -21477,12 +21499,6 @@ static IrInstruction *ir_analyze_instruction_switch_br(IrAnalyze *ira, |
| 21477 | if (type_is_invalid(new_value->value->type)) | 21499 | if (type_is_invalid(new_value->value->type)) |
| 21478 | continue; | 21500 | continue; |
| 21479 | 21501 | ||
| 21480 | if (new_value->value->type->id == ZigTypeIdEnum) { | ||
| 21481 | new_value = ir_analyze_union_tag(ira, &switch_br_instruction->base, new_value); | ||
| 21482 | if (type_is_invalid(new_value->value->type)) | ||
| 21483 | continue; | ||
| 21484 | } | ||
| 21485 | |||
| 21486 | IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type); | 21502 | IrInstruction *casted_new_value = ir_implicit_cast(ira, new_value, target_value->value->type); |
| 21487 | if (type_is_invalid(casted_new_value->value->type)) | 21503 | if (type_is_invalid(casted_new_value->value->type)) |
| 21488 | continue; | 21504 | continue; |
| ... | @@ -21598,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -21598,7 +21614,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 21598 | case ZigTypeIdEnum: { | 21614 | case ZigTypeIdEnum: { |
| 21599 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) | 21615 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 21600 | return ira->codegen->invalid_instruction; | 21616 | return ira->codegen->invalid_instruction; |
| 21601 | if (target_type->data.enumeration.src_field_count < 2) { | 21617 | if (target_type->data.enumeration.src_field_count == 1) { |
| 21602 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; | 21618 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 21603 | IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); | 21619 | IrInstruction *result = ir_const(ira, &switch_target_instruction->base, target_type); |
| 21604 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 21620 | 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 | ... | @@ -22319,11 +22335,39 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns |
| 22319 | if (type_is_invalid(target->value->type)) | 22335 | if (type_is_invalid(target->value->type)) |
| 22320 | return ira->codegen->invalid_instruction; | 22336 | return ira->codegen->invalid_instruction; |
| 22321 | 22337 | ||
| 22338 | if (target->value->type->id == ZigTypeIdEnumLiteral) { | ||
| 22339 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | ||
| 22340 | Buf *field_name = target->value->data.x_enum_literal; | ||
| 22341 | ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee; | ||
| 22342 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(field_name), true); | ||
| 22343 | return result; | ||
| 22344 | } | ||
| 22345 | |||
| 22346 | if (target->value->type->id == ZigTypeIdUnion) { | ||
| 22347 | target = ir_analyze_union_tag(ira, &instruction->base, target); | ||
| 22348 | if (type_is_invalid(target->value->type)) | ||
| 22349 | return ira->codegen->invalid_instruction; | ||
| 22350 | } | ||
| 22351 | |||
| 22322 | assert(target->value->type->id == ZigTypeIdEnum); | 22352 | assert(target->value->type->id == ZigTypeIdEnum); |
| 22323 | 22353 | ||
| 22354 | if (target->value->type->data.enumeration.src_field_count == 1 && | ||
| 22355 | !target->value->type->data.enumeration.non_exhaustive) { | ||
| 22356 | TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0]; | ||
| 22357 | ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee; | ||
| 22358 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | ||
| 22359 | init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true); | ||
| 22360 | return result; | ||
| 22361 | } | ||
| 22362 | |||
| 22324 | if (instr_is_comptime(target)) { | 22363 | if (instr_is_comptime(target)) { |
| 22325 | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) | 22364 | if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown))) |
| 22326 | return ira->codegen->invalid_instruction; | 22365 | return ira->codegen->invalid_instruction; |
| 22366 | if (target->value->type->data.enumeration.non_exhaustive) { | ||
| 22367 | add_node_error(ira->codegen, instruction->base.source_node, | ||
| 22368 | buf_sprintf("TODO @tagName on non-exhaustive enum https://github.com/ziglang/zig/issues/3991")); | ||
| 22369 | return ira->codegen->invalid_instruction; | ||
| 22370 | } | ||
| 22327 | TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint); | 22371 | TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint); |
| 22328 | ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee; | 22372 | ZigValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee; |
| 22329 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | 22373 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| ... | @@ -23074,7 +23118,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr | ... | @@ -23074,7 +23118,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 23074 | result->special = ConstValSpecialStatic; | 23118 | result->special = ConstValSpecialStatic; |
| 23075 | result->type = ir_type_info_get_type(ira, "Enum", nullptr); | 23119 | result->type = ir_type_info_get_type(ira, "Enum", nullptr); |
| 23076 | 23120 | ||
| 23077 | ZigValue **fields = alloc_const_vals_ptrs(4); | 23121 | ZigValue **fields = alloc_const_vals_ptrs(5); |
| 23078 | result->data.x_struct.fields = fields; | 23122 | result->data.x_struct.fields = fields; |
| 23079 | 23123 | ||
| 23080 | // layout: ContainerLayout | 23124 | // layout: ContainerLayout |
| ... | @@ -23120,6 +23164,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr | ... | @@ -23120,6 +23164,11 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 23120 | { | 23164 | { |
| 23121 | return err; | 23165 | return err; |
| 23122 | } | 23166 | } |
| 23167 | // is_exhaustive: bool | ||
| 23168 | ensure_field_index(result->type, "is_exhaustive", 4); | ||
| 23169 | fields[4]->special = ConstValSpecialStatic; | ||
| 23170 | fields[4]->type = ira->codegen->builtin_types.entry_bool; | ||
| 23171 | fields[4]->data.x_bool = !type_entry->data.enumeration.non_exhaustive; | ||
| 23123 | 23172 | ||
| 23124 | break; | 23173 | break; |
| 23125 | } | 23174 | } |
| ... | @@ -23335,7 +23384,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr | ... | @@ -23335,7 +23384,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 23335 | struct_field_val->special = ConstValSpecialStatic; | 23384 | struct_field_val->special = ConstValSpecialStatic; |
| 23336 | struct_field_val->type = type_info_struct_field_type; | 23385 | struct_field_val->type = type_info_struct_field_type; |
| 23337 | 23386 | ||
| 23338 | ZigValue **inner_fields = alloc_const_vals_ptrs(3); | 23387 | ZigValue **inner_fields = alloc_const_vals_ptrs(4); |
| 23339 | inner_fields[1]->special = ConstValSpecialStatic; | 23388 | inner_fields[1]->special = ConstValSpecialStatic; |
| 23340 | inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); | 23389 | inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); |
| 23341 | 23390 | ||
| ... | @@ -23358,6 +23407,12 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr | ... | @@ -23358,6 +23407,12 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr |
| 23358 | inner_fields[2]->type = ira->codegen->builtin_types.entry_type; | 23407 | inner_fields[2]->type = ira->codegen->builtin_types.entry_type; |
| 23359 | inner_fields[2]->data.x_type = struct_field->type_entry; | 23408 | inner_fields[2]->data.x_type = struct_field->type_entry; |
| 23360 | 23409 | ||
| 23410 | // default_value: var | ||
| 23411 | inner_fields[3]->special = ConstValSpecialStatic; | ||
| 23412 | inner_fields[3]->type = get_optional_type(ira->codegen, struct_field->type_entry); | ||
| 23413 | memoize_field_init_val(ira->codegen, type_entry, struct_field); | ||
| 23414 | set_optional_payload(inner_fields[3], struct_field->init_val); | ||
| 23415 | |||
| 23361 | ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; | 23416 | ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; |
| 23362 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); | 23417 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); |
| 23363 | 23418 | ||
| ... | @@ -26433,10 +26488,27 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -26433,10 +26488,27 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 26433 | bigint_incr(&field_index); | 26488 | bigint_incr(&field_index); |
| 26434 | } | 26489 | } |
| 26435 | } | 26490 | } |
| 26436 | if (!instruction->have_else_prong) { | 26491 | if (instruction->have_underscore_prong) { |
| 26437 | if (switch_type->data.enumeration.layout == ContainerLayoutExtern) { | 26492 | if (!switch_type->data.enumeration.non_exhaustive){ |
| 26493 | ir_add_error(ira, &instruction->base, | ||
| 26494 | buf_sprintf("switch on non-exhaustive enum has `_` prong")); | ||
| 26495 | } | ||
| 26496 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { | ||
| 26497 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; | ||
| 26498 | if (buf_eql_str(enum_field->name, "_")) | ||
| 26499 | continue; | ||
| 26500 | |||
| 26501 | auto entry = field_prev_uses.maybe_get(enum_field->value); | ||
| 26502 | if (!entry) { | ||
| 26503 | ir_add_error(ira, &instruction->base, | ||
| 26504 | buf_sprintf("enumeration value '%s.%s' not handled in switch", buf_ptr(&switch_type->name), | ||
| 26505 | buf_ptr(enum_field->name))); | ||
| 26506 | } | ||
| 26507 | } | ||
| 26508 | } else if (!instruction->have_else_prong) { | ||
| 26509 | if (switch_type->data.enumeration.non_exhaustive) { | ||
| 26438 | ir_add_error(ira, &instruction->base, | 26510 | ir_add_error(ira, &instruction->base, |
| 26439 | buf_sprintf("switch on an extern enum must have an else prong")); | 26511 | buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); |
| 26440 | } | 26512 | } |
| 26441 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { | 26513 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { |
| 26442 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; | 26514 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; |
| ... | @@ -29415,7 +29487,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { | ... | @@ -29415,7 +29487,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { |
| 29415 | 29487 | ||
| 29416 | val->special = ConstValSpecialStatic; | 29488 | val->special = ConstValSpecialStatic; |
| 29417 | assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); | 29489 | assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt); |
| 29418 | bigint_init_unsigned(&val->data.x_bigint, abi_size); | 29490 | if (lazy_size_of->bit_size) |
| 29491 | bigint_init_unsigned(&val->data.x_bigint, size_in_bits); | ||
| 29492 | else | ||
| 29493 | bigint_init_unsigned(&val->data.x_bigint, abi_size); | ||
| 29419 | 29494 | ||
| 29420 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. | 29495 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. |
| 29421 | return ErrorNone; | 29496 | return ErrorNone; |
src/ir_print.cpp+4-1| ... | @@ -1039,7 +1039,10 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { | ... | @@ -1039,7 +1039,10 @@ static void ir_print_asm_gen(IrPrint *irp, IrInstructionAsmGen *instruction) { |
| 1039 | } | 1039 | } |
| 1040 | 1040 | ||
| 1041 | static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { | 1041 | static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { |
| 1042 | fprintf(irp->f, "@sizeOf("); | 1042 | if (instruction->bit_size) |
| 1043 | fprintf(irp->f, "@bitSizeOf("); | ||
| 1044 | else | ||
| 1045 | fprintf(irp->f, "@sizeOf("); | ||
| 1043 | ir_print_other_instruction(irp, instruction->type_value); | 1046 | ir_print_other_instruction(irp, instruction->type_value); |
| 1044 | fprintf(irp->f, ")"); | 1047 | fprintf(irp->f, ")"); |
| 1045 | } | 1048 | } |
test/compile_errors.zig+50-19| ... | @@ -2,6 +2,56 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,56 @@ const tests = @import("tests.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addTest("non-exhaustive enums", | ||
| 6 | \\const A = enum { | ||
| 7 | \\ a, | ||
| 8 | \\ b, | ||
| 9 | \\ _ = 1, | ||
| 10 | \\}; | ||
| 11 | \\const B = enum(u1) { | ||
| 12 | \\ a, | ||
| 13 | \\ _, | ||
| 14 | \\ b, | ||
| 15 | \\}; | ||
| 16 | \\const C = enum(u1) { | ||
| 17 | \\ a, | ||
| 18 | \\ b, | ||
| 19 | \\ _, | ||
| 20 | \\}; | ||
| 21 | \\pub export fn entry() void { | ||
| 22 | \\ _ = A; | ||
| 23 | \\ _ = B; | ||
| 24 | \\ _ = C; | ||
| 25 | \\} | ||
| 26 | , &[_][]const u8{ | ||
| 27 | "tmp.zig:4:5: error: non-exhaustive enum must specify size", | ||
| 28 | "error: value assigned to '_' field of non-exhaustive enum", | ||
| 29 | "error: non-exhaustive enum specifies every value", | ||
| 30 | "error: '_' field of non-exhaustive enum must be last", | ||
| 31 | }); | ||
| 32 | |||
| 33 | cases.addTest("switching with non-exhaustive enums", | ||
| 34 | \\const E = enum(u8) { | ||
| 35 | \\ a, | ||
| 36 | \\ b, | ||
| 37 | \\ _, | ||
| 38 | \\}; | ||
| 39 | \\pub export fn entry() void { | ||
| 40 | \\ var e: E = .b; | ||
| 41 | \\ switch (e) { // error: switch not handling the tag `b` | ||
| 42 | \\ .a => {}, | ||
| 43 | \\ _ => {}, | ||
| 44 | \\ } | ||
| 45 | \\ switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong | ||
| 46 | \\ .a => {}, | ||
| 47 | \\ .b => {}, | ||
| 48 | \\ } | ||
| 49 | \\} | ||
| 50 | , &[_][]const u8{ | ||
| 51 | "tmp.zig:8:5: error: enumeration value 'E.b' not handled in switch", | ||
| 52 | "tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong", | ||
| 53 | }); | ||
| 54 | |||
| 5 | cases.addTest("@export with empty name string", | 55 | cases.addTest("@export with empty name string", |
| 6 | \\pub export fn entry() void { } | 56 | \\pub export fn entry() void { } |
| 7 | \\comptime { | 57 | \\comptime { |
| ... | @@ -139,25 +189,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -139,25 +189,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 139 | "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address", | 189 | "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address", |
| 140 | }); | 190 | }); |
| 141 | 191 | ||
| 142 | cases.add("switch on extern enum missing else prong", | ||
| 143 | \\const i = extern enum { | ||
| 144 | \\ n = 0, | ||
| 145 | \\ o = 2, | ||
| 146 | \\ p = 4, | ||
| 147 | \\ q = 4, | ||
| 148 | \\}; | ||
| 149 | \\pub fn main() void { | ||
| 150 | \\ var x = @intToEnum(i, 52); | ||
| 151 | \\ switch (x) { | ||
| 152 | \\ .n, | ||
| 153 | \\ .o, | ||
| 154 | \\ .p => unreachable, | ||
| 155 | \\ } | ||
| 156 | \\} | ||
| 157 | , &[_][]const u8{ | ||
| 158 | "tmp.zig:9:5: error: switch on an extern enum must have an else prong", | ||
| 159 | }); | ||
| 160 | |||
| 161 | cases.add("invalid float literal", | 192 | cases.add("invalid float literal", |
| 162 | \\const std = @import("std"); | 193 | \\const std = @import("std"); |
| 163 | \\ | 194 | \\ |
test/stage1/behavior/cast.zig-1| ... | @@ -618,7 +618,6 @@ test "peer resolution of string literals" { | ... | @@ -618,7 +618,6 @@ test "peer resolution of string literals" { |
| 618 | .b => "two", | 618 | .b => "two", |
| 619 | .c => "three", | 619 | .c => "three", |
| 620 | .d => "four", | 620 | .d => "four", |
| 621 | else => unreachable, | ||
| 622 | }; | 621 | }; |
| 623 | expect(mem.eql(u8, cmd, "two")); | 622 | expect(mem.eql(u8, cmd, "two")); |
| 624 | } | 623 | } |
test/stage1/behavior/enum.zig+71-9| ... | @@ -11,16 +11,9 @@ test "extern enum" { | ... | @@ -11,16 +11,9 @@ test "extern enum" { |
| 11 | }; | 11 | }; |
| 12 | fn doTheTest(y: c_int) void { | 12 | fn doTheTest(y: c_int) void { |
| 13 | var x = i.o; | 13 | var x = i.o; |
| 14 | expect(@enumToInt(x) == 2); | ||
| 15 | x = @intToEnum(i, 12); | ||
| 16 | expect(@enumToInt(x) == 12); | ||
| 17 | x = @intToEnum(i, y); | ||
| 18 | expect(@enumToInt(x) == 52); | ||
| 19 | switch (x) { | 14 | switch (x) { |
| 20 | .n, | 15 | .n, .p => unreachable, |
| 21 | .o, | 16 | .o => {}, |
| 22 | .p => unreachable, | ||
| 23 | else => {}, | ||
| 24 | } | 17 | } |
| 25 | } | 18 | } |
| 26 | }; | 19 | }; |
| ... | @@ -28,6 +21,70 @@ test "extern enum" { | ... | @@ -28,6 +21,70 @@ test "extern enum" { |
| 28 | comptime S.doTheTest(52); | 21 | comptime S.doTheTest(52); |
| 29 | } | 22 | } |
| 30 | 23 | ||
| 24 | test "non-exhaustive enum" { | ||
| 25 | const S = struct { | ||
| 26 | const E = enum(u8) { | ||
| 27 | a, | ||
| 28 | b, | ||
| 29 | _, | ||
| 30 | }; | ||
| 31 | fn doTheTest(y: u8) void { | ||
| 32 | var e: E = .b; | ||
| 33 | expect(switch (e) { | ||
| 34 | .a => false, | ||
| 35 | .b => true, | ||
| 36 | _ => false, | ||
| 37 | }); | ||
| 38 | e = @intToEnum(E, 12); | ||
| 39 | expect(switch (e) { | ||
| 40 | .a => false, | ||
| 41 | .b => false, | ||
| 42 | _ => true, | ||
| 43 | }); | ||
| 44 | |||
| 45 | expect(switch (e) { | ||
| 46 | .a => false, | ||
| 47 | .b => false, | ||
| 48 | else => true, | ||
| 49 | }); | ||
| 50 | e = .b; | ||
| 51 | expect(switch (e) { | ||
| 52 | .a => false, | ||
| 53 | else => true, | ||
| 54 | }); | ||
| 55 | |||
| 56 | expect(@typeInfo(E).Enum.fields.len == 2); | ||
| 57 | e = @intToEnum(E, 12); | ||
| 58 | expect(@enumToInt(e) == 12); | ||
| 59 | e = @intToEnum(E, y); | ||
| 60 | expect(@enumToInt(e) == 52); | ||
| 61 | expect(@typeInfo(E).Enum.is_exhaustive == false); | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | S.doTheTest(52); | ||
| 65 | comptime S.doTheTest(52); | ||
| 66 | } | ||
| 67 | |||
| 68 | test "empty non-exhaustive enum" { | ||
| 69 | const S = struct { | ||
| 70 | const E = enum(u8) { | ||
| 71 | _, | ||
| 72 | }; | ||
| 73 | fn doTheTest(y: u8) void { | ||
| 74 | var e = @intToEnum(E, y); | ||
| 75 | expect(switch (e) { | ||
| 76 | _ => true, | ||
| 77 | }); | ||
| 78 | expect(@enumToInt(e) == y); | ||
| 79 | |||
| 80 | expect(@typeInfo(E).Enum.fields.len == 0); | ||
| 81 | expect(@typeInfo(E).Enum.is_exhaustive == false); | ||
| 82 | } | ||
| 83 | }; | ||
| 84 | S.doTheTest(42); | ||
| 85 | comptime S.doTheTest(42); | ||
| 86 | } | ||
| 87 | |||
| 31 | test "enum type" { | 88 | test "enum type" { |
| 32 | const foo1 = Foo{ .One = 13 }; | 89 | const foo1 = Foo{ .One = 13 }; |
| 33 | const foo2 = Foo{ | 90 | const foo2 = Foo{ |
| ... | @@ -1057,3 +1114,8 @@ test "enum with one member default to u0 tag type" { | ... | @@ -1057,3 +1114,8 @@ test "enum with one member default to u0 tag type" { |
| 1057 | }; | 1114 | }; |
| 1058 | comptime expect(@TagType(E0) == u0); | 1115 | comptime expect(@TagType(E0) == u0); |
| 1059 | } | 1116 | } |
| 1117 | |||
| 1118 | test "tagName on enum literals" { | ||
| 1119 | expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); | ||
| 1120 | comptime expect(mem.eql(u8, @tagName(.FooBar), "FooBar")); | ||
| 1121 | } |
test/stage1/behavior/sizeof_and_typeof.zig+11| ... | @@ -124,3 +124,14 @@ fn fn1(alpha: bool) void { | ... | @@ -124,3 +124,14 @@ fn fn1(alpha: bool) void { |
| 124 | test "lazy @sizeOf result is checked for definedness" { | 124 | test "lazy @sizeOf result is checked for definedness" { |
| 125 | const f = fn1; | 125 | const f = fn1; |
| 126 | } | 126 | } |
| 127 | |||
| 128 | test "@bitSizeOf" { | ||
| 129 | expect(@bitSizeOf(u2) == 2); | ||
| 130 | expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); | ||
| 131 | expect(@bitSizeOf(struct { | ||
| 132 | a: u2 | ||
| 133 | }) == 8); | ||
| 134 | expect(@bitSizeOf(packed struct { | ||
| 135 | a: u2 | ||
| 136 | }) == 2); | ||
| 137 | } |
test/stage1/behavior/type_info.zig+4-1| ... | @@ -237,9 +237,11 @@ fn testStruct() void { | ... | @@ -237,9 +237,11 @@ fn testStruct() void { |
| 237 | const struct_info = @typeInfo(TestStruct); | 237 | const struct_info = @typeInfo(TestStruct); |
| 238 | expect(@as(TypeId, struct_info) == TypeId.Struct); | 238 | expect(@as(TypeId, struct_info) == TypeId.Struct); |
| 239 | expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); | 239 | expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); |
| 240 | expect(struct_info.Struct.fields.len == 3); | 240 | expect(struct_info.Struct.fields.len == 4); |
| 241 | expect(struct_info.Struct.fields[1].offset == null); | 241 | expect(struct_info.Struct.fields[1].offset == null); |
| 242 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); | 242 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); |
| 243 | expect(struct_info.Struct.fields[2].default_value == null); | ||
| 244 | expect(struct_info.Struct.fields[3].default_value.? == 4); | ||
| 243 | expect(struct_info.Struct.decls.len == 2); | 245 | expect(struct_info.Struct.decls.len == 2); |
| 244 | expect(struct_info.Struct.decls[0].is_pub); | 246 | expect(struct_info.Struct.decls[0].is_pub); |
| 245 | expect(!struct_info.Struct.decls[0].data.Fn.is_extern); | 247 | expect(!struct_info.Struct.decls[0].data.Fn.is_extern); |
| ... | @@ -254,6 +256,7 @@ const TestStruct = packed struct { | ... | @@ -254,6 +256,7 @@ const TestStruct = packed struct { |
| 254 | fieldA: usize, | 256 | fieldA: usize, |
| 255 | fieldB: void, | 257 | fieldB: void, |
| 256 | fieldC: *Self, | 258 | fieldC: *Self, |
| 259 | fieldD: u32 = 4, | ||
| 257 | 260 | ||
| 258 | pub fn foo(self: *const Self) void {} | 261 | pub fn foo(self: *const Self) void {} |
| 259 | }; | 262 | }; |
test/stage1/behavior/union.zig+9| ... | @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { | ... | @@ -629,3 +629,12 @@ test "union initializer generates padding only if needed" { |
| 629 | var v = U{ .A = 532 }; | 629 | var v = U{ .A = 532 }; |
| 630 | expect(v.A == 532); | 630 | expect(v.A == 532); |
| 631 | } | 631 | } |
| 632 | |||
| 633 | test "runtime tag name with single field" { | ||
| 634 | const U = union(enum) { | ||
| 635 | A: i32, | ||
| 636 | }; | ||
| 637 | |||
| 638 | var v = U{ .A = 42 }; | ||
| 639 | expect(std.mem.eql(u8, @tagName(v), "A")); | ||
| 640 | } |
test/translate_c.zig+21-10| ... | @@ -629,6 +629,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -629,6 +629,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 629 | \\ VAL21 = 6917529027641081853, | 629 | \\ VAL21 = 6917529027641081853, |
| 630 | \\ VAL22 = 0, | 630 | \\ VAL22 = 0, |
| 631 | \\ VAL23 = -1, | 631 | \\ VAL23 = -1, |
| 632 | \\ _, | ||
| 632 | \\}; | 633 | \\}; |
| 633 | }); | 634 | }); |
| 634 | } | 635 | } |
| ... | @@ -988,8 +989,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -988,8 +989,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 988 | \\enum enum_ty { FOO }; | 989 | \\enum enum_ty { FOO }; |
| 989 | , &[_][]const u8{ | 990 | , &[_][]const u8{ |
| 990 | \\pub const FOO = @enumToInt(enum_enum_ty.FOO); | 991 | \\pub const FOO = @enumToInt(enum_enum_ty.FOO); |
| 991 | \\pub const enum_enum_ty = extern enum { | 992 | \\pub const enum_enum_ty = extern enum(c_int) { |
| 992 | \\ FOO, | 993 | \\ FOO, |
| 994 | \\ _, | ||
| 993 | \\}; | 995 | \\}; |
| 994 | \\pub extern var my_enum: enum_enum_ty; | 996 | \\pub extern var my_enum: enum_enum_ty; |
| 995 | }); | 997 | }); |
| ... | @@ -1102,28 +1104,31 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1102,28 +1104,31 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1102 | \\pub const a = @enumToInt(enum_unnamed_1.a); | 1104 | \\pub const a = @enumToInt(enum_unnamed_1.a); |
| 1103 | \\pub const b = @enumToInt(enum_unnamed_1.b); | 1105 | \\pub const b = @enumToInt(enum_unnamed_1.b); |
| 1104 | \\pub const c = @enumToInt(enum_unnamed_1.c); | 1106 | \\pub const c = @enumToInt(enum_unnamed_1.c); |
| 1105 | \\const enum_unnamed_1 = extern enum { | 1107 | \\const enum_unnamed_1 = extern enum(c_int) { |
| 1106 | \\ a, | 1108 | \\ a, |
| 1107 | \\ b, | 1109 | \\ b, |
| 1108 | \\ c, | 1110 | \\ c, |
| 1111 | \\ _, | ||
| 1109 | \\}; | 1112 | \\}; |
| 1110 | \\pub const d = enum_unnamed_1; | 1113 | \\pub const d = enum_unnamed_1; |
| 1111 | \\pub const e = @enumToInt(enum_unnamed_2.e); | 1114 | \\pub const e = @enumToInt(enum_unnamed_2.e); |
| 1112 | \\pub const f = @enumToInt(enum_unnamed_2.f); | 1115 | \\pub const f = @enumToInt(enum_unnamed_2.f); |
| 1113 | \\pub const g = @enumToInt(enum_unnamed_2.g); | 1116 | \\pub const g = @enumToInt(enum_unnamed_2.g); |
| 1114 | \\const enum_unnamed_2 = extern enum { | 1117 | \\const enum_unnamed_2 = extern enum(c_int) { |
| 1115 | \\ e = 0, | 1118 | \\ e = 0, |
| 1116 | \\ f = 4, | 1119 | \\ f = 4, |
| 1117 | \\ g = 5, | 1120 | \\ g = 5, |
| 1121 | \\ _, | ||
| 1118 | \\}; | 1122 | \\}; |
| 1119 | \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e); | 1123 | \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e); |
| 1120 | \\pub const i = @enumToInt(enum_unnamed_3.i); | 1124 | \\pub const i = @enumToInt(enum_unnamed_3.i); |
| 1121 | \\pub const j = @enumToInt(enum_unnamed_3.j); | 1125 | \\pub const j = @enumToInt(enum_unnamed_3.j); |
| 1122 | \\pub const k = @enumToInt(enum_unnamed_3.k); | 1126 | \\pub const k = @enumToInt(enum_unnamed_3.k); |
| 1123 | \\const enum_unnamed_3 = extern enum { | 1127 | \\const enum_unnamed_3 = extern enum(c_int) { |
| 1124 | \\ i, | 1128 | \\ i, |
| 1125 | \\ j, | 1129 | \\ j, |
| 1126 | \\ k, | 1130 | \\ k, |
| 1131 | \\ _, | ||
| 1127 | \\}; | 1132 | \\}; |
| 1128 | \\pub const struct_Baz = extern struct { | 1133 | \\pub const struct_Baz = extern struct { |
| 1129 | \\ l: enum_unnamed_3, | 1134 | \\ l: enum_unnamed_3, |
| ... | @@ -1132,10 +1137,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1132,10 +1137,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1132 | \\pub const n = @enumToInt(enum_i.n); | 1137 | \\pub const n = @enumToInt(enum_i.n); |
| 1133 | \\pub const o = @enumToInt(enum_i.o); | 1138 | \\pub const o = @enumToInt(enum_i.o); |
| 1134 | \\pub const p = @enumToInt(enum_i.p); | 1139 | \\pub const p = @enumToInt(enum_i.p); |
| 1135 | \\pub const enum_i = extern enum { | 1140 | \\pub const enum_i = extern enum(c_int) { |
| 1136 | \\ n, | 1141 | \\ n, |
| 1137 | \\ o, | 1142 | \\ o, |
| 1138 | \\ p, | 1143 | \\ p, |
| 1144 | \\ _, | ||
| 1139 | \\}; | 1145 | \\}; |
| 1140 | , | 1146 | , |
| 1141 | \\pub const Baz = struct_Baz; | 1147 | \\pub const Baz = struct_Baz; |
| ... | @@ -1563,9 +1569,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1563,9 +1569,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1563 | , &[_][]const u8{ | 1569 | , &[_][]const u8{ |
| 1564 | \\pub const One = @enumToInt(enum_unnamed_1.One); | 1570 | \\pub const One = @enumToInt(enum_unnamed_1.One); |
| 1565 | \\pub const Two = @enumToInt(enum_unnamed_1.Two); | 1571 | \\pub const Two = @enumToInt(enum_unnamed_1.Two); |
| 1566 | \\const enum_unnamed_1 = extern enum { | 1572 | \\const enum_unnamed_1 = extern enum(c_int) { |
| 1567 | \\ One, | 1573 | \\ One, |
| 1568 | \\ Two, | 1574 | \\ Two, |
| 1575 | \\ _, | ||
| 1569 | \\}; | 1576 | \\}; |
| 1570 | }); | 1577 | }); |
| 1571 | 1578 | ||
| ... | @@ -1665,10 +1672,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1665,10 +1672,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1665 | \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p); | 1672 | \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p); |
| 1666 | \\} | 1673 | \\} |
| 1667 | , &[_][]const u8{ | 1674 | , &[_][]const u8{ |
| 1668 | \\pub const enum_Foo = extern enum { | 1675 | \\pub const enum_Foo = extern enum(c_int) { |
| 1669 | \\ A, | 1676 | \\ A, |
| 1670 | \\ B, | 1677 | \\ B, |
| 1671 | \\ C, | 1678 | \\ C, |
| 1679 | \\ _, | ||
| 1672 | \\}; | 1680 | \\}; |
| 1673 | \\pub const SomeTypedef = c_int; | 1681 | \\pub const SomeTypedef = c_int; |
| 1674 | \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int { | 1682 | \\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 { | ... | @@ -1710,9 +1718,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1710 | \\ y: c_int, | 1718 | \\ y: c_int, |
| 1711 | \\}; | 1719 | \\}; |
| 1712 | , | 1720 | , |
| 1713 | \\pub const enum_Bar = extern enum { | 1721 | \\pub const enum_Bar = extern enum(c_int) { |
| 1714 | \\ A, | 1722 | \\ A, |
| 1715 | \\ B, | 1723 | \\ B, |
| 1724 | \\ _, | ||
| 1716 | \\}; | 1725 | \\}; |
| 1717 | \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; | 1726 | \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; |
| 1718 | , | 1727 | , |
| ... | @@ -1973,10 +1982,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1973,10 +1982,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1973 | \\ return 4; | 1982 | \\ return 4; |
| 1974 | \\} | 1983 | \\} |
| 1975 | , &[_][]const u8{ | 1984 | , &[_][]const u8{ |
| 1976 | \\pub const enum_SomeEnum = extern enum { | 1985 | \\pub const enum_SomeEnum = extern enum(c_int) { |
| 1977 | \\ A, | 1986 | \\ A, |
| 1978 | \\ B, | 1987 | \\ B, |
| 1979 | \\ C, | 1988 | \\ C, |
| 1989 | \\ _, | ||
| 1980 | \\}; | 1990 | \\}; |
| 1981 | \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int { | 1991 | \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int { |
| 1982 | \\ var a = arg_a; | 1992 | \\ var a = arg_a; |
| ... | @@ -2414,10 +2424,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -2414,10 +2424,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2414 | \\pub const FooA = @enumToInt(enum_Foo.A); | 2424 | \\pub const FooA = @enumToInt(enum_Foo.A); |
| 2415 | \\pub const FooB = @enumToInt(enum_Foo.B); | 2425 | \\pub const FooB = @enumToInt(enum_Foo.B); |
| 2416 | \\pub const Foo1 = @enumToInt(enum_Foo.@"1"); | 2426 | \\pub const Foo1 = @enumToInt(enum_Foo.@"1"); |
| 2417 | \\pub const enum_Foo = extern enum { | 2427 | \\pub const enum_Foo = extern enum(c_int) { |
| 2418 | \\ A = 2, | 2428 | \\ A = 2, |
| 2419 | \\ B = 5, | 2429 | \\ B = 5, |
| 2420 | \\ @"1" = 6, | 2430 | \\ @"1" = 6, |
| 2431 | \\ _, | ||
| 2421 | \\}; | 2432 | \\}; |
| 2422 | , | 2433 | , |
| 2423 | \\pub const Foo = enum_Foo; | 2434 | \\pub const Foo = enum_Foo; |