authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-10-04 10:39:26+03:00
committergravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-10-04 10:39:26+03:00
log23cd3b33312ea5fcae32dcb6cd53cbd502361ce9
treeeae3657140271fb945dae6e4e1ad9c788808ac58
parent82f0ede3ad4150a80ab745419664f1dce4a6be9c
parent8170a3d574a7118a6ee616d1b1258b2e839de173

Merge branch 'master' of https://github.com/ziglang/zig into add_some_frees


43 files changed, 2551 insertions(+), 2349 deletions(-)

CMakeLists.txt+4-1
...@@ -63,6 +63,9 @@ endif()...@@ -63,6 +63,9 @@ endif()
6363
64if(ZIG_STATIC)64if(ZIG_STATIC)
65 set(ZIG_STATIC_LLVM "on")65 set(ZIG_STATIC_LLVM "on")
66 set(ZIG_LINK_MODE "Static")
67else()
68 set(ZIG_LINK_MODE "Dynamic")
66endif()69endif()
6770
68string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_DIR}")71string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_DIR}")
...@@ -74,6 +77,7 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)...@@ -74,6 +77,7 @@ option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)
74set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")77set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")
75set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")78set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")
76set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")79set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")
80set(ZIG_PREFER_LLVM_CONFIG off CACHE BOOL "(when cross compiling) use llvm-config to find target llvm dependencies if needed")
7781
78find_package(llvm)82find_package(llvm)
79find_package(clang)83find_package(clang)
...@@ -257,7 +261,6 @@ target_include_directories(embedded_softfloat PUBLIC...@@ -257,7 +261,6 @@ target_include_directories(embedded_softfloat PUBLIC
257)261)
258include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include")262include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include")
259set(SOFTFLOAT_LIBRARIES embedded_softfloat)263set(SOFTFLOAT_LIBRARIES embedded_softfloat)
260include_directories("${CMAKE_SOURCE_DIR}/deps/dbg-macro")
261264
262find_package(Threads)265find_package(Threads)
263266
ci/azure/pipelines.yml+1-1
...@@ -41,7 +41,7 @@ jobs:...@@ -41,7 +41,7 @@ jobs:
4141
42 steps:42 steps:
43 - powershell: |43 - powershell: |
44 (New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2020-07-20/msys2-base-x86_64-20200720.sfx.exe", "sfx.exe")44 (New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2020-09-03/msys2-base-x86_64-20200903.sfx.exe", "sfx.exe")
45 .\sfx.exe -y -o\45 .\sfx.exe -y -o\
46 del sfx.exe46 del sfx.exe
47 displayName: Download/Extract/Install MSYS247 displayName: Download/Extract/Install MSYS2
cmake/Findllvm.cmake+5-5
...@@ -32,7 +32,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)...@@ -32,7 +32,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)
32 /usr/local/llvm10/lib32 /usr/local/llvm10/lib
33 /usr/local/llvm100/lib33 /usr/local/llvm100/lib
34 )34 )
35elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")35elseif(("${ZIG_TARGET_TRIPLE}" STREQUAL "native") OR ZIG_PREFER_LLVM_CONFIG)
36 find_program(LLVM_CONFIG_EXE36 find_program(LLVM_CONFIG_EXE
37 NAMES llvm-config-10 llvm-config-10.0 llvm-config100 llvm-config10 llvm-config37 NAMES llvm-config-10 llvm-config-10.0 llvm-config100 llvm-config10 llvm-config
38 PATHS38 PATHS
...@@ -55,13 +55,13 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")...@@ -55,13 +55,13 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
55 OUTPUT_STRIP_TRAILING_WHITESPACE)55 OUTPUT_STRIP_TRAILING_WHITESPACE)
5656
57 if("${LLVM_CONFIG_VERSION}" VERSION_LESS 10)57 if("${LLVM_CONFIG_VERSION}" VERSION_LESS 10)
58 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")58 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
59 endif()59 endif()
60 if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 11)60 if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 11)
61 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")61 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
62 endif()62 endif()
63 if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 11)63 if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 11)
64 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")64 message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
65 endif()65 endif()
6666
67 execute_process(67 execute_process(
...@@ -72,7 +72,7 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")...@@ -72,7 +72,7 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
72 function(NEED_TARGET TARGET_NAME)72 function(NEED_TARGET TARGET_NAME)
73 list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)73 list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)
74 if (${_index} EQUAL -1)74 if (${_index} EQUAL -1)
75 message(FATAL_ERROR "LLVM is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")75 message(FATAL_ERROR "LLVM (according to ${LLVM_CONFIG_EXE}) is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
76 endif()76 endif()
77 endfunction(NEED_TARGET)77 endfunction(NEED_TARGET)
78 NEED_TARGET("AArch64")78 NEED_TARGET("AArch64")
deps/dbg-macro/LICENSE deleted-21
...@@ -1,21 +0,0 @@
1MIT License
2
3Copyright (c) 2019 David Peter <mail@david-peter.de>
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
deps/dbg-macro/README.md deleted-172
...@@ -1,172 +0,0 @@
1# `dbg(…)`
2
3[![Build Status](https://travis-ci.org/sharkdp/dbg-macro.svg?branch=master)](https://travis-ci.org/sharkdp/dbg-macro) [![Build status](https://ci.appveyor.com/api/projects/status/vmo9rw4te2wifkul/branch/master?svg=true)](https://ci.appveyor.com/project/sharkdp/dbg-macro) [![Try it online](https://img.shields.io/badge/try-online-f34b7d.svg)](https://repl.it/@sharkdp/dbg-macro-demo) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](dbg.h)
4
5*A macro for `printf`-style debugging fans.*
6
7Debuggers are great. But sometimes you just don't have the time or patience to set
8up everything correctly and just want a quick way to inspect some values at runtime.
9
10This projects provides a [single header file](dbg.h) with a `dbg(…)`
11macro that can be used in all circumstances where you would typically write
12`printf("…", …)` or `std::cout << …`. But it comes with a few extras.
13
14## Examples
15
16``` c++
17#include <vector>
18#include <dbg.h>
19
20// You can use "dbg(..)" in expressions:
21int factorial(int n) {
22 if (dbg(n <= 1)) {
23 return dbg(1);
24 } else {
25 return dbg(n * factorial(n - 1));
26 }
27}
28
29int main() {
30 std::string message = "hello";
31 dbg(message); // [example.cpp:15 (main)] message = "hello" (std::string)
32
33 const int a = 2;
34 const int b = dbg(3 * a) + 1; // [example.cpp:18 (main)] 3 * a = 6 (int)
35
36 std::vector<int> numbers{b, 13, 42};
37 dbg(numbers); // [example.cpp:21 (main)] numbers = {7, 13, 42} (size: 3) (std::vector<int>)
38
39 dbg("this line is executed"); // [example.cpp:23 (main)] this line is executed
40
41 factorial(4);
42
43 return 0;
44}
45```
46
47The code above produces this output ([try it yourself](https://repl.it/@sharkdp/dbg-macro-demo)):
48
49![dbg(…) macro output](https://i.imgur.com/NHEYk9A.png)
50
51## Features
52
53 * Easy to read, colorized output (colors auto-disable when the output is not an interactive terminal)
54 * Prints file name, line number, function name and the original expression
55 * Adds type information for the printed-out value
56 * Specialized pretty-printers for containers, pointers, string literals, enums, `std::optional`, etc.
57 * Can be used inside expressions (passing through the original value)
58 * The `dbg.h` header issues a compiler warning when included (so you don't forget to remove it).
59 * Compatible and tested with C++11, C++14 and C++17.
60
61## Installation
62
63To make this practical, the `dbg.h` header should to be readily available from all kinds of different
64places and in all kinds of environments. The quick & dirty way is to actually copy the header file
65to `/usr/include` or to clone the repository and symlink `dbg.h` to `/usr/include/dbg.h`.
66``` bash
67git clone https://github.com/sharkdp/dbg-macro
68sudo ln -s $(readlink -f dbg-macro/dbg.h) /usr/include/dbg.h
69```
70If you don't want to make untracked changes to your filesystem, check below if there is a package for
71your operating system or package manager.
72
73### On Arch Linux
74
75You can install [`dbg-macro` from the AUR](https://aur.archlinux.org/packages/dbg-macro/):
76``` bash
77yay -S dbg-macro
78```
79
80### With vcpkg
81
82You can install the [`dbg-macro` port](https://github.com/microsoft/vcpkg/tree/master/ports/dbg-macro) via:
83``` bash
84vcpkg install dbg-macro
85```
86
87## Configuration
88
89* Set the `DBG_MACRO_DISABLE` flag to disable the `dbg(…)` macro (i.e. to make it a no-op).
90* Set the `DBG_MACRO_NO_WARNING` flag to disable the *"'dbg.h' header is included in your code base"* warnings.
91
92## Advanced features
93
94### Hexadecimal, octal and binary format
95
96If you want to format integers in hexadecimal, octal or binary representation, you can
97simply wrap them in `dbg::hex(…)`, `dbg::oct(…)` or `dbg::bin(…)`:
98```c++
99const uint32_t secret = 12648430;
100dbg(dbg::hex(secret));
101```
102
103### Printing type names
104
105`dbg(…)` already prints the type for each value in parenthesis (see screenshot above). But
106sometimes you just want to print a type (maybe because you don't have a value for that type).
107In this case, you can use the `dbg::type<T>()` helper to pretty-print a given type `T`.
108For example:
109```c++
110template <typename T>
111void my_function_template() {
112 using MyDependentType = typename std::remove_reference<T>::type&&;
113 dbg(dbg::type<MyDependentType>());
114}
115```
116
117### Print the current time
118
119To print a timestamp, you can use the `dbg::time()` helper:
120```c++
121dbg(dbg::time());
122```
123
124### Customization
125
126If you want `dbg(…)` to work for your custom datatype, you can simply overload `operator<<` for
127`std::ostream&`:
128```c++
129std::ostream& operator<<(std::ostream& out, const user_defined_type& v) {
130 out << "…";
131 return out;
132}
133```
134
135If you want to modify the type name that is printed by `dbg(…)`, you can add a custom
136`get_type_name` overload:
137```c++
138// Customization point for type information
139namespace dbg {
140 std::string get_type_name(type_tag<bool>) {
141 return "truth value";
142 }
143}
144```
145
146## Development
147
148If you want to contribute to `dbg-macro`, here is how you can build the tests and demos:
149
150Make sure that the submodule(s) are up to date:
151```bash
152git submodule update --init
153```
154
155Then, use the typical `cmake` workflow. Usage of `-DCMAKE_CXX_STANDARD=17` is optional,
156but recommended in order to have the largest set of features enabled:
157```bash
158mkdir build
159cd build
160cmake .. -DCMAKE_CXX_STANDARD=17
161make
162```
163
164To run the tests, simply call:
165```bash
166make test
167```
168You can find the unit tests in `tests/basic.cpp`.
169
170## Acknowledgement
171
172This project is inspired by Rusts [`dbg!(…)` macro](https://doc.rust-lang.org/std/macro.dbg.html).
deps/dbg-macro/dbg.h deleted-711
...@@ -1,711 +0,0 @@
1/*****************************************************************************
2
3 dbg(...) macro
4
5License (MIT):
6
7 Copyright (c) 2019 David Peter <mail@david-peter.de>
8
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to
11 deal in the Software without restriction, including without limitation the
12 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 sell copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 SOFTWARE.
26
27*****************************************************************************/
28
29#ifndef DBG_MACRO_DBG_H
30#define DBG_MACRO_DBG_H
31
32#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
33#define DBG_MACRO_UNIX
34#elif defined(_MSC_VER)
35#define DBG_MACRO_WINDOWS
36#endif
37
38#ifndef DBG_MACRO_NO_WARNING
39#pragma message("WARNING: the 'dbg.h' header is included in your code base")
40#endif // DBG_MACRO_NO_WARNING
41
42#include <algorithm>
43#include <chrono>
44#include <ctime>
45#include <iomanip>
46#include <ios>
47#include <iostream>
48#include <memory>
49#include <sstream>
50#include <string>
51#include <tuple>
52#include <type_traits>
53#include <vector>
54
55#ifdef DBG_MACRO_UNIX
56#include <unistd.h>
57#endif
58
59#if __cplusplus >= 201703L || defined(_MSC_VER)
60#define DBG_MACRO_CXX_STANDARD 17
61#elif __cplusplus >= 201402L
62#define DBG_MACRO_CXX_STANDARD 14
63#else
64#define DBG_MACRO_CXX_STANDARD 11
65#endif
66
67#if DBG_MACRO_CXX_STANDARD >= 17
68#include <optional>
69#include <variant>
70#endif
71
72namespace dbg {
73
74#ifdef DBG_MACRO_UNIX
75inline bool isColorizedOutputEnabled() {
76 return isatty(fileno(stderr));
77}
78#else
79inline bool isColorizedOutputEnabled() {
80 return true;
81}
82#endif
83
84struct time {};
85
86namespace pretty_function {
87
88// Compiler-agnostic version of __PRETTY_FUNCTION__ and constants to
89// extract the template argument in `type_name_impl`
90
91#if defined(__clang__)
92#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
93static constexpr size_t PREFIX_LENGTH =
94 sizeof("const char *dbg::type_name_impl() [T = ") - 1;
95static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
96#elif defined(__GNUC__) && !defined(__clang__)
97#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
98static constexpr size_t PREFIX_LENGTH =
99 sizeof("const char* dbg::type_name_impl() [with T = ") - 1;
100static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
101#elif defined(_MSC_VER)
102#define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__
103static constexpr size_t PREFIX_LENGTH =
104 sizeof("const char *__cdecl dbg::type_name_impl<") - 1;
105static constexpr size_t SUFFIX_LENGTH = sizeof(">(void)") - 1;
106#else
107#error "This compiler is currently not supported by dbg_macro."
108#endif
109
110} // namespace pretty_function
111
112// Formatting helpers
113
114template <typename T>
115struct print_formatted {
116 static_assert(std::is_integral<T>::value,
117 "Only integral types are supported.");
118
119 print_formatted(T value, int numeric_base)
120 : inner(value), base(numeric_base) {}
121
122 operator T() const { return inner; }
123
124 const char* prefix() const {
125 switch (base) {
126 case 8:
127 return "0o";
128 case 16:
129 return "0x";
130 case 2:
131 return "0b";
132 default:
133 return "";
134 }
135 }
136
137 T inner;
138 int base;
139};
140
141template <typename T>
142print_formatted<T> hex(T value) {
143 return print_formatted<T>{value, 16};
144}
145
146template <typename T>
147print_formatted<T> oct(T value) {
148 return print_formatted<T>{value, 8};
149}
150
151template <typename T>
152print_formatted<T> bin(T value) {
153 return print_formatted<T>{value, 2};
154}
155
156// Implementation of 'type_name<T>()'
157
158template <typename T>
159const char* type_name_impl() {
160 return DBG_MACRO_PRETTY_FUNCTION;
161}
162
163template <typename T>
164struct type_tag {};
165
166template <int&... ExplicitArgumentBarrier, typename T>
167std::string get_type_name(type_tag<T>) {
168 namespace pf = pretty_function;
169
170 std::string type = type_name_impl<T>();
171 return type.substr(pf::PREFIX_LENGTH,
172 type.size() - pf::PREFIX_LENGTH - pf::SUFFIX_LENGTH);
173}
174
175template <typename T>
176std::string type_name() {
177 if (std::is_volatile<T>::value) {
178 if (std::is_pointer<T>::value) {
179 return type_name<typename std::remove_volatile<T>::type>() + " volatile";
180 } else {
181 return "volatile " + type_name<typename std::remove_volatile<T>::type>();
182 }
183 }
184 if (std::is_const<T>::value) {
185 if (std::is_pointer<T>::value) {
186 return type_name<typename std::remove_const<T>::type>() + " const";
187 } else {
188 return "const " + type_name<typename std::remove_const<T>::type>();
189 }
190 }
191 if (std::is_pointer<T>::value) {
192 return type_name<typename std::remove_pointer<T>::type>() + "*";
193 }
194 if (std::is_lvalue_reference<T>::value) {
195 return type_name<typename std::remove_reference<T>::type>() + "&";
196 }
197 if (std::is_rvalue_reference<T>::value) {
198 return type_name<typename std::remove_reference<T>::type>() + "&&";
199 }
200 return get_type_name(type_tag<T>{});
201}
202
203inline std::string get_type_name(type_tag<short>) {
204 return "short";
205}
206
207inline std::string get_type_name(type_tag<unsigned short>) {
208 return "unsigned short";
209}
210
211inline std::string get_type_name(type_tag<long>) {
212 return "long";
213}
214
215inline std::string get_type_name(type_tag<unsigned long>) {
216 return "unsigned long";
217}
218
219inline std::string get_type_name(type_tag<std::string>) {
220 return "std::string";
221}
222
223template <typename T>
224std::string get_type_name(type_tag<std::vector<T, std::allocator<T>>>) {
225 return "std::vector<" + type_name<T>() + ">";
226}
227
228template <typename T1, typename T2>
229std::string get_type_name(type_tag<std::pair<T1, T2>>) {
230 return "std::pair<" + type_name<T1>() + ", " + type_name<T2>() + ">";
231}
232
233template <typename... T>
234std::string type_list_to_string() {
235 std::string result;
236 auto unused = {(result += type_name<T>() + ", ", 0)..., 0};
237 static_cast<void>(unused);
238
239 if (sizeof...(T) > 0) {
240 result.pop_back();
241 result.pop_back();
242 }
243 return result;
244}
245
246template <typename... T>
247std::string get_type_name(type_tag<std::tuple<T...>>) {
248 return "std::tuple<" + type_list_to_string<T...>() + ">";
249}
250
251template <typename T>
252inline std::string get_type_name(type_tag<print_formatted<T>>) {
253 return type_name<T>();
254}
255
256// Implementation of 'is_detected' to specialize for container-like types
257
258namespace detail_detector {
259
260struct nonesuch {
261 nonesuch() = delete;
262 ~nonesuch() = delete;
263 nonesuch(nonesuch const&) = delete;
264 void operator=(nonesuch const&) = delete;
265};
266
267template <typename...>
268using void_t = void;
269
270template <class Default,
271 class AlwaysVoid,
272 template <class...>
273 class Op,
274 class... Args>
275struct detector {
276 using value_t = std::false_type;
277 using type = Default;
278};
279
280template <class Default, template <class...> class Op, class... Args>
281struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
282 using value_t = std::true_type;
283 using type = Op<Args...>;
284};
285
286} // namespace detail_detector
287
288template <template <class...> class Op, class... Args>
289using is_detected = typename detail_detector::
290 detector<detail_detector::nonesuch, void, Op, Args...>::value_t;
291
292namespace detail {
293
294namespace {
295using std::begin;
296using std::end;
297#if DBG_MACRO_CXX_STANDARD < 17
298template <typename T>
299constexpr auto size(const T& c) -> decltype(c.size()) {
300 return c.size();
301}
302template <typename T, std::size_t N>
303constexpr std::size_t size(const T (&)[N]) {
304 return N;
305}
306#else
307using std::size;
308#endif
309} // namespace
310
311template <typename T>
312using detect_begin_t = decltype(detail::begin(std::declval<T>()));
313
314template <typename T>
315using detect_end_t = decltype(detail::end(std::declval<T>()));
316
317template <typename T>
318using detect_size_t = decltype(detail::size(std::declval<T>()));
319
320template <typename T>
321struct is_container {
322 static constexpr bool value =
323 is_detected<detect_begin_t, T>::value &&
324 is_detected<detect_end_t, T>::value &&
325 is_detected<detect_size_t, T>::value &&
326 !std::is_same<std::string,
327 typename std::remove_cv<
328 typename std::remove_reference<T>::type>::type>::value;
329};
330
331template <typename T>
332using ostream_operator_t =
333 decltype(std::declval<std::ostream&>() << std::declval<T>());
334
335template <typename T>
336struct has_ostream_operator : is_detected<ostream_operator_t, T> {};
337
338} // namespace detail
339
340// Helper to dbg(…)-print types
341template <typename T>
342struct print_type {};
343
344template <typename T>
345print_type<T> type() {
346 return print_type<T>{};
347}
348
349// Specializations of "pretty_print"
350
351template <typename T>
352inline void pretty_print(std::ostream& stream, const T& value, std::true_type) {
353 stream << value;
354}
355
356template <typename T>
357inline void pretty_print(std::ostream&, const T&, std::false_type) {
358 static_assert(detail::has_ostream_operator<const T&>::value,
359 "Type does not support the << ostream operator");
360}
361
362template <typename T>
363inline typename std::enable_if<!detail::is_container<const T&>::value &&
364 !std::is_enum<T>::value,
365 bool>::type
366pretty_print(std::ostream& stream, const T& value) {
367 pretty_print(stream, value,
368 typename detail::has_ostream_operator<const T&>::type{});
369 return true;
370}
371
372inline bool pretty_print(std::ostream& stream, const bool& value) {
373 stream << std::boolalpha << value;
374 return true;
375}
376
377inline bool pretty_print(std::ostream& stream, const char& value) {
378 const bool printable = value >= 0x20 && value <= 0x7E;
379
380 if (printable) {
381 stream << "'" << value << "'";
382 } else {
383 stream << "'\\x" << std::setw(2) << std::setfill('0') << std::hex
384 << std::uppercase << (0xFF & value) << "'";
385 }
386 return true;
387}
388
389template <typename P>
390inline bool pretty_print(std::ostream& stream, P* const& value) {
391 if (value == nullptr) {
392 stream << "nullptr";
393 } else {
394 stream << value;
395 }
396 return true;
397}
398
399template <typename T, typename Deleter>
400inline bool pretty_print(std::ostream& stream,
401 std::unique_ptr<T, Deleter>& value) {
402 pretty_print(stream, value.get());
403 return true;
404}
405
406template <typename T>
407inline bool pretty_print(std::ostream& stream, std::shared_ptr<T>& value) {
408 pretty_print(stream, value.get());
409 stream << " (use_count = " << value.use_count() << ")";
410
411 return true;
412}
413
414template <size_t N>
415inline bool pretty_print(std::ostream& stream, const char (&value)[N]) {
416 stream << value;
417 return false;
418}
419
420template <>
421inline bool pretty_print(std::ostream& stream, const char* const& value) {
422 stream << '"' << value << '"';
423 return true;
424}
425
426template <size_t Idx>
427struct pretty_print_tuple {
428 template <typename... Ts>
429 static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
430 pretty_print_tuple<Idx - 1>::print(stream, tuple);
431 stream << ", ";
432 pretty_print(stream, std::get<Idx>(tuple));
433 }
434};
435
436template <>
437struct pretty_print_tuple<0> {
438 template <typename... Ts>
439 static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
440 pretty_print(stream, std::get<0>(tuple));
441 }
442};
443
444template <typename... Ts>
445inline bool pretty_print(std::ostream& stream, const std::tuple<Ts...>& value) {
446 stream << "{";
447 pretty_print_tuple<sizeof...(Ts) - 1>::print(stream, value);
448 stream << "}";
449
450 return true;
451}
452
453template <>
454inline bool pretty_print(std::ostream& stream, const std::tuple<>&) {
455 stream << "{}";
456
457 return true;
458}
459
460template <>
461inline bool pretty_print(std::ostream& stream, const time&) {
462 using namespace std::chrono;
463
464 const auto now = system_clock::now();
465 const auto us =
466 duration_cast<microseconds>(now.time_since_epoch()).count() % 1000000;
467 const auto hms = system_clock::to_time_t(now);
468 const std::tm* tm = std::localtime(&hms);
469 stream << "current time = " << std::put_time(tm, "%H:%M:%S") << '.'
470 << std::setw(6) << std::setfill('0') << us;
471
472 return false;
473}
474
475// Converts decimal integer to binary string
476template <typename T>
477std::string decimalToBinary(T n) {
478 const size_t length = 8 * sizeof(T);
479 std::string toRet;
480 toRet.resize(length);
481
482 for (size_t i = 0; i < length; ++i) {
483 const auto bit_at_index_i = (n >> i) & 1;
484 toRet[length - 1 - i] = bit_at_index_i + '0';
485 }
486
487 return toRet;
488}
489
490template <typename T>
491inline bool pretty_print(std::ostream& stream,
492 const print_formatted<T>& value) {
493 if (value.inner < 0) {
494 stream << "-";
495 }
496 stream << value.prefix();
497
498 // Print using setbase
499 if (value.base != 2) {
500 stream << std::setw(sizeof(T)) << std::setfill('0')
501 << std::setbase(value.base) << std::uppercase;
502
503 if (value.inner >= 0) {
504 // The '+' sign makes sure that a uint_8 is printed as a number
505 stream << +value.inner;
506 } else {
507 using unsigned_type = typename std::make_unsigned<T>::type;
508 stream << +(static_cast<unsigned_type>(-(value.inner + 1)) + 1);
509 }
510 } else {
511 // Print for binary
512 if (value.inner >= 0) {
513 stream << decimalToBinary(value.inner);
514 } else {
515 using unsigned_type = typename std::make_unsigned<T>::type;
516 stream << decimalToBinary<unsigned_type>(
517 static_cast<unsigned_type>(-(value.inner + 1)) + 1);
518 }
519 }
520
521 return true;
522}
523
524template <typename T>
525inline bool pretty_print(std::ostream& stream, const print_type<T>&) {
526 stream << type_name<T>();
527
528 stream << " [sizeof: " << sizeof(T) << " byte, ";
529
530 stream << "trivial: ";
531 if (std::is_trivial<T>::value) {
532 stream << "yes";
533 } else {
534 stream << "no";
535 }
536
537 stream << ", standard layout: ";
538 if (std::is_standard_layout<T>::value) {
539 stream << "yes";
540 } else {
541 stream << "no";
542 }
543 stream << "]";
544
545 return false;
546}
547
548template <typename Container>
549inline typename std::enable_if<detail::is_container<const Container&>::value,
550 bool>::type
551pretty_print(std::ostream& stream, const Container& value) {
552 stream << "{";
553 const size_t size = detail::size(value);
554 const size_t n = std::min(size_t{10}, size);
555 size_t i = 0;
556 using std::begin;
557 using std::end;
558 for (auto it = begin(value); it != end(value) && i < n; ++it, ++i) {
559 pretty_print(stream, *it);
560 if (i != n - 1) {
561 stream << ", ";
562 }
563 }
564
565 if (size > n) {
566 stream << ", ...";
567 stream << " size:" << size;
568 }
569
570 stream << "}";
571 return true;
572}
573
574template <typename Enum>
575inline typename std::enable_if<std::is_enum<Enum>::value, bool>::type
576pretty_print(std::ostream& stream, Enum const& value) {
577 using UnderlyingType = typename std::underlying_type<Enum>::type;
578 stream << static_cast<UnderlyingType>(value);
579
580 return true;
581}
582
583inline bool pretty_print(std::ostream& stream, const std::string& value) {
584 stream << '"' << value << '"';
585 return true;
586}
587
588template <typename T1, typename T2>
589inline bool pretty_print(std::ostream& stream, const std::pair<T1, T2>& value) {
590 stream << "{";
591 pretty_print(stream, value.first);
592 stream << ", ";
593 pretty_print(stream, value.second);
594 stream << "}";
595 return true;
596}
597
598#if DBG_MACRO_CXX_STANDARD >= 17
599
600template <typename T>
601inline bool pretty_print(std::ostream& stream, const std::optional<T>& value) {
602 if (value) {
603 stream << '{';
604 pretty_print(stream, *value);
605 stream << '}';
606 } else {
607 stream << "nullopt";
608 }
609
610 return true;
611}
612
613template <typename... Ts>
614inline bool pretty_print(std::ostream& stream,
615 const std::variant<Ts...>& value) {
616 stream << "{";
617 std::visit([&stream](auto&& arg) { pretty_print(stream, arg); }, value);
618 stream << "}";
619
620 return true;
621}
622
623#endif
624
625class DebugOutput {
626 public:
627 DebugOutput(const char* filepath,
628 int line,
629 const char* function_name,
630 const char* expression)
631 : m_use_colorized_output(isColorizedOutputEnabled()),
632 m_filepath(filepath),
633 m_line(line),
634 m_function_name(function_name),
635 m_expression(expression) {
636 const std::size_t path_length = m_filepath.length();
637 if (path_length > MAX_PATH_LENGTH) {
638 m_filepath = ".." + m_filepath.substr(path_length - MAX_PATH_LENGTH,
639 MAX_PATH_LENGTH);
640 }
641 }
642
643 template <typename T>
644 T&& print(const std::string& type, T&& value) const {
645 const T& ref = value;
646 std::stringstream stream_value;
647 const bool print_expr_and_type = pretty_print(stream_value, ref);
648
649 std::stringstream output;
650 output << ansi(ANSI_DEBUG) << "[" << m_filepath << ":" << m_line << " ("
651 << m_function_name << ")] " << ansi(ANSI_RESET);
652 if (print_expr_and_type) {
653 output << ansi(ANSI_EXPRESSION) << m_expression << ansi(ANSI_RESET)
654 << " = ";
655 }
656 output << ansi(ANSI_VALUE) << stream_value.str() << ansi(ANSI_RESET);
657 if (print_expr_and_type) {
658 output << " (" << ansi(ANSI_TYPE) << type << ansi(ANSI_RESET) << ")";
659 }
660 output << std::endl;
661 std::cerr << output.str();
662
663 return std::forward<T>(value);
664 }
665
666 private:
667 const char* ansi(const char* code) const {
668 if (m_use_colorized_output) {
669 return code;
670 } else {
671 return ANSI_EMPTY;
672 }
673 }
674
675 const bool m_use_colorized_output;
676
677 std::string m_filepath;
678 const int m_line;
679 const std::string m_function_name;
680 const std::string m_expression;
681
682 static constexpr std::size_t MAX_PATH_LENGTH = 20;
683
684 static constexpr const char* const ANSI_EMPTY = "";
685 static constexpr const char* const ANSI_DEBUG = "\x1b[02m";
686 static constexpr const char* const ANSI_EXPRESSION = "\x1b[36m";
687 static constexpr const char* const ANSI_VALUE = "\x1b[01m";
688 static constexpr const char* const ANSI_TYPE = "\x1b[32m";
689 static constexpr const char* const ANSI_RESET = "\x1b[0m";
690};
691
692// Identity function to suppress "-Wunused-value" warnings in DBG_MACRO_DISABLE
693// mode
694template <typename T>
695T&& identity(T&& t) {
696 return std::forward<T>(t);
697}
698
699} // namespace dbg
700
701#ifndef DBG_MACRO_DISABLE
702// We use a variadic macro to support commas inside expressions (e.g.
703// initializer lists):
704#define dbg(...) \
705 dbg::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
706 .print(dbg::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))
707#else
708#define dbg(...) dbg::identity(__VA_ARGS__)
709#endif // DBG_MACRO_DISABLE
710
711#endif // DBG_MACRO_DBG_H
lib/libc/mingw/lib32/user32.def created+998
...@@ -0,0 +1,998 @@
1LIBRARY USER32.dll
2EXPORTS
3;ord_1500@16 @1500
4;ord_1501@4 @1501
5;ord_1502@12 @1502
6ActivateKeyboardLayout@8
7AddClipboardFormatListener@4
8AdjustWindowRect@12
9AdjustWindowRectEx@16
10AlignRects@16
11AllowForegroundActivation@0
12AllowSetForegroundWindow@4
13AnimateWindow@12
14AnyPopup@0
15AppendMenuA@16
16AppendMenuW@16
17ArrangeIconicWindows@4
18AttachThreadInput@12
19BeginDeferWindowPos@4
20BeginPaint@8
21BlockInput@4
22BringWindowToTop@4
23BroadcastSystemMessage@20
24BroadcastSystemMessageA@20
25BroadcastSystemMessageExA@24
26BroadcastSystemMessageExW@24
27BroadcastSystemMessageW@20
28BuildReasonArray@12
29CalcChildScroll@8
30CalcMenuBar@20
31CalculatePopupWindowPosition@20
32CallMsgFilter@8
33CallMsgFilterA@8
34CallMsgFilterW@8
35CallNextHookEx@16
36CallWindowProcA@20
37CallWindowProcW@20
38CancelShutdown@0
39CascadeChildWindows@8
40CascadeWindows@20
41ChangeClipboardChain@8
42ChangeDisplaySettingsA@8
43ChangeDisplaySettingsExA@20
44ChangeDisplaySettingsExW@20
45ChangeDisplaySettingsW@8
46ChangeMenuA@20
47ChangeMenuW@20
48ChangeWindowMessageFilter@8
49ChangeWindowMessageFilterEx@16
50CharLowerA@4
51CharLowerBuffA@8
52CharLowerBuffW@8
53CharLowerW@4
54CharNextA@4
55;ord_1550@12 @1550
56;ord_1551@8 @1551
57;ord_1552@8 @1552
58;ord_1553@12 @1553
59;ord_1554@8 @1554
60;ord_1555@16 @1555
61;ord_1556@4 @1556
62CharNextExA@12
63CharNextW@4
64CharPrevA@8
65CharPrevExA@16
66CharPrevW@8
67CharToOemA@8
68CharToOemBuffA@12
69CharToOemBuffW@12
70CharToOemW@8
71CharUpperA@4
72CharUpperBuffA@8
73CharUpperBuffW@8
74CharUpperW@4
75CheckDesktopByThreadId@4
76CheckDBCSEnabledExt@0
77CheckDlgButton@12
78CheckMenuItem@12
79CheckMenuRadioItem@20
80CheckProcessForClipboardAccess@8
81CheckProcessSession@4
82CheckRadioButton@16
83CheckWindowThreadDesktop@8
84ChildWindowFromPoint@12
85ChildWindowFromPointEx@16
86CliImmSetHotKey@16
87ClientThreadSetup@0
88ClientToScreen@8
89ClipCursor@4
90CloseClipboard@0
91CloseDesktop@4
92CloseGestureInfoHandle@4
93CloseTouchInputHandle@4
94CloseWindow@4
95CloseWindowStation@4
96ConsoleControl@12
97ControlMagnification@8
98CopyAcceleratorTableA@12
99CopyAcceleratorTableW@12
100CopyIcon@4
101CopyImage@20
102CopyRect@8
103CountClipboardFormats@0
104CreateAcceleratorTableA@8
105CreateAcceleratorTableW@8
106CreateCaret@16
107CreateCursor@28
108CreateDCompositionHwndTarget@12
109CreateDesktopA@24
110CreateDesktopExA@32
111CreateDesktopExW@32
112CreateDesktopW@24
113CreateDialogIndirectParamA@20
114CreateDialogIndirectParamAorW@24
115CreateDialogIndirectParamW@20
116CreateDialogParamA@20
117CreateDialogParamW@20
118CreateIcon@28
119CreateIconFromResource@16
120CreateIconFromResourceEx@28
121CreateIconIndirect@4
122CreateMDIWindowA@40
123CreateMDIWindowW@40
124CreateMenu@0
125CreatePopupMenu@0
126CreateSystemThreads@16 ; ReactOS has the @8 variant
127CreateWindowExA@48
128CreateWindowExW@48
129CreateWindowInBand@52
130CreateWindowIndirect@4
131CreateWindowStationA@16
132CreateWindowStationW@16
133CsrBroadcastSystemMessageExW@24
134CtxInitUser32@0
135DdeAbandonTransaction@12
136DdeAccessData@8
137DdeAddData@16
138DdeClientTransaction@32
139DdeCmpStringHandles@8
140DdeConnect@16
141DdeConnectList@20
142DdeCreateDataHandle@28
143DdeCreateStringHandleA@12
144DdeCreateStringHandleW@12
145DdeDisconnect@4
146DdeDisconnectList@4
147DdeEnableCallback@12
148DdeFreeDataHandle@4
149DdeFreeStringHandle@8
150DdeGetData@16
151DdeGetLastError@4
152DdeGetQualityOfService@12
153DdeImpersonateClient@4
154DdeInitializeA@16
155DdeInitializeW@16
156DdeKeepStringHandle@8
157DdeNameService@16
158DdePostAdvise@12
159DdeQueryConvInfo@12
160DdeQueryNextServer@8
161DdeQueryStringA@20
162DdeQueryStringW@20
163DdeReconnect@4
164DdeSetQualityOfService@12
165DdeSetUserHandle@12
166DdeUnaccessData@4
167DdeUninitialize@4
168DefDlgProcA@16
169DefDlgProcW@16
170DefFrameProcA@20
171DefFrameProcW@20
172DefMDIChildProcA@16
173DefMDIChildProcW@16
174DefRawInputProc@12
175DefWindowProcA@16
176DefWindowProcW@16
177DeferWindowPos@32
178DeferWindowPosAndBand@36
179DeleteMenu@12
180DeregisterShellHookWindow@4
181DestroyAcceleratorTable@4
182DestroyCaret@0
183DestroyCursor@4
184DestroyDCompositionHwndTarget@8
185DestroyIcon@4
186DestroyMenu@4
187DestroyReasons@4
188DestroyWindow@4
189DeviceEventWorker@24 ; No documentation whatsoever, ReactOS has a stub with @20 - https://www.reactos.org/archives/public/ros-diffs/2011-February/040308.html
190DialogBoxIndirectParamA@20
191DialogBoxIndirectParamAorW@24
192DialogBoxIndirectParamW@20
193DialogBoxParamA@20
194DialogBoxParamW@20
195DisableProcessWindowsGhosting@0
196DispatchMessageA@4
197DispatchMessageW@4
198DisplayConfigGetDeviceInfo@4
199DisplayConfigSetDeviceInfo@4
200DisplayExitWindowsWarnings@4
201DlgDirListA@20
202DlgDirListComboBoxA@20
203DlgDirListComboBoxW@20
204DlgDirListW@20
205DlgDirSelectComboBoxExA@16
206DlgDirSelectComboBoxExW@16
207DlgDirSelectExA@16
208DlgDirSelectExW@16
209DoSoundConnect@0
210DoSoundDisconnect@0
211DragDetect@12
212DragObject@20
213DrawAnimatedRects@16
214DrawCaption@16
215DrawCaptionTempA@28
216DrawCaptionTempW@28
217DrawEdge@16
218DrawFocusRect@8
219DrawFrame@16
220DrawFrameControl@16
221DrawIcon@16
222DrawIconEx@36
223DrawMenuBar@4
224DrawMenuBarTemp@20
225DrawStateA@40
226DrawStateW@40
227DrawTextA@20
228DrawTextExA@24
229DrawTextExW@24
230DrawTextW@20
231DwmGetDxSharedSurface@24
232DwmGetRemoteSessionOcclusionEvent@0
233DwmGetRemoteSessionOcclusionState@0
234DwmLockScreenUpdates@4
235DwmStartRedirection@8 ; Mentioned on http://habrahabr.ru/post/145174/ , enables GDI virtualization (for security purposes)
236DwmStopRedirection@0
237DwmValidateWindow@8
238EditWndProc@16
239EmptyClipboard@0
240EnableMenuItem@12
241EnableMouseInPointer@4
242EnableScrollBar@12
243EnableSessionForMMCSS@4
244EnableWindow@8
245EndDeferWindowPos@4
246EndDeferWindowPosEx@8
247EndDialog@8
248EndMenu@0
249EndPaint@8
250EndTask@12
251EnterReaderModeHelper@4
252EnumChildWindows@12
253EnumClipboardFormats@4
254EnumDesktopWindows@12
255EnumDesktopsA@12
256EnumDesktopsW@12
257EnumDisplayDevicesA@16
258EnumDisplayDevicesW@16
259EnumDisplayMonitors@16
260EnumDisplaySettingsA@12
261EnumDisplaySettingsExA@16
262EnumDisplaySettingsExW@16
263EnumDisplaySettingsW@12
264EnumPropsA@8
265EnumPropsExA@12
266EnumPropsExW@12
267EnumPropsW@8
268EnumThreadWindows@12
269EnumWindowStationsA@8
270EnumWindowStationsW@8
271EnumWindows@8
272EqualRect@8
273EvaluateProximityToPolygon@16
274EvaluateProximityToRect@12
275ExcludeUpdateRgn@8
276ExitWindowsEx@8
277FillRect@12
278FindWindowA@8
279FindWindowExA@16
280FindWindowExW@16
281FindWindowW@8
282FlashWindow@8
283FlashWindowEx@4
284FrameRect@12
285FreeDDElParam@8
286FrostCrashedWindow@8
287GetActiveWindow@0
288GetAltTabInfo@20
289GetAltTabInfoA@20
290GetAltTabInfoW@20
291GetAncestor@8
292GetAppCompatFlags2@4
293GetAppCompatFlags@8 ; ReactOS has @4 version http://doxygen.reactos.org/d9/d71/undocuser_8h_a9b76cdc68c523a061c86a40367049ed2.html
294GetAsyncKeyState@4
295GetAutoRotationState@4
296GetCIMSSM@4
297GetCapture@0
298GetCaretBlinkTime@0
299GetCaretPos@4
300GetClassInfoA@12
301GetClassInfoExA@12
302GetClassInfoExW@12
303GetClassInfoW@12
304GetClassLongA@8
305GetClassLongW@8
306GetClassNameA@12
307GetClassNameW@12
308GetClassWord@8
309GetClientRect@8
310GetClipCursor@4
311GetClipboardAccessToken@8
312GetClipboardData@4
313GetClipboardFormatNameA@12
314GetClipboardFormatNameW@12
315GetClipboardOwner@0
316GetClipboardSequenceNumber@0
317GetClipboardViewer@0
318GetComboBoxInfo@8
319GetCurrentInputMessageSource@4
320GetCursor@0
321GetCursorFrameInfo@20
322GetCursorInfo@4
323GetCursorPos@4
324GetDC@4
325GetDCEx@12
326GetDesktopID@8
327GetDesktopWindow@0
328GetDialogBaseUnits@0
329GetDisplayAutoRotationPreferences@4
330GetDisplayConfigBufferSizes@12
331GetDlgCtrlID@4
332GetDlgItem@8
333GetDlgItemInt@16
334GetDlgItemTextA@16
335GetDlgItemTextW@16
336GetDoubleClickTime@0
337GetDpiForMonitorInternal@16
338GetFocus@0
339GetForegroundWindow@0
340GetGUIThreadInfo@8
341GetGestureConfig@24
342GetGestureExtraArgs@12
343GetGestureInfo@8
344GetGuiResources@8
345GetIconInfo@8
346GetIconInfoExA@8
347GetIconInfoExW@8
348GetInputDesktop@0
349GetInputLocaleInfo@8
350GetInputState@0
351GetInternalWindowPos@12
352GetKBCodePage@0
353GetKeyNameTextA@12
354GetKeyNameTextW@12
355GetKeyState@4
356GetKeyboardLayout@4
357GetKeyboardLayoutList@8
358GetKeyboardLayoutNameA@4
359GetKeyboardLayoutNameW@4
360GetKeyboardState@4
361GetKeyboardType@4
362GetLastActivePopup@4
363GetLastInputInfo@4
364GetLayeredWindowAttributes@16
365GetListBoxInfo@4
366GetMagnificationDesktopColorEffect@4
367GetMagnificationDesktopMagnification@12
368GetMagnificationLensCtxInformation@16
369GetMenu@4
370GetMenuBarInfo@16
371GetMenuCheckMarkDimensions@0
372GetMenuContextHelpId@4
373GetMenuDefaultItem@12
374GetMenuInfo@8
375GetMenuItemCount@4
376GetMenuItemID@8
377GetMenuItemInfoA@16
378GetMenuItemInfoW@16
379GetMenuItemRect@16
380GetMenuState@12
381GetMenuStringA@20
382GetMenuStringW@20
383GetMessageA@16
384GetMessageExtraInfo@0
385GetMessagePos@0
386GetMessageTime@0
387GetMessageW@16
388GetMonitorInfoA@8
389GetMonitorInfoW@8
390GetMouseMovePointsEx@20
391GetNextDlgGroupItem@12
392GetNextDlgTabItem@12
393GetOpenClipboardWindow@0
394GetParent@4
395GetPhysicalCursorPos@4
396GetPointerCursorId@8
397GetPointerDevice@8
398GetPointerDeviceCursors@12
399GetPointerDeviceProperties@12
400GetPointerDeviceRects@12
401GetPointerDevices@8
402GetPointerFrameInfo@12
403GetPointerFrameInfoHistory@16
404GetPointerFramePenInfo@12
405GetPointerFramePenInfoHistory@16
406GetPointerFrameTouchInfo@12
407GetPointerFrameTouchInfoHistory@16
408GetPointerInfo@8
409GetPointerInfoHistory@12
410GetPointerInputTransform@12
411GetPointerPenInfo@8
412GetPointerPenInfoHistory@12
413GetPointerTouchInfo@8
414GetPointerTouchInfoHistory@12
415GetPointerType@8
416GetPriorityClipboardFormat@8
417GetProcessDefaultLayout@4
418GetProcessDpiAwarenessInternal@8
419GetProcessWindowStation@0
420GetProgmanWindow@0
421GetPropA@8
422GetPropW@8
423GetQueueStatus@4
424GetRawInputBuffer@12
425GetRawInputData@20
426GetRawInputDeviceInfoA@16
427GetRawInputDeviceInfoW@16
428GetRawInputDeviceList@12
429GetRawPointerDeviceData@20
430GetReasonTitleFromReasonCode@12
431GetRegisteredRawInputDevices@12
432GetQueueStatus@4
433GetScrollBarInfo@12
434GetScrollInfo@12
435GetScrollPos@8
436GetScrollRange@16
437GetSendMessageReceiver@4
438GetShellWindow@0
439GetSubMenu@8
440GetSysColor@4
441GetSysColorBrush@4
442GetSystemMenu@8
443GetSystemMetrics@4
444GetTabbedTextExtentA@20
445GetTabbedTextExtentW@20
446GetTaskmanWindow@0
447GetThreadDesktop@4
448GetTitleBarInfo@8
449GetTopLevelWindow@4
450GetTopWindow@4
451GetTouchInputInfo@16
452GetUnpredictedMessagePos@0
453GetUpdateRect@12
454GetUpdateRgn@12
455GetUpdatedClipboardFormats@12
456GetUserObjectInformationA@20
457GetUserObjectInformationW@20
458GetUserObjectSecurity@20
459GetWinStationInfo@4
460GetWindow@8
461GetWindowBand@8
462GetWindowCompositionAttribute@8
463GetWindowCompositionInfo@8
464GetWindowContextHelpId@4
465GetWindowDC@4
466GetWindowDisplayAffinity@8
467GetWindowFeedbackSetting@20
468GetWindowInfo@8
469GetWindowLongA@8
470GetWindowLongW@8
471GetWindowMinimizeRect@8
472GetWindowModuleFileName@12
473GetWindowModuleFileNameA@12
474GetWindowModuleFileNameW@12
475GetWindowPlacement@8
476GetWindowRect@8
477GetWindowRgn@8
478GetWindowRgnBox@8
479GetWindowRgnEx@12
480GetWindowTextA@12
481GetWindowTextLengthA@4
482GetWindowTextLengthW@4
483GetWindowTextW@12
484GetWindowThreadProcessId@8
485GetWindowWord@8
486GhostWindowFromHungWindow@4
487GrayStringA@36
488GrayStringW@36
489HideCaret@4
490HiliteMenuItem@16
491HungWindowFromGhostWindow@4
492IMPGetIMEA@8
493IMPGetIMEW@8
494IMPQueryIMEA@4
495IMPQueryIMEW@4
496IMPSetIMEA@8
497IMPSetIMEW@8
498ImpersonateDdeClientWindow@8
499InSendMessage@0
500InSendMessageEx@4
501InflateRect@12
502InitializeLpkHooks@4
503InitializeWin32EntryTable@4
504InitializeTouchInjection@8
505InjectTouchInput@8
506InsertMenuA@20
507InsertMenuItemA@16
508InsertMenuItemW@16
509InsertMenuW@20
510InternalGetWindowIcon@8
511;ord_2001@4 @2001
512;ord_2002@4 @2002
513InternalGetWindowText@12
514IntersectRect@12
515;ord_2005@4 @2005
516InvalidateRect@12
517InvalidateRgn@12
518InvertRect@8
519IsCharAlphaA@4
520;ord_2010@16 @2010
521IsCharAlphaNumericA@4
522IsCharAlphaNumericW@4
523IsCharAlphaW@4
524IsCharLowerA@4
525IsCharLowerW@4
526IsCharUpperA@4
527IsCharUpperW@4
528IsChild@8
529IsClipboardFormatAvailable@4
530IsDialogMessage@8
531IsDialogMessageA@8
532IsDialogMessageW@8
533IsDlgButtonChecked@8
534IsGUIThread@4
535IsHungAppWindow@4
536IsIconic@4
537IsImmersiveProcess@4
538IsInDesktopWindowBand@4
539IsMenu@4
540IsProcess16Bit@0
541IsMouseInPointerEnabled@0
542IsProcessDPIAware@0
543IsQueueAttached@0
544IsRectEmpty@4
545IsSETEnabled@0
546IsServerSideWindow@4
547IsThreadDesktopComposited@0
548IsTopLevelWindow@4
549IsTouchWindow@8
550IsWinEventHookInstalled@4
551IsWindow@4
552IsWindowEnabled@4
553IsWindowInDestroy@4
554IsWindowRedirectedForPrint@4
555IsWindowUnicode@4
556IsWindowVisible@4
557IsWow64Message@0
558IsZoomed@4
559KillSystemTimer@8
560KillTimer@8
561LoadAcceleratorsA@8
562LoadAcceleratorsW@8
563LoadBitmapA@8
564LoadBitmapW@8
565LoadCursorA@8
566LoadCursorFromFileA@4
567LoadCursorFromFileW@4
568;ord_2000@0 @2000
569;ord_2001@4 @2001
570;ord_2002@4 @2002
571LoadCursorW@8
572LoadIconA@8
573;ord_2005@4 @2005
574LoadIconW@8
575LoadImageA@24
576LoadImageW@24
577LoadKeyboardLayoutA@8
578LoadKeyboardLayoutEx@12
579LoadKeyboardLayoutW@8
580LoadLocalFonts@0
581LoadMenuA@8
582LoadMenuIndirectA@4
583LoadMenuIndirectW@4
584LoadMenuW@8
585LoadRemoteFonts@0
586LoadStringA@16
587LoadStringW@16
588LockSetForegroundWindow@4
589LockWindowStation@4
590LockWindowUpdate@4
591LockWorkStation@0
592LogicalToPhysicalPoint@8
593LogicalToPhysicalPointForPerMonitorDPI@8
594LookupIconIdFromDirectory@8
595LookupIconIdFromDirectoryEx@20
596MBToWCSEx@24
597MBToWCSExt@20
598MB_GetString@4
599MapDialogRect@8
600MapVirtualKeyA@8
601MapVirtualKeyExA@12
602MapVirtualKeyExW@12
603MapVirtualKeyW@8
604MapWindowPoints@16
605MenuItemFromPoint@16
606MenuWindowProcA@20
607MenuWindowProcW@20
608MessageBeep@4
609MessageBoxA@16
610MessageBoxExA@20
611MessageBoxExW@20
612MessageBoxIndirectA@4
613MessageBoxIndirectW@4
614MessageBoxTimeoutA@24
615MessageBoxTimeoutW@24
616MessageBoxW@16
617ModifyMenuA@20
618ModifyMenuW@20
619MonitorFromPoint@12
620MonitorFromRect@8
621MonitorFromWindow@8
622MoveWindow@24
623MsgWaitForMultipleObjects@20
624MsgWaitForMultipleObjectsEx@20
625NotifyOverlayWindow@8
626NotifyWinEvent@16
627OemKeyScan@4
628OemToCharA@8
629OemToCharBuffA@12
630OemToCharBuffW@12
631OemToCharW@8
632OffsetRect@12
633OpenClipboard@4
634OpenDesktopA@16
635OpenDesktopW@16
636OpenIcon@4
637OpenInputDesktop@12
638OpenThreadDesktop@16
639OpenWindowStationA@12
640OpenWindowStationW@12
641PackDDElParam@12
642PackTouchHitTestingProximityEvaluation@8
643PaintDesktop@4
644PaintMenuBar@24
645PaintMonitor@12
646PeekMessageA@20
647PeekMessageW@20
648PhysicalToLogicalPoint@8
649PhysicalToLogicalPointForPerMonitorDPI@8
650PostMessageA@16
651PostMessageW@16
652PostQuitMessage@4
653PostThreadMessageA@16
654PostThreadMessageW@16
655PrintWindow@12
656PrivateExtractIconExA@20
657PrivateExtractIconExW@20
658PrivateExtractIconsA@32
659PrivateExtractIconsW@32
660PrivateSetDbgTag@8
661PrivateSetRipFlags@8
662PrivateRegisterICSProc@4
663PtInRect@12
664QueryBSDRWindow@0
665QueryDisplayConfig@24
666QuerySendMessage@4
667QueryUserCounters@20
668RealChildWindowFromPoint@12
669RealGetWindowClass@12
670RealGetWindowClassA@12
671RealGetWindowClassW@12
672ReasonCodeNeedsBugID@4
673ReasonCodeNeedsComment@4
674RecordShutdownReason@4
675RedrawWindow@16
676RegisterBSDRWindow@8
677RegisterClassA@4
678RegisterClassExA@4
679RegisterClassExW@4
680RegisterClassW@4
681RegisterClipboardFormatA@4
682RegisterClipboardFormatW@4
683RegisterDeviceNotificationA@12
684RegisterDeviceNotificationW@12
685RegisterErrorReportingDialog@8
686RegisterFrostWindow@8
687RegisterGhostWindow@8
688RegisterHotKey@16
689RegisterPowerSettingNotification@12
690RegisterLogonProcess@8
691RegisterMessagePumpHook@4
692RegisterPointerDeviceNotifications@8
693RegisterPointerInputTarget@8
694RegisterPowerSettingNotification@12
695RegisterRawInputDevices@12
696RegisterServicesProcess@4
697RegisterSessionPort@4 ; Undocumented, rumored to be related to ALPC - http://blogs.msdn.com/b/ntdebugging/archive/2007/07/26/lpc-local-procedure-calls-part-1-architecture.aspx
698RegisterShellHookWindow@4
699RegisterSuspendResumeNotification@8
700RegisterSystemThread@8
701RegisterTasklist@4
702RegisterTouchHitTestingWindow@8
703RegisterTouchWindow@8
704RegisterUserApiHook@4 ; Prototype changed in 2003 - https://www.reactos.org/wiki/Techwiki:RegisterUserApiHook
705RegisterWindowMessageA@4
706RegisterWindowMessageW@4
707ReleaseCapture@0
708ReleaseDC@8
709RemoveClipboardFormatListener@4
710RemoveMenu@12
711RemovePropA@8
712RemovePropW@8
713ReplyMessage@4
714ResolveDesktopForWOW@4
715ReuseDDElParam@20
716ScreenToClient@8
717ScrollChildren@12
718ScrollDC@28
719ScrollWindow@20
720ScrollWindowEx@32
721SendDlgItemMessageA@20
722SendDlgItemMessageW@20
723SendIMEMessageExA@8
724SendIMEMessageExW@8
725SendInput@12
726SendMessageA@16
727SendMessageCallbackA@24
728SendMessageCallbackW@24
729SendMessageTimeoutA@28
730SendMessageTimeoutW@28
731SendMessageW@16
732SendNotifyMessageA@16
733SendNotifyMessageW@16
734SetActiveWindow@4
735SetCapture@4
736SetCaretBlinkTime@4
737SetCaretPos@8
738SetClassLongA@12
739SetClassLongW@12
740SetClassWord@12
741SetClipboardData@8
742SetClipboardViewer@4
743SetConsoleReserveKeys@8
744SetCoalescableTimer@20
745SetCursor@4
746SetCursorContents@8
747SetCursorPos@8
748SetDebugErrorLevel@4
749SetDeskWallpaper@4
750SetDisplayAutoRotationPreferences@4
751SetDisplayConfig@20
752SetDlgItemInt@16
753SetDlgItemTextA@12
754SetDlgItemTextW@12
755SetDoubleClickTime@4
756SetFocus@4
757SetForegroundWindow@4
758SetGestureConfig@20
759SetImmersiveBackgroundWindow@4
760SetInternalWindowPos@16
761SetKeyboardState@4
762SetLastErrorEx@8
763SetLayeredWindowAttributes@16
764SetLogonNotifyWindow@4
765SetMagnificationDesktopColorEffect@4
766SetMagnificationDesktopMagnification@16
767SetMagnificationLensCtxInformation@16
768SetMenu@8
769SetMenuContextHelpId@8
770SetMenuDefaultItem@12
771SetMenuInfo@8
772SetMenuItemBitmaps@20
773SetMenuItemInfoA@16
774SetMenuItemInfoW@16
775SetMessageExtraInfo@4
776SetMessageQueue@4
777SetMirrorRendering@8
778SetParent@8
779SetPhysicalCursorPos@8
780SetProcessDPIAware@0
781SetProcessDefaultLayout@4
782SetProcessDpiAwarenessInternal@4
783SetProcessRestrictionExemption@4
784SetProcessWindowStation@4
785SetProgmanWindow@4
786SetPropA@12
787SetPropW@12
788SetRect@20
789SetRectEmpty@4
790SetScrollInfo@16
791SetScrollPos@16
792SetScrollRange@20
793SetShellWindow@4
794SetShellWindowEx@8
795SetSysColors@12
796SetSysColorsTemp@12
797SetSystemCursor@8
798SetSystemMenu@8
799SetSystemTimer@16
800SetTaskmanWindow@4
801SetThreadDesktop@4
802SetThreadInputBlocked@8
803SetTimer@16
804SetUserObjectInformationA@16
805SetUserObjectInformationW@16
806SetUserObjectSecurity@12
807SetWinEventHook@28
808SetWindowBand@12
809SetWindowCompositionAttribute@8
810SetWindowCompositionTransition@28
811SetWindowContextHelpId@8
812SetWindowDisplayAffinity@8
813SetWindowFeedbackSetting@20
814SetWindowLongA@12
815SetWindowLongW@12
816SetWindowPlacement@8
817SetWindowPos@28
818SetWindowRgn@12
819SetWindowRgnEx@12
820SetWindowStationUser@16
821SetWindowTextA@8
822SetWindowTextW@8
823SetWindowWord@12
824SetWindowsHookA@8
825SetWindowsHookExA@16
826SetWindowsHookExW@16
827SetWindowsHookW@8
828SfmDxBindSwapChain@12
829SfmDxGetSwapChainStats@8
830SfmDxOpenSwapChain@16
831SfmDxQuerySwapChainBindingStatus@12
832SfmDxReleaseSwapChain@8
833SfmDxReportPendingBindingsToDwm@0
834SfmDxSetSwapChainBindingStatus@8
835SfmDxSetSwapChainStats@8
836ShowCaret@4
837ShowCursor@4
838ShowOwnedPopups@8
839ShowScrollBar@12
840ShowStartGlass@4
841ShowSystemCursor@4
842ShowWindow@8
843ShowWindowAsync@8
844ShutdownBlockReasonCreate@8
845ShutdownBlockReasonDestroy@4
846ShutdownBlockReasonQuery@12
847SignalRedirectionStartComplete@0
848SkipPointerFrameMessages@4
849SoftModalMessageBox@4
850SoundSentry@0
851SubtractRect@12
852SwapMouseButton@4
853SwitchDesktop@4
854SwitchDesktopWithFade@12 ; Same as SwithDesktop(), only with fade (done at log-in), only usable by winlogon - http://blog.airesoft.co.uk/2010/08/things-microsoft-can-do-that-you-cant/
855SwitchToThisWindow@8
856SystemParametersInfoA@16
857SystemParametersInfoW@16
858TabbedTextOutA@32
859TabbedTextOutW@32
860TileChildWindows@8
861TileWindows@20
862ToAscii@20
863ToAsciiEx@24
864ToUnicode@24
865ToUnicodeEx@28
866TrackMouseEvent@4
867TrackPopupMenu@28
868TrackPopupMenuEx@24
869TranslateAccelerator@12
870TranslateAcceleratorA@12
871TranslateAcceleratorW@12
872TranslateMDISysAccel@8
873TranslateMessage@4
874TranslateMessageEx@8
875UnhookWinEvent@4
876UnhookWindowsHook@8
877UnhookWindowsHookEx@4
878UnionRect@12
879UnloadKeyboardLayout@4
880UnlockWindowStation@4
881UnpackDDElParam@16
882UnregisterClassA@8
883UnregisterClassW@8
884UnregisterDeviceNotification@4
885UnregisterHotKey@8
886UnregisterMessagePumpHook@0
887UnregisterPointerInputTarget@8
888UnregisterPowerSettingNotification@4
889UnregisterSessionPort@0
890UnregisterSuspendResumeNotification@4
891UnregisterTouchWindow@4
892UnregisterUserApiHook@0
893UpdateDefaultDesktopThumbnail@20
894UpdateLayeredWindow@36
895UpdateLayeredWindowIndirect@8
896UpdatePerUserSystemParameters@4 ; Undocumented, seems to apply certain registry settings to desktop, etc. ReactOS has @8 version - http://doxygen.reactos.org/d0/d92/win32ss_2user_2user32_2misc_2misc_8c_a1ff565f0af6bac6dce604f9f4473fe79.html ; @4 is rumored to be without the first DWORD
897UpdateWindow@4
898UpdateWindowInputSinkHints@8
899UpdateWindowTransform@12
900User32InitializeImmEntryTable@4
901UserClientDllInitialize@12
902UserHandleGrantAccess@12
903UserLpkPSMTextOut@24
904UserLpkTabbedTextOut@48
905UserRealizePalette@4
906UserRegisterWowHandlers@8
907VRipOutput@0
908VTagOutput@0
909ValidateRect@8
910ValidateRgn@8
911VkKeyScanA@4
912VkKeyScanExA@8
913VkKeyScanExW@8
914VkKeyScanW@4
915WCSToMBEx@24
916WINNLSEnableIME@8
917WINNLSGetEnableStatus@4
918WINNLSGetIMEHotkey@4
919WaitForInputIdle@8
920WaitForRedirectionStartComplete@0
921WaitMessage@0
922Win32PoolAllocationStats@24
923WinHelpA@16
924WinHelpW@16
925WindowFromDC@4
926WindowFromPhysicalPoint@8
927WindowFromPoint@8
928_UserTestTokenForInteractive@8
929gSharedInfo DATA
930gapfnScSendMessage DATA
931keybd_event@16
932mouse_event@20
933wsprintfA
934wsprintfW
935wvsprintfA@12
936wvsprintfW@12
937;ord_2500@16 @2500
938;ord_2501@12 @2501
939;ord_2502@8 @2502
940;ord_2503@24 @2503
941;ord_2504@8 @2504
942;ord_2505@8 @2505
943;ord_2506@12 @2506
944;ord_2507@4 @2507
945;ord_2508@8 @2508
946;ord_2509@4 @2509
947;ord_2510@12 @2510
948;ord_2511@8 @2511
949;ord_2512@12 @2512
950;ord_2513@4 @2513
951;ord_2514@8 @2514
952;ord_2515@8 @2515
953;ord_2516@12 @2516
954;ord_2517@4 @2517
955;ord_2518@0 @2518
956;ord_2519@4 @2519
957;ord_2520@0 @2520
958;ord_2521@8 @2521
959;ord_2522@4 @2522
960;ord_2523@8 @2523
961;ord_2524@8 @2524
962;ord_2525@12 @2525
963;ord_2526@12 @2526
964;ord_2527@12 @2527
965IsThreadMessageQueueAttached@4
966;ord_2529@4 @2529
967;ord_2530@8 @2530
968;ord_2531@16 @2531
969;ord_2532@8 @2532
970;ord_2533@4 @2533
971;ord_2534@8 @2534
972;ord_2535@0 @2535
973;ord_2536@8 @2536
974;ord_2537@16 @2537
975;ord_2538@4 @2538
976;ord_2539@4 @2539
977;ord_2540@4 @2540
978;ord_2541@0 @2541
979;ord_2544@4 @2544
980;ord_2545@8 @2545
981;ord_2546@4 @2546
982;ord_2547@4 @2547
983;ord_2548@4 @2548
984;ord_2549@4 @2549
985;ord_2550@8 @2550
986;ord_2551@20 @2551
987;ord_2552@8 @2552
988;ord_2553@32 @2553
989;ord_2554@12 @2554
990;ord_2555@16 @2555
991;ord_2556@8 @2556
992;ord_2557@12 @2557
993;ord_2558@12 @2558
994;ord_2559@16 @2559
995;ord_2560@20 @2560
996;ord_2561@0 @2561
997;ord_2562@0 @2562
998;ord_2563@0 @2563
lib/std/array_list.zig+407-167
...@@ -371,7 +371,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -371,7 +371,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
371 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {371 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
372 var self = Self{};372 var self = Self{};
373373
374 const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);374 const new_memory = try allocator.allocAdvanced(T, alignment, num, .at_least);
375 self.items.ptr = new_memory.ptr;375 self.items.ptr = new_memory.ptr;
376 self.capacity = new_memory.len;376 self.capacity = new_memory.len;
377377
...@@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
419 /// Replace range of elements `list[start..start+len]` with `new_items`419 /// Replace range of elements `list[start..start+len]` with `new_items`
420 /// grows list if `len < new_items.len`. may allocate420 /// grows list if `len < new_items.len`. may allocate
421 /// shrinks list if `len > new_items.len`421 /// shrinks list if `len > new_items.len`
422 pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {422 pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void {
423 var managed = self.toManaged(allocator);423 var managed = self.toManaged(allocator);
424 try managed.replaceRange(start, len, new_items);424 try managed.replaceRange(start, len, new_items);
425 self.* = managed.toUnmanaged();425 self.* = managed.toUnmanaged();
...@@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
617 };617 };
618}618}
619619
620test "std.ArrayList.init" {620test "std.ArrayList/ArrayListUnmanaged.init" {
621 var list = ArrayList(i32).init(testing.allocator);621 {
622 defer list.deinit();622 var list = ArrayList(i32).init(testing.allocator);
623 defer list.deinit();
623624
624 testing.expect(list.items.len == 0);625 testing.expect(list.items.len == 0);
625 testing.expect(list.capacity == 0);626 testing.expect(list.capacity == 0);
626}627 }
627628
628test "std.ArrayList.initCapacity" {629 {
629 var list = try ArrayList(i8).initCapacity(testing.allocator, 200);630 var list = ArrayListUnmanaged(i32){};
630 defer list.deinit();
631 testing.expect(list.items.len == 0);
632 testing.expect(list.capacity >= 200);
633}
634631
635test "std.ArrayList.basic" {632 testing.expect(list.items.len == 0);
636 var list = ArrayList(i32).init(testing.allocator);633 testing.expect(list.capacity == 0);
637 defer list.deinit();634 }
635}
638636
637test "std.ArrayList/ArrayListUnmanaged.initCapacity" {
638 const a = testing.allocator;
639 {639 {
640 var i: usize = 0;640 var list = try ArrayList(i8).initCapacity(a, 200);
641 while (i < 10) : (i += 1) {641 defer list.deinit();
642 list.append(@intCast(i32, i + 1)) catch unreachable;642 testing.expect(list.items.len == 0);
643 }643 testing.expect(list.capacity >= 200);
644 }
645 {
646 var list = try ArrayListUnmanaged(i8).initCapacity(a, 200);
647 defer list.deinit(a);
648 testing.expect(list.items.len == 0);
649 testing.expect(list.capacity >= 200);
644 }650 }
651}
645652
653test "std.ArrayList/ArrayListUnmanaged.basic" {
654 const a = testing.allocator;
646 {655 {
647 var i: usize = 0;656 var list = ArrayList(i32).init(a);
648 while (i < 10) : (i += 1) {657 defer list.deinit();
649 testing.expect(list.items[i] == @intCast(i32, i + 1));658
659 {
660 var i: usize = 0;
661 while (i < 10) : (i += 1) {
662 list.append(@intCast(i32, i + 1)) catch unreachable;
663 }
664 }
665
666 {
667 var i: usize = 0;
668 while (i < 10) : (i += 1) {
669 testing.expect(list.items[i] == @intCast(i32, i + 1));
670 }
671 }
672
673 for (list.items) |v, i| {
674 testing.expect(v == @intCast(i32, i + 1));
650 }675 }
651 }
652676
653 for (list.items) |v, i| {677 testing.expect(list.pop() == 10);
654 testing.expect(v == @intCast(i32, i + 1));678 testing.expect(list.items.len == 9);
679
680 list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;
681 testing.expect(list.items.len == 12);
682 testing.expect(list.pop() == 3);
683 testing.expect(list.pop() == 2);
684 testing.expect(list.pop() == 1);
685 testing.expect(list.items.len == 9);
686
687 list.appendSlice(&[_]i32{}) catch unreachable;
688 testing.expect(list.items.len == 9);
689
690 // can only set on indices < self.items.len
691 list.items[7] = 33;
692 list.items[8] = 42;
693
694 testing.expect(list.pop() == 42);
695 testing.expect(list.pop() == 33);
655 }696 }
697 {
698 var list = ArrayListUnmanaged(i32){};
699 defer list.deinit(a);
700
701 {
702 var i: usize = 0;
703 while (i < 10) : (i += 1) {
704 list.append(a, @intCast(i32, i + 1)) catch unreachable;
705 }
706 }
707
708 {
709 var i: usize = 0;
710 while (i < 10) : (i += 1) {
711 testing.expect(list.items[i] == @intCast(i32, i + 1));
712 }
713 }
714
715 for (list.items) |v, i| {
716 testing.expect(v == @intCast(i32, i + 1));
717 }
656718
657 testing.expect(list.pop() == 10);719 testing.expect(list.pop() == 10);
658 testing.expect(list.items.len == 9);720 testing.expect(list.items.len == 9);
659721
660 list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;722 list.appendSlice(a, &[_]i32{ 1, 2, 3 }) catch unreachable;
661 testing.expect(list.items.len == 12);723 testing.expect(list.items.len == 12);
662 testing.expect(list.pop() == 3);724 testing.expect(list.pop() == 3);
663 testing.expect(list.pop() == 2);725 testing.expect(list.pop() == 2);
664 testing.expect(list.pop() == 1);726 testing.expect(list.pop() == 1);
665 testing.expect(list.items.len == 9);727 testing.expect(list.items.len == 9);
666728
667 list.appendSlice(&[_]i32{}) catch unreachable;729 list.appendSlice(a, &[_]i32{}) catch unreachable;
668 testing.expect(list.items.len == 9);730 testing.expect(list.items.len == 9);
669731
670 // can only set on indices < self.items.len732 // can only set on indices < self.items.len
671 list.items[7] = 33;733 list.items[7] = 33;
672 list.items[8] = 42;734 list.items[8] = 42;
673735
674 testing.expect(list.pop() == 42);736 testing.expect(list.pop() == 42);
675 testing.expect(list.pop() == 33);737 testing.expect(list.pop() == 33);
738 }
676}739}
677740
678test "std.ArrayList.appendNTimes" {741test "std.ArrayList/ArrayListUnmanaged.appendNTimes" {
679 var list = ArrayList(i32).init(testing.allocator);742 const a = testing.allocator;
680 defer list.deinit();743 {
744 var list = ArrayList(i32).init(a);
745 defer list.deinit();
746
747 try list.appendNTimes(2, 10);
748 testing.expectEqual(@as(usize, 10), list.items.len);
749 for (list.items) |element| {
750 testing.expectEqual(@as(i32, 2), element);
751 }
752 }
753 {
754 var list = ArrayListUnmanaged(i32){};
755 defer list.deinit(a);
681756
682 try list.appendNTimes(2, 10);757 try list.appendNTimes(a, 2, 10);
683 testing.expectEqual(@as(usize, 10), list.items.len);758 testing.expectEqual(@as(usize, 10), list.items.len);
684 for (list.items) |element| {759 for (list.items) |element| {
685 testing.expectEqual(@as(i32, 2), element);760 testing.expectEqual(@as(i32, 2), element);
761 }
686 }762 }
687}763}
688764
689test "std.ArrayList.appendNTimes with failing allocator" {765test "std.ArrayList/ArrayListUnmanaged.appendNTimes with failing allocator" {
690 var list = ArrayList(i32).init(testing.failing_allocator);766 const a = testing.failing_allocator;
691 defer list.deinit();767 {
692 testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));768 var list = ArrayList(i32).init(a);
769 defer list.deinit();
770 testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
771 }
772 {
773 var list = ArrayListUnmanaged(i32){};
774 defer list.deinit(a);
775 testing.expectError(error.OutOfMemory, list.appendNTimes(a, 2, 10));
776 }
693}777}
694778
695test "std.ArrayList.orderedRemove" {779test "std.ArrayList/ArrayListUnmanaged.orderedRemove" {
696 var list = ArrayList(i32).init(testing.allocator);780 const a = testing.allocator;
697 defer list.deinit();781 {
782 var list = ArrayList(i32).init(a);
783 defer list.deinit();
784
785 try list.append(1);
786 try list.append(2);
787 try list.append(3);
788 try list.append(4);
789 try list.append(5);
790 try list.append(6);
791 try list.append(7);
792
793 //remove from middle
794 testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
795 testing.expectEqual(@as(i32, 5), list.items[3]);
796 testing.expectEqual(@as(usize, 6), list.items.len);
797
798 //remove from end
799 testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
800 testing.expectEqual(@as(usize, 5), list.items.len);
801
802 //remove from front
803 testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
804 testing.expectEqual(@as(i32, 2), list.items[0]);
805 testing.expectEqual(@as(usize, 4), list.items.len);
806 }
807 {
808 var list = ArrayListUnmanaged(i32){};
809 defer list.deinit(a);
698810
699 try list.append(1);811 try list.append(a, 1);
700 try list.append(2);812 try list.append(a, 2);
701 try list.append(3);813 try list.append(a, 3);
702 try list.append(4);814 try list.append(a, 4);
703 try list.append(5);815 try list.append(a, 5);
704 try list.append(6);816 try list.append(a, 6);
705 try list.append(7);817 try list.append(a, 7);
706818
707 //remove from middle819 //remove from middle
708 testing.expectEqual(@as(i32, 4), list.orderedRemove(3));820 testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
709 testing.expectEqual(@as(i32, 5), list.items[3]);821 testing.expectEqual(@as(i32, 5), list.items[3]);
710 testing.expectEqual(@as(usize, 6), list.items.len);822 testing.expectEqual(@as(usize, 6), list.items.len);
711823
712 //remove from end824 //remove from end
713 testing.expectEqual(@as(i32, 7), list.orderedRemove(5));825 testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
714 testing.expectEqual(@as(usize, 5), list.items.len);826 testing.expectEqual(@as(usize, 5), list.items.len);
715827
716 //remove from front828 //remove from front
717 testing.expectEqual(@as(i32, 1), list.orderedRemove(0));829 testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
718 testing.expectEqual(@as(i32, 2), list.items[0]);830 testing.expectEqual(@as(i32, 2), list.items[0]);
719 testing.expectEqual(@as(usize, 4), list.items.len);831 testing.expectEqual(@as(usize, 4), list.items.len);
832 }
720}833}
721834
722test "std.ArrayList.swapRemove" {835test "std.ArrayList/ArrayListUnmanaged.swapRemove" {
723 var list = ArrayList(i32).init(testing.allocator);836 const a = testing.allocator;
724 defer list.deinit();837 {
838 var list = ArrayList(i32).init(a);
839 defer list.deinit();
725840
726 try list.append(1);841 try list.append(1);
727 try list.append(2);842 try list.append(2);
728 try list.append(3);843 try list.append(3);
729 try list.append(4);844 try list.append(4);
730 try list.append(5);845 try list.append(5);
731 try list.append(6);846 try list.append(6);
732 try list.append(7);847 try list.append(7);
733848
734 //remove from middle849 //remove from middle
735 testing.expect(list.swapRemove(3) == 4);850 testing.expect(list.swapRemove(3) == 4);
736 testing.expect(list.items[3] == 7);851 testing.expect(list.items[3] == 7);
737 testing.expect(list.items.len == 6);852 testing.expect(list.items.len == 6);
738853
739 //remove from end854 //remove from end
740 testing.expect(list.swapRemove(5) == 6);855 testing.expect(list.swapRemove(5) == 6);
741 testing.expect(list.items.len == 5);856 testing.expect(list.items.len == 5);
742857
743 //remove from front858 //remove from front
744 testing.expect(list.swapRemove(0) == 1);859 testing.expect(list.swapRemove(0) == 1);
745 testing.expect(list.items[0] == 5);860 testing.expect(list.items[0] == 5);
746 testing.expect(list.items.len == 4);861 testing.expect(list.items.len == 4);
862 }
863 {
864 var list = ArrayListUnmanaged(i32){};
865 defer list.deinit(a);
866
867 try list.append(a, 1);
868 try list.append(a, 2);
869 try list.append(a, 3);
870 try list.append(a, 4);
871 try list.append(a, 5);
872 try list.append(a, 6);
873 try list.append(a, 7);
874
875 //remove from middle
876 testing.expect(list.swapRemove(3) == 4);
877 testing.expect(list.items[3] == 7);
878 testing.expect(list.items.len == 6);
879
880 //remove from end
881 testing.expect(list.swapRemove(5) == 6);
882 testing.expect(list.items.len == 5);
883
884 //remove from front
885 testing.expect(list.swapRemove(0) == 1);
886 testing.expect(list.items[0] == 5);
887 testing.expect(list.items.len == 4);
888 }
747}889}
748890
749test "std.ArrayList.insert" {891test "std.ArrayList/ArrayListUnmanaged.insert" {
750 var list = ArrayList(i32).init(testing.allocator);892 const a = testing.allocator;
751 defer list.deinit();893 {
894 var list = ArrayList(i32).init(a);
895 defer list.deinit();
752896
753 try list.append(1);897 try list.append(1);
754 try list.append(2);898 try list.append(2);
755 try list.append(3);899 try list.append(3);
756 try list.insert(0, 5);900 try list.insert(0, 5);
757 testing.expect(list.items[0] == 5);901 testing.expect(list.items[0] == 5);
758 testing.expect(list.items[1] == 1);902 testing.expect(list.items[1] == 1);
759 testing.expect(list.items[2] == 2);903 testing.expect(list.items[2] == 2);
760 testing.expect(list.items[3] == 3);904 testing.expect(list.items[3] == 3);
905 }
906 {
907 var list = ArrayListUnmanaged(i32){};
908 defer list.deinit(a);
909
910 try list.append(a, 1);
911 try list.append(a, 2);
912 try list.append(a, 3);
913 try list.insert(a, 0, 5);
914 testing.expect(list.items[0] == 5);
915 testing.expect(list.items[1] == 1);
916 testing.expect(list.items[2] == 2);
917 testing.expect(list.items[3] == 3);
918 }
761}919}
762920
763test "std.ArrayList.insertSlice" {921test "std.ArrayList/ArrayListUnmanaged.insertSlice" {
764 var list = ArrayList(i32).init(testing.allocator);922 const a = testing.allocator;
765 defer list.deinit();923 {
924 var list = ArrayList(i32).init(a);
925 defer list.deinit();
766926
767 try list.append(1);927 try list.append(1);
768 try list.append(2);928 try list.append(2);
769 try list.append(3);929 try list.append(3);
770 try list.append(4);930 try list.append(4);
771 try list.insertSlice(1, &[_]i32{ 9, 8 });931 try list.insertSlice(1, &[_]i32{ 9, 8 });
772 testing.expect(list.items[0] == 1);932 testing.expect(list.items[0] == 1);
773 testing.expect(list.items[1] == 9);933 testing.expect(list.items[1] == 9);
774 testing.expect(list.items[2] == 8);934 testing.expect(list.items[2] == 8);
775 testing.expect(list.items[3] == 2);935 testing.expect(list.items[3] == 2);
776 testing.expect(list.items[4] == 3);936 testing.expect(list.items[4] == 3);
777 testing.expect(list.items[5] == 4);937 testing.expect(list.items[5] == 4);
778938
779 const items = [_]i32{1};939 const items = [_]i32{1};
780 try list.insertSlice(0, items[0..0]);940 try list.insertSlice(0, items[0..0]);
781 testing.expect(list.items.len == 6);941 testing.expect(list.items.len == 6);
782 testing.expect(list.items[0] == 1);942 testing.expect(list.items[0] == 1);
943 }
944 {
945 var list = ArrayListUnmanaged(i32){};
946 defer list.deinit(a);
947
948 try list.append(a, 1);
949 try list.append(a, 2);
950 try list.append(a, 3);
951 try list.append(a, 4);
952 try list.insertSlice(a, 1, &[_]i32{ 9, 8 });
953 testing.expect(list.items[0] == 1);
954 testing.expect(list.items[1] == 9);
955 testing.expect(list.items[2] == 8);
956 testing.expect(list.items[3] == 2);
957 testing.expect(list.items[4] == 3);
958 testing.expect(list.items[5] == 4);
959
960 const items = [_]i32{1};
961 try list.insertSlice(a, 0, items[0..0]);
962 testing.expect(list.items.len == 6);
963 testing.expect(list.items[0] == 1);
964 }
783}965}
784966
785test "std.ArrayList.replaceRange" {967test "std.ArrayList/ArrayListUnmanaged.replaceRange" {
786 var arena = std.heap.ArenaAllocator.init(testing.allocator);968 var arena = std.heap.ArenaAllocator.init(testing.allocator);
787 defer arena.deinit();969 defer arena.deinit();
970 const a = &arena.allocator;
788971
789 const alloc = &arena.allocator;
790 const init = [_]i32{ 1, 2, 3, 4, 5 };972 const init = [_]i32{ 1, 2, 3, 4, 5 };
791 const new = [_]i32{ 0, 0, 0 };973 const new = [_]i32{ 0, 0, 0 };
792974
793 var list_zero = ArrayList(i32).init(alloc);975 const result_zero = [_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 };
794 var list_eq = ArrayList(i32).init(alloc);976 const result_eq = [_]i32{ 1, 0, 0, 0, 5 };
795 var list_lt = ArrayList(i32).init(alloc);977 const result_le = [_]i32{ 1, 0, 0, 0, 4, 5 };
796 var list_gt = ArrayList(i32).init(alloc);978 const result_gt = [_]i32{ 1, 0, 0, 0 };
797979
798 try list_zero.appendSlice(&init);980 {
799 try list_eq.appendSlice(&init);981 var list_zero = ArrayList(i32).init(a);
800 try list_lt.appendSlice(&init);982 var list_eq = ArrayList(i32).init(a);
801 try list_gt.appendSlice(&init);983 var list_lt = ArrayList(i32).init(a);
802984 var list_gt = ArrayList(i32).init(a);
803 try list_zero.replaceRange(1, 0, &new);985
804 try list_eq.replaceRange(1, 3, &new);986 try list_zero.appendSlice(&init);
805 try list_lt.replaceRange(1, 2, &new);987 try list_eq.appendSlice(&init);
806988 try list_lt.appendSlice(&init);
807 // after_range > new_items.len in function body989 try list_gt.appendSlice(&init);
808 testing.expect(1 + 4 > new.len);990
809 try list_gt.replaceRange(1, 4, &new);991 try list_zero.replaceRange(1, 0, &new);
810992 try list_eq.replaceRange(1, 3, &new);
811 testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 });993 try list_lt.replaceRange(1, 2, &new);
812 testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 });994
813 testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 });995 // after_range > new_items.len in function body
814 testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 });996 testing.expect(1 + 4 > new.len);
997 try list_gt.replaceRange(1, 4, &new);
998
999 testing.expectEqualSlices(i32, list_zero.items, &result_zero);
1000 testing.expectEqualSlices(i32, list_eq.items, &result_eq);
1001 testing.expectEqualSlices(i32, list_lt.items, &result_le);
1002 testing.expectEqualSlices(i32, list_gt.items, &result_gt);
1003 }
1004 {
1005 var list_zero = ArrayListUnmanaged(i32){};
1006 var list_eq = ArrayListUnmanaged(i32){};
1007 var list_lt = ArrayListUnmanaged(i32){};
1008 var list_gt = ArrayListUnmanaged(i32){};
1009
1010 try list_zero.appendSlice(a, &init);
1011 try list_eq.appendSlice(a, &init);
1012 try list_lt.appendSlice(a, &init);
1013 try list_gt.appendSlice(a, &init);
1014
1015 try list_zero.replaceRange(a, 1, 0, &new);
1016 try list_eq.replaceRange(a, 1, 3, &new);
1017 try list_lt.replaceRange(a, 1, 2, &new);
1018
1019 // after_range > new_items.len in function body
1020 testing.expect(1 + 4 > new.len);
1021 try list_gt.replaceRange(a, 1, 4, &new);
1022
1023 testing.expectEqualSlices(i32, list_zero.items, &result_zero);
1024 testing.expectEqualSlices(i32, list_eq.items, &result_eq);
1025 testing.expectEqualSlices(i32, list_lt.items, &result_le);
1026 testing.expectEqualSlices(i32, list_gt.items, &result_gt);
1027 }
815}1028}
8161029
817const Item = struct {1030const Item = struct {
...@@ -819,11 +1032,25 @@ const Item = struct {...@@ -819,11 +1032,25 @@ const Item = struct {
819 sub_items: ArrayList(Item),1032 sub_items: ArrayList(Item),
820};1033};
8211034
822test "std.ArrayList: ArrayList(T) of struct T" {1035const ItemUnmanaged = struct {
823 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) };1036 integer: i32,
824 defer root.sub_items.deinit();1037 sub_items: ArrayListUnmanaged(ItemUnmanaged),
825 try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) });1038};
826 testing.expect(root.sub_items.items[0].integer == 42);1039
1040test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" {
1041 const a = std.testing.allocator;
1042 {
1043 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(a) };
1044 defer root.sub_items.deinit();
1045 try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(a) });
1046 testing.expect(root.sub_items.items[0].integer == 42);
1047 }
1048 {
1049 var root = ItemUnmanaged{ .integer = 1, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} };
1050 defer root.sub_items.deinit(a);
1051 try root.sub_items.append(a, ItemUnmanaged{ .integer = 42, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} });
1052 testing.expect(root.sub_items.items[0].integer == 42);
1053 }
827}1054}
8281055
829test "std.ArrayList(u8) implements outStream" {1056test "std.ArrayList(u8) implements outStream" {
...@@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" {...@@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" {
837 testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span());1064 testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span());
838}1065}
8391066
840test "std.ArrayList.shrink still sets length on error.OutOfMemory" {1067test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" {
841 // use an arena allocator to make sure realloc returns error.OutOfMemory1068 // use an arena allocator to make sure realloc returns error.OutOfMemory
842 var arena = std.heap.ArenaAllocator.init(testing.allocator);1069 var arena = std.heap.ArenaAllocator.init(testing.allocator);
843 defer arena.deinit();1070 defer arena.deinit();
1071 const a = &arena.allocator;
8441072
845 var list = ArrayList(i32).init(&arena.allocator);1073 {
1074 var list = ArrayList(i32).init(a);
8461075
847 try list.append(1);1076 try list.append(1);
848 try list.append(2);1077 try list.append(2);
849 try list.append(3);1078 try list.append(3);
8501079
851 list.shrink(1);1080 list.shrink(1);
852 testing.expect(list.items.len == 1);1081 testing.expect(list.items.len == 1);
1082 }
1083 {
1084 var list = ArrayListUnmanaged(i32){};
1085
1086 try list.append(a, 1);
1087 try list.append(a, 2);
1088 try list.append(a, 3);
1089
1090 list.shrink(a, 1);
1091 testing.expect(list.items.len == 1);
1092 }
853}1093}
8541094
855test "std.ArrayList.writer" {1095test "std.ArrayList.writer" {
...@@ -864,7 +1104,7 @@ test "std.ArrayList.writer" {...@@ -864,7 +1104,7 @@ test "std.ArrayList.writer" {
864 testing.expectEqualSlices(u8, list.items, "abcdefg");1104 testing.expectEqualSlices(u8, list.items, "abcdefg");
865}1105}
8661106
867test "addManyAsArray" {1107test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
868 const a = std.testing.allocator;1108 const a = std.testing.allocator;
869 {1109 {
870 var list = ArrayList(u8).init(a);1110 var list = ArrayList(u8).init(a);
lib/std/build.zig+6-2
...@@ -1239,6 +1239,7 @@ pub const LibExeObjStep = struct {...@@ -1239,6 +1239,7 @@ pub const LibExeObjStep = struct {
1239 /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF1239 /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
1240 /// file.1240 /// file.
1241 link_eh_frame_hdr: bool = false,1241 link_eh_frame_hdr: bool = false,
1242 link_emit_relocs: bool = false,
12421243
1243 /// Place every function in its own section so that unused ones may be1244 /// Place every function in its own section so that unused ones may be
1244 /// safely garbage-collected during the linking phase.1245 /// safely garbage-collected during the linking phase.
...@@ -2075,6 +2076,9 @@ pub const LibExeObjStep = struct {...@@ -2075,6 +2076,9 @@ pub const LibExeObjStep = struct {
2075 if (self.link_eh_frame_hdr) {2076 if (self.link_eh_frame_hdr) {
2076 try zig_args.append("--eh-frame-hdr");2077 try zig_args.append("--eh-frame-hdr");
2077 }2078 }
2079 if (self.link_emit_relocs) {
2080 try zig_args.append("--emit-relocs");
2081 }
2078 if (self.link_function_sections) {2082 if (self.link_function_sections) {
2079 try zig_args.append("-ffunction-sections");2083 try zig_args.append("-ffunction-sections");
2080 }2084 }
...@@ -2168,8 +2172,8 @@ pub const LibExeObjStep = struct {...@@ -2168,8 +2172,8 @@ pub const LibExeObjStep = struct {
2168 }2172 }
21692173
2170 if (self.linker_script) |linker_script| {2174 if (self.linker_script) |linker_script| {
2171 zig_args.append("--linker-script") catch unreachable;2175 try zig_args.append("--script");
2172 zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;2176 try zig_args.append(builder.pathFromRoot(linker_script));
2173 }2177 }
21742178
2175 if (self.version_script) |version_script| {2179 if (self.version_script) |version_script| {
lib/std/builtin.zig+3
...@@ -262,6 +262,7 @@ pub const TypeInfo = union(enum) {...@@ -262,6 +262,7 @@ pub const TypeInfo = union(enum) {
262 field_type: type,262 field_type: type,
263 default_value: anytype,263 default_value: anytype,
264 is_comptime: bool,264 is_comptime: bool,
265 alignment: comptime_int,
265 };266 };
266267
267 /// This data structure is used by the Zig language code generation and268 /// This data structure is used by the Zig language code generation and
...@@ -318,6 +319,7 @@ pub const TypeInfo = union(enum) {...@@ -318,6 +319,7 @@ pub const TypeInfo = union(enum) {
318 pub const UnionField = struct {319 pub const UnionField = struct {
319 name: []const u8,320 name: []const u8,
320 field_type: type,321 field_type: type,
322 alignment: comptime_int,
321 };323 };
322324
323 /// This data structure is used by the Zig language code generation and325 /// This data structure is used by the Zig language code generation and
...@@ -341,6 +343,7 @@ pub const TypeInfo = union(enum) {...@@ -341,6 +343,7 @@ pub const TypeInfo = union(enum) {
341 /// therefore must be kept in sync with the compiler implementation.343 /// therefore must be kept in sync with the compiler implementation.
342 pub const Fn = struct {344 pub const Fn = struct {
343 calling_convention: CallingConvention,345 calling_convention: CallingConvention,
346 alignment: comptime_int,
344 is_generic: bool,347 is_generic: bool,
345 is_var_args: bool,348 is_var_args: bool,
346 return_type: ?type,349 return_type: ?type,
lib/std/c/darwin.zig+1-1
...@@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig");...@@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig");
1212
13extern "c" fn __error() *c_int;13extern "c" fn __error() *c_int;
14pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;14pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
15pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;15pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
16pub extern "c" fn _dyld_image_count() u32;16pub extern "c" fn _dyld_image_count() u32;
17pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;17pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
18pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;18pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
lib/std/crypto.zig+46-40
...@@ -4,6 +4,48 @@...@@ -4,6 +4,48 @@
4// The MIT license requires this copyright notice to be included in all copies4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.5// and substantial portions of the software.
66
7/// Authenticated Encryption with Associated Data
8pub const aead = struct {
9 const chacha20 = @import("crypto/chacha20.zig");
10
11 pub const Gimli = @import("crypto/gimli.zig").Aead;
12 pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
13 pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
14 pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
15 pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
16};
17
18/// Authentication (MAC) functions.
19pub const auth = struct {
20 pub const hmac = @import("crypto/hmac.zig");
21 pub const siphash = @import("crypto/siphash.zig");
22};
23
24/// Core functions, that should rarely be used directly by applications.
25pub const core = struct {
26 pub const aes = @import("crypto/aes.zig");
27 pub const Gimli = @import("crypto/gimli.zig").State;
28
29 /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
30 ///
31 /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
32 ///
33 /// Most applications may want to use AEADs instead.
34 pub const modes = @import("crypto/modes.zig");
35};
36
37/// Diffie-Hellman key exchange functions.
38pub const dh = struct {
39 pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
40};
41
42/// Elliptic-curve arithmetic.
43pub const ecc = struct {
44 pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
45 pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
46 pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
47};
48
7/// Hash functions.49/// Hash functions.
8pub const hash = struct {50pub const hash = struct {
9 pub const Md5 = @import("crypto/md5.zig").Md5;51 pub const Md5 = @import("crypto/md5.zig").Md5;
...@@ -15,26 +57,15 @@ pub const hash = struct {...@@ -15,26 +57,15 @@ pub const hash = struct {
15 pub const Gimli = @import("crypto/gimli.zig").Hash;57 pub const Gimli = @import("crypto/gimli.zig").Hash;
16};58};
1759
18/// Authentication (MAC) functions.60/// Key derivation functions.
19pub const auth = struct {61pub const kdf = struct {
20 pub const hmac = @import("crypto/hmac.zig");62 pub const hkdf = @import("crypto/hkdf.zig");
21 pub const siphash = @import("crypto/siphash.zig");
22};
23
24/// Authenticated Encryption with Associated Data
25pub const aead = struct {
26 const chacha20 = @import("crypto/chacha20.zig");
27
28 pub const Gimli = @import("crypto/gimli.zig").Aead;
29 pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
30 pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
31 pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
32 pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
33};63};
3464
35/// MAC functions requiring single-use secret keys.65/// MAC functions requiring single-use secret keys.
36pub const onetimeauth = struct {66pub const onetimeauth = struct {
37 pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;67 pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
68 pub const Ghash = @import("crypto/ghash.zig").Ghash;
38};69};
3970
40/// A password hashing function derives a uniform key from low-entropy input material such as passwords.71/// A password hashing function derives a uniform key from low-entropy input material such as passwords.
...@@ -57,31 +88,6 @@ pub const pwhash = struct {...@@ -57,31 +88,6 @@ pub const pwhash = struct {
57 pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;88 pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;
58};89};
5990
60/// Core functions, that should rarely be used directly by applications.
61pub const core = struct {
62 pub const aes = @import("crypto/aes.zig");
63 pub const Gimli = @import("crypto/gimli.zig").State;
64
65 /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
66 ///
67 /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
68 ///
69 /// Most applications may want to use AEADs instead.
70 pub const modes = @import("crypto/modes.zig");
71};
72
73/// Elliptic-curve arithmetic.
74pub const ecc = struct {
75 pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
76 pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
77 pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
78};
79
80/// Diffie-Hellman key exchange functions.
81pub const dh = struct {
82 pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
83};
84
85/// Digital signature functions.91/// Digital signature functions.
86pub const sign = struct {92pub const sign = struct {
87 pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;93 pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
lib/std/crypto/benchmark.zig+1
...@@ -57,6 +57,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64...@@ -57,6 +57,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
57}57}
5858
59const macs = [_]Crypto{59const macs = [_]Crypto{
60 Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" },
60 Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },61 Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
61 Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },62 Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },
62 Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },63 Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },
lib/std/crypto/ghash.zig created+310
...@@ -0,0 +1,310 @@
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2015-2020 Zig Contributors
3// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
4// The MIT license requires this copyright notice to be included in all copies
5// and substantial portions of the software.
6//
7// Adapted from BearSSL's ctmul64 implementation originally written by Thomas Pornin <pornin@bolet.org>
8
9const std = @import("../std.zig");
10const assert = std.debug.assert;
11const math = std.math;
12const mem = std.mem;
13
14/// GHASH is a universal hash function that features multiplication
15/// by a fixed parameter within a Galois field.
16///
17/// It is not a general purpose hash function - The key must be secret, unpredictable and never reused.
18///
19/// GHASH is typically used to compute the authentication tag in the AES-GCM construction.
20pub const Ghash = struct {
21 pub const block_size: usize = 16;
22 pub const mac_length = 16;
23 pub const minimum_key_length = 16;
24
25 y0: u64 = 0,
26 y1: u64 = 0,
27 h0: u64,
28 h1: u64,
29 h2: u64,
30 h0r: u64,
31 h1r: u64,
32 h2r: u64,
33
34 hh0: u64 = undefined,
35 hh1: u64 = undefined,
36 hh2: u64 = undefined,
37 hh0r: u64 = undefined,
38 hh1r: u64 = undefined,
39 hh2r: u64 = undefined,
40
41 leftover: usize = 0,
42 buf: [block_size]u8 align(16) = undefined,
43
44 pub fn init(key: *const [minimum_key_length]u8) Ghash {
45 const h1 = mem.readIntBig(u64, key[0..8]);
46 const h0 = mem.readIntBig(u64, key[8..16]);
47 const h1r = @bitReverse(u64, h1);
48 const h0r = @bitReverse(u64, h0);
49 const h2 = h0 ^ h1;
50 const h2r = h0r ^ h1r;
51
52 if (std.builtin.mode == .ReleaseSmall) {
53 return Ghash{
54 .h0 = h0,
55 .h1 = h1,
56 .h2 = h2,
57 .h0r = h0r,
58 .h1r = h1r,
59 .h2r = h2r,
60 };
61 } else {
62 // Precompute H^2
63 var hh = Ghash{
64 .h0 = h0,
65 .h1 = h1,
66 .h2 = h2,
67 .h0r = h0r,
68 .h1r = h1r,
69 .h2r = h2r,
70 };
71 hh.update(key);
72 const hh1 = hh.y1;
73 const hh0 = hh.y0;
74 const hh1r = @bitReverse(u64, hh1);
75 const hh0r = @bitReverse(u64, hh0);
76 const hh2 = hh0 ^ hh1;
77 const hh2r = hh0r ^ hh1r;
78
79 return Ghash{
80 .h0 = h0,
81 .h1 = h1,
82 .h2 = h2,
83 .h0r = h0r,
84 .h1r = h1r,
85 .h2r = h2r,
86
87 .hh0 = hh0,
88 .hh1 = hh1,
89 .hh2 = hh2,
90 .hh0r = hh0r,
91 .hh1r = hh1r,
92 .hh2r = hh2r,
93 };
94 }
95 }
96
97 inline fn clmul_pclmul(x: u64, y: u64) u64 {
98 const Vector = std.meta.Vector;
99 const product = asm (
100 \\ vpclmulqdq $0x00, %[x], %[y], %[out]
101 : [out] "=x" (-> Vector(2, u64))
102 : [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))),
103 [y] "x" (@bitCast(Vector(2, u64), @as(u128, y)))
104 );
105 return product[0];
106 }
107
108 fn clmul_soft(x: u64, y: u64) u64 {
109 const x0 = x & 0x1111111111111111;
110 const x1 = x & 0x2222222222222222;
111 const x2 = x & 0x4444444444444444;
112 const x3 = x & 0x8888888888888888;
113 const y0 = y & 0x1111111111111111;
114 const y1 = y & 0x2222222222222222;
115 const y2 = y & 0x4444444444444444;
116 const y3 = y & 0x8888888888888888;
117 var z0 = (x0 *% y0) ^ (x1 *% y3) ^ (x2 *% y2) ^ (x3 *% y1);
118 var z1 = (x0 *% y1) ^ (x1 *% y0) ^ (x2 *% y3) ^ (x3 *% y2);
119 var z2 = (x0 *% y2) ^ (x1 *% y1) ^ (x2 *% y0) ^ (x3 *% y3);
120 var z3 = (x0 *% y3) ^ (x1 *% y2) ^ (x2 *% y1) ^ (x3 *% y0);
121 z0 &= 0x1111111111111111;
122 z1 &= 0x2222222222222222;
123 z2 &= 0x4444444444444444;
124 z3 &= 0x8888888888888888;
125 return z0 | z1 | z2 | z3;
126 }
127
128 const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul);
129 const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);
130 const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft;
131
132 fn blocks(st: *Ghash, msg: []const u8) void {
133 assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks
134 var y1 = st.y1;
135 var y0 = st.y0;
136
137 var i: usize = 0;
138
139 // 2-blocks aggregated reduction
140 if (std.builtin.mode != .ReleaseSmall) {
141 while (i + 32 <= msg.len) : (i += 32) {
142 // B0 * H^2 unreduced
143 y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
144 y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
145
146 const y1r = @bitReverse(u64, y1);
147 const y0r = @bitReverse(u64, y0);
148 const y2 = y0 ^ y1;
149 const y2r = y0r ^ y1r;
150
151 var z0 = clmul(y0, st.hh0);
152 var z1 = clmul(y1, st.hh1);
153 var z2 = clmul(y2, st.hh2) ^ z0 ^ z1;
154 var z0h = clmul(y0r, st.hh0r);
155 var z1h = clmul(y1r, st.hh1r);
156 var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h;
157
158 // B1 * H unreduced
159 const sy1 = mem.readIntBig(u64, msg[i..][16..24]);
160 const sy0 = mem.readIntBig(u64, msg[i..][24..32]);
161
162 const sy1r = @bitReverse(u64, sy1);
163 const sy0r = @bitReverse(u64, sy0);
164 const sy2 = sy0 ^ sy1;
165 const sy2r = sy0r ^ sy1r;
166
167 const sz0 = clmul(sy0, st.h0);
168 const sz1 = clmul(sy1, st.h1);
169 const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1;
170 const sz0h = clmul(sy0r, st.h0r);
171 const sz1h = clmul(sy1r, st.h1r);
172 const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h;
173
174 // ((B0 * H^2) + B1 * H) (mod M)
175 z0 ^= sz0;
176 z1 ^= sz1;
177 z2 ^= sz2;
178 z0h ^= sz0h;
179 z1h ^= sz1h;
180 z2h ^= sz2h;
181 z0h = @bitReverse(u64, z0h) >> 1;
182 z1h = @bitReverse(u64, z1h) >> 1;
183 z2h = @bitReverse(u64, z2h) >> 1;
184
185 var v3 = z1h;
186 var v2 = z1 ^ z2h;
187 var v1 = z0h ^ z2;
188 var v0 = z0;
189
190 v3 = (v3 << 1) | (v2 >> 63);
191 v2 = (v2 << 1) | (v1 >> 63);
192 v1 = (v1 << 1) | (v0 >> 63);
193 v0 = (v0 << 1);
194
195 v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
196 v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
197 y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
198 y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
199 }
200 }
201
202 // single block
203 while (i + 16 <= msg.len) : (i += 16) {
204 y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
205 y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
206
207 const y1r = @bitReverse(u64, y1);
208 const y0r = @bitReverse(u64, y0);
209 const y2 = y0 ^ y1;
210 const y2r = y0r ^ y1r;
211
212 const z0 = clmul(y0, st.h0);
213 const z1 = clmul(y1, st.h1);
214 var z2 = clmul(y2, st.h2) ^ z0 ^ z1;
215 var z0h = clmul(y0r, st.h0r);
216 var z1h = clmul(y1r, st.h1r);
217 var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h;
218 z0h = @bitReverse(u64, z0h) >> 1;
219 z1h = @bitReverse(u64, z1h) >> 1;
220 z2h = @bitReverse(u64, z2h) >> 1;
221
222 // shift & reduce
223 var v3 = z1h;
224 var v2 = z1 ^ z2h;
225 var v1 = z0h ^ z2;
226 var v0 = z0;
227
228 v3 = (v3 << 1) | (v2 >> 63);
229 v2 = (v2 << 1) | (v1 >> 63);
230 v1 = (v1 << 1) | (v0 >> 63);
231 v0 = (v0 << 1);
232
233 v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
234 v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
235 y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
236 y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
237 }
238 st.y1 = y1;
239 st.y0 = y0;
240 }
241
242 pub fn update(st: *Ghash, m: []const u8) void {
243 var mb = m;
244
245 if (st.leftover > 0) {
246 const want = math.min(block_size - st.leftover, mb.len);
247 const mc = mb[0..want];
248 for (mc) |x, i| {
249 st.buf[st.leftover + i] = x;
250 }
251 mb = mb[want..];
252 st.leftover += want;
253 if (st.leftover > block_size) {
254 return;
255 }
256 st.blocks(&st.buf);
257 st.leftover = 0;
258 }
259 if (mb.len >= block_size) {
260 const want = mb.len & ~(block_size - 1);
261 st.blocks(mb[0..want]);
262 mb = mb[want..];
263 }
264 if (mb.len > 0) {
265 for (mb) |x, i| {
266 st.buf[st.leftover + i] = x;
267 }
268 st.leftover += mb.len;
269 }
270 }
271
272 pub fn final(st: *Ghash, out: *[mac_length]u8) void {
273 if (st.leftover > 0) {
274 var i = st.leftover;
275 while (i < block_size) : (i += 1) {
276 st.buf[i] = 0;
277 }
278 st.blocks(&st.buf);
279 }
280 mem.writeIntBig(u64, out[0..8], st.y1);
281 mem.writeIntBig(u64, out[8..16], st.y0);
282
283 mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Ghash)]);
284 }
285
286 pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
287 var st = Ghash.init(key);
288 st.update(msg);
289 st.final(out);
290 }
291};
292
293const htest = @import("test.zig");
294
295test "ghash" {
296 const key = [_]u8{0x42} ** 16;
297 const m = [_]u8{0x69} ** 256;
298
299 var st = Ghash.init(&key);
300 st.update(&m);
301 var out: [16]u8 = undefined;
302 st.final(&out);
303 htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
304
305 st = Ghash.init(&key);
306 st.update(m[0..100]);
307 st.update(m[100..]);
308 st.final(&out);
309 htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
310}
lib/std/crypto/hkdf.zig created+66
...@@ -0,0 +1,66 @@
1const std = @import("../std.zig");
2const assert = std.debug.assert;
3const hmac = std.crypto.auth.hmac;
4const mem = std.mem;
5
6/// HKDF-SHA256
7pub const HkdfSha256 = Hkdf(hmac.sha2.HmacSha256);
8
9/// HKDF-SHA512
10pub const HkdfSha512 = Hkdf(hmac.sha2.HmacSha512);
11
12/// The Hkdf construction takes some source of initial keying material and
13/// derives one or more uniform keys from it.
14pub fn Hkdf(comptime Hmac: type) type {
15 return struct {
16 /// Return a master key from a salt and initial keying material.
17 fn extract(salt: []const u8, ikm: []const u8) [Hmac.mac_length]u8 {
18 var prk: [Hmac.mac_length]u8 = undefined;
19 Hmac.create(&prk, ikm, salt);
20 return prk;
21 }
22
23 /// Derive a subkey from a master key `prk` and a subkey description `ctx`.
24 fn expand(out: []u8, ctx: []const u8, prk: [Hmac.mac_length]u8) void {
25 assert(out.len < Hmac.mac_length * 255); // output size is too large for the Hkdf construction
26 var i: usize = 0;
27 var counter = [1]u8{1};
28 while (i + Hmac.mac_length <= out.len) : (i += Hmac.mac_length) {
29 var st = Hmac.init(&prk);
30 if (i != 0) {
31 st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
32 }
33 st.update(ctx);
34 st.update(&counter);
35 st.final(out[i..][0..Hmac.mac_length]);
36 counter[0] += 1;
37 }
38 const left = out.len % Hmac.mac_length;
39 if (left > 0) {
40 var st = Hmac.init(&prk);
41 if (i != 0) {
42 st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
43 }
44 st.update(ctx);
45 st.update(&counter);
46 var tmp: [Hmac.mac_length]u8 = undefined;
47 st.final(tmp[0..Hmac.mac_length]);
48 mem.copy(u8, out[i..][0..left], tmp[0..left]);
49 }
50 }
51 };
52}
53
54const htest = @import("test.zig");
55
56test "Hkdf" {
57 const ikm = [_]u8{0x0b} ** 22;
58 const salt = [_]u8{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
59 const context = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
60 const kdf = HkdfSha256;
61 const prk = kdf.extract(&salt, &ikm);
62 htest.assertEqual("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", &prk);
63 var out: [42]u8 = undefined;
64 kdf.expand(&out, &context, prk);
65 htest.assertEqual("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", &out);
66}
lib/std/crypto/poly1305.zig+3-8
...@@ -22,8 +22,7 @@ pub const Poly1305 = struct {...@@ -22,8 +22,7 @@ pub const Poly1305 = struct {
22 // partial block buffer22 // partial block buffer
23 buf: [block_size]u8 align(16) = undefined,23 buf: [block_size]u8 align(16) = undefined,
2424
25 pub fn init(key: []const u8) Poly1305 {25 pub fn init(key: *const [minimum_key_length]u8) Poly1305 {
26 std.debug.assert(key.len >= minimum_key_length);
27 const t0 = mem.readIntLittle(u64, key[0..8]);26 const t0 = mem.readIntLittle(u64, key[0..8]);
28 const t1 = mem.readIntLittle(u64, key[8..16]);27 const t1 = mem.readIntLittle(u64, key[8..16]);
29 return Poly1305{28 return Poly1305{
...@@ -115,8 +114,7 @@ pub const Poly1305 = struct {...@@ -115,8 +114,7 @@ pub const Poly1305 = struct {
115 }114 }
116 }115 }
117116
118 pub fn final(st: *Poly1305, out: []u8) void {117 pub fn final(st: *Poly1305, out: *[mac_length]u8) void {
119 std.debug.assert(out.len >= mac_length);
120 if (st.leftover > 0) {118 if (st.leftover > 0) {
121 var i = st.leftover;119 var i = st.leftover;
122 st.buf[i] = 1;120 st.buf[i] = 1;
...@@ -187,10 +185,7 @@ pub const Poly1305 = struct {...@@ -187,10 +185,7 @@ pub const Poly1305 = struct {
187 std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]);185 std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]);
188 }186 }
189187
190 pub fn create(out: []u8, msg: []const u8, key: []const u8) void {188 pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
191 std.debug.assert(out.len >= mac_length);
192 std.debug.assert(key.len >= minimum_key_length);
193
194 var st = Poly1305.init(key);189 var st = Poly1305.init(key);
195 st.update(msg);190 st.update(msg);
196 st.final(out);191 st.final(out);
lib/std/fmt.zig+10
...@@ -1181,6 +1181,16 @@ fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, uppercase: bool, opti...@@ -1181,6 +1181,16 @@ fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, uppercase: bool, opti
1181 return buf[0..formatIntBuf(buf, value, base, uppercase, options)];1181 return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
1182}1182}
11831183
1184pub fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args)]u8 {
1185 comptime var buf: [count(fmt, args)]u8 = undefined;
1186 _ = bufPrint(&buf, fmt, args) catch unreachable;
1187 return &buf;
1188}
1189
1190test "comptimePrint" {
1191 std.testing.expectEqualSlices(u8, "100", comptime comptimePrint("{}", .{100}));
1192}
1193
1184test "parse u64 digit too big" {1194test "parse u64 digit too big" {
1185 _ = parseUnsigned(u64, "123a", 10) catch |err| {1195 _ = parseUnsigned(u64, "123a", 10) catch |err| {
1186 if (err == error.InvalidCharacter) return;1196 if (err == error.InvalidCharacter) return;
lib/std/fs.zig+12-4
...@@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {...@@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
2162 return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags);2162 return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags);
2163}2163}
21642164
2165pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;2165pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError;
21662166
2167/// `selfExePath` except allocates the result on the heap.2167/// `selfExePath` except allocates the result on the heap.
2168/// Caller owns returned memory.2168/// Caller owns returned memory.
...@@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {...@@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {
2190/// TODO make the return type of this a null terminated pointer2190/// TODO make the return type of this a null terminated pointer
2191pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {2191pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
2192 if (is_darwin) {2192 if (is_darwin) {
2193 var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32)));2193 // Note that _NSGetExecutablePath() will return "a path" to
2194 const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len);2194 // the executable not a "real path" to the executable.
2195 var symlink_path_buf: [MAX_PATH_BYTES:0]u8 = undefined;
2196 var u32_len: u32 = MAX_PATH_BYTES + 1; // include the sentinel
2197 const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len);
2195 if (rc != 0) return error.NameTooLong;2198 if (rc != 0) return error.NameTooLong;
2196 return mem.spanZ(@ptrCast([*:0]u8, out_buffer));2199
2200 var real_path_buf: [MAX_PATH_BYTES]u8 = undefined;
2201 const real_path = try std.os.realpathZ(&symlink_path_buf, &real_path_buf);
2202 if (real_path.len > out_buffer.len) return error.NameTooLong;
2203 std.mem.copy(u8, out_buffer, real_path);
2204 return out_buffer[0..real_path.len];
2197 }2205 }
2198 switch (builtin.os.tag) {2206 switch (builtin.os.tag) {
2199 .linux => return os.readlinkZ("/proc/self/exe", out_buffer),2207 .linux => return os.readlinkZ("/proc/self/exe", out_buffer),
lib/std/math/big/int.zig+120
...@@ -58,6 +58,11 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {...@@ -58,6 +58,11 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {
58 return (string_len + (limb_bits / base - 1)) / (limb_bits / base);58 return (string_len + (limb_bits / base - 1)) / (limb_bits / base);
59}59}
6060
61pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize {
62 // The 1 accounts for the multiplication carry
63 return 1 + (a_bit_count * y + (limb_bits - 1)) / limb_bits;
64}
65
61/// a + b * c + *carry, sets carry to the overflow bits66/// a + b * c + *carry, sets carry to the overflow bits
62pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {67pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {
63 @setRuntimeSafety(debug_safety);68 @setRuntimeSafety(debug_safety);
...@@ -597,6 +602,52 @@ pub const Mutable = struct {...@@ -597,6 +602,52 @@ pub const Mutable = struct {
597 return gcdLehmer(rma, x_copy, y_copy, limbs_buffer);602 return gcdLehmer(rma, x_copy, y_copy, limbs_buffer);
598 }603 }
599604
605 /// q = a ^ b
606 ///
607 /// r may not alias a.
608 ///
609 /// Asserts that `r` has enough limbs to store the result. Upper bound is
610 /// `calcPowLimbsBufferLen(a.bitCountAbs(), b)`.
611 ///
612 /// `limbs_buffer` is used for temporary storage.
613 /// The amount required is given by `calcPowLimbsBufferLen`.
614 pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void {
615 assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing
616
617 // Handle all the trivial cases first
618 switch (b) {
619 0 => {
620 // a^0 = 1
621 return r.set(1);
622 },
623 1 => {
624 // a^1 = a
625 return r.copy(a);
626 },
627 else => {},
628 }
629
630 if (a.eqZero()) {
631 // 0^b = 0
632 return r.set(0);
633 } else if (a.limbs.len == 1 and a.limbs[0] == 1) {
634 // 1^b = 1 and -1^b = ±1
635 r.set(1);
636 r.positive = a.positive or (b & 1) == 0;
637 return;
638 }
639
640 // Here a>1 and b>1
641 const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
642 assert(r.limbs.len >= needed_limbs);
643 assert(limbs_buffer.len >= needed_limbs);
644
645 llpow(r.limbs, a.limbs, b, limbs_buffer);
646
647 r.normalize(needed_limbs);
648 r.positive = a.positive or (b & 1) == 0;
649 }
650
600 /// rma may not alias x or y.651 /// rma may not alias x or y.
601 /// x and y may alias each other.652 /// x and y may alias each other.
602 /// Asserts that `rma` has enough limbs to store the result. Upper bound is given by `calcGcdNoAliasLimbLen`.653 /// Asserts that `rma` has enough limbs to store the result. Upper bound is given by `calcGcdNoAliasLimbLen`.
...@@ -1775,6 +1826,29 @@ pub const Managed = struct {...@@ -1775,6 +1826,29 @@ pub const Managed = struct {
1775 try m.gcd(x.toConst(), y.toConst(), &limbs_buffer);1826 try m.gcd(x.toConst(), y.toConst(), &limbs_buffer);
1776 rma.setMetadata(m.positive, m.len);1827 rma.setMetadata(m.positive, m.len);
1777 }1828 }
1829
1830 pub fn pow(rma: *Managed, a: Managed, b: u32) !void {
1831 const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
1832
1833 const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs);
1834 defer rma.allocator.free(limbs_buffer);
1835
1836 if (rma.limbs.ptr == a.limbs.ptr) {
1837 var m = try Managed.initCapacity(rma.allocator, needed_limbs);
1838 errdefer m.deinit();
1839 var m_mut = m.toMutable();
1840 try m_mut.pow(a.toConst(), b, limbs_buffer);
1841 m.setMetadata(m_mut.positive, m_mut.len);
1842
1843 rma.deinit();
1844 rma.swap(&m);
1845 } else {
1846 try rma.ensureCapacity(needed_limbs);
1847 var rma_mut = rma.toMutable();
1848 try rma_mut.pow(a.toConst(), b, limbs_buffer);
1849 rma.setMetadata(rma_mut.positive, rma_mut.len);
1850 }
1851 }
1778};1852};
17791853
1780/// Knuth 4.3.1, Algorithm M.1854/// Knuth 4.3.1, Algorithm M.
...@@ -2129,6 +2203,52 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void {...@@ -2129,6 +2203,52 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void {
2129 }2203 }
2130}2204}
21312205
2206/// Knuth 4.6.3
2207fn llpow(r: []Limb, a: []const Limb, b: u32, tmp_limbs: []Limb) void {
2208 mem.copy(Limb, r, a);
2209 mem.set(Limb, r[a.len..], 0);
2210
2211 // Multiplication requires no aliasing between the operand and the result
2212 // variable, use the output limbs and another temporary set to overcome this
2213 // limit.
2214 // Note that the order is important in the code below.
2215 var list = [_][]Limb{ r, tmp_limbs };
2216 var index: usize = 0;
2217
2218 // Scan the exponent as a binary number, from left to right, dropping the
2219 // most significant bit set
2220 var exp = @bitReverse(u32, b) >> (1 + @intCast(u5, @clz(u32, b)));
2221 while (exp != 0) : (exp >>= 1) {
2222 // Square
2223 {
2224 const cur_buf = list[index];
2225 const cur_buf_len = llnormalize(cur_buf);
2226 const cur_buf_out = list[index ^ 1];
2227
2228 mem.set(Limb, cur_buf_out, 0);
2229 llmulacc(null, cur_buf_out, cur_buf[0..cur_buf_len], cur_buf[0..cur_buf_len]);
2230
2231 index ^= 1;
2232 }
2233
2234 if ((exp & 1) != 0) {
2235 // Multiply
2236 const cur_buf = list[index];
2237 const cur_buf_len = llnormalize(cur_buf);
2238 const cur_buf_out = list[index ^ 1];
2239
2240 mem.set(Limb, cur_buf_out, 0);
2241 llmulacc(null, cur_buf_out, cur_buf, a);
2242
2243 index ^= 1;
2244 }
2245 }
2246
2247 if (index != 0) {
2248 mem.copy(Limb, r, tmp_limbs);
2249 }
2250}
2251
2132// Storage must live for the lifetime of the returned value2252// Storage must live for the lifetime of the returned value
2133fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {2253fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {
2134 assert(storage.len >= 2);2254 assert(storage.len >= 2);
lib/std/math/big/int_test.zig+45
...@@ -1480,3 +1480,48 @@ test "big.int const to managed" {...@@ -1480,3 +1480,48 @@ test "big.int const to managed" {
14801480
1481 testing.expect(a.toConst().eq(b.toConst()));1481 testing.expect(a.toConst().eq(b.toConst()));
1482}1482}
1483
1484test "big.int pow" {
1485 {
1486 var a = try Managed.initSet(testing.allocator, 10);
1487 defer a.deinit();
1488
1489 var y = try Managed.init(testing.allocator);
1490 defer y.deinit();
1491
1492 // y and a are not aliased
1493 try y.pow(a, 123);
1494 // y and a are aliased
1495 try a.pow(a, 123);
1496
1497 testing.expect(a.eq(y));
1498
1499 const ys = try y.toString(testing.allocator, 16, false);
1500 defer testing.allocator.free(ys);
1501 testing.expectEqualSlices(
1502 u8,
1503 "183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++
1504 "4933f60e8000000000000000000000000000000",
1505 ys,
1506 );
1507 }
1508 // Special cases
1509 {
1510 var a = try Managed.initSet(testing.allocator, 0);
1511 defer a.deinit();
1512
1513 try a.pow(a, 100);
1514 testing.expectEqual(@as(i32, 0), try a.to(i32));
1515
1516 try a.set(1);
1517 try a.pow(a, 0);
1518 testing.expectEqual(@as(i32, 1), try a.to(i32));
1519 try a.pow(a, 100);
1520 testing.expectEqual(@as(i32, 1), try a.to(i32));
1521 try a.set(-1);
1522 try a.pow(a, 15);
1523 testing.expectEqual(@as(i32, -1), try a.to(i32));
1524 try a.pow(a, 16);
1525 testing.expectEqual(@as(i32, 1), try a.to(i32));
1526 }
1527}
lib/std/meta.zig+2
...@@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type {...@@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type {
854 .field_type = arg.arg_type.?,854 .field_type = arg.arg_type.?,
855 .default_value = @as(?(arg.arg_type.?), null),855 .default_value = @as(?(arg.arg_type.?), null),
856 .is_comptime = false,856 .is_comptime = false,
857 .alignment = @alignOf(arg.arg_type.?),
857 };858 };
858 }859 }
859860
...@@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type {...@@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type {
884 .field_type = T,885 .field_type = T,
885 .default_value = @as(?T, null),886 .default_value = @as(?T, null),
886 .is_comptime = false,887 .is_comptime = false,
888 .alignment = @alignOf(T),
887 };889 };
888 }890 }
889891
lib/std/meta/trailer_flags.zig+1
...@@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type {...@@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
47 @as(?struct_field.field_type, null),47 @as(?struct_field.field_type, null),
48 ),48 ),
49 .is_comptime = false,49 .is_comptime = false,
50 .alignment = @alignOf(?struct_field.field_type),
50 };51 };
51 }52 }
52 break :blk @Type(.{53 break :blk @Type(.{
lib/std/os.zig+1-1
...@@ -3993,7 +3993,7 @@ pub const RealPathError = error{...@@ -3993,7 +3993,7 @@ pub const RealPathError = error{
3993/// Expands all symbolic links and resolves references to `.`, `..`, and3993/// Expands all symbolic links and resolves references to `.`, `..`, and
3994/// extra `/` characters in `pathname`.3994/// extra `/` characters in `pathname`.
3995/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.3995/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
3996/// See also `realpathC` and `realpathW`.3996/// See also `realpathZ` and `realpathW`.
3997pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {3997pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
3998 if (builtin.os.tag == .windows) {3998 if (builtin.os.tag == .windows) {
3999 const pathname_w = try windows.sliceToPrefixedFileW(pathname);3999 const pathname_w = try windows.sliceToPrefixedFileW(pathname);
lib/std/packed_int_array.zig+15
...@@ -318,9 +318,12 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)...@@ -318,9 +318,12 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)
318 };318 };
319}319}
320320
321const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true;
322
321test "PackedIntArray" {323test "PackedIntArray" {
322 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.324 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
323 if (builtin.arch == .wasm32) return error.SkipZigTest;325 if (builtin.arch == .wasm32) return error.SkipZigTest;
326 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
324327
325 @setEvalBranchQuota(10000);328 @setEvalBranchQuota(10000);
326 const max_bits = 256;329 const max_bits = 256;
...@@ -358,6 +361,7 @@ test "PackedIntArray" {...@@ -358,6 +361,7 @@ test "PackedIntArray" {
358}361}
359362
360test "PackedIntArray init" {363test "PackedIntArray init" {
364 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
361 const PackedArray = PackedIntArray(u3, 8);365 const PackedArray = PackedIntArray(u3, 8);
362 var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });366 var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
363 var i = @as(usize, 0);367 var i = @as(usize, 0);
...@@ -367,6 +371,7 @@ test "PackedIntArray init" {...@@ -367,6 +371,7 @@ test "PackedIntArray init" {
367test "PackedIntSlice" {371test "PackedIntSlice" {
368 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.372 // TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
369 if (builtin.arch == .wasm32) return error.SkipZigTest;373 if (builtin.arch == .wasm32) return error.SkipZigTest;
374 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
370375
371 @setEvalBranchQuota(10000);376 @setEvalBranchQuota(10000);
372 const max_bits = 256;377 const max_bits = 256;
...@@ -405,6 +410,7 @@ test "PackedIntSlice" {...@@ -405,6 +410,7 @@ test "PackedIntSlice" {
405}410}
406411
407test "PackedIntSlice of PackedInt(Array/Slice)" {412test "PackedIntSlice of PackedInt(Array/Slice)" {
413 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
408 const max_bits = 16;414 const max_bits = 16;
409 const int_count = 19;415 const int_count = 19;
410416
...@@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {...@@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {
470}476}
471477
472test "PackedIntSlice accumulating bit offsets" {478test "PackedIntSlice accumulating bit offsets" {
479 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
473 //bit_offset is u3, so standard debugging asserts should catch480 //bit_offset is u3, so standard debugging asserts should catch
474 // anything481 // anything
475 {482 {
...@@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" {...@@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" {
497//@NOTE: As I do not have a big endian system to test this on,504//@NOTE: As I do not have a big endian system to test this on,
498// big endian values were not tested505// big endian values were not tested
499test "PackedInt(Array/Slice) sliceCast" {506test "PackedInt(Array/Slice) sliceCast" {
507 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
508
500 const PackedArray = PackedIntArray(u1, 16);509 const PackedArray = PackedIntArray(u1, 16);
501 var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });510 var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
502 const packed_slice_cast_2 = packed_array.sliceCast(u2);511 const packed_slice_cast_2 = packed_array.sliceCast(u2);
...@@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" {...@@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" {
537}546}
538547
539test "PackedInt(Array/Slice)Endian" {548test "PackedInt(Array/Slice)Endian" {
549 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
550
540 {551 {
541 const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);552 const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
542 var packed_array_be = PackedArrayBe.init([_]u4{ 0, 1, 2, 3, 4, 5, 6, 7 });553 var packed_array_be = PackedArrayBe.init([_]u4{ 0, 1, 2, 3, 4, 5, 6, 7 });
...@@ -604,6 +615,8 @@ test "PackedInt(Array/Slice)Endian" {...@@ -604,6 +615,8 @@ test "PackedInt(Array/Slice)Endian" {
604// after this one is not mapped and will cause a segfault if we615// after this one is not mapped and will cause a segfault if we
605// don't account for the bounds.616// don't account for the bounds.
606test "PackedIntArray at end of available memory" {617test "PackedIntArray at end of available memory" {
618 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
619
607 switch (builtin.os.tag) {620 switch (builtin.os.tag) {
608 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},621 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
609 else => return,622 else => return,
...@@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" {...@@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" {
623}636}
624637
625test "PackedIntSlice at end of available memory" {638test "PackedIntSlice at end of available memory" {
639 if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
640
626 switch (builtin.os.tag) {641 switch (builtin.os.tag) {
627 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},642 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
628 else => return,643 else => return,
src/Compilation.zig+22-9
...@@ -352,6 +352,7 @@ pub const InitOptions = struct {...@@ -352,6 +352,7 @@ pub const InitOptions = struct {
352 time_report: bool = false,352 time_report: bool = false,
353 stack_report: bool = false,353 stack_report: bool = false,
354 link_eh_frame_hdr: bool = false,354 link_eh_frame_hdr: bool = false,
355 link_emit_relocs: bool = false,
355 linker_script: ?[]const u8 = null,356 linker_script: ?[]const u8 = null,
356 version_script: ?[]const u8 = null,357 version_script: ?[]const u8 = null,
357 override_soname: ?[]const u8 = null,358 override_soname: ?[]const u8 = null,
...@@ -447,6 +448,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -447,6 +448,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
447 options.system_libs.len != 0 or448 options.system_libs.len != 0 or
448 options.link_libc or options.link_libcpp or449 options.link_libc or options.link_libcpp or
449 options.link_eh_frame_hdr or450 options.link_eh_frame_hdr or
451 options.link_emit_relocs or
450 options.output_mode == .Lib or452 options.output_mode == .Lib or
451 options.lld_argv.len != 0 or453 options.lld_argv.len != 0 or
452 options.linker_script != null or options.version_script != null)454 options.linker_script != null or options.version_script != null)
...@@ -769,6 +771,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -769,6 +771,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
769 .version_script = options.version_script,771 .version_script = options.version_script,
770 .gc_sections = options.linker_gc_sections,772 .gc_sections = options.linker_gc_sections,
771 .eh_frame_hdr = options.link_eh_frame_hdr,773 .eh_frame_hdr = options.link_eh_frame_hdr,
774 .emit_relocs = options.link_emit_relocs,
772 .rdynamic = options.rdynamic,775 .rdynamic = options.rdynamic,
773 .extra_lld_args = options.lld_argv,776 .extra_lld_args = options.lld_argv,
774 .override_soname = options.override_soname,777 .override_soname = options.override_soname,
...@@ -1146,7 +1149,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1146,7 +1149,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
1146 };1149 };
1147}1150}
11481151
1149pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {1152pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemory }!void {
1153 var progress: std.Progress = .{};
1154 var main_progress_node = try progress.start("", null);
1155 defer main_progress_node.end();
1156 if (self.color == .Off) progress.terminal = null;
1157
1158 var c_comp_progress_node = main_progress_node.start("Compile C Objects", self.c_source_files.len);
1159 defer c_comp_progress_node.end();
1160
1150 while (self.work_queue.readItem()) |work_item| switch (work_item) {1161 while (self.work_queue.readItem()) |work_item| switch (work_item) {
1151 .codegen_decl => |decl| switch (decl.analysis) {1162 .codegen_decl => |decl| switch (decl.analysis) {
1152 .unreferenced => unreachable,1163 .unreferenced => unreachable,
...@@ -1223,7 +1234,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {...@@ -1223,7 +1234,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
1223 };1234 };
1224 },1235 },
1225 .c_object => |c_object| {1236 .c_object => |c_object| {
1226 self.updateCObject(c_object) catch |err| switch (err) {1237 self.updateCObject(c_object, &c_comp_progress_node) catch |err| switch (err) {
1227 error.AnalysisFail => continue,1238 error.AnalysisFail => continue,
1228 else => {1239 else => {
1229 try self.failed_c_objects.ensureCapacity(self.gpa, self.failed_c_objects.items().len + 1);1240 try self.failed_c_objects.ensureCapacity(self.gpa, self.failed_c_objects.items().len + 1);
...@@ -1309,7 +1320,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {...@@ -1309,7 +1320,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
1309 if (!build_options.is_stage1)1320 if (!build_options.is_stage1)
1310 unreachable;1321 unreachable;
13111322
1312 self.updateStage1Module() catch |err| {1323 self.updateStage1Module(main_progress_node) catch |err| {
1313 fatal("unable to build stage1 zig object: {}", .{@errorName(err)});1324 fatal("unable to build stage1 zig object: {}", .{@errorName(err)});
1314 };1325 };
1315 },1326 },
...@@ -1470,7 +1481,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -1470,7 +1481,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
1470 };1481 };
1471}1482}
14721483
1473fn updateCObject(comp: *Compilation, c_object: *CObject) !void {1484fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *std.Progress.Node) !void {
1474 if (!build_options.have_llvm) {1485 if (!build_options.have_llvm) {
1475 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});1486 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
1476 }1487 }
...@@ -1513,6 +1524,12 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1513,6 +1524,12 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
1513 const arena = &arena_allocator.allocator;1524 const arena = &arena_allocator.allocator;
15141525
1515 const c_source_basename = std.fs.path.basename(c_object.src.src_path);1526 const c_source_basename = std.fs.path.basename(c_object.src.src_path);
1527
1528 c_comp_progress_node.activate();
1529 var child_progress_node = c_comp_progress_node.start(c_source_basename, null);
1530 child_progress_node.activate();
1531 defer child_progress_node.end();
1532
1516 // Special case when doing build-obj for just one C file. When there are more than one object1533 // Special case when doing build-obj for just one C file. When there are more than one object
1517 // file and building an object we need to link them together, but with just one it should go1534 // file and building an object we need to link them together, but with just one it should go
1518 // directly to the output file.1535 // directly to the output file.
...@@ -2506,7 +2523,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR...@@ -2506,7 +2523,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
2506 };2523 };
2507}2524}
25082525
2509fn updateStage1Module(comp: *Compilation) !void {2526fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void {
2510 const tracy = trace(@src());2527 const tracy = trace(@src());
2511 defer tracy.end();2528 defer tracy.end();
25122529
...@@ -2612,10 +2629,6 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2612,10 +2629,6 @@ fn updateStage1Module(comp: *Compilation) !void {
2612 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,2629 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
2613 .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?,2630 .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?,
2614 };2631 };
2615 var progress: std.Progress = .{};
2616 var main_progress_node = try progress.start("", null);
2617 defer main_progress_node.end();
2618 if (comp.color == .Off) progress.terminal = null;
26192632
2620 comp.stage1_cache_manifest = &man;2633 comp.stage1_cache_manifest = &man;
26212634
src/link.zig+1
...@@ -60,6 +60,7 @@ pub const Options = struct {...@@ -60,6 +60,7 @@ pub const Options = struct {
60 link_libcpp: bool,60 link_libcpp: bool,
61 function_sections: bool,61 function_sections: bool,
62 eh_frame_hdr: bool,62 eh_frame_hdr: bool,
63 emit_relocs: bool,
63 rdynamic: bool,64 rdynamic: bool,
64 z_nodelete: bool,65 z_nodelete: bool,
65 z_defs: bool,66 z_defs: bool,
src/link/Elf.zig+5
...@@ -1286,6 +1286,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1286,6 +1286,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1286 man.hash.add(stack_size);1286 man.hash.add(stack_size);
1287 man.hash.add(gc_sections);1287 man.hash.add(gc_sections);
1288 man.hash.add(self.base.options.eh_frame_hdr);1288 man.hash.add(self.base.options.eh_frame_hdr);
1289 man.hash.add(self.base.options.emit_relocs);
1289 man.hash.add(self.base.options.rdynamic);1290 man.hash.add(self.base.options.rdynamic);
1290 man.hash.addListOfBytes(self.base.options.extra_lld_args);1291 man.hash.addListOfBytes(self.base.options.extra_lld_args);
1291 man.hash.addListOfBytes(self.base.options.lib_dirs);1292 man.hash.addListOfBytes(self.base.options.lib_dirs);
...@@ -1364,6 +1365,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1364,6 +1365,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1364 if (self.base.options.eh_frame_hdr) {1365 if (self.base.options.eh_frame_hdr) {
1365 try argv.append("--eh-frame-hdr");1366 try argv.append("--eh-frame-hdr");
1366 }1367 }
1368
1369 if (self.base.options.emit_relocs) {
1370 try argv.append("--emit-relocs");
1371 }
13671372
1368 if (self.base.options.rdynamic) {1373 if (self.base.options.rdynamic) {
1369 try argv.append("--export-dynamic");1374 try argv.append("--export-dynamic");
src/main.zig+9
...@@ -273,6 +273,7 @@ const usage_build_generic =...@@ -273,6 +273,7 @@ const usage_build_generic =
273 \\ -rdynamic Add all symbols to the dynamic symbol table273 \\ -rdynamic Add all symbols to the dynamic symbol table
274 \\ -rpath [path] Add directory to the runtime library search path274 \\ -rpath [path] Add directory to the runtime library search path
275 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker275 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
276 \\ --emit-relocs Enable output of relocation sections for post build tools
276 \\ -dynamic Force output to be dynamically linked277 \\ -dynamic Force output to be dynamically linked
277 \\ -static Force output to be statically linked278 \\ -static Force output to be statically linked
278 \\ -Bsymbolic Bind global references locally279 \\ -Bsymbolic Bind global references locally
...@@ -438,6 +439,7 @@ fn buildOutputType(...@@ -438,6 +439,7 @@ fn buildOutputType(
438 var use_lld: ?bool = null;439 var use_lld: ?bool = null;
439 var use_clang: ?bool = null;440 var use_clang: ?bool = null;
440 var link_eh_frame_hdr = false;441 var link_eh_frame_hdr = false;
442 var link_emit_relocs = false;
441 var each_lib_rpath = false;443 var each_lib_rpath = false;
442 var libc_paths_file: ?[]const u8 = null;444 var libc_paths_file: ?[]const u8 = null;
443 var machine_code_model: std.builtin.CodeModel = .default;445 var machine_code_model: std.builtin.CodeModel = .default;
...@@ -838,6 +840,8 @@ fn buildOutputType(...@@ -838,6 +840,8 @@ fn buildOutputType(
838 function_sections = true;840 function_sections = true;
839 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {841 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
840 link_eh_frame_hdr = true;842 link_eh_frame_hdr = true;
843 } else if (mem.eql(u8, arg, "--emit-relocs")) {
844 link_emit_relocs = true;
841 } else if (mem.eql(u8, arg, "-Bsymbolic")) {845 } else if (mem.eql(u8, arg, "-Bsymbolic")) {
842 linker_bind_global_refs_locally = true;846 linker_bind_global_refs_locally = true;
843 } else if (mem.eql(u8, arg, "--verbose-link")) {847 } else if (mem.eql(u8, arg, "--verbose-link")) {
...@@ -1206,6 +1210,10 @@ fn buildOutputType(...@@ -1206,6 +1210,10 @@ fn buildOutputType(
1206 fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});1210 fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});
1207 }1211 }
12081212
1213 if (root_src_file == null and arg_mode == .zig_test) {
1214 fatal("one zig source file is required to run `zig test`", .{});
1215 }
1216
1209 const root_name = if (provided_name) |n| n else blk: {1217 const root_name = if (provided_name) |n| n else blk: {
1210 if (arg_mode == .zig_test) {1218 if (arg_mode == .zig_test) {
1211 break :blk "test";1219 break :blk "test";
...@@ -1580,6 +1588,7 @@ fn buildOutputType(...@@ -1580,6 +1588,7 @@ fn buildOutputType(
1580 .linker_z_nodelete = linker_z_nodelete,1588 .linker_z_nodelete = linker_z_nodelete,
1581 .linker_z_defs = linker_z_defs,1589 .linker_z_defs = linker_z_defs,
1582 .link_eh_frame_hdr = link_eh_frame_hdr,1590 .link_eh_frame_hdr = link_eh_frame_hdr,
1591 .link_emit_relocs = link_emit_relocs,
1583 .stack_size_override = stack_size_override,1592 .stack_size_override = stack_size_override,
1584 .strip = strip,1593 .strip = strip,
1585 .single_threaded = single_threaded,1594 .single_threaded = single_threaded,
src/mingw.zig+6-5
...@@ -32,6 +32,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {...@@ -32,6 +32,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
32 var args = std.ArrayList([]const u8).init(arena);32 var args = std.ArrayList([]const u8).init(arena);
33 try add_cc_args(comp, arena, &args);33 try add_cc_args(comp, arena, &args);
34 try args.appendSlice(&[_][]const u8{34 try args.appendSlice(&[_][]const u8{
35 "-D_SYSCRT=1",
36 "-DCRTDLL=1",
35 "-U__CRTDLL__",37 "-U__CRTDLL__",
36 "-D__MSVCRT__",38 "-D__MSVCRT__",
37 // Uncomment these 3 things for crtu39 // Uncomment these 3 things for crtu
...@@ -53,6 +55,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {...@@ -53,6 +55,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
53 var args = std.ArrayList([]const u8).init(arena);55 var args = std.ArrayList([]const u8).init(arena);
54 try add_cc_args(comp, arena, &args);56 try add_cc_args(comp, arena, &args);
55 try args.appendSlice(&[_][]const u8{57 try args.appendSlice(&[_][]const u8{
58 "-D_SYSCRT=1",
59 "-DCRTDLL=1",
56 "-U__CRTDLL__",60 "-U__CRTDLL__",
57 "-D__MSVCRT__",61 "-D__MSVCRT__",
58 });62 });
...@@ -437,11 +441,8 @@ fn findDef(comp: *Compilation, allocator: *Allocator, lib_name: []const u8) ![]u...@@ -437,11 +441,8 @@ fn findDef(comp: *Compilation, allocator: *Allocator, lib_name: []const u8) ![]u
437 const lib_path = switch (target.cpu.arch) {441 const lib_path = switch (target.cpu.arch) {
438 .i386 => "lib32",442 .i386 => "lib32",
439 .x86_64 => "lib64",443 .x86_64 => "lib64",
440 .arm, .armeb => switch (target.cpu.arch.ptrBitWidth()) {444 .arm, .armeb, .thumb, .thumbeb, .aarch64_32 => "libarm32",
441 32 => "libarm32",445 .aarch64, .aarch64_be => "libarm64",
442 64 => "libarm64",
443 else => unreachable,
444 },
445 else => unreachable,446 else => unreachable,
446 };447 };
447448
src/stage1.zig+5-1
...@@ -39,7 +39,11 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {...@@ -39,7 +39,11 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
39 for (args) |*arg, i| {39 for (args) |*arg, i| {
40 arg.* = mem.spanZ(argv[i]);40 arg.* = mem.spanZ(argv[i]);
41 }41 }
42 stage2.mainArgs(gpa, arena, args) catch |err| fatal("{}", .{@errorName(err)});42 if (std.builtin.mode == .Debug) {
43 stage2.mainArgs(gpa, arena, args) catch unreachable;
44 } else {
45 stage2.mainArgs(gpa, arena, args) catch |err| fatal("{}", .{@errorName(err)});
46 }
43 return 0;47 return 0;
44}48}
4549
src/stage1/all_types.hpp+1-5
...@@ -18,11 +18,6 @@...@@ -18,11 +18,6 @@
18#include "target.hpp"18#include "target.hpp"
19#include "tokenizer.hpp"19#include "tokenizer.hpp"
2020
21#ifndef NDEBUG
22#define DBG_MACRO_NO_WARNING
23#include <dbg.h>
24#endif
25
26struct AstNode;21struct AstNode;
27struct ZigFn;22struct ZigFn;
28struct Scope;23struct Scope;
...@@ -1456,6 +1451,7 @@ struct ZigTypeEnum {...@@ -1456,6 +1451,7 @@ struct ZigTypeEnum {
1456 ContainerLayout layout;1451 ContainerLayout layout;
1457 ResolveStatus resolve_status;1452 ResolveStatus resolve_status;
14581453
1454 bool has_explicit_tag_type;
1459 bool non_exhaustive;1455 bool non_exhaustive;
1460 bool resolve_loop_flag;1456 bool resolve_loop_flag;
1461};1457};
src/stage1/analyze.cpp+14-4
...@@ -1802,10 +1802,18 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {...@@ -1802,10 +1802,18 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1802 }1802 }
1803 return type_allowed_in_extern(g, child_type, result);1803 return type_allowed_in_extern(g, child_type, result);
1804 }1804 }
1805 case ZigTypeIdEnum:1805 case ZigTypeIdEnum: {
1806 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||1806 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1807 type_entry->data.enumeration.layout == ContainerLayoutPacked;1807 return err;
1808 return ErrorNone;1808 ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
1809 if (type_entry->data.enumeration.has_explicit_tag_type) {
1810 return type_allowed_in_extern(g, tag_int_type, result);
1811 } else {
1812 *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
1813 type_entry->data.enumeration.layout == ContainerLayoutPacked;
1814 return ErrorNone;
1815 }
1816 }
1809 case ZigTypeIdUnion:1817 case ZigTypeIdUnion:
1810 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||1818 *result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
1811 type_entry->data.unionation.layout == ContainerLayoutPacked;1819 type_entry->data.unionation.layout == ContainerLayoutPacked;
...@@ -2639,9 +2647,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2639,9 +2647,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2639 if (decl_node->type == NodeTypeContainerDecl) {2647 if (decl_node->type == NodeTypeContainerDecl) {
2640 if (decl_node->data.container_decl.init_arg_expr != nullptr) {2648 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
2641 wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);2649 wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
2650 enum_type->data.enumeration.has_explicit_tag_type = true;
2642 }2651 }
2643 } else {2652 } else {
2644 wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;2653 wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
2654 enum_type->data.enumeration.has_explicit_tag_type = true;
2645 }2655 }
26462656
2647 if (wanted_tag_int_type != nullptr) {2657 if (wanted_tag_int_type != nullptr) {
src/stage1/codegen.cpp+1-1
...@@ -8837,7 +8837,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -8837,7 +8837,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
8837 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");8837 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
8838 buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");8838 buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
8839 buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");8839 buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
8840 buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n");8840 buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_LINK_MODE);
8841 buf_appendf(contents, "pub const is_test = false;\n");8841 buf_appendf(contents, "pub const is_test = false;\n");
8842 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));8842 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
8843 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);8843 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
src/stage1/config.h.in+1
...@@ -21,5 +21,6 @@...@@ -21,5 +21,6 @@
21#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"21#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
22#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"22#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"
23#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"23#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
24#define ZIG_LINK_MODE "@ZIG_LINK_MODE@"
2425
25#endif26#endif
src/stage1/ir.cpp+154-27
...@@ -25034,7 +25034,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, IrInst *source_instr,...@@ -25034,7 +25034,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, IrInst *source_instr,
25034 fields[2]->special = ConstValSpecialStatic;25034 fields[2]->special = ConstValSpecialStatic;
25035 fields[2]->type = ira->codegen->builtin_types.entry_bool;25035 fields[2]->type = ira->codegen->builtin_types.entry_bool;
25036 fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;25036 fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;
25037 // alignment: u3225037 // alignment: comptime_int
25038 ensure_field_index(result->type, "alignment", 3);25038 ensure_field_index(result->type, "alignment", 3);
25039 fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int;25039 fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int;
25040 if (attrs_type->data.pointer.explicit_alignment != 0) {25040 if (attrs_type->data.pointer.explicit_alignment != 0) {
...@@ -25438,11 +25438,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25438,11 +25438,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25438 union_field_val->special = ConstValSpecialStatic;25438 union_field_val->special = ConstValSpecialStatic;
25439 union_field_val->type = type_info_union_field_type;25439 union_field_val->type = type_info_union_field_type;
2544025440
25441 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);25441 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);
25442 // field_type: type
25442 inner_fields[1]->special = ConstValSpecialStatic;25443 inner_fields[1]->special = ConstValSpecialStatic;
25443 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;25444 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
25444 inner_fields[1]->data.x_type = union_field->type_entry;25445 inner_fields[1]->data.x_type = union_field->type_entry;
2544525446
25447 // alignment: comptime_int
25448 inner_fields[2]->special = ConstValSpecialStatic;
25449 inner_fields[2]->type = ira->codegen->builtin_types.entry_num_lit_int;
25450 bigint_init_unsigned(&inner_fields[2]->data.x_bigint, union_field->align);
25451
25446 ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;25452 ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
25447 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);25453 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
2544825454
...@@ -25509,7 +25515,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25509,7 +25515,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25509 struct_field_val->special = ConstValSpecialStatic;25515 struct_field_val->special = ConstValSpecialStatic;
25510 struct_field_val->type = type_info_struct_field_type;25516 struct_field_val->type = type_info_struct_field_type;
2551125517
25512 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4);25518 ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 5);
2551325519
25514 inner_fields[1]->special = ConstValSpecialStatic;25520 inner_fields[1]->special = ConstValSpecialStatic;
25515 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;25521 inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
...@@ -25525,10 +25531,16 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25525,10 +25531,16 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25525 }25531 }
25526 set_optional_payload(inner_fields[2], struct_field->init_val);25532 set_optional_payload(inner_fields[2], struct_field->init_val);
2552725533
25534 // is_comptime: bool
25528 inner_fields[3]->special = ConstValSpecialStatic;25535 inner_fields[3]->special = ConstValSpecialStatic;
25529 inner_fields[3]->type = ira->codegen->builtin_types.entry_bool;25536 inner_fields[3]->type = ira->codegen->builtin_types.entry_bool;
25530 inner_fields[3]->data.x_bool = struct_field->is_comptime;25537 inner_fields[3]->data.x_bool = struct_field->is_comptime;
2553125538
25539 // alignment: comptime_int
25540 inner_fields[4]->special = ConstValSpecialStatic;
25541 inner_fields[4]->type = ira->codegen->builtin_types.entry_num_lit_int;
25542 bigint_init_unsigned(&inner_fields[4]->data.x_bigint, struct_field->align);
25543
25532 ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;25544 ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
25533 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);25545 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
2553425546
...@@ -25559,7 +25571,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25559,7 +25571,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25559 result->special = ConstValSpecialStatic;25571 result->special = ConstValSpecialStatic;
25560 result->type = ir_type_info_get_type(ira, "Fn", nullptr);25572 result->type = ir_type_info_get_type(ira, "Fn", nullptr);
2556125573
25562 ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5);25574 ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 6);
25563 result->data.x_struct.fields = fields;25575 result->data.x_struct.fields = fields;
2556425576
25565 // calling_convention: TypeInfo.CallingConvention25577 // calling_convention: TypeInfo.CallingConvention
...@@ -25567,38 +25579,42 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25567,38 +25579,42 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25567 fields[0]->special = ConstValSpecialStatic;25579 fields[0]->special = ConstValSpecialStatic;
25568 fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention");25580 fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention");
25569 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);25581 bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
25582 // alignment: u29
25583 ensure_field_index(result->type, "alignment", 1);
25584 fields[1]->special = ConstValSpecialStatic;
25585 fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
25586 bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.fn.fn_type_id.alignment);
25570 // is_generic: bool25587 // is_generic: bool
25571 ensure_field_index(result->type, "is_generic", 1);25588 ensure_field_index(result->type, "is_generic", 2);
25572 bool is_generic = type_entry->data.fn.is_generic;25589 bool is_generic = type_entry->data.fn.is_generic;
25573 fields[1]->special = ConstValSpecialStatic;
25574 fields[1]->type = ira->codegen->builtin_types.entry_bool;
25575 fields[1]->data.x_bool = is_generic;
25576 // is_varargs: bool
25577 ensure_field_index(result->type, "is_var_args", 2);
25578 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
25579 fields[2]->special = ConstValSpecialStatic;25590 fields[2]->special = ConstValSpecialStatic;
25580 fields[2]->type = ira->codegen->builtin_types.entry_bool;25591 fields[2]->type = ira->codegen->builtin_types.entry_bool;
25581 fields[2]->data.x_bool = type_entry->data.fn.fn_type_id.is_var_args;25592 fields[2]->data.x_bool = is_generic;
25582 // return_type: ?type25593 // is_varargs: bool
25583 ensure_field_index(result->type, "return_type", 3);25594 ensure_field_index(result->type, "is_var_args", 3);
25595 bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
25584 fields[3]->special = ConstValSpecialStatic;25596 fields[3]->special = ConstValSpecialStatic;
25585 fields[3]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);25597 fields[3]->type = ira->codegen->builtin_types.entry_bool;
25598 fields[3]->data.x_bool = is_varargs;
25599 // return_type: ?type
25600 ensure_field_index(result->type, "return_type", 4);
25601 fields[4]->special = ConstValSpecialStatic;
25602 fields[4]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
25586 if (type_entry->data.fn.fn_type_id.return_type == nullptr)25603 if (type_entry->data.fn.fn_type_id.return_type == nullptr)
25587 fields[3]->data.x_optional = nullptr;25604 fields[4]->data.x_optional = nullptr;
25588 else {25605 else {
25589 ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>();25606 ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>();
25590 return_type->special = ConstValSpecialStatic;25607 return_type->special = ConstValSpecialStatic;
25591 return_type->type = ira->codegen->builtin_types.entry_type;25608 return_type->type = ira->codegen->builtin_types.entry_type;
25592 return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;25609 return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
25593 fields[3]->data.x_optional = return_type;25610 fields[4]->data.x_optional = return_type;
25594 }25611 }
25595 // args: []TypeInfo.FnArg25612 // args: []TypeInfo.FnArg
25596 ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);25613 ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
25597 if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) {25614 if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
25598 zig_unreachable();25615 zig_unreachable();
25599 }25616 }
25600 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count -25617 size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count;
25601 (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC);
2560225618
25603 ZigValue *fn_arg_array = ira->codegen->pass1_arena->create<ZigValue>();25619 ZigValue *fn_arg_array = ira->codegen->pass1_arena->create<ZigValue>();
25604 fn_arg_array->special = ConstValSpecialStatic;25620 fn_arg_array->special = ConstValSpecialStatic;
...@@ -25606,7 +25622,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy...@@ -25606,7 +25622,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
25606 fn_arg_array->data.x_array.special = ConstArraySpecialNone;25622 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
25607 fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count);25623 fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count);
2560825624
25609 init_const_slice(ira->codegen, fields[4], fn_arg_array, 0, fn_arg_count, false);25625 init_const_slice(ira->codegen, fields[5], fn_arg_array, 0, fn_arg_count, false);
2561025626
25611 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {25627 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
25612 FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];25628 FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index];
...@@ -25875,8 +25891,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -25875,8 +25891,9 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
25875 buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));25891 buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
25876 return ira->codegen->invalid_inst_gen->value->type;25892 return ira->codegen->invalid_inst_gen->value->type;
25877 }25893 }
25878 BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);25894
25879 if (bi == nullptr)25895 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
25896 if (alignment == nullptr)
25880 return ira->codegen->invalid_inst_gen->value->type;25897 return ira->codegen->invalid_inst_gen->value->type;
2588125898
25882 bool is_const;25899 bool is_const;
...@@ -25903,7 +25920,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -25903,7 +25920,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
25903 is_const,25920 is_const,
25904 is_volatile,25921 is_volatile,
25905 ptr_len,25922 ptr_len,
25906 bigint_as_u32(bi),25923 bigint_as_u32(alignment),
25907 0, // bit_offset_in_host25924 0, // bit_offset_in_host
25908 0, // host_int_bytes25925 0, // host_int_bytes
25909 is_allowzero,25926 is_allowzero,
...@@ -26140,6 +26157,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26140,6 +26157,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26140 }26157 }
26141 if ((err = get_const_field_bool(ira, source_instr->source_node, field_value, "is_comptime", 3, &field->is_comptime)))26158 if ((err = get_const_field_bool(ira, source_instr->source_node, field_value, "is_comptime", 3, &field->is_comptime)))
26142 return ira->codegen->invalid_inst_gen->value->type;26159 return ira->codegen->invalid_inst_gen->value->type;
26160 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 4);
26161 if (alignment == nullptr)
26162 return ira->codegen->invalid_inst_gen->value->type;
26163 field->align = bigint_as_u32(alignment);
26143 }26164 }
2614426165
26145 return entry;26166 return entry;
...@@ -26157,6 +26178,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26157,6 +26178,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26157 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);26178 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
2615826179
26159 ZigType *tag_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "tag_type", 1);26180 ZigType *tag_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "tag_type", 1);
26181 if (type_is_invalid(tag_type))
26182 return ira->codegen->invalid_inst_gen->value->type;
26183 if (tag_type->id != ZigTypeIdInt) {
26184 ir_add_error(ira, source_instr, buf_sprintf(
26185 "TypeInfo.Enum.tag_type must be an integer type, not '%s'", buf_ptr(&tag_type->name)));
26186 return ira->codegen->invalid_inst_gen->value->type;
26187 }
2616026188
26161 ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);26189 ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);
26162 if (fields_value == nullptr)26190 if (fields_value == nullptr)
...@@ -26302,14 +26330,113 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26302,14 +26330,113 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
26302 return ira->codegen->invalid_inst_gen->value->type;26330 return ira->codegen->invalid_inst_gen->value->type;
26303 field->type_val = type_value;26331 field->type_val = type_value;
26304 field->type_entry = type_value->data.x_type;26332 field->type_entry = type_value->data.x_type;
26333 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 2);
26334 if (alignment == nullptr)
26335 return ira->codegen->invalid_inst_gen->value->type;
26336 field->align = bigint_as_u32(alignment);
26305 }26337 }
26306 return entry;26338 return entry;
26307 }26339 }
26308 case ZigTypeIdFn:26340 case ZigTypeIdFn:
26309 case ZigTypeIdBoundFn:26341 case ZigTypeIdBoundFn: {
26310 ir_add_error(ira, source_instr, buf_sprintf(26342 assert(payload->special == ConstValSpecialStatic);
26311 "@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId)));26343 assert(payload->type == ir_type_info_get_type(ira, "Fn", nullptr));
26312 return ira->codegen->invalid_inst_gen->value->type;26344
26345 ZigValue *cc_value = get_const_field(ira, source_instr->source_node, payload, "calling_convention", 0);
26346 if (cc_value == nullptr)
26347 return ira->codegen->invalid_inst_gen->value->type;
26348 assert(cc_value->special == ConstValSpecialStatic);
26349 assert(cc_value->type == get_builtin_type(ira->codegen, "CallingConvention"));
26350 CallingConvention cc = (CallingConvention)bigint_as_u32(&cc_value->data.x_enum_tag);
26351
26352 BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 1);
26353 if (alignment == nullptr)
26354 return ira->codegen->invalid_inst_gen->value->type;
26355
26356 Error err;
26357 bool is_generic;
26358 if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_generic", 2, &is_generic)))
26359 return ira->codegen->invalid_inst_gen->value->type;
26360 if (is_generic) {
26361 ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.Fn.is_generic must be false for @Type"));
26362 return ira->codegen->invalid_inst_gen->value->type;
26363 }
26364
26365 bool is_var_args;
26366 if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_var_args", 3, &is_var_args)))
26367 return ira->codegen->invalid_inst_gen->value->type;
26368 if (is_var_args && cc != CallingConventionC) {
26369 ir_add_error(ira, source_instr, buf_sprintf("varargs functions must have C calling convention"));
26370 return ira->codegen->invalid_inst_gen->value->type;
26371 }
26372
26373 ZigType *return_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "return_type", 4);
26374 if (return_type == nullptr) {
26375 ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.Fn.return_type must be non-null for @Type"));
26376 return ira->codegen->invalid_inst_gen->value->type;
26377 }
26378
26379 ZigValue *args_value = get_const_field(ira, source_instr->source_node, payload, "args", 5);
26380 if (args_value == nullptr)
26381 return ira->codegen->invalid_inst_gen->value->type;
26382 assert(args_value->special == ConstValSpecialStatic);
26383 assert(is_slice(args_value->type));
26384 ZigValue *args_ptr = args_value->data.x_struct.fields[slice_ptr_index];
26385 ZigValue *args_len_value = args_value->data.x_struct.fields[slice_len_index];
26386 size_t args_len = bigint_as_usize(&args_len_value->data.x_bigint);
26387
26388 FnTypeId fn_type_id = {};
26389 fn_type_id.return_type = return_type;
26390 fn_type_id.param_info = heap::c_allocator.allocate<FnTypeParamInfo>(args_len);
26391 fn_type_id.param_count = args_len;
26392 fn_type_id.next_param_index = args_len;
26393 fn_type_id.is_var_args = is_var_args;
26394 fn_type_id.cc = cc;
26395 fn_type_id.alignment = bigint_as_u32(alignment);
26396
26397 assert(args_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
26398 assert(args_ptr->data.x_ptr.data.base_array.elem_index == 0);
26399 ZigValue *args_arr = args_ptr->data.x_ptr.data.base_array.array_val;
26400 assert(args_arr->special == ConstValSpecialStatic);
26401 assert(args_arr->data.x_array.special == ConstArraySpecialNone);
26402 for (size_t i = 0; i < args_len; i++) {
26403 ZigValue *arg_value = &args_arr->data.x_array.data.s_none.elements[i];
26404 assert(arg_value->type == ir_type_info_get_type(ira, "FnArg", nullptr));
26405 FnTypeParamInfo *info = &fn_type_id.param_info[i];
26406 Error err;
26407 bool is_generic;
26408 if ((err = get_const_field_bool(ira, source_instr->source_node, arg_value, "is_generic", 0, &is_generic)))
26409 return ira->codegen->invalid_inst_gen->value->type;
26410 if (is_generic) {
26411 ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.FnArg.is_generic must be false for @Type"));
26412 return ira->codegen->invalid_inst_gen->value->type;
26413 }
26414 if ((err = get_const_field_bool(ira, source_instr->source_node, arg_value, "is_noalias", 1, &info->is_noalias)))
26415 return ira->codegen->invalid_inst_gen->value->type;
26416 ZigType *type = get_const_field_meta_type_optional(
26417 ira, source_instr->source_node, arg_value, "arg_type", 2);
26418 if (type == nullptr) {
26419 ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.FnArg.arg_type must be non-null for @Type"));
26420 return ira->codegen->invalid_inst_gen->value->type;
26421 }
26422 info->type = type;
26423 }
26424
26425 ZigType *entry = get_fn_type(ira->codegen, &fn_type_id);
26426
26427 switch (tagTypeId) {
26428 case ZigTypeIdFn:
26429 return entry;
26430 case ZigTypeIdBoundFn: {
26431 ZigType *bound_fn_entry = new_type_table_entry(ZigTypeIdBoundFn);
26432 bound_fn_entry->name = *buf_sprintf("(bound %s)", buf_ptr(&entry->name));
26433 bound_fn_entry->data.bound_fn.fn_type = entry;
26434 return bound_fn_entry;
26435 }
26436 default:
26437 zig_unreachable();
26438 }
26439 }
26313 }26440 }
26314 zig_unreachable();26441 zig_unreachable();
26315}26442}
src/stage1/os.cpp+21-1053
...@@ -94,106 +94,6 @@ static clock_serv_t macos_monotonic_clock;...@@ -94,106 +94,6 @@ static clock_serv_t macos_monotonic_clock;
94extern char **environ;94extern char **environ;
95#endif95#endif
9696
97#if defined(ZIG_OS_POSIX)
98static void populate_termination(Termination *term, int status) {
99 if (WIFEXITED(status)) {
100 term->how = TerminationIdClean;
101 term->code = WEXITSTATUS(status);
102 } else if (WIFSIGNALED(status)) {
103 term->how = TerminationIdSignaled;
104 term->code = WTERMSIG(status);
105 } else if (WIFSTOPPED(status)) {
106 term->how = TerminationIdStopped;
107 term->code = WSTOPSIG(status);
108 } else {
109 term->how = TerminationIdUnknown;
110 term->code = status;
111 }
112}
113
114static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) {
115 const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
116 for (size_t i = 0; i < args.length; i += 1) {
117 argv[i] = args.at(i);
118 }
119 argv[args.length] = nullptr;
120
121 pid_t pid;
122 int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ);
123 if (rc != 0) {
124 zig_panic("unable to spawn %s: %s", args.at(0), strerror(rc));
125 }
126
127 int status;
128 waitpid(pid, &status, 0);
129 populate_termination(term, status);
130 heap::c_allocator.deallocate(argv, args.length + 1);
131}
132#endif
133
134#if defined(ZIG_OS_WINDOWS)
135
136static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) {
137 buf_resize(command_line, 0);
138 const char *prefix = "\"";
139 for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) {
140 const char *arg = args.at(arg_i);
141 buf_append_str(command_line, prefix);
142 prefix = " \"";
143 size_t arg_len = strlen(arg);
144 for (size_t c_i = 0; c_i < arg_len; c_i += 1) {
145 if (arg[c_i] == '\"') {
146 zig_panic("TODO");
147 }
148 buf_append_char(command_line, arg[c_i]);
149 }
150 buf_append_char(command_line, '\"');
151 }
152}
153
154static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) {
155 Buf command_line = BUF_INIT;
156 os_windows_create_command_line(&command_line, args);
157
158 PROCESS_INFORMATION piProcInfo = {0};
159 STARTUPINFOW siStartInfo = {0};
160 siStartInfo.cb = sizeof(STARTUPINFOW);
161
162 Slice<uint8_t> exe_slice = str(args.at(0));
163 auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1);
164 exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0;
165
166 auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1);
167 command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0;
168
169 BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr,
170 &siStartInfo, &piProcInfo);
171
172 if (!success) {
173 zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line));
174 }
175
176 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
177
178 DWORD exit_code;
179 if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
180 zig_panic("GetExitCodeProcess failed");
181 }
182 term->how = TerminationIdClean;
183 term->code = exit_code;
184}
185#endif
186
187void os_spawn_process(ZigList<const char *> &args, Termination *term) {
188#if defined(ZIG_OS_WINDOWS)
189 os_spawn_process_windows(args, term);
190#elif defined(ZIG_OS_POSIX)
191 os_spawn_process_posix(args, term);
192#else
193#error "missing os_spawn_process implementation"
194#endif
195}
196
197void os_path_dirname(Buf *full_path, Buf *out_dirname) {97void os_path_dirname(Buf *full_path, Buf *out_dirname) {
198 return os_path_split(full_path, out_dirname, nullptr);98 return os_path_split(full_path, out_dirname, nullptr);
199}99}
...@@ -281,71 +181,27 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {...@@ -281,71 +181,27 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
281 buf_append_buf(out_full_path, basename);181 buf_append_buf(out_full_path, basename);
282}182}
283183
284Error os_path_real(Buf *rel_path, Buf *out_abs_path) {
285#if defined(ZIG_OS_WINDOWS)
286 PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path));
287 PathSpace out_abs_path_space;
288
289 if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) {
290 zig_panic("_wfullpath failed");
291 }
292 utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]);
293 return ErrorNone;
294#elif defined(ZIG_OS_POSIX)
295 buf_resize(out_abs_path, PATH_MAX + 1);
296 char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path));
297 if (!result) {
298 int err = errno;
299 if (err == EACCES) {
300 return ErrorAccess;
301 } else if (err == ENOENT) {
302 return ErrorFileNotFound;
303 } else if (err == ENOMEM) {
304 return ErrorNoMem;
305 } else {
306 return ErrorFileSystem;
307 }
308 }
309 buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
310 return ErrorNone;
311#else
312#error "missing os_path_real implementation"
313#endif
314}
315
316#if defined(ZIG_OS_WINDOWS)
317// Ported from std/os/path.zig
318static bool isAbsoluteWindows(Slice<uint8_t> path) {
319 if (path.ptr[0] == '/')
320 return true;
321
322 if (path.ptr[0] == '\\') {
323 return true;
324 }
325 if (path.len < 3) {
326 return false;
327 }
328 if (path.ptr[1] == ':') {
329 if (path.ptr[2] == '/')
330 return true;
331 if (path.ptr[2] == '\\')
332 return true;
333 }
334 return false;
335}
336#endif
337
338bool os_path_is_absolute(Buf *path) {
339#if defined(ZIG_OS_WINDOWS)
340 return isAbsoluteWindows(buf_to_slice(path));
341#elif defined(ZIG_OS_POSIX)
342 return buf_ptr(path)[0] == '/';
343#else
344#error "missing os_path_is_absolute implementation"
345#endif
346}
347184
348#if defined(ZIG_OS_WINDOWS)185#if defined(ZIG_OS_WINDOWS)
186// Ported from std/os/path.zig
187static bool isAbsoluteWindows(Slice<uint8_t> path) {
188 if (path.ptr[0] == '/')
189 return true;
190
191 if (path.ptr[0] == '\\') {
192 return true;
193 }
194 if (path.len < 3) {
195 return false;
196 }
197 if (path.ptr[1] == ':') {
198 if (path.ptr[2] == '/')
199 return true;
200 if (path.ptr[2] == '\\')
201 return true;
202 }
203 return false;
204}
349205
350enum WindowsPathKind {206enum WindowsPathKind {
351 WindowsPathKindNone,207 WindowsPathKindNone,
...@@ -688,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {...@@ -688,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
688 size_t max_size = 0;544 size_t max_size = 0;
689 for (size_t i = 0; i < paths_len; i += 1) {545 for (size_t i = 0; i < paths_len; i += 1) {
690 Buf *p = paths_ptr[i];546 Buf *p = paths_ptr[i];
691 if (os_path_is_absolute(p)) {547 if (buf_ptr(p)[0] == '/') {
692 first_index = i;548 first_index = i;
693 have_abs = true;549 have_abs = true;
694 max_size = 0;550 max_size = 0;
...@@ -788,256 +644,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {...@@ -788,256 +644,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {
788 zig_unreachable();644 zig_unreachable();
789}645}
790646
791Error os_file_exists(Buf *full_path, bool *result) {
792#if defined(ZIG_OS_WINDOWS)
793 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
794 *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES;
795 return ErrorNone;
796#else
797 *result = access(buf_ptr(full_path), F_OK) != -1;
798 return ErrorNone;
799#endif
800}
801
802#if defined(ZIG_OS_POSIX)
803static Error os_exec_process_posix(ZigList<const char *> &args,
804 Termination *term, Buf *out_stderr, Buf *out_stdout)
805{
806 int stdin_pipe[2];
807 int stdout_pipe[2];
808 int stderr_pipe[2];
809 int err_pipe[2];
810
811 int err;
812 if ((err = pipe(stdin_pipe)))
813 zig_panic("pipe failed");
814 if ((err = pipe(stdout_pipe)))
815 zig_panic("pipe failed");
816 if ((err = pipe(stderr_pipe)))
817 zig_panic("pipe failed");
818 if ((err = pipe(err_pipe)))
819 zig_panic("pipe failed");
820
821 pid_t pid = fork();
822 if (pid == -1)
823 zig_panic("fork failed: %s", strerror(errno));
824 if (pid == 0) {
825 // child
826 if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
827 zig_panic("dup2 failed");
828
829 if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1)
830 zig_panic("dup2 failed");
831
832 if (dup2(stderr_pipe[1], STDERR_FILENO) == -1)
833 zig_panic("dup2 failed");
834
835 const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
836 argv[args.length] = nullptr;
837 for (size_t i = 0; i < args.length; i += 1) {
838 argv[i] = args.at(i);
839 }
840 execvp(argv[0], const_cast<char * const *>(argv));
841 Error report_err = ErrorUnexpected;
842 if (errno == ENOENT) {
843 report_err = ErrorFileNotFound;
844 }
845 if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) {
846 zig_panic("write failed");
847 }
848 exit(1);
849 } else {
850 // parent
851 close(stdin_pipe[0]);
852 close(stdin_pipe[1]);
853 close(stdout_pipe[1]);
854 close(stderr_pipe[1]);
855
856 int status;
857 waitpid(pid, &status, 0);
858 populate_termination(term, status);
859
860 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
861 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
862 Error err1 = os_fetch_file(stdout_f, out_stdout);
863 Error err2 = os_fetch_file(stderr_f, out_stderr);
864
865 fclose(stdout_f);
866 fclose(stderr_f);
867
868 if (err1) return err1;
869 if (err2) return err2;
870
871 Error child_err = ErrorNone;
872 if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) {
873 zig_panic("write failed");
874 }
875 close(err_pipe[1]);
876 if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) {
877 zig_panic("write failed");
878 }
879 close(err_pipe[0]);
880 return child_err;
881 }
882}
883#endif
884
885#if defined(ZIG_OS_WINDOWS)
886
887//static void win32_panic(const char *str) {
888// DWORD err = GetLastError();
889// LPSTR messageBuffer = nullptr;
890// FormatMessageA(
891// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
892// NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
893// zig_panic(str, messageBuffer);
894// LocalFree(messageBuffer);
895//}
896
897static Error os_exec_process_windows(ZigList<const char *> &args,
898 Termination *term, Buf *out_stderr, Buf *out_stdout)
899{
900 Buf command_line = BUF_INIT;
901 os_windows_create_command_line(&command_line, args);
902
903 HANDLE g_hChildStd_IN_Rd = NULL;
904 HANDLE g_hChildStd_IN_Wr = NULL;
905 HANDLE g_hChildStd_OUT_Rd = NULL;
906 HANDLE g_hChildStd_OUT_Wr = NULL;
907 HANDLE g_hChildStd_ERR_Rd = NULL;
908 HANDLE g_hChildStd_ERR_Wr = NULL;
909
910 SECURITY_ATTRIBUTES saAttr;
911 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
912 saAttr.bInheritHandle = TRUE;
913 saAttr.lpSecurityDescriptor = NULL;
914
915 if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) {
916 zig_panic("StdoutRd CreatePipe");
917 }
918
919 if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
920 zig_panic("Stdout SetHandleInformation");
921 }
922
923 if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) {
924 zig_panic("stderr CreatePipe");
925 }
926
927 if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) {
928 zig_panic("stderr SetHandleInformation");
929 }
930
931 if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) {
932 zig_panic("Stdin CreatePipe");
933 }
934
935 if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) {
936 zig_panic("Stdin SetHandleInformation");
937 }
938
939
940 PROCESS_INFORMATION piProcInfo = {0};
941 STARTUPINFO siStartInfo = {0};
942 siStartInfo.cb = sizeof(STARTUPINFO);
943 siStartInfo.hStdError = g_hChildStd_ERR_Wr;
944 siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
945 siStartInfo.hStdInput = g_hChildStd_IN_Rd;
946 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
947
948 const char *exe = args.at(0);
949 BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
950 &siStartInfo, &piProcInfo);
951
952 if (!success) {
953 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
954 CloseHandle(piProcInfo.hProcess);
955 CloseHandle(piProcInfo.hThread);
956 return ErrorFileNotFound;
957 }
958 zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));
959 }
960
961 if (!CloseHandle(g_hChildStd_IN_Wr)) {
962 zig_panic("stdinwr closehandle");
963 }
964
965 CloseHandle(g_hChildStd_IN_Rd);
966 CloseHandle(g_hChildStd_ERR_Wr);
967 CloseHandle(g_hChildStd_OUT_Wr);
968
969 static const size_t BUF_SIZE = 4 * 1024;
970 {
971 DWORD dwRead;
972 char chBuf[BUF_SIZE];
973
974 buf_resize(out_stdout, 0);
975 for (;;) {
976 success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
977 if (!success || dwRead == 0) break;
978
979 buf_append_mem(out_stdout, chBuf, dwRead);
980 }
981 CloseHandle(g_hChildStd_OUT_Rd);
982 }
983 {
984 DWORD dwRead;
985 char chBuf[BUF_SIZE];
986
987 buf_resize(out_stderr, 0);
988 for (;;) {
989 success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
990 if (!success || dwRead == 0) break;
991
992 buf_append_mem(out_stderr, chBuf, dwRead);
993 }
994 CloseHandle(g_hChildStd_ERR_Rd);
995 }
996
997 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
998
999 DWORD exit_code;
1000 if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
1001 zig_panic("GetExitCodeProcess failed");
1002 }
1003 term->how = TerminationIdClean;
1004 term->code = exit_code;
1005
1006 CloseHandle(piProcInfo.hProcess);
1007 CloseHandle(piProcInfo.hThread);
1008
1009 return ErrorNone;
1010}
1011#endif
1012
1013Error os_execv(const char *exe, const char **argv) {
1014#if defined(ZIG_OS_WINDOWS)
1015 return ErrorUnsupportedOperatingSystem;
1016#else
1017 execv(exe, (char *const *)argv);
1018 switch (errno) {
1019 case ENOMEM:
1020 return ErrorSystemResources;
1021 case EIO:
1022 return ErrorFileSystem;
1023 default:
1024 return ErrorUnexpected;
1025 }
1026#endif
1027}
1028
1029Error os_exec_process(ZigList<const char *> &args,
1030 Termination *term, Buf *out_stderr, Buf *out_stdout)
1031{
1032#if defined(ZIG_OS_WINDOWS)
1033 return os_exec_process_windows(args, term, out_stderr, out_stdout);
1034#elif defined(ZIG_OS_POSIX)
1035 return os_exec_process_posix(args, term, out_stderr, out_stdout);
1036#else
1037#error "missing os_exec_process implementation"
1038#endif
1039}
1040
1041Error os_write_file(Buf *full_path, Buf *contents) {647Error os_write_file(Buf *full_path, Buf *contents) {
1042#if defined(ZIG_OS_WINDOWS)648#if defined(ZIG_OS_WINDOWS)
1043 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));649 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
...@@ -1076,35 +682,6 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {...@@ -1076,35 +682,6 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
1076 }682 }
1077}683}
1078684
1079Error os_dump_file(Buf *src_path, FILE *dest_file) {
1080 Error err;
1081
1082#if defined(ZIG_OS_WINDOWS)
1083 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
1084 FILE *src_f = _wfopen(&path_space.data.items[0], L"rb");
1085#else
1086 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1087#endif
1088 if (!src_f) {
1089 int err = errno;
1090 if (err == ENOENT) {
1091 return ErrorFileNotFound;
1092 } else if (err == EACCES || err == EPERM) {
1093 return ErrorAccess;
1094 } else {
1095 return ErrorFileSystem;
1096 }
1097 }
1098 copy_open_files(src_f, dest_file);
1099 if ((err = copy_open_files(src_f, dest_file))) {
1100 fclose(src_f);
1101 return err;
1102 }
1103
1104 fclose(src_f);
1105 return ErrorNone;
1106}
1107
1108#if defined(ZIG_OS_WINDOWS)685#if defined(ZIG_OS_WINDOWS)
1109static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {686static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
1110 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;687 mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
...@@ -1118,88 +695,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) {...@@ -1118,88 +695,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) {
1118}695}
1119#endif696#endif
1120697
1121static Error set_file_times(OsFile file, OsTimeStamp ts) {
1122#if defined(ZIG_OS_WINDOWS)
1123 FILETIME ft = windows_os_timestamp_to_filetime(ts);
1124 if (SetFileTime(file, nullptr, &ft, &ft) == 0) {
1125 return ErrorUnexpected;
1126 }
1127 return ErrorNone;
1128#else
1129 struct timespec times[2] = {
1130 { (time_t)ts.sec, (long)ts.nsec },
1131 { (time_t)ts.sec, (long)ts.nsec },
1132 };
1133 if (futimens(file, times) == -1) {
1134 switch (errno) {
1135 case EBADF:
1136 zig_panic("futimens EBADF");
1137 default:
1138 return ErrorUnexpected;
1139 }
1140 }
1141 return ErrorNone;
1142#endif
1143}
1144
1145Error os_update_file(Buf *src_path, Buf *dst_path) {
1146 Error err;
1147
1148 OsFile src_file;
1149 OsFileAttr src_attr;
1150 if ((err = os_file_open_r(src_path, &src_file, &src_attr))) {
1151 return err;
1152 }
1153
1154 OsFile dst_file;
1155 OsFileAttr dst_attr;
1156 if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) {
1157 os_file_close(&src_file);
1158 return err;
1159 }
1160
1161 if (src_attr.size == dst_attr.size &&
1162 src_attr.mode == dst_attr.mode &&
1163 src_attr.mtime.sec == dst_attr.mtime.sec &&
1164 src_attr.mtime.nsec == dst_attr.mtime.nsec)
1165 {
1166 os_file_close(&src_file);
1167 os_file_close(&dst_file);
1168 return ErrorNone;
1169 }
1170#if defined(ZIG_OS_WINDOWS)
1171 if (SetEndOfFile(dst_file) == 0) {
1172 return ErrorUnexpected;
1173 }
1174#else
1175 if (ftruncate(dst_file, 0) == -1) {
1176 return ErrorUnexpected;
1177 }
1178#endif
1179#if defined(ZIG_OS_WINDOWS)
1180 FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb");
1181 FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb");
1182#else
1183 FILE *src_libc_file = fdopen(src_file, "rb");
1184 FILE *dst_libc_file = fdopen(dst_file, "wb");
1185#endif
1186 assert(src_libc_file);
1187 assert(dst_libc_file);
1188
1189 if ((err = copy_open_files(src_libc_file, dst_libc_file))) {
1190 fclose(src_libc_file);
1191 fclose(dst_libc_file);
1192 return err;
1193 }
1194 if (fflush(dst_libc_file) == -1) {
1195 return ErrorUnexpected;
1196 }
1197 err = set_file_times(dst_file, src_attr.mtime);
1198 fclose(src_libc_file);
1199 fclose(dst_libc_file);
1200 return err;
1201}
1202
1203Error os_copy_file(Buf *src_path, Buf *dest_path) {698Error os_copy_file(Buf *src_path, Buf *dest_path) {
1204#if defined(ZIG_OS_WINDOWS)699#if defined(ZIG_OS_WINDOWS)
1205 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));700 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
...@@ -1360,14 +855,6 @@ bool os_stderr_tty(void) {...@@ -1360,14 +855,6 @@ bool os_stderr_tty(void) {
1360#endif855#endif
1361}856}
1362857
1363Error os_delete_file(Buf *path) {
1364 if (remove(buf_ptr(path))) {
1365 return ErrorFileSystem;
1366 } else {
1367 return ErrorNone;
1368 }
1369}
1370
1371Error os_rename(Buf *src_path, Buf *dest_path) {858Error os_rename(Buf *src_path, Buf *dest_path) {
1372 if (buf_eql_buf(src_path, dest_path)) {859 if (buf_eql_buf(src_path, dest_path)) {
1373 return ErrorNone;860 return ErrorNone;
...@@ -1386,30 +873,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) {...@@ -1386,30 +873,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
1386 return ErrorNone;873 return ErrorNone;
1387}874}
1388875
1389OsTimeStamp os_timestamp_calendar(void) {
1390 OsTimeStamp result;
1391#if defined(ZIG_OS_WINDOWS)
1392 FILETIME ft;
1393 GetSystemTimeAsFileTime(&ft);
1394 windows_filetime_to_os_timestamp(&ft, &result);
1395#elif defined(__MACH__)
1396 mach_timespec_t mts;
1397
1398 kern_return_t err = clock_get_time(macos_calendar_clock, &mts);
1399 assert(!err);
1400
1401 result.sec = mts.tv_sec;
1402 result.nsec = mts.tv_nsec;
1403#else
1404 struct timespec tms;
1405 clock_gettime(CLOCK_REALTIME, &tms);
1406
1407 result.sec = tms.tv_sec;
1408 result.nsec = tms.tv_nsec;
1409#endif
1410 return result;
1411}
1412
1413OsTimeStamp os_timestamp_monotonic(void) {876OsTimeStamp os_timestamp_monotonic(void) {
1414 OsTimeStamp result;877 OsTimeStamp result;
1415#if defined(ZIG_OS_WINDOWS)878#if defined(ZIG_OS_WINDOWS)
...@@ -1503,49 +966,8 @@ Error os_make_dir(Buf *path) {...@@ -1503,49 +966,8 @@ Error os_make_dir(Buf *path) {
1503#endif966#endif
1504}967}
1505968
1506static void init_rand() {
1507#if defined(ZIG_OS_WINDOWS)
1508 char bytes[sizeof(unsigned)];
1509 unsigned seed;
1510 RtlGenRandom(bytes, sizeof(unsigned));
1511 memcpy(&seed, bytes, sizeof(unsigned));
1512 srand(seed);
1513#elif defined(ZIG_OS_LINUX)
1514 unsigned char *ptr_random = (unsigned char*)getauxval(AT_RANDOM);
1515 unsigned seed;
1516 memcpy(&seed, ptr_random, sizeof(seed));
1517 srand(seed);
1518#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
1519 unsigned seed;
1520 size_t len = sizeof(seed);
1521 int mib[2] = { CTL_KERN, KERN_ARND };
1522 if (sysctl(mib, 2, &seed, &len, NULL, 0) != 0) {
1523 zig_panic("unable to query random data from sysctl");
1524 }
1525 srand(seed);
1526#else
1527 int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
1528 if (fd == -1) {
1529 zig_panic("unable to open /dev/urandom");
1530 }
1531 char bytes[sizeof(unsigned)];
1532 ssize_t amt_read;
1533 while ((amt_read = read(fd, bytes, sizeof(unsigned))) == -1) {
1534 if (errno == EINTR) continue;
1535 zig_panic("unable to read /dev/urandom");
1536 }
1537 if (amt_read != sizeof(unsigned)) {
1538 zig_panic("unable to read enough bytes from /dev/urandom");
1539 }
1540 close(fd);
1541 unsigned seed;
1542 memcpy(&seed, bytes, sizeof(unsigned));
1543 srand(seed);
1544#endif
1545}
1546969
1547int os_init(void) {970int os_init(void) {
1548 init_rand();
1549#if defined(ZIG_OS_WINDOWS)971#if defined(ZIG_OS_WINDOWS)
1550 _setmode(fileno(stdout), _O_BINARY);972 _setmode(fileno(stdout), _O_BINARY);
1551 _setmode(fileno(stderr), _O_BINARY);973 _setmode(fileno(stderr), _O_BINARY);
...@@ -1582,71 +1004,6 @@ int os_init(void) {...@@ -1582,71 +1004,6 @@ int os_init(void) {
1582 return 0;1004 return 0;
1583}1005}
15841006
1585Error os_self_exe_path(Buf *out_path) {
1586#if defined(ZIG_OS_WINDOWS)
1587 PathSpace path_space;
1588 DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE);
1589 if (copied_amt <= 0) {
1590 return ErrorFileNotFound;
1591 }
1592 utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]);
1593 return ErrorNone;
1594
1595#elif defined(ZIG_OS_DARWIN)
1596 // How long is the executable's path?
1597 uint32_t u32_len = 0;
1598 int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
1599 assert(ret1 != 0);
1600
1601 Buf *tmp = buf_alloc_fixed(u32_len);
1602
1603 // Fill the executable path.
1604 int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
1605 assert(ret2 == 0);
1606
1607 // According to libuv project, PATH_MAX*2 works around a libc bug where
1608 // the resolved path is sometimes bigger than PATH_MAX.
1609 buf_resize(out_path, PATH_MAX*2);
1610 char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
1611 if (!real_path) {
1612 buf_init_from_buf(out_path, tmp);
1613 return ErrorNone;
1614 }
1615
1616 // Resize out_path for the correct length.
1617 buf_resize(out_path, strlen(buf_ptr(out_path)));
1618
1619 return ErrorNone;
1620#elif defined(ZIG_OS_LINUX)
1621 buf_resize(out_path, PATH_MAX);
1622 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
1623 if (amt == -1) {
1624 return ErrorUnexpected;
1625 }
1626 buf_resize(out_path, amt);
1627 return ErrorNone;
1628#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_DRAGONFLY)
1629 buf_resize(out_path, PATH_MAX);
1630 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
1631 size_t cb = PATH_MAX;
1632 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1633 return ErrorUnexpected;
1634 }
1635 buf_resize(out_path, cb - 1);
1636 return ErrorNone;
1637#elif defined(ZIG_OS_NETBSD)
1638 buf_resize(out_path, PATH_MAX);
1639 int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
1640 size_t cb = PATH_MAX;
1641 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1642 return ErrorUnexpected;
1643 }
1644 buf_resize(out_path, cb - 1);
1645 return ErrorNone;
1646#endif
1647 return ErrorFileNotFound;
1648}
1649
1650#define VT_RED "\x1b[31;1m"1007#define VT_RED "\x1b[31;1m"
1651#define VT_GREEN "\x1b[32;1m"1008#define VT_GREEN "\x1b[32;1m"
1652#define VT_CYAN "\x1b[36;1m"1009#define VT_CYAN "\x1b[36;1m"
...@@ -1956,392 +1313,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {...@@ -1956,392 +1313,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
1956 return path_space;1313 return path_space;
1957}1314}
1958#endif1315#endif
1959
1960// Ported from std.os.getAppDataDir
1961Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1962#if defined(ZIG_OS_WINDOWS)
1963 WCHAR *dir_path_ptr;
1964 switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
1965 case S_OK:
1966 // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
1967 utf16le_ptr_to_utf8(out_path, dir_path_ptr);
1968 CoTaskMemFree(dir_path_ptr);
1969 buf_appendf(out_path, "\\%s", appname);
1970 return ErrorNone;
1971 case E_OUTOFMEMORY:
1972 return ErrorNoMem;
1973 default:
1974 return ErrorUnexpected;
1975 }
1976 zig_unreachable();
1977#elif defined(ZIG_OS_DARWIN)
1978 const char *home_dir = getenv("HOME");
1979 if (home_dir == nullptr) {
1980 // TODO use /etc/passwd
1981 return ErrorFileNotFound;
1982 }
1983 buf_resize(out_path, 0);
1984 buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
1985 return ErrorNone;
1986#elif defined(ZIG_OS_POSIX)
1987 const char *cache_dir = getenv("XDG_CACHE_HOME");
1988 if (cache_dir == nullptr) {
1989 cache_dir = getenv("HOME");
1990 if (cache_dir == nullptr) {
1991 // TODO use /etc/passwd
1992 return ErrorFileNotFound;
1993 }
1994 if (cache_dir[0] == 0) {
1995 return ErrorFileNotFound;
1996 }
1997 buf_init_from_str(out_path, cache_dir);
1998 if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
1999 buf_append_char(out_path, '/');
2000 }
2001 buf_appendf(out_path, ".cache/%s", appname);
2002 } else {
2003 if (cache_dir[0] == 0) {
2004 return ErrorFileNotFound;
2005 }
2006 buf_init_from_str(out_path, cache_dir);
2007 if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
2008 buf_append_char(out_path, '/');
2009 }
2010 buf_appendf(out_path, "%s", appname);
2011 }
2012 return ErrorNone;
2013#endif
2014}
2015
2016#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
2017static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
2018 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
2019 if (info->dlpi_name[0] == '/') {
2020 libs->append(buf_create_from_str(info->dlpi_name));
2021 }
2022 return 0;
2023}
2024#endif
2025
2026Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
2027#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
2028 paths.resize(0);
2029 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
2030 return ErrorNone;
2031#elif defined(ZIG_OS_DARWIN)
2032 paths.resize(0);
2033 uint32_t img_count = _dyld_image_count();
2034 for (uint32_t i = 0; i != img_count; i += 1) {
2035 const char *name = _dyld_get_image_name(i);
2036 paths.append(buf_create_from_str(name));
2037 }
2038 return ErrorNone;
2039#elif defined(ZIG_OS_WINDOWS)
2040 // zig is built statically on windows, so we can return an empty list
2041 paths.resize(0);
2042 return ErrorNone;
2043#else
2044#error unimplemented
2045#endif
2046}
2047
2048Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
2049#if defined(ZIG_OS_WINDOWS)
2050 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
2051 HANDLE result = CreateFileW(&path_space.data.items[0],
2052 need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
2053 need_write ? 0 : FILE_SHARE_READ,
2054 nullptr,
2055 need_write ? OPEN_ALWAYS : OPEN_EXISTING,
2056 FILE_ATTRIBUTE_NORMAL, nullptr);
2057
2058 if (result == INVALID_HANDLE_VALUE) {
2059 DWORD err = GetLastError();
2060 switch (err) {
2061 case ERROR_SHARING_VIOLATION:
2062 return ErrorSharingViolation;
2063 case ERROR_ALREADY_EXISTS:
2064 return ErrorPathAlreadyExists;
2065 case ERROR_FILE_EXISTS:
2066 return ErrorPathAlreadyExists;
2067 case ERROR_FILE_NOT_FOUND:
2068 return ErrorFileNotFound;
2069 case ERROR_PATH_NOT_FOUND:
2070 return ErrorFileNotFound;
2071 case ERROR_ACCESS_DENIED:
2072 return ErrorAccess;
2073 case ERROR_PIPE_BUSY:
2074 return ErrorPipeBusy;
2075 default:
2076 return ErrorUnexpected;
2077 }
2078 }
2079 *out_file = result;
2080
2081 if (attr != nullptr) {
2082 BY_HANDLE_FILE_INFORMATION file_info;
2083 if (!GetFileInformationByHandle(result, &file_info)) {
2084 CloseHandle(result);
2085 return ErrorUnexpected;
2086 }
2087 windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime);
2088 attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
2089 attr->mode = 0;
2090 attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow;
2091 }
2092
2093 return ErrorNone;
2094#else
2095 for (;;) {
2096 int fd = open(buf_ptr(full_path),
2097 need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode);
2098 if (fd == -1) {
2099 switch (errno) {
2100 case EINTR:
2101 continue;
2102 case EINVAL:
2103 zig_unreachable();
2104 case EFAULT:
2105 zig_unreachable();
2106 case EACCES:
2107 case EPERM:
2108 return ErrorAccess;
2109 case EISDIR:
2110 return ErrorIsDir;
2111 case ENOENT:
2112 return ErrorFileNotFound;
2113 default:
2114 return ErrorFileSystem;
2115 }
2116 }
2117 struct stat statbuf;
2118 if (fstat(fd, &statbuf) == -1) {
2119 close(fd);
2120 return ErrorFileSystem;
2121 }
2122 if (S_ISDIR(statbuf.st_mode)) {
2123 close(fd);
2124 return ErrorIsDir;
2125 }
2126 *out_file = fd;
2127
2128 if (attr != nullptr) {
2129 attr->inode = statbuf.st_ino;
2130#if defined(ZIG_OS_DARWIN)
2131 attr->mtime.sec = statbuf.st_mtimespec.tv_sec;
2132 attr->mtime.nsec = statbuf.st_mtimespec.tv_nsec;
2133#else
2134 attr->mtime.sec = statbuf.st_mtim.tv_sec;
2135 attr->mtime.nsec = statbuf.st_mtim.tv_nsec;
2136#endif
2137 attr->mode = statbuf.st_mode;
2138 attr->size = statbuf.st_size;
2139 }
2140 return ErrorNone;
2141 }
2142#endif
2143}
2144
2145Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
2146 return os_file_open_rw(full_path, out_file, attr, false, 0);
2147}
2148
2149Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) {
2150 return os_file_open_rw(full_path, out_file, attr, true, mode);
2151}
2152
2153Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
2154#if defined(ZIG_OS_WINDOWS)
2155 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
2156 for (;;) {
2157 HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE,
2158 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
2159
2160 if (result == INVALID_HANDLE_VALUE) {
2161 DWORD err = GetLastError();
2162 switch (err) {
2163 case ERROR_SHARING_VIOLATION:
2164 // TODO wait for the lock instead of sleeping
2165 Sleep(10);
2166 continue;
2167 case ERROR_ALREADY_EXISTS:
2168 return ErrorPathAlreadyExists;
2169 case ERROR_FILE_EXISTS:
2170 return ErrorPathAlreadyExists;
2171 case ERROR_FILE_NOT_FOUND:
2172 return ErrorFileNotFound;
2173 case ERROR_PATH_NOT_FOUND:
2174 return ErrorFileNotFound;
2175 case ERROR_ACCESS_DENIED:
2176 return ErrorAccess;
2177 case ERROR_PIPE_BUSY:
2178 return ErrorPipeBusy;
2179 default:
2180 return ErrorUnexpected;
2181 }
2182 }
2183 *out_file = result;
2184 return ErrorNone;
2185 }
2186#else
2187 int fd;
2188 for (;;) {
2189 fd = open(buf_ptr(full_path), O_RDWR|O_CLOEXEC|O_CREAT, 0666);
2190 if (fd == -1) {
2191 switch (errno) {
2192 case EINTR:
2193 continue;
2194 case EINVAL:
2195 zig_unreachable();
2196 case EFAULT:
2197 zig_unreachable();
2198 case EACCES:
2199 case EPERM:
2200 return ErrorAccess;
2201 case EISDIR:
2202 return ErrorIsDir;
2203 case ENOENT:
2204 return ErrorFileNotFound;
2205 case ENOTDIR:
2206 return ErrorNotDir;
2207 default:
2208 return ErrorFileSystem;
2209 }
2210 }
2211 break;
2212 }
2213 for (;;) {
2214 struct flock lock;
2215 lock.l_type = F_WRLCK;
2216 lock.l_whence = SEEK_SET;
2217 lock.l_start = 0;
2218 lock.l_len = 0;
2219 if (fcntl(fd, F_SETLKW, &lock) == -1) {
2220 switch (errno) {
2221 case EINTR:
2222 continue;
2223 case EBADF:
2224 zig_unreachable();
2225 case EFAULT:
2226 zig_unreachable();
2227 case EINVAL:
2228 zig_unreachable();
2229 default:
2230 close(fd);
2231 return ErrorFileSystem;
2232 }
2233 }
2234 break;
2235 }
2236 *out_file = fd;
2237 return ErrorNone;
2238#endif
2239}
2240
2241Error os_file_read(OsFile file, void *ptr, size_t *len) {
2242#if defined(ZIG_OS_WINDOWS)
2243 DWORD amt_read;
2244 if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0)
2245 return ErrorUnexpected;
2246 *len = amt_read;
2247 return ErrorNone;
2248#else
2249 for (;;) {
2250 ssize_t rc = read(file, ptr, *len);
2251 if (rc == -1) {
2252 switch (errno) {
2253 case EINTR:
2254 continue;
2255 case EBADF:
2256 zig_unreachable();
2257 case EFAULT:
2258 zig_unreachable();
2259 case EISDIR:
2260 return ErrorIsDir;
2261 default:
2262 return ErrorFileSystem;
2263 }
2264 }
2265 *len = rc;
2266 return ErrorNone;
2267 }
2268#endif
2269}
2270
2271Error os_file_read_all(OsFile file, Buf *contents) {
2272 Error err;
2273 size_t index = 0;
2274 for (;;) {
2275 size_t amt = buf_len(contents) - index;
2276
2277 if (amt < 4096) {
2278 buf_resize(contents, buf_len(contents) + (4096 - amt));
2279 amt = buf_len(contents) - index;
2280 }
2281
2282 if ((err = os_file_read(file, buf_ptr(contents) + index, &amt)))
2283 return err;
2284
2285 if (amt == 0) {
2286 buf_resize(contents, index);
2287 return ErrorNone;
2288 }
2289
2290 index += amt;
2291 }
2292}
2293
2294Error os_file_overwrite(OsFile file, Buf *contents) {
2295#if defined(ZIG_OS_WINDOWS)
2296 if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
2297 return ErrorFileSystem;
2298 if (!SetEndOfFile(file))
2299 return ErrorFileSystem;
2300 DWORD bytes_written;
2301 if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr))
2302 return ErrorFileSystem;
2303 return ErrorNone;
2304#else
2305 if (lseek(file, 0, SEEK_SET) == -1)
2306 return ErrorUnexpectedSeekFailure;
2307 if (ftruncate(file, 0) == -1)
2308 return ErrorUnexpectedFileTruncationFailure;
2309 for (;;) {
2310 if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {
2311 switch (errno) {
2312 case EINTR:
2313 continue;
2314 case EINVAL:
2315 zig_unreachable();
2316 case EBADF:
2317 zig_unreachable();
2318 case EFAULT:
2319 zig_unreachable();
2320 case EDQUOT:
2321 return ErrorDiskQuota;
2322 case ENOSPC:
2323 return ErrorDiskSpace;
2324 case EFBIG:
2325 return ErrorFileTooBig;
2326 case EIO:
2327 return ErrorFileSystem;
2328 case EPERM:
2329 return ErrorAccess;
2330 default:
2331 return ErrorUnexpectedWriteFailure;
2332 }
2333 }
2334 return ErrorNone;
2335 }
2336#endif
2337}
2338
2339void os_file_close(OsFile *file) {
2340#if defined(ZIG_OS_WINDOWS)
2341 CloseHandle(*file);
2342 *file = NULL;
2343#else
2344 close(*file);
2345 *file = -1;
2346#endif
2347}
src/stage1/os.hpp-52
...@@ -70,66 +70,25 @@ enum TermColor {...@@ -70,66 +70,25 @@ enum TermColor {
70 TermColorReset,70 TermColorReset,
71};71};
7272
73enum TerminationId {
74 TerminationIdClean,
75 TerminationIdSignaled,
76 TerminationIdStopped,
77 TerminationIdUnknown,
78};
79
80struct Termination {
81 TerminationId how;
82 int code;
83};
84
85#if defined(ZIG_OS_WINDOWS)
86#define OsFile void *
87#else
88#define OsFile int
89#endif
90
91struct OsTimeStamp {73struct OsTimeStamp {
92 int64_t sec;74 int64_t sec;
93 int64_t nsec;75 int64_t nsec;
94};76};
9577
96struct OsFileAttr {
97 OsTimeStamp mtime;
98 uint64_t size;
99 uint64_t inode;
100 uint32_t mode;
101};
102
103int os_init(void);78int os_init(void);
10479
105void os_spawn_process(ZigList<const char *> &args, Termination *term);
106Error os_exec_process(ZigList<const char *> &args,
107 Termination *term, Buf *out_stderr, Buf *out_stdout);
108Error os_execv(const char *exe, const char **argv);
109
110void os_path_dirname(Buf *full_path, Buf *out_dirname);80void os_path_dirname(Buf *full_path, Buf *out_dirname);
111void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);81void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
112void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);82void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
113void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);83void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
114Error os_path_real(Buf *rel_path, Buf *out_abs_path);
115Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);84Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
116bool os_path_is_absolute(Buf *path);85bool os_path_is_absolute(Buf *path);
11786
118Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);87Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
119Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);88Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
12089
121Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr);
122Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode);
123Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
124Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
125Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
126Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
127void os_file_close(OsFile *file);
128
129Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);90Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
130Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);91Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
131Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
132Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
13392
134Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);93Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
135Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);94Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);
...@@ -139,22 +98,11 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);...@@ -139,22 +98,11 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
139bool os_stderr_tty(void);98bool os_stderr_tty(void);
140void os_stderr_set_color(TermColor color);99void os_stderr_set_color(TermColor color);
141100
142Error os_delete_file(Buf *path);
143
144Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
145
146Error os_rename(Buf *src_path, Buf *dest_path);101Error os_rename(Buf *src_path, Buf *dest_path);
147OsTimeStamp os_timestamp_monotonic(void);102OsTimeStamp os_timestamp_monotonic(void);
148OsTimeStamp os_timestamp_calendar(void);
149103
150bool os_is_sep(uint8_t c);104bool os_is_sep(uint8_t c);
151105
152Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
153
154Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
155
156Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
157
158const size_t PATH_MAX_WIDE = 32767;106const size_t PATH_MAX_WIDE = 32767;
159107
160struct PathSpace {108struct PathSpace {
src/stage1/zig0.cpp+10
...@@ -430,6 +430,16 @@ int main(int argc, char **argv) {...@@ -430,6 +430,16 @@ int main(int argc, char **argv) {
430 return print_error_usage(arg0);430 return print_error_usage(arg0);
431 }431 }
432432
433 if (override_lib_dir == nullptr) {
434 fprintf(stderr, "missing --override-lib-dir\n");
435 return print_error_usage(arg0);
436 }
437
438 if (emit_bin_path == nullptr) {
439 fprintf(stderr, "missing -femit-bin=\n");
440 return print_error_usage(arg0);
441 }
442
433 ZigStage1 *stage1 = zig_stage1_create(optimize_mode,443 ZigStage1 *stage1 = zig_stage1_create(optimize_mode,
434 nullptr, 0,444 nullptr, 0,
435 in_file, strlen(in_file),445 in_file, strlen(in_file),
src/target.zig+1-1
...@@ -130,7 +130,6 @@ pub fn osRequiresLibC(target: std.Target) bool {...@@ -130,7 +130,6 @@ pub fn osRequiresLibC(target: std.Target) bool {
130130
131pub fn libcNeedsLibUnwind(target: std.Target) bool {131pub fn libcNeedsLibUnwind(target: std.Target) bool {
132 return switch (target.os.tag) {132 return switch (target.os.tag) {
133 .windows,
134 .macosx,133 .macosx,
135 .ios,134 .ios,
136 .watchos,135 .watchos,
...@@ -138,6 +137,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool {...@@ -138,6 +137,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool {
138 .freestanding,137 .freestanding,
139 => false,138 => false,
140139
140 .windows => target.abi != .msvc,
141 else => true,141 else => true,
142 };142 };
143}143}
test/compile_errors.zig+182-47
...@@ -2,20 +2,175 @@ const tests = @import("tests.zig");...@@ -2,20 +2,175 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add("slice sentinel mismatch",5 cases.add("@Type for exhaustive enum with undefined tag type",
6 \\const TypeInfo = @import("builtin").TypeInfo;
7 \\const Tag = @Type(.{
8 \\ .Enum = .{
9 \\ .layout = .Auto,
10 \\ .tag_type = undefined,
11 \\ .fields = &[_]TypeInfo.EnumField{},
12 \\ .decls = &[_]TypeInfo.Declaration{},
13 \\ .is_exhaustive = false,
14 \\ },
15 \\});
6 \\export fn entry() void {16 \\export fn entry() void {
7 \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };17 \\ _ = @intToEnum(Tag, 0);
8 \\}18 \\}
9 , &[_][]const u8{19 , &[_][]const u8{
10 "tmp.zig:2:62: error: index 3 outside vector of size 3",20 "tmp.zig:2:20: error: use of undefined value here causes undefined behavior",
11 });21 });
1222
13 cases.add("slice sentinel mismatch",23 cases.add("extern struct with non-extern-compatible integer tag type",
24 \\pub const E = enum(u31) { A, B, C };
25 \\pub const S = extern struct {
26 \\ e: E,
27 \\};
14 \\export fn entry() void {28 \\export fn entry() void {
15 \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };29 \\ const s: S = undefined;
16 \\}30 \\}
17 , &[_][]const u8{31 , &[_][]const u8{
18 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",32 "tmp.zig:3:5: error: extern structs cannot contain fields of type 'E'",
33 });
34
35 cases.add("@Type for exhaustive enum with non-integer tag type",
36 \\const TypeInfo = @import("builtin").TypeInfo;
37 \\const Tag = @Type(.{
38 \\ .Enum = .{
39 \\ .layout = .Auto,
40 \\ .tag_type = bool,
41 \\ .fields = &[_]TypeInfo.EnumField{},
42 \\ .decls = &[_]TypeInfo.Declaration{},
43 \\ .is_exhaustive = false,
44 \\ },
45 \\});
46 \\export fn entry() void {
47 \\ _ = @intToEnum(Tag, 0);
48 \\}
49 , &[_][]const u8{
50 "tmp.zig:2:20: error: TypeInfo.Enum.tag_type must be an integer type, not 'bool'",
51 });
52
53 cases.add("extern struct with extern-compatible but inferred integer tag type",
54 \\pub const E = enum {
55 \\@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",
56 \\@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23",
57 \\@"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34",
58 \\@"35",@"36",@"37",@"38",@"39",@"40",@"41",@"42",@"43",@"44",@"45",
59 \\@"46",@"47",@"48",@"49",@"50",@"51",@"52",@"53",@"54",@"55",@"56",
60 \\@"57",@"58",@"59",@"60",@"61",@"62",@"63",@"64",@"65",@"66",@"67",
61 \\@"68",@"69",@"70",@"71",@"72",@"73",@"74",@"75",@"76",@"77",@"78",
62 \\@"79",@"80",@"81",@"82",@"83",@"84",@"85",@"86",@"87",@"88",@"89",
63 \\@"90",@"91",@"92",@"93",@"94",@"95",@"96",@"97",@"98",@"99",@"100",
64 \\@"101",@"102",@"103",@"104",@"105",@"106",@"107",@"108",@"109",
65 \\@"110",@"111",@"112",@"113",@"114",@"115",@"116",@"117",@"118",
66 \\@"119",@"120",@"121",@"122",@"123",@"124",@"125",@"126",@"127",
67 \\@"128",@"129",@"130",@"131",@"132",@"133",@"134",@"135",@"136",
68 \\@"137",@"138",@"139",@"140",@"141",@"142",@"143",@"144",@"145",
69 \\@"146",@"147",@"148",@"149",@"150",@"151",@"152",@"153",@"154",
70 \\@"155",@"156",@"157",@"158",@"159",@"160",@"161",@"162",@"163",
71 \\@"164",@"165",@"166",@"167",@"168",@"169",@"170",@"171",@"172",
72 \\@"173",@"174",@"175",@"176",@"177",@"178",@"179",@"180",@"181",
73 \\@"182",@"183",@"184",@"185",@"186",@"187",@"188",@"189",@"190",
74 \\@"191",@"192",@"193",@"194",@"195",@"196",@"197",@"198",@"199",
75 \\@"200",@"201",@"202",@"203",@"204",@"205",@"206",@"207",@"208",
76 \\@"209",@"210",@"211",@"212",@"213",@"214",@"215",@"216",@"217",
77 \\@"218",@"219",@"220",@"221",@"222",@"223",@"224",@"225",@"226",
78 \\@"227",@"228",@"229",@"230",@"231",@"232",@"233",@"234",@"235",
79 \\@"236",@"237",@"238",@"239",@"240",@"241",@"242",@"243",@"244",
80 \\@"245",@"246",@"247",@"248",@"249",@"250",@"251",@"252",@"253",
81 \\@"254",@"255"
82 \\};
83 \\pub const S = extern struct {
84 \\ e: E,
85 \\};
86 \\export fn entry() void {
87 \\ if (@TagType(E) != u8) @compileError("did not infer u8 tag type");
88 \\ const s: S = undefined;
89 \\}
90 , &[_][]const u8{
91 "tmp.zig:31:5: error: extern structs cannot contain fields of type 'E'",
92 });
93
94 cases.add("@Type for tagged union with extra enum field",
95 \\const TypeInfo = @import("builtin").TypeInfo;
96 \\const Tag = @Type(.{
97 \\ .Enum = .{
98 \\ .layout = .Auto,
99 \\ .tag_type = u2,
100 \\ .fields = &[_]TypeInfo.EnumField{
101 \\ .{ .name = "signed", .value = 0 },
102 \\ .{ .name = "unsigned", .value = 1 },
103 \\ .{ .name = "arst", .value = 2 },
104 \\ },
105 \\ .decls = &[_]TypeInfo.Declaration{},
106 \\ .is_exhaustive = true,
107 \\ },
108 \\});
109 \\const Tagged = @Type(.{
110 \\ .Union = .{
111 \\ .layout = .Auto,
112 \\ .tag_type = Tag,
113 \\ .fields = &[_]TypeInfo.UnionField{
114 \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
115 \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
116 \\ },
117 \\ .decls = &[_]TypeInfo.Declaration{},
118 \\ },
119 \\});
120 \\export fn entry() void {
121 \\ var tagged = Tagged{ .signed = -1 };
122 \\ tagged = .{ .unsigned = 1 };
123 \\}
124 , &[_][]const u8{
125 "tmp.zig:15:23: error: enum field missing: 'arst'",
126 "tmp.zig:27:24: note: referenced here",
127 });
128 cases.add("@Type(.Fn) with is_generic = true",
129 \\const Foo = @Type(.{
130 \\ .Fn = .{
131 \\ .calling_convention = .Unspecified,
132 \\ .alignment = 0,
133 \\ .is_generic = true,
134 \\ .is_var_args = false,
135 \\ .return_type = u0,
136 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
137 \\ },
138 \\});
139 \\comptime { _ = Foo; }
140 , &[_][]const u8{
141 "tmp.zig:1:20: error: TypeInfo.Fn.is_generic must be false for @Type",
142 });
143
144 cases.add("@Type(.Fn) with is_var_args = true and non-C callconv",
145 \\const Foo = @Type(.{
146 \\ .Fn = .{
147 \\ .calling_convention = .Unspecified,
148 \\ .alignment = 0,
149 \\ .is_generic = false,
150 \\ .is_var_args = true,
151 \\ .return_type = u0,
152 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
153 \\ },
154 \\});
155 \\comptime { _ = Foo; }
156 , &[_][]const u8{
157 "tmp.zig:1:20: error: varargs functions must have C calling convention",
158 });
159
160 cases.add("@Type(.Fn) with return_type = null",
161 \\const Foo = @Type(.{
162 \\ .Fn = .{
163 \\ .calling_convention = .Unspecified,
164 \\ .alignment = 0,
165 \\ .is_generic = false,
166 \\ .is_var_args = false,
167 \\ .return_type = null,
168 \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
169 \\ },
170 \\});
171 \\comptime { _ = Foo; }
172 , &[_][]const u8{
173 "tmp.zig:1:20: error: TypeInfo.Fn.return_type must be non-null for @Type",
19 });174 });
20175
21 cases.add("@Type for union with opaque field",176 cases.add("@Type for union with opaque field",
...@@ -25,7 +180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -25,7 +180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
25 \\ .layout = .Auto,180 \\ .layout = .Auto,
26 \\ .tag_type = null,181 \\ .tag_type = null,
27 \\ .fields = &[_]TypeInfo.UnionField{182 \\ .fields = &[_]TypeInfo.UnionField{
28 \\ .{ .name = "foo", .field_type = @Type(.Opaque) },183 \\ .{ .name = "foo", .field_type = @Type(.Opaque), .alignment = 1 },
29 \\ },184 \\ },
30 \\ .decls = &[_]TypeInfo.Declaration{},185 \\ .decls = &[_]TypeInfo.Declaration{},
31 \\ },186 \\ },
...@@ -38,6 +193,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -38,6 +193,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
38 "tmp.zig:13:17: note: referenced here",193 "tmp.zig:13:17: note: referenced here",
39 });194 });
40195
196 cases.add("slice sentinel mismatch",
197 \\export fn entry() void {
198 \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };
199 \\}
200 , &[_][]const u8{
201 "tmp.zig:2:62: error: index 3 outside vector of size 3",
202 });
203
204 cases.add("slice sentinel mismatch",
205 \\export fn entry() void {
206 \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
207 \\}
208 , &[_][]const u8{
209 "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
210 });
211
41 cases.add("@Type for union with zero fields",212 cases.add("@Type for union with zero fields",
42 \\const TypeInfo = @import("builtin").TypeInfo;213 \\const TypeInfo = @import("builtin").TypeInfo;
43 \\const Untagged = @Type(.{214 \\const Untagged = @Type(.{
...@@ -94,9 +265,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -94,9 +265,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
94 \\ .layout = .Auto,265 \\ .layout = .Auto,
95 \\ .tag_type = Tag,266 \\ .tag_type = Tag,
96 \\ .fields = &[_]TypeInfo.UnionField{267 \\ .fields = &[_]TypeInfo.UnionField{
97 \\ .{ .name = "signed", .field_type = i32 },268 \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
98 \\ .{ .name = "unsigned", .field_type = u32 },269 \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
99 \\ .{ .name = "arst", .field_type = f32 },270 \\ .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) },
100 \\ },271 \\ },
101 \\ .decls = &[_]TypeInfo.Declaration{},272 \\ .decls = &[_]TypeInfo.Declaration{},
102 \\ },273 \\ },
...@@ -111,42 +282,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -111,42 +282,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
111 "tmp.zig:27:24: note: referenced here",282 "tmp.zig:27:24: note: referenced here",
112 });283 });
113284
114 cases.add("@Type for tagged union with extra enum field",
115 \\const TypeInfo = @import("builtin").TypeInfo;
116 \\const Tag = @Type(.{
117 \\ .Enum = .{
118 \\ .layout = .Auto,
119 \\ .tag_type = u2,
120 \\ .fields = &[_]TypeInfo.EnumField{
121 \\ .{ .name = "signed", .value = 0 },
122 \\ .{ .name = "unsigned", .value = 1 },
123 \\ .{ .name = "arst", .field_type = 2 },
124 \\ },
125 \\ .decls = &[_]TypeInfo.Declaration{},
126 \\ .is_exhaustive = true,
127 \\ },
128 \\});
129 \\const Tagged = @Type(.{
130 \\ .Union = .{
131 \\ .layout = .Auto,
132 \\ .tag_type = Tag,
133 \\ .fields = &[_]TypeInfo.UnionField{
134 \\ .{ .name = "signed", .field_type = i32 },
135 \\ .{ .name = "unsigned", .field_type = u32 },
136 \\ },
137 \\ .decls = &[_]TypeInfo.Declaration{},
138 \\ },
139 \\});
140 \\export fn entry() void {
141 \\ var tagged = Tagged{ .signed = -1 };
142 \\ tagged = .{ .unsigned = 1 };
143 \\}
144 , &[_][]const u8{
145 "tmp.zig:9:32: error: no member named 'field_type' in struct 'std.builtin.EnumField'",
146 "tmp.zig:18:21: note: referenced here",
147 "tmp.zig:27:18: note: referenced here",
148 });
149
150 cases.add("@Type with undefined",285 cases.add("@Type with undefined",
151 \\comptime {286 \\comptime {
152 \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });287 \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
...@@ -7556,7 +7691,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7556,7 +7691,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7556 });7691 });
75577692
7558 cases.add( // fixed bug #20327693 cases.add( // fixed bug #2032
7559 "compile diagnostic string for top level decl type",7694 "compile diagnostic string for top level decl type",
7560 \\export fn entry() void {7695 \\export fn entry() void {
7561 \\ var foo: u32 = @This(){};7696 \\ var foo: u32 = @This(){};
7562 \\}7697 \\}
test/stage1/behavior/bugs/1467.zig created+7
...@@ -0,0 +1,7 @@
1pub const E = enum(u32) { A, B, C };
2pub const S = extern struct {
3 e: E,
4};
5test "bug 1467" {
6 const s: S = undefined;
7}
test/stage1/behavior/type.zig+35-8
...@@ -320,8 +320,8 @@ test "Type.Union" {...@@ -320,8 +320,8 @@ test "Type.Union" {
320 .layout = .Auto,320 .layout = .Auto,
321 .tag_type = null,321 .tag_type = null,
322 .fields = &[_]TypeInfo.UnionField{322 .fields = &[_]TypeInfo.UnionField{
323 .{ .name = "int", .field_type = i32 },323 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
324 .{ .name = "float", .field_type = f32 },324 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
325 },325 },
326 .decls = &[_]TypeInfo.Declaration{},326 .decls = &[_]TypeInfo.Declaration{},
327 },327 },
...@@ -336,8 +336,8 @@ test "Type.Union" {...@@ -336,8 +336,8 @@ test "Type.Union" {
336 .layout = .Packed,336 .layout = .Packed,
337 .tag_type = null,337 .tag_type = null,
338 .fields = &[_]TypeInfo.UnionField{338 .fields = &[_]TypeInfo.UnionField{
339 .{ .name = "signed", .field_type = i32 },339 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
340 .{ .name = "unsigned", .field_type = u32 },340 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
341 },341 },
342 .decls = &[_]TypeInfo.Declaration{},342 .decls = &[_]TypeInfo.Declaration{},
343 },343 },
...@@ -363,8 +363,8 @@ test "Type.Union" {...@@ -363,8 +363,8 @@ test "Type.Union" {
363 .layout = .Auto,363 .layout = .Auto,
364 .tag_type = Tag,364 .tag_type = Tag,
365 .fields = &[_]TypeInfo.UnionField{365 .fields = &[_]TypeInfo.UnionField{
366 .{ .name = "signed", .field_type = i32 },366 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
367 .{ .name = "unsigned", .field_type = u32 },367 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
368 },368 },
369 .decls = &[_]TypeInfo.Declaration{},369 .decls = &[_]TypeInfo.Declaration{},
370 },370 },
...@@ -392,7 +392,7 @@ test "Type.Union from Type.Enum" {...@@ -392,7 +392,7 @@ test "Type.Union from Type.Enum" {
392 .layout = .Auto,392 .layout = .Auto,
393 .tag_type = Tag,393 .tag_type = Tag,
394 .fields = &[_]TypeInfo.UnionField{394 .fields = &[_]TypeInfo.UnionField{
395 .{ .name = "working_as_expected", .field_type = u32 },395 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
396 },396 },
397 .decls = &[_]TypeInfo.Declaration{},397 .decls = &[_]TypeInfo.Declaration{},
398 },398 },
...@@ -408,7 +408,7 @@ test "Type.Union from regular enum" {...@@ -408,7 +408,7 @@ test "Type.Union from regular enum" {
408 .layout = .Auto,408 .layout = .Auto,
409 .tag_type = E,409 .tag_type = E,
410 .fields = &[_]TypeInfo.UnionField{410 .fields = &[_]TypeInfo.UnionField{
411 .{ .name = "working_as_expected", .field_type = u32 },411 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
412 },412 },
413 .decls = &[_]TypeInfo.Declaration{},413 .decls = &[_]TypeInfo.Declaration{},
414 },414 },
...@@ -416,3 +416,30 @@ test "Type.Union from regular enum" {...@@ -416,3 +416,30 @@ test "Type.Union from regular enum" {
416 _ = T;416 _ = T;
417 _ = @typeInfo(T).Union;417 _ = @typeInfo(T).Union;
418}418}
419
420test "Type.Fn" {
421 // wasm doesn't support align attributes on functions
422 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
423
424 const foo = struct {
425 fn func(a: usize, b: bool) align(4) callconv(.C) usize {
426 return 0;
427 }
428 }.func;
429 const Foo = @Type(@typeInfo(@TypeOf(foo)));
430 const foo_2: Foo = foo;
431}
432
433test "Type.BoundFn" {
434 // wasm doesn't support align attributes on functions
435 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
436
437 const TestStruct = packed struct {
438 pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {}
439 };
440 const test_instance: TestStruct = undefined;
441 testing.expect(std.meta.eql(
442 @typeName(@TypeOf(test_instance.foo)),
443 @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
444 ));
445}
test/stage1/behavior/type_info.zig+19-2
...@@ -211,7 +211,9 @@ fn testUnion() void {...@@ -211,7 +211,9 @@ fn testUnion() void {
211 expect(notag_union_info.Union.tag_type == null);211 expect(notag_union_info.Union.tag_type == null);
212 expect(notag_union_info.Union.layout == .Auto);212 expect(notag_union_info.Union.layout == .Auto);
213 expect(notag_union_info.Union.fields.len == 2);213 expect(notag_union_info.Union.fields.len == 2);
214 expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
214 expect(notag_union_info.Union.fields[1].field_type == u32);215 expect(notag_union_info.Union.fields[1].field_type == u32);
216 expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
215217
216 const TestExternUnion = extern union {218 const TestExternUnion = extern union {
217 foo: *c_void,219 foo: *c_void,
...@@ -229,13 +231,18 @@ test "type info: struct info" {...@@ -229,13 +231,18 @@ test "type info: struct info" {
229}231}
230232
231fn testStruct() void {233fn testStruct() void {
234 const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
235 expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
236
232 const struct_info = @typeInfo(TestStruct);237 const struct_info = @typeInfo(TestStruct);
233 expect(struct_info == .Struct);238 expect(struct_info == .Struct);
234 expect(struct_info.Struct.layout == .Packed);239 expect(struct_info.Struct.layout == .Packed);
235 expect(struct_info.Struct.fields.len == 4);240 expect(struct_info.Struct.fields.len == 4);
241 expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
236 expect(struct_info.Struct.fields[2].field_type == *TestStruct);242 expect(struct_info.Struct.fields[2].field_type == *TestStruct);
237 expect(struct_info.Struct.fields[2].default_value == null);243 expect(struct_info.Struct.fields[2].default_value == null);
238 expect(struct_info.Struct.fields[3].default_value.? == 4);244 expect(struct_info.Struct.fields[3].default_value.? == 4);
245 expect(struct_info.Struct.fields[3].alignment == 1);
239 expect(struct_info.Struct.decls.len == 2);246 expect(struct_info.Struct.decls.len == 2);
240 expect(struct_info.Struct.decls[0].is_pub);247 expect(struct_info.Struct.decls[0].is_pub);
241 expect(!struct_info.Struct.decls[0].data.Fn.is_extern);248 expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
...@@ -244,8 +251,12 @@ fn testStruct() void {...@@ -244,8 +251,12 @@ fn testStruct() void {
244 expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);251 expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
245}252}
246253
254const TestUnpackedStruct = struct {
255 fieldA: u32 = 4,
256};
257
247const TestStruct = packed struct {258const TestStruct = packed struct {
248 fieldA: usize,259 fieldA: usize align(2 * @alignOf(usize)),
249 fieldB: void,260 fieldB: void,
250 fieldC: *Self,261 fieldC: *Self,
251 fieldD: u32 = 4,262 fieldD: u32 = 4,
...@@ -255,6 +266,8 @@ const TestStruct = packed struct {...@@ -255,6 +266,8 @@ const TestStruct = packed struct {
255};266};
256267
257test "type info: function type info" {268test "type info: function type info" {
269 // wasm doesn't support align attributes on functions
270 if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
258 testFunction();271 testFunction();
259 comptime testFunction();272 comptime testFunction();
260}273}
...@@ -262,11 +275,14 @@ test "type info: function type info" {...@@ -262,11 +275,14 @@ test "type info: function type info" {
262fn testFunction() void {275fn testFunction() void {
263 const fn_info = @typeInfo(@TypeOf(foo));276 const fn_info = @typeInfo(@TypeOf(foo));
264 expect(fn_info == .Fn);277 expect(fn_info == .Fn);
278 expect(fn_info.Fn.alignment == 0);
265 expect(fn_info.Fn.calling_convention == .C);279 expect(fn_info.Fn.calling_convention == .C);
266 expect(!fn_info.Fn.is_generic);280 expect(!fn_info.Fn.is_generic);
267 expect(fn_info.Fn.args.len == 2);281 expect(fn_info.Fn.args.len == 2);
268 expect(fn_info.Fn.is_var_args);282 expect(fn_info.Fn.is_var_args);
269 expect(fn_info.Fn.return_type.? == usize);283 expect(fn_info.Fn.return_type.? == usize);
284 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
285 expect(fn_aligned_info.Fn.alignment == 4);
270286
271 const test_instance: TestStruct = undefined;287 const test_instance: TestStruct = undefined;
272 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));288 const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
...@@ -274,7 +290,8 @@ fn testFunction() void {...@@ -274,7 +290,8 @@ fn testFunction() void {
274 expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);290 expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
275}291}
276292
277extern fn foo(a: usize, b: bool, ...) usize;293extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
294extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
278295
279test "typeInfo with comptime parameter in struct fn def" {296test "typeInfo with comptime parameter in struct fn def" {
280 const S = struct {297 const S = struct {