authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-22 12:12:36-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-22 12:12:36-05:00
log97b2ac598b91194c09a96c9ed86e4f9b266d019c
treef8ddd18aaf3a52981f3a97faeac8ef7bd20e6908
parent7e674d6761c057985003694f98861f589b6cf313
parentc522699f28c1df806865c527a7a68a875e606527
signaturelock-open Commit is signed but in an unrecognized format.

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


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}")
4545
46set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")46set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
47set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")47set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
48set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
49set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation")48set(ZIG_ENABLE_MEM_PROFILE off CACHE BOOL "Activate memory usage instrumentation")
5049
51if(ZIG_STATIC)50if(ZIG_STATIC)
...@@ -414,19 +413,26 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")...@@ -414,19 +413,26 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
414else()413else()
415 set(LIBUSERLAND_RELEASE_MODE "true")414 set(LIBUSERLAND_RELEASE_MODE "true")
416endif()415endif()
417if(ZIG_SKIP_INSTALL_LIB_FILES)416
418 set(ZIG_BUILD_INSTALL_STEP "")417set(BUILD_LIBUSERLAND_ARGS "build"
419else()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.
427if(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()
421endif()432endif()
433
422add_custom_target(zig_build_libuserland ALL434add_custom_target(zig_build_libuserland ALL
423 COMMAND zig0 build435 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 zig0436 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)
445endif()451endif()
446add_dependencies(zig zig_build_libuserland)452add_dependencies(zig zig_build_libuserland)
453
447install(TARGETS zig DESTINATION bin)454install(TARGETS zig DESTINATION bin)
455
456# CODE has no effect with Visual Studio build system generator.
457if(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)
464endif()
CONTRIBUTING.md+20-15
...@@ -51,23 +51,28 @@ knowledge of Zig internals.**...@@ -51,23 +51,28 @@ knowledge of Zig internals.**
5151
52### Editing Source Code52### Editing Source Code
5353
54First, build the Stage 1 compiler as described in [the Building section](#building).54First, build the Stage 1 compiler as described in [Building from Source](README.md#Building-from-Source).
5555
56One modification you may want to make is adding `-DZIG_SKIP_INSTALL_LIB_FILES=ON`56Zig locates lib files relative to executable path by searching up the
57to the cmake line. If you use the build directory as a working directory to run57filesystem tree for a sub-path of `lib/zig/std/std.zig` or `lib/std/std.zig`.
58tests with, zig will find the lib files in the source directory, and they will not58Typically the former is an install and the latter a git working tree which
59be "installed" every time you run `make`. This will allow you to make modifications59contains the build directory.
60directly to the standard library, for example, and have them effective immediately.60
61Note that if you already ran `make` or `make install` with the default cmake61During development it is not necessary to perform installs when modifying
62settings, there will already be a `lib/` directory in your build directory. When62stage1 or userland sources and in fact it is faster and simpler to run,
63executed from the build directory, zig will find this instead of the source lib/63test and debug from a git working tree.
64directory. 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
68build and install. To avoid install, pass cmake option `-DZIG_SKIP_INSTALL_LIB_FILES=ON`.
6569
66To test changes, do the following from the build directory:70To test changes, do the following from the build directory:
6771
681. Run `make install` (on POSIX) or721. Run `make` (on POSIX) or
69 `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).73 `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
702. `bin/zig build test` (on POSIX) or `bin\zig.exe build test` (on Windows).742. `$BUILD_DIR/zig build test` (on POSIX) or
75 `$BUILD_DIR/Release\zig.exe build test` (on Windows).
7176
72That runs the whole test suite, which does a lot of extra testing that you77That runs the whole test suite, which does a lot of extra testing that you
73likely won't always need, and can take upwards of 1 hour. This is what the78likely 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,
85not the other ones. Combining this suggestion with the previous one, you could90not the other ones. Combining this suggestion with the previous one, you could
86do this:91do this:
8792
88`bin/zig build test-std -Dskip-release` (on POSIX) or93`$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).
9095
91This will run only the standard library tests, in debug mode only, for all96This will run only the standard library tests, in debug mode only, for all
92targets (it will cross-compile the tests for non-native targets but not run97targets (it will cross-compile the tests for non-native targets but not run
cmake/install.cmake created+37
...@@ -0,0 +1,37 @@
1message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib")
2
3if(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)
11endif()
12
13execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}
14 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
15 RESULT_VARIABLE _result
16)
17if(_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)
37endif()
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#}
2910const std = @import("std");
2911const assert = std.debug.assert;
2912
2913const Number = enum(u8) {
2914 One,
2915 Two,
2916 Three,
2917 _,
2918};
2919
2920test "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#}
28972938
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#}
68176858
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 as8098 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#}
80498103
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 }
16881688
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 }
16921694
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 };
209210
210 /// This data structure is used by the Zig language code generation and211 /// 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 };
257259
258 /// This data structure is used by the Zig language code generation and260 /// 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;
189189
190pub extern "c" fn freeaddrinfo(res: *addrinfo) void;190pub extern "c" fn freeaddrinfo(res: *addrinfo) void;
191191
...@@ -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;
201201
202pub extern "c" fn gai_strerror(errcode: c_int) [*:0]const u8;202pub extern "c" fn gai_strerror(errcode: EAI) [*:0]const u8;
203203
204pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int;204pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int;
205205
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 resolution70/// prevent service name resolution
71pub const AI_NUMERICSERV = 0x00001000;71pub const AI_NUMERICSERV = 0x00001000;
7272
73/// address family for hostname not supported73pub const EAI = extern enum(c_int) {
74pub const EAI_ADDRFAMILY = 1;74 /// address family for hostname not supported
75 ADDRFAMILY = 1,
7576
76/// temporary failure in name resolution77 /// temporary failure in name resolution
77pub const EAI_AGAIN = 2;78 AGAIN = 2,
7879
79/// invalid value for ai_flags80 /// invalid value for ai_flags
80pub const EAI_BADFLAGS = 3;81 BADFLAGS = 3,
8182
82/// non-recoverable failure in name resolution83 /// non-recoverable failure in name resolution
83pub const EAI_FAIL = 4;84 FAIL = 4,
8485
85/// ai_family not supported86 /// ai_family not supported
86pub const EAI_FAMILY = 5;87 FAMILY = 5,
8788
88/// memory allocation failure89 /// memory allocation failure
89pub const EAI_MEMORY = 6;90 MEMORY = 6,
9091
91/// no address associated with hostname92 /// no address associated with hostname
92pub const EAI_NODATA = 7;93 NODATA = 7,
9394
94/// hostname nor servname provided, or not known95 /// hostname nor servname provided, or not known
95pub const EAI_NONAME = 8;96 NONAME = 8,
9697
97/// servname not supported for ai_socktype98 /// servname not supported for ai_socktype
98pub const EAI_SERVICE = 9;99 SERVICE = 9,
99100
100/// ai_socktype not supported101 /// ai_socktype not supported
101pub const EAI_SOCKTYPE = 10;102 SOCKTYPE = 10,
102103
103/// system error returned in errno104 /// system error returned in errno
104pub const EAI_SYSTEM = 11;105 SYSTEM = 11,
105106
106/// invalid value for hints107 /// invalid value for hints
107pub const EAI_BADHINTS = 12;108 BADHINTS = 12,
108109
109/// resolved protocol is unknown110 /// resolved protocol is unknown
110pub const EAI_PROTOCOL = 13;111 PROTOCOL = 13,
112
113 /// argument buffer overflow
114 OVERFLOW = 14,
115
116 _,
117};
111118
112/// argument buffer overflow
113pub const EAI_OVERFLOW = 14;
114pub const EAI_MAX = 15;119pub const EAI_MAX = 15;
115120
116pub const pthread_mutex_t = extern struct {121pub 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};
2525
26/// address family for hostname not supported26pub const EAI = extern enum(c_int) {
27pub const EAI_ADDRFAMILY = 1;27 /// address family for hostname not supported
28 ADDRFAMILY = 1,
2829
29/// name could not be resolved at this time30 /// name could not be resolved at this time
30pub const EAI_AGAIN = 2;31 AGAIN = 2,
3132
32/// flags parameter had an invalid value33 /// flags parameter had an invalid value
33pub const EAI_BADFLAGS = 3;34 BADFLAGS = 3,
3435
35/// non-recoverable failure in name resolution36 /// non-recoverable failure in name resolution
36pub const EAI_FAIL = 4;37 FAIL = 4,
3738
38/// address family not recognized39 /// address family not recognized
39pub const EAI_FAMILY = 5;40 FAMILY = 5,
4041
41/// memory allocation failure42 /// memory allocation failure
42pub const EAI_MEMORY = 6;43 MEMORY = 6,
4344
44/// no address associated with hostname45 /// no address associated with hostname
45pub const EAI_NODATA = 7;46 NODATA = 7,
4647
47/// name does not resolve48 /// name does not resolve
48pub const EAI_NONAME = 8;49 NONAME = 8,
4950
50/// service not recognized for socket type51 /// service not recognized for socket type
51pub const EAI_SERVICE = 9;52 SERVICE = 9,
5253
53/// intended socket type was not recognized54 /// intended socket type was not recognized
54pub const EAI_SOCKTYPE = 10;55 SOCKTYPE = 10,
5556
56/// system error returned in errno57 /// system error returned in errno
57pub const EAI_SYSTEM = 11;58 SYSTEM = 11,
5859
59/// invalid value for hints60 /// invalid value for hints
60pub const EAI_BADHINTS = 12;61 BADHINTS = 12,
6162
62/// resolved protocol is unknown63 /// resolved protocol is unknown
63pub const EAI_PROTOCOL = 13;64 PROTOCOL = 13,
6465
65/// argument buffer overflow66 /// argument buffer overflow
66pub const EAI_OVERFLOW = 14;67 OVERFLOW = 14,
68
69 _,
70};
6771
68pub const EAI_MAX = 15;72pub const EAI_MAX = 15;
6973
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;
32pub const NI_DGRAM = 0x10;32pub const NI_DGRAM = 0x10;
33pub const NI_NUMERICSCOPE = 0x100;33pub const NI_NUMERICSCOPE = 0x100;
3434
35pub const EAI_BADFLAGS = -1;35pub const EAI = extern enum(c_int) {
36pub const EAI_NONAME = -2;36 BADFLAGS = -1,
37pub const EAI_AGAIN = -3;37 NONAME = -2,
38pub const EAI_FAIL = -4;38 AGAIN = -3,
39pub const EAI_FAMILY = -6;39 FAIL = -4,
40pub const EAI_SOCKTYPE = -7;40 FAMILY = -6,
41pub const EAI_SERVICE = -8;41 SOCKTYPE = -7,
42pub const EAI_MEMORY = -10;42 SERVICE = -8,
43pub const EAI_SYSTEM = -11;43 MEMORY = -10,
44pub const EAI_OVERFLOW = -12;44 SYSTEM = -11,
45 OVERFLOW = -12,
4546
46pub const EAI_NODATA = -5;47 NODATA = -5,
47pub const EAI_ADDRFAMILY = -9;48 ADDRFAMILY = -9,
48pub const EAI_INPROGRESS = -100;49 INPROGRESS = -100,
49pub const EAI_CANCELED = -101;50 CANCELED = -101,
50pub const EAI_NOTCANCELED = -102;51 NOTCANCELED = -102,
51pub const EAI_ALLDONE = -103;52 ALLDONE = -103,
52pub const EAI_INTR = -104;53 INTR = -104,
53pub const EAI_IDN_ENCODE = -105;54 IDN_ENCODE = -105,
55
56 _,
57};
5458
55pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;59pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
56pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;60pub 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 }
278278
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 }
283283
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}
12861283
1287test "cstr" {1284test "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}
12911296
1292test "filesize" {1297test "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");
9const debug = std.debug;9const debug = std.debug;
10const testing = std.testing;10const testing = std.testing;
1111
12pub const Polynomial = struct {12pub 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};
1718
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.
19pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);20pub const Crc32 = Crc32WithPoly(.IEEE);
2021
21// slicing-by-8 crc32 implementation.22// slicing-by-8 crc32 implementation.
22pub fn Crc32WithPoly(comptime poly: u32) type {23pub 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}
101102
102test "crc32 ieee" {103test "crc32 ieee" {
103 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);104 const Crc32Ieee = Crc32WithPoly(.IEEE);
104105
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}
109110
110test "crc32 castagnoli" {111test "crc32 castagnoli" {
111 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);112 const Crc32Castagnoli = Crc32WithPoly(.Castagnoli);
112113
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}
117118
118// half-byte lookup table implementation.119// half-byte lookup table implementation.
119pub fn Crc32SmallWithPoly(comptime poly: u32) type {120pub 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}
165166
166test "small crc32 ieee" {167test "small crc32 ieee" {
167 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);168 const Crc32Ieee = Crc32SmallWithPoly(.IEEE);
168169
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}
173174
174test "small crc32 castagnoli" {175test "small crc32 castagnoli" {
175 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);176 const Crc32Castagnoli = Crc32SmallWithPoly(.Castagnoli);
176177
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 hints458 .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 hints465 .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};
2020
21const is_mips = builtin.arch == .mipsel;21const is_mips = builtin.arch.isMIPS();
2222
23pub const pid_t = i32;23pub const pid_t = i32;
24pub const fd_t = i32;24pub 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 }
1818
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 });
2222
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 });
2626
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 });
3131
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 });
3535
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 });
3939
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 });
4343
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 });
4747
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 }
5151
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 });
5555
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 });
148148
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 });
153155
...@@ -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 });
179181
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 }
181185
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 });
224228
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 });
231235
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 LLVM253 // 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 {
254267
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}
297303
298const std = @import("std");
299const assert = std.debug.assert;
300const 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.
304pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {306pub 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
324const is_arm_64 = switch (builtin.arch) {
325 builtin.Arch.aarch64,
326 builtin.Arch.aarch64_be,
327 => true,
328 else => false,
329};
330
331const 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
342const 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 builtins1// ARM specific builtins
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const is_test = builtin.is_test;
43
5const __divmodsi4 = @import("int.zig").__divmodsi4;4const __divmodsi4 = @import("int.zig").__divmodsi4;
6const __udivmodsi4 = @import("int.zig").__udivmodsi4;5const __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}
3534
36pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {35// Dummy functions to avoid errors during the linking phase
37 unreachable;36pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {}
38}37pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {}
39pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {38pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {}
40 unreachable;
41}
42pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {
43 unreachable;
44}
4539
46// This function can only clobber r0 according to the ABI40// This function can only clobber r0 according to the ABI
47pub fn __aeabi_read_tp() callconv(.Naked) void {41pub fn __aeabi_read_tp() callconv(.Naked) void {
42 @setRuntimeSafety(false);
48 asm volatile (43 asm volatile (
49 \\ mrc p15, 0, r0, c13, c0, 344 \\ mrc p15, 0, r0, c13, c0, 3
50 \\ bx lr45 \\ 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 respected51// calling convention is always respected
5752
58pub fn __aeabi_uidivmod() callconv(.Naked) void {53pub fn __aeabi_uidivmod() callconv(.Naked) void {
54 @setRuntimeSafety(false);
59 // Divide r0 by r1; the quotient goes in r0, the remainder in r155 // 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}
7470
75pub fn __aeabi_uldivmod() callconv(.Naked) void {71pub 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:r273 // 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}
9390
94pub fn __aeabi_idivmod() callconv(.Naked) void {91pub fn __aeabi_idivmod() callconv(.Naked) void {
92 @setRuntimeSafety(false);
95 // Divide r0 by r1; the quotient goes in r0, the remainder in r193 // 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}
110108
111pub fn __aeabi_ldivmod() callconv(.Naked) void {109pub 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:r2111 // 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
5const ConditionalOperator = enum {
6 Eq,
7 Lt,
8 Le,
9 Ge,
10 Gt,
11};
12
13pub fn __aeabi_dcmpeq() callconv(.Naked) noreturn {
14 @setRuntimeSafety(false);
15 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq});
16 unreachable;
17}
18
19pub fn __aeabi_dcmplt() callconv(.Naked) noreturn {
20 @setRuntimeSafety(false);
21 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt});
22 unreachable;
23}
24
25pub fn __aeabi_dcmple() callconv(.Naked) noreturn {
26 @setRuntimeSafety(false);
27 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le});
28 unreachable;
29}
30
31pub fn __aeabi_dcmpge() callconv(.Naked) noreturn {
32 @setRuntimeSafety(false);
33 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge});
34 unreachable;
35}
36
37pub fn __aeabi_dcmpgt() callconv(.Naked) noreturn {
38 @setRuntimeSafety(false);
39 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt});
40 unreachable;
41}
42
43fn 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
5const ConditionalOperator = enum {
6 Eq,
7 Lt,
8 Le,
9 Ge,
10 Gt,
11};
12
13pub fn __aeabi_fcmpeq() callconv(.Naked) noreturn {
14 @setRuntimeSafety(false);
15 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq});
16 unreachable;
17}
18
19pub fn __aeabi_fcmplt() callconv(.Naked) noreturn {
20 @setRuntimeSafety(false);
21 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt});
22 unreachable;
23}
24
25pub fn __aeabi_fcmple() callconv(.Naked) noreturn {
26 @setRuntimeSafety(false);
27 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le});
28 unreachable;
29}
30
31pub fn __aeabi_fcmpge() callconv(.Naked) noreturn {
32 @setRuntimeSafety(false);
33 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge});
34 unreachable;
35}
36
37pub fn __aeabi_fcmpgt() callconv(.Naked) noreturn {
38 @setRuntimeSafety(false);
39 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt});
40 unreachable;
41}
42
43fn 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 @@
1const builtin = @import("builtin");
2
3fn __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
22fn __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
55fn __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
104pub 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
114test "test clzsi2" {
115 _ = @import("clzsi2_test.zig");
116}
lib/std/special/compiler_rt/clzsi2_test.zig created+292
...@@ -0,0 +1,292 @@
1const clzsi2 = @import("clzsi2.zig");
2const testing = @import("std").testing;
3
4fn 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
12test "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
5const std = @import("std");
6const builtin = @import("builtin");
7
8const LE = extern enum(i32) {
9 Less = -1,
10 Equal = 0,
11 Greater = 1,
12 Unordered = 1,
13};
14
15const GE = extern enum(i32) {
16 Less = -1,
17 Equal = 0,
18 Greater = 1,
19 Unordered = -1,
20};
21
22pub 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
68pub 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
87pub 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
92pub 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
97pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 {
98 return __lesf2(a, b);
99}
100
101pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
102 return __lesf2(a, b);
103}
104
105pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 {
106 return __lesf2(a, b);
107}
108
109pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 {
110 return __gesf2(a, b);
111}
112
113// Comparison between f64
114
115pub 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
120pub 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
125pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 {
126 return __ledf2(a, b);
127}
128
129pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
130 return __ledf2(a, b);
131}
132
133pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 {
134 return __ledf2(a, b);
135}
136
137pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 {
138 return __gedf2(a, b);
139}
140
141// Comparison between f128
142
143pub 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
148pub 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
153pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
154 return __letf2(a, b);
155}
156
157pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
158 return __letf2(a, b);
159}
160
161pub fn __netf2(a: f128, b: f128) callconv(.C) i32 {
162 return __letf2(a, b);
163}
164
165pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
166 return __getf2(a, b);
167}
168
169// Unordered comparison between f32/f64/f128
170
171pub 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
176pub 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
181pub 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
188pub 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
193pub 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
198pub 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
203pub 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
208pub 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
213pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 {
214 @setRuntimeSafety(false);
215 return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b });
216}
217
218pub 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
223pub 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
228pub 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
233pub 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
238pub 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
243pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 {
244 @setRuntimeSafety(false);
245 return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b });
246}
247
248test "comparesf2" {
249 _ = @import("comparesf2_test.zig");
250}
251test "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
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const fp_t = f64;
10const rep_t = u64;
11const srep_t = i64;
12
13const typeWidth = rep_t.bit_count;
14const significandBits = std.math.floatMantissaBits(fp_t);
15const exponentBits = std.math.floatExponentBits(fp_t);
16const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
17const absMask = signBit - 1;
18const implicitBit = @as(rep_t, 1) << significandBits;
19const significandMask = implicitBit - 1;
20const exponentMask = absMask ^ significandMask;
21const 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
25const LE_LESS = @as(c_int, -1);
26const LE_EQUAL = @as(c_int, 0);
27const LE_GREATER = @as(c_int, 1);
28const LE_UNORDERED = @as(c_int, 1);
29
30pub 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
68const GE_LESS = @as(c_int, -1);
69const GE_EQUAL = @as(c_int, 0);
70const GE_GREATER = @as(c_int, 1);
71const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
72
73pub 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
97pub 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
104pub fn __eqdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
105 return __ledf2(a, b);
106}
107
108pub fn __ltdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
109 return __ledf2(a, b);
110}
111
112pub fn __nedf2(a: fp_t, b: fp_t) callconv(.C) c_int {
113 return __ledf2(a, b);
114}
115
116pub fn __gtdf2(a: fp_t, b: fp_t) callconv(.C) c_int {
117 return __gedf2(a, b);
118}
119
120pub 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
125test "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");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const is_test = builtin.is_test;7const is_test = builtin.is_test;
88
9const comparedf2 = @import("comparedf2.zig");9const comparedf2 = @import("compareXf2.zig");
1010
11const TestVector = struct {11const 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
5const std = @import("std");
6const builtin = @import("builtin");
7const is_test = builtin.is_test;
8
9const fp_t = f32;
10const rep_t = u32;
11const srep_t = i32;
12
13const typeWidth = rep_t.bit_count;
14const significandBits = std.math.floatMantissaBits(fp_t);
15const exponentBits = std.math.floatExponentBits(fp_t);
16const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
17const absMask = signBit - 1;
18const implicitBit = @as(rep_t, 1) << significandBits;
19const significandMask = implicitBit - 1;
20const exponentMask = absMask ^ significandMask;
21const 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
25const LE_LESS = @as(c_int, -1);
26const LE_EQUAL = @as(c_int, 0);
27const LE_GREATER = @as(c_int, 1);
28const LE_UNORDERED = @as(c_int, 1);
29
30pub 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
68const GE_LESS = @as(c_int, -1);
69const GE_EQUAL = @as(c_int, 0);
70const GE_GREATER = @as(c_int, 1);
71const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
72
73pub 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
97pub 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
104pub fn __eqsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
105 return __lesf2(a, b);
106}
107
108pub fn __ltsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
109 return __lesf2(a, b);
110}
111
112pub fn __nesf2(a: fp_t, b: fp_t) callconv(.C) c_int {
113 return __lesf2(a, b);
114}
115
116pub fn __gtsf2(a: fp_t, b: fp_t) callconv(.C) c_int {
117 return __gesf2(a, b);
118}
119
120pub 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
125test "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");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const is_test = builtin.is_test;7const is_test = builtin.is_test;
88
9const comparesf2 = @import("comparesf2.zig");9const comparesf2 = @import("compareXf2.zig");
1010
11const TestVector = struct {11const 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
3const LE_LESS = @as(c_int, -1);
4const LE_EQUAL = @as(c_int, 0);
5const LE_GREATER = @as(c_int, 1);
6const LE_UNORDERED = @as(c_int, 1);
7
8const rep_t = u128;
9const srep_t = i128;
10
11const typeWidth = rep_t.bit_count;
12const significandBits = 112;
13const exponentBits = (typeWidth - significandBits - 1);
14const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
15const absMask = signBit - 1;
16const implicitBit = @as(rep_t, 1) << significandBits;
17const significandMask = implicitBit - 1;
18const exponentMask = absMask ^ significandMask;
19const infRep = exponentMask;
20
21const builtin = @import("builtin");
22const is_test = builtin.is_test;
23
24pub 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
63const GE_LESS = @as(c_int, -1);
64const GE_EQUAL = @as(c_int, 0);
65const GE_GREATER = @as(c_int, 1);
66const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED
67
68pub 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
93pub 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;
88
9var starting_stack_ptr: [*]usize = undefined;9var starting_stack_ptr: [*]usize = undefined;
1010
11const is_wasm = switch (builtin.arch) {11const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start";
12 .wasm32, .wasm64 => true,
13 else => false,
14};
15
16const is_mips = switch (builtin.arch) {
17 .mips, .mipsel, .mips64, .mips64el => true,
18 else => false,
19};
20const start_sym_name = if (is_mips) "__start" else "_start";
2112
22comptime {13comptime {
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 };
148158
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);
290290
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 end294 // 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 functions440 .Auto => unreachable, // Not legal on functions
442 .Register => unreachable, // Not legal on functions441 .Register => unreachable, // Not legal on functions
443 else => unreachable,
444 },442 },
445 };443 };
446444
...@@ -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 and875 // 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.
879877
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/msvc880 container_node.init_arg_expr = .{
883 if (int_type.ptr != null and881 .Type = if (int_type.ptr != null and
884 !isCBuiltinType(int_type, .UInt) and882 !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, ")");
899895
900 container_node.lbrace_token = try appendToken(c, .LBrace, "{");896 container_node.lbrace_token = try appendToken(c, .LBrace, "{");
901897
...@@ -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, "}");
957966
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 }
12481245
...@@ -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}
16841680
...@@ -2206,6 +2202,19 @@ fn transDoWhileLoop(...@@ -2206,6 +2202,19 @@ fn transDoWhileLoop(
2206 .id = .Loop,2202 .id = .Loop,
2207 };2203 };
22082204
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: do2232 // c: do
...@@ -2236,19 +2242,6 @@ fn transDoWhileLoop(...@@ -2236,19 +2242,6 @@ fn transDoWhileLoop(
2236 break :blk block;2242 break :blk block;
2237 };2243 };
22382244
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 {
4783fn transCreateNodeIdentifier(c: *Context, name: []const u8) !*ast.Node {4776fn 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
49234915
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 };
49304921
src/all_types.hpp+6
...@@ -358,6 +358,8 @@ struct LazyValueSizeOf {...@@ -358,6 +358,8 @@ struct LazyValueSizeOf {
358358
359 IrAnalyze *ira;359 IrAnalyze *ira;
360 IrInstruction *target_type;360 IrInstruction *target_type;
361
362 bool bit_size;
361};363};
362364
363struct LazyValueSliceType {365struct 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;
13851387
1388 bool non_exhaustive;
1386 bool resolve_loop_flag;1389 bool resolve_loop_flag;
1387};1390};
13881391
...@@ -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};
17581762
1759struct BuiltinFnEntry {1763struct BuiltinFnEntry {
...@@ -3146,6 +3150,7 @@ struct IrInstructionAsmGen {...@@ -3146,6 +3150,7 @@ struct IrInstructionAsmGen {
3146struct IrInstructionSizeOf {3150struct IrInstructionSizeOf {
3147 IrInstruction base;3151 IrInstruction base;
31483152
3153 bool bit_size;
3149 IrInstruction *type_value;3154 IrInstruction *type_value;
3150};3155};
31513156
...@@ -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};
36693675
3670struct IrInstructionCheckStatementIsVoid {3676struct 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 }
25712571
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;
25772573
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 }
26212614
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);
26292623
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;
26312650
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 }
26502669
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
82888312
8289 uint32_t field_count = enum_type->data.enumeration.src_field_count;8313 uint32_t field_count = enum_type->data.enumeration.src_field_count;
82908314
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);
82938317
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);
33583358
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 }
50685073
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);
50705075
...@@ -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}
83038309
8304static const char *bool_to_str(bool b) {8310static 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}
23942394
2395static IrInstruction *ir_build_size_of(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) {2395static 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;
23982399
2399 ir_ref_instruction(type_value, irb->current_basic_block);2400 ir_ref_instruction(type_value, irb->current_basic_block);
24002401
...@@ -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
34513452
3452static IrInstruction *ir_build_check_switch_prongs(IrBuilder *irb, Scope *scope, AstNode *source_node,3453static 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;
34623464
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;
52575260
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;
60296032
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);
81228101
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 }
81968175
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 }
82008229
...@@ -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;
82098240
8210 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);8241 ResultLocPeer *this_peer_result_loc = create_peer_result(peer_parent);
82118242
...@@ -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 }
82508281
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);
82538284
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 }
82718302
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;
1279112822
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;
2106821100
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;
2135821390
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);
2142921457
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;
2147921501
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;
2232122337
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);
2232322353
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);
2307623120
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;
2307923123
23080 // layout: ContainerLayout23124 // 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;
2312323172
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;
2333723386
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);
2334123390
...@@ -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;
2336023409
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);
2336323418
...@@ -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) {
2941529487
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);
2941929494
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}
10401040
1041static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {1041static 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");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub 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 });
141191
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}
3023
24test "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
68test "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
31test "enum type" {88test "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
1118test "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 {
124test "lazy @sizeOf result is checked for definedness" {124test "lazy @sizeOf result is checked for definedness" {
125 const f = fn1;125 const f = fn1;
126}126}
127
128test "@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,
257260
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
633test "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 });
15711578
...@@ -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;