| author | |
| committer | |
| log | 23cd3b33312ea5fcae32dcb6cd53cbd502361ce9 |
| tree | eae3657140271fb945dae6e4e1ad9c788808ac58 |
| parent | 82f0ede3ad4150a80ab745419664f1dce4a6be9c |
| parent | 8170a3d574a7118a6ee616d1b1258b2e839de173 |
43 files changed, 2551 insertions(+), 2349 deletions(-)
CMakeLists.txt+4-1| ... | ... | @@ -63,6 +63,9 @@ endif() |
| 63 | 63 | |
| 64 | 64 | if(ZIG_STATIC) |
| 65 | 65 | set(ZIG_STATIC_LLVM "on") |
| 66 | set(ZIG_LINK_MODE "Static") | |
| 67 | else() | |
| 68 | set(ZIG_LINK_MODE "Dynamic") | |
| 66 | 69 | endif() |
| 67 | 70 | |
| 68 | 71 | string(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 | 77 | set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for") |
| 75 | 78 | set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for") |
| 76 | 79 | set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary") |
| 80 | set(ZIG_PREFER_LLVM_CONFIG off CACHE BOOL "(when cross compiling) use llvm-config to find target llvm dependencies if needed") | |
| 77 | 81 | |
| 78 | 82 | find_package(llvm) |
| 79 | 83 | find_package(clang) |
| ... | ... | @@ -257,7 +261,6 @@ target_include_directories(embedded_softfloat PUBLIC |
| 257 | 261 | ) |
| 258 | 262 | include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include") |
| 259 | 263 | set(SOFTFLOAT_LIBRARIES embedded_softfloat) |
| 260 | include_directories("${CMAKE_SOURCE_DIR}/deps/dbg-macro") | |
| 261 | 264 | |
| 262 | 265 | find_package(Threads) |
| 263 | 266 |
ci/azure/pipelines.yml+1-1| ... | ... | @@ -41,7 +41,7 @@ jobs: |
| 41 | 41 | |
| 42 | 42 | steps: |
| 43 | 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 | 45 | .\sfx.exe -y -o\ |
| 46 | 46 | del sfx.exe |
| 47 | 47 | displayName: Download/Extract/Install MSYS2 |
cmake/Findllvm.cmake+5-5| ... | ... | @@ -32,7 +32,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB) |
| 32 | 32 | /usr/local/llvm10/lib |
| 33 | 33 | /usr/local/llvm100/lib |
| 34 | 34 | ) |
| 35 | elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native") | |
| 35 | elseif(("${ZIG_TARGET_TRIPLE}" STREQUAL "native") OR ZIG_PREFER_LLVM_CONFIG) | |
| 36 | 36 | find_program(LLVM_CONFIG_EXE |
| 37 | 37 | NAMES llvm-config-10 llvm-config-10.0 llvm-config100 llvm-config10 llvm-config |
| 38 | 38 | PATHS |
| ... | ... | @@ -55,13 +55,13 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native") |
| 55 | 55 | OUTPUT_STRIP_TRAILING_WHITESPACE) |
| 56 | 56 | |
| 57 | 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 | 59 | endif() |
| 60 | 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 | 62 | endif() |
| 63 | 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 | 65 | endif() |
| 66 | 66 | |
| 67 | 67 | execute_process( |
| ... | ... | @@ -72,7 +72,7 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native") |
| 72 | 72 | function(NEED_TARGET TARGET_NAME) |
| 73 | 73 | list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index) |
| 74 | 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 | 76 | endif() |
| 77 | 77 | endfunction(NEED_TARGET) |
| 78 | 78 | NEED_TARGET("AArch64") |
deps/dbg-macro/LICENSE deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | MIT License | |
| 2 | ||
| 3 | Copyright (c) 2019 David Peter <mail@david-peter.de> | |
| 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 | of this software and associated documentation files (the "Software"), to deal | |
| 7 | in the Software without restriction, including without limitation the rights | |
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 | copies of the Software, and to permit persons to whom the Software is | |
| 10 | furnished to do so, subject to the following conditions: | |
| 11 | ||
| 12 | The above copyright notice and this permission notice shall be included in all | |
| 13 | copies or substantial portions of the Software. | |
| 14 | ||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 | SOFTWARE. |
deps/dbg-macro/README.md deleted-172| ... | ... | @@ -1,172 +0,0 @@ |
| 1 | # `dbg(…)` | |
| 2 | ||
| 3 | [](https://travis-ci.org/sharkdp/dbg-macro) [](https://ci.appveyor.com/project/sharkdp/dbg-macro) [](https://repl.it/@sharkdp/dbg-macro-demo) [](dbg.h) | |
| 4 | ||
| 5 | *A macro for `printf`-style debugging fans.* | |
| 6 | ||
| 7 | Debuggers are great. But sometimes you just don't have the time or patience to set | |
| 8 | up everything correctly and just want a quick way to inspect some values at runtime. | |
| 9 | ||
| 10 | This projects provides a [single header file](dbg.h) with a `dbg(…)` | |
| 11 | macro 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: | |
| 21 | int factorial(int n) { | |
| 22 | if (dbg(n <= 1)) { | |
| 23 | return dbg(1); | |
| 24 | } else { | |
| 25 | return dbg(n * factorial(n - 1)); | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | int 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 | ||
| 47 | The code above produces this output ([try it yourself](https://repl.it/@sharkdp/dbg-macro-demo)): | |
| 48 | ||
| 49 |  | |
| 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 | ||
| 63 | To make this practical, the `dbg.h` header should to be readily available from all kinds of different | |
| 64 | places and in all kinds of environments. The quick & dirty way is to actually copy the header file | |
| 65 | to `/usr/include` or to clone the repository and symlink `dbg.h` to `/usr/include/dbg.h`. | |
| 66 | ``` bash | |
| 67 | git clone https://github.com/sharkdp/dbg-macro | |
| 68 | sudo ln -s $(readlink -f dbg-macro/dbg.h) /usr/include/dbg.h | |
| 69 | ``` | |
| 70 | If you don't want to make untracked changes to your filesystem, check below if there is a package for | |
| 71 | your operating system or package manager. | |
| 72 | ||
| 73 | ### On Arch Linux | |
| 74 | ||
| 75 | You can install [`dbg-macro` from the AUR](https://aur.archlinux.org/packages/dbg-macro/): | |
| 76 | ``` bash | |
| 77 | yay -S dbg-macro | |
| 78 | ``` | |
| 79 | ||
| 80 | ### With vcpkg | |
| 81 | ||
| 82 | You can install the [`dbg-macro` port](https://github.com/microsoft/vcpkg/tree/master/ports/dbg-macro) via: | |
| 83 | ``` bash | |
| 84 | vcpkg 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 | ||
| 96 | If you want to format integers in hexadecimal, octal or binary representation, you can | |
| 97 | simply wrap them in `dbg::hex(…)`, `dbg::oct(…)` or `dbg::bin(…)`: | |
| 98 | ```c++ | |
| 99 | const uint32_t secret = 12648430; | |
| 100 | dbg(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 | |
| 106 | sometimes you just want to print a type (maybe because you don't have a value for that type). | |
| 107 | In this case, you can use the `dbg::type<T>()` helper to pretty-print a given type `T`. | |
| 108 | For example: | |
| 109 | ```c++ | |
| 110 | template <typename T> | |
| 111 | void 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 | ||
| 119 | To print a timestamp, you can use the `dbg::time()` helper: | |
| 120 | ```c++ | |
| 121 | dbg(dbg::time()); | |
| 122 | ``` | |
| 123 | ||
| 124 | ### Customization | |
| 125 | ||
| 126 | If you want `dbg(…)` to work for your custom datatype, you can simply overload `operator<<` for | |
| 127 | `std::ostream&`: | |
| 128 | ```c++ | |
| 129 | std::ostream& operator<<(std::ostream& out, const user_defined_type& v) { | |
| 130 | out << "…"; | |
| 131 | return out; | |
| 132 | } | |
| 133 | ``` | |
| 134 | ||
| 135 | If 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 | |
| 139 | namespace dbg { | |
| 140 | std::string get_type_name(type_tag<bool>) { | |
| 141 | return "truth value"; | |
| 142 | } | |
| 143 | } | |
| 144 | ``` | |
| 145 | ||
| 146 | ## Development | |
| 147 | ||
| 148 | If you want to contribute to `dbg-macro`, here is how you can build the tests and demos: | |
| 149 | ||
| 150 | Make sure that the submodule(s) are up to date: | |
| 151 | ```bash | |
| 152 | git submodule update --init | |
| 153 | ``` | |
| 154 | ||
| 155 | Then, use the typical `cmake` workflow. Usage of `-DCMAKE_CXX_STANDARD=17` is optional, | |
| 156 | but recommended in order to have the largest set of features enabled: | |
| 157 | ```bash | |
| 158 | mkdir build | |
| 159 | cd build | |
| 160 | cmake .. -DCMAKE_CXX_STANDARD=17 | |
| 161 | make | |
| 162 | ``` | |
| 163 | ||
| 164 | To run the tests, simply call: | |
| 165 | ```bash | |
| 166 | make test | |
| 167 | ``` | |
| 168 | You can find the unit tests in `tests/basic.cpp`. | |
| 169 | ||
| 170 | ## Acknowledgement | |
| 171 | ||
| 172 | This 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 | ||
| 5 | License (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 | ||
| 72 | namespace dbg { | |
| 73 | ||
| 74 | #ifdef DBG_MACRO_UNIX | |
| 75 | inline bool isColorizedOutputEnabled() { | |
| 76 | return isatty(fileno(stderr)); | |
| 77 | } | |
| 78 | #else | |
| 79 | inline bool isColorizedOutputEnabled() { | |
| 80 | return true; | |
| 81 | } | |
| 82 | #endif | |
| 83 | ||
| 84 | struct time {}; | |
| 85 | ||
| 86 | namespace 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__ | |
| 93 | static constexpr size_t PREFIX_LENGTH = | |
| 94 | sizeof("const char *dbg::type_name_impl() [T = ") - 1; | |
| 95 | static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; | |
| 96 | #elif defined(__GNUC__) && !defined(__clang__) | |
| 97 | #define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__ | |
| 98 | static constexpr size_t PREFIX_LENGTH = | |
| 99 | sizeof("const char* dbg::type_name_impl() [with T = ") - 1; | |
| 100 | static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; | |
| 101 | #elif defined(_MSC_VER) | |
| 102 | #define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__ | |
| 103 | static constexpr size_t PREFIX_LENGTH = | |
| 104 | sizeof("const char *__cdecl dbg::type_name_impl<") - 1; | |
| 105 | static 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 | ||
| 114 | template <typename T> | |
| 115 | struct 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 | ||
| 141 | template <typename T> | |
| 142 | print_formatted<T> hex(T value) { | |
| 143 | return print_formatted<T>{value, 16}; | |
| 144 | } | |
| 145 | ||
| 146 | template <typename T> | |
| 147 | print_formatted<T> oct(T value) { | |
| 148 | return print_formatted<T>{value, 8}; | |
| 149 | } | |
| 150 | ||
| 151 | template <typename T> | |
| 152 | print_formatted<T> bin(T value) { | |
| 153 | return print_formatted<T>{value, 2}; | |
| 154 | } | |
| 155 | ||
| 156 | // Implementation of 'type_name<T>()' | |
| 157 | ||
| 158 | template <typename T> | |
| 159 | const char* type_name_impl() { | |
| 160 | return DBG_MACRO_PRETTY_FUNCTION; | |
| 161 | } | |
| 162 | ||
| 163 | template <typename T> | |
| 164 | struct type_tag {}; | |
| 165 | ||
| 166 | template <int&... ExplicitArgumentBarrier, typename T> | |
| 167 | std::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 | ||
| 175 | template <typename T> | |
| 176 | std::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 | ||
| 203 | inline std::string get_type_name(type_tag<short>) { | |
| 204 | return "short"; | |
| 205 | } | |
| 206 | ||
| 207 | inline std::string get_type_name(type_tag<unsigned short>) { | |
| 208 | return "unsigned short"; | |
| 209 | } | |
| 210 | ||
| 211 | inline std::string get_type_name(type_tag<long>) { | |
| 212 | return "long"; | |
| 213 | } | |
| 214 | ||
| 215 | inline std::string get_type_name(type_tag<unsigned long>) { | |
| 216 | return "unsigned long"; | |
| 217 | } | |
| 218 | ||
| 219 | inline std::string get_type_name(type_tag<std::string>) { | |
| 220 | return "std::string"; | |
| 221 | } | |
| 222 | ||
| 223 | template <typename T> | |
| 224 | std::string get_type_name(type_tag<std::vector<T, std::allocator<T>>>) { | |
| 225 | return "std::vector<" + type_name<T>() + ">"; | |
| 226 | } | |
| 227 | ||
| 228 | template <typename T1, typename T2> | |
| 229 | std::string get_type_name(type_tag<std::pair<T1, T2>>) { | |
| 230 | return "std::pair<" + type_name<T1>() + ", " + type_name<T2>() + ">"; | |
| 231 | } | |
| 232 | ||
| 233 | template <typename... T> | |
| 234 | std::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 | ||
| 246 | template <typename... T> | |
| 247 | std::string get_type_name(type_tag<std::tuple<T...>>) { | |
| 248 | return "std::tuple<" + type_list_to_string<T...>() + ">"; | |
| 249 | } | |
| 250 | ||
| 251 | template <typename T> | |
| 252 | inline 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 | ||
| 258 | namespace detail_detector { | |
| 259 | ||
| 260 | struct nonesuch { | |
| 261 | nonesuch() = delete; | |
| 262 | ~nonesuch() = delete; | |
| 263 | nonesuch(nonesuch const&) = delete; | |
| 264 | void operator=(nonesuch const&) = delete; | |
| 265 | }; | |
| 266 | ||
| 267 | template <typename...> | |
| 268 | using void_t = void; | |
| 269 | ||
| 270 | template <class Default, | |
| 271 | class AlwaysVoid, | |
| 272 | template <class...> | |
| 273 | class Op, | |
| 274 | class... Args> | |
| 275 | struct detector { | |
| 276 | using value_t = std::false_type; | |
| 277 | using type = Default; | |
| 278 | }; | |
| 279 | ||
| 280 | template <class Default, template <class...> class Op, class... Args> | |
| 281 | struct 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 | ||
| 288 | template <template <class...> class Op, class... Args> | |
| 289 | using is_detected = typename detail_detector:: | |
| 290 | detector<detail_detector::nonesuch, void, Op, Args...>::value_t; | |
| 291 | ||
| 292 | namespace detail { | |
| 293 | ||
| 294 | namespace { | |
| 295 | using std::begin; | |
| 296 | using std::end; | |
| 297 | #if DBG_MACRO_CXX_STANDARD < 17 | |
| 298 | template <typename T> | |
| 299 | constexpr auto size(const T& c) -> decltype(c.size()) { | |
| 300 | return c.size(); | |
| 301 | } | |
| 302 | template <typename T, std::size_t N> | |
| 303 | constexpr std::size_t size(const T (&)[N]) { | |
| 304 | return N; | |
| 305 | } | |
| 306 | #else | |
| 307 | using std::size; | |
| 308 | #endif | |
| 309 | } // namespace | |
| 310 | ||
| 311 | template <typename T> | |
| 312 | using detect_begin_t = decltype(detail::begin(std::declval<T>())); | |
| 313 | ||
| 314 | template <typename T> | |
| 315 | using detect_end_t = decltype(detail::end(std::declval<T>())); | |
| 316 | ||
| 317 | template <typename T> | |
| 318 | using detect_size_t = decltype(detail::size(std::declval<T>())); | |
| 319 | ||
| 320 | template <typename T> | |
| 321 | struct 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 | ||
| 331 | template <typename T> | |
| 332 | using ostream_operator_t = | |
| 333 | decltype(std::declval<std::ostream&>() << std::declval<T>()); | |
| 334 | ||
| 335 | template <typename T> | |
| 336 | struct has_ostream_operator : is_detected<ostream_operator_t, T> {}; | |
| 337 | ||
| 338 | } // namespace detail | |
| 339 | ||
| 340 | // Helper to dbg(…)-print types | |
| 341 | template <typename T> | |
| 342 | struct print_type {}; | |
| 343 | ||
| 344 | template <typename T> | |
| 345 | print_type<T> type() { | |
| 346 | return print_type<T>{}; | |
| 347 | } | |
| 348 | ||
| 349 | // Specializations of "pretty_print" | |
| 350 | ||
| 351 | template <typename T> | |
| 352 | inline void pretty_print(std::ostream& stream, const T& value, std::true_type) { | |
| 353 | stream << value; | |
| 354 | } | |
| 355 | ||
| 356 | template <typename T> | |
| 357 | inline 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 | ||
| 362 | template <typename T> | |
| 363 | inline typename std::enable_if<!detail::is_container<const T&>::value && | |
| 364 | !std::is_enum<T>::value, | |
| 365 | bool>::type | |
| 366 | pretty_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 | ||
| 372 | inline bool pretty_print(std::ostream& stream, const bool& value) { | |
| 373 | stream << std::boolalpha << value; | |
| 374 | return true; | |
| 375 | } | |
| 376 | ||
| 377 | inline 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 | ||
| 389 | template <typename P> | |
| 390 | inline 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 | ||
| 399 | template <typename T, typename Deleter> | |
| 400 | inline bool pretty_print(std::ostream& stream, | |
| 401 | std::unique_ptr<T, Deleter>& value) { | |
| 402 | pretty_print(stream, value.get()); | |
| 403 | return true; | |
| 404 | } | |
| 405 | ||
| 406 | template <typename T> | |
| 407 | inline 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 | ||
| 414 | template <size_t N> | |
| 415 | inline bool pretty_print(std::ostream& stream, const char (&value)[N]) { | |
| 416 | stream << value; | |
| 417 | return false; | |
| 418 | } | |
| 419 | ||
| 420 | template <> | |
| 421 | inline bool pretty_print(std::ostream& stream, const char* const& value) { | |
| 422 | stream << '"' << value << '"'; | |
| 423 | return true; | |
| 424 | } | |
| 425 | ||
| 426 | template <size_t Idx> | |
| 427 | struct 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 | ||
| 436 | template <> | |
| 437 | struct 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 | ||
| 444 | template <typename... Ts> | |
| 445 | inline 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 | ||
| 453 | template <> | |
| 454 | inline bool pretty_print(std::ostream& stream, const std::tuple<>&) { | |
| 455 | stream << "{}"; | |
| 456 | ||
| 457 | return true; | |
| 458 | } | |
| 459 | ||
| 460 | template <> | |
| 461 | inline 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 | |
| 476 | template <typename T> | |
| 477 | std::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 | ||
| 490 | template <typename T> | |
| 491 | inline 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 | ||
| 524 | template <typename T> | |
| 525 | inline 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 | ||
| 548 | template <typename Container> | |
| 549 | inline typename std::enable_if<detail::is_container<const Container&>::value, | |
| 550 | bool>::type | |
| 551 | pretty_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 | ||
| 574 | template <typename Enum> | |
| 575 | inline typename std::enable_if<std::is_enum<Enum>::value, bool>::type | |
| 576 | pretty_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 | ||
| 583 | inline bool pretty_print(std::ostream& stream, const std::string& value) { | |
| 584 | stream << '"' << value << '"'; | |
| 585 | return true; | |
| 586 | } | |
| 587 | ||
| 588 | template <typename T1, typename T2> | |
| 589 | inline 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 | ||
| 600 | template <typename T> | |
| 601 | inline 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 | ||
| 613 | template <typename... Ts> | |
| 614 | inline 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 | ||
| 625 | class 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 | |
| 694 | template <typename T> | |
| 695 | T&& 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 @@ |
| 1 | LIBRARY USER32.dll | |
| 2 | EXPORTS | |
| 3 | ;ord_1500@16 @1500 | |
| 4 | ;ord_1501@4 @1501 | |
| 5 | ;ord_1502@12 @1502 | |
| 6 | ActivateKeyboardLayout@8 | |
| 7 | AddClipboardFormatListener@4 | |
| 8 | AdjustWindowRect@12 | |
| 9 | AdjustWindowRectEx@16 | |
| 10 | AlignRects@16 | |
| 11 | AllowForegroundActivation@0 | |
| 12 | AllowSetForegroundWindow@4 | |
| 13 | AnimateWindow@12 | |
| 14 | AnyPopup@0 | |
| 15 | AppendMenuA@16 | |
| 16 | AppendMenuW@16 | |
| 17 | ArrangeIconicWindows@4 | |
| 18 | AttachThreadInput@12 | |
| 19 | BeginDeferWindowPos@4 | |
| 20 | BeginPaint@8 | |
| 21 | BlockInput@4 | |
| 22 | BringWindowToTop@4 | |
| 23 | BroadcastSystemMessage@20 | |
| 24 | BroadcastSystemMessageA@20 | |
| 25 | BroadcastSystemMessageExA@24 | |
| 26 | BroadcastSystemMessageExW@24 | |
| 27 | BroadcastSystemMessageW@20 | |
| 28 | BuildReasonArray@12 | |
| 29 | CalcChildScroll@8 | |
| 30 | CalcMenuBar@20 | |
| 31 | CalculatePopupWindowPosition@20 | |
| 32 | CallMsgFilter@8 | |
| 33 | CallMsgFilterA@8 | |
| 34 | CallMsgFilterW@8 | |
| 35 | CallNextHookEx@16 | |
| 36 | CallWindowProcA@20 | |
| 37 | CallWindowProcW@20 | |
| 38 | CancelShutdown@0 | |
| 39 | CascadeChildWindows@8 | |
| 40 | CascadeWindows@20 | |
| 41 | ChangeClipboardChain@8 | |
| 42 | ChangeDisplaySettingsA@8 | |
| 43 | ChangeDisplaySettingsExA@20 | |
| 44 | ChangeDisplaySettingsExW@20 | |
| 45 | ChangeDisplaySettingsW@8 | |
| 46 | ChangeMenuA@20 | |
| 47 | ChangeMenuW@20 | |
| 48 | ChangeWindowMessageFilter@8 | |
| 49 | ChangeWindowMessageFilterEx@16 | |
| 50 | CharLowerA@4 | |
| 51 | CharLowerBuffA@8 | |
| 52 | CharLowerBuffW@8 | |
| 53 | CharLowerW@4 | |
| 54 | CharNextA@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 | |
| 62 | CharNextExA@12 | |
| 63 | CharNextW@4 | |
| 64 | CharPrevA@8 | |
| 65 | CharPrevExA@16 | |
| 66 | CharPrevW@8 | |
| 67 | CharToOemA@8 | |
| 68 | CharToOemBuffA@12 | |
| 69 | CharToOemBuffW@12 | |
| 70 | CharToOemW@8 | |
| 71 | CharUpperA@4 | |
| 72 | CharUpperBuffA@8 | |
| 73 | CharUpperBuffW@8 | |
| 74 | CharUpperW@4 | |
| 75 | CheckDesktopByThreadId@4 | |
| 76 | CheckDBCSEnabledExt@0 | |
| 77 | CheckDlgButton@12 | |
| 78 | CheckMenuItem@12 | |
| 79 | CheckMenuRadioItem@20 | |
| 80 | CheckProcessForClipboardAccess@8 | |
| 81 | CheckProcessSession@4 | |
| 82 | CheckRadioButton@16 | |
| 83 | CheckWindowThreadDesktop@8 | |
| 84 | ChildWindowFromPoint@12 | |
| 85 | ChildWindowFromPointEx@16 | |
| 86 | CliImmSetHotKey@16 | |
| 87 | ClientThreadSetup@0 | |
| 88 | ClientToScreen@8 | |
| 89 | ClipCursor@4 | |
| 90 | CloseClipboard@0 | |
| 91 | CloseDesktop@4 | |
| 92 | CloseGestureInfoHandle@4 | |
| 93 | CloseTouchInputHandle@4 | |
| 94 | CloseWindow@4 | |
| 95 | CloseWindowStation@4 | |
| 96 | ConsoleControl@12 | |
| 97 | ControlMagnification@8 | |
| 98 | CopyAcceleratorTableA@12 | |
| 99 | CopyAcceleratorTableW@12 | |
| 100 | CopyIcon@4 | |
| 101 | CopyImage@20 | |
| 102 | CopyRect@8 | |
| 103 | CountClipboardFormats@0 | |
| 104 | CreateAcceleratorTableA@8 | |
| 105 | CreateAcceleratorTableW@8 | |
| 106 | CreateCaret@16 | |
| 107 | CreateCursor@28 | |
| 108 | CreateDCompositionHwndTarget@12 | |
| 109 | CreateDesktopA@24 | |
| 110 | CreateDesktopExA@32 | |
| 111 | CreateDesktopExW@32 | |
| 112 | CreateDesktopW@24 | |
| 113 | CreateDialogIndirectParamA@20 | |
| 114 | CreateDialogIndirectParamAorW@24 | |
| 115 | CreateDialogIndirectParamW@20 | |
| 116 | CreateDialogParamA@20 | |
| 117 | CreateDialogParamW@20 | |
| 118 | CreateIcon@28 | |
| 119 | CreateIconFromResource@16 | |
| 120 | CreateIconFromResourceEx@28 | |
| 121 | CreateIconIndirect@4 | |
| 122 | CreateMDIWindowA@40 | |
| 123 | CreateMDIWindowW@40 | |
| 124 | CreateMenu@0 | |
| 125 | CreatePopupMenu@0 | |
| 126 | CreateSystemThreads@16 ; ReactOS has the @8 variant | |
| 127 | CreateWindowExA@48 | |
| 128 | CreateWindowExW@48 | |
| 129 | CreateWindowInBand@52 | |
| 130 | CreateWindowIndirect@4 | |
| 131 | CreateWindowStationA@16 | |
| 132 | CreateWindowStationW@16 | |
| 133 | CsrBroadcastSystemMessageExW@24 | |
| 134 | CtxInitUser32@0 | |
| 135 | DdeAbandonTransaction@12 | |
| 136 | DdeAccessData@8 | |
| 137 | DdeAddData@16 | |
| 138 | DdeClientTransaction@32 | |
| 139 | DdeCmpStringHandles@8 | |
| 140 | DdeConnect@16 | |
| 141 | DdeConnectList@20 | |
| 142 | DdeCreateDataHandle@28 | |
| 143 | DdeCreateStringHandleA@12 | |
| 144 | DdeCreateStringHandleW@12 | |
| 145 | DdeDisconnect@4 | |
| 146 | DdeDisconnectList@4 | |
| 147 | DdeEnableCallback@12 | |
| 148 | DdeFreeDataHandle@4 | |
| 149 | DdeFreeStringHandle@8 | |
| 150 | DdeGetData@16 | |
| 151 | DdeGetLastError@4 | |
| 152 | DdeGetQualityOfService@12 | |
| 153 | DdeImpersonateClient@4 | |
| 154 | DdeInitializeA@16 | |
| 155 | DdeInitializeW@16 | |
| 156 | DdeKeepStringHandle@8 | |
| 157 | DdeNameService@16 | |
| 158 | DdePostAdvise@12 | |
| 159 | DdeQueryConvInfo@12 | |
| 160 | DdeQueryNextServer@8 | |
| 161 | DdeQueryStringA@20 | |
| 162 | DdeQueryStringW@20 | |
| 163 | DdeReconnect@4 | |
| 164 | DdeSetQualityOfService@12 | |
| 165 | DdeSetUserHandle@12 | |
| 166 | DdeUnaccessData@4 | |
| 167 | DdeUninitialize@4 | |
| 168 | DefDlgProcA@16 | |
| 169 | DefDlgProcW@16 | |
| 170 | DefFrameProcA@20 | |
| 171 | DefFrameProcW@20 | |
| 172 | DefMDIChildProcA@16 | |
| 173 | DefMDIChildProcW@16 | |
| 174 | DefRawInputProc@12 | |
| 175 | DefWindowProcA@16 | |
| 176 | DefWindowProcW@16 | |
| 177 | DeferWindowPos@32 | |
| 178 | DeferWindowPosAndBand@36 | |
| 179 | DeleteMenu@12 | |
| 180 | DeregisterShellHookWindow@4 | |
| 181 | DestroyAcceleratorTable@4 | |
| 182 | DestroyCaret@0 | |
| 183 | DestroyCursor@4 | |
| 184 | DestroyDCompositionHwndTarget@8 | |
| 185 | DestroyIcon@4 | |
| 186 | DestroyMenu@4 | |
| 187 | DestroyReasons@4 | |
| 188 | DestroyWindow@4 | |
| 189 | DeviceEventWorker@24 ; No documentation whatsoever, ReactOS has a stub with @20 - https://www.reactos.org/archives/public/ros-diffs/2011-February/040308.html | |
| 190 | DialogBoxIndirectParamA@20 | |
| 191 | DialogBoxIndirectParamAorW@24 | |
| 192 | DialogBoxIndirectParamW@20 | |
| 193 | DialogBoxParamA@20 | |
| 194 | DialogBoxParamW@20 | |
| 195 | DisableProcessWindowsGhosting@0 | |
| 196 | DispatchMessageA@4 | |
| 197 | DispatchMessageW@4 | |
| 198 | DisplayConfigGetDeviceInfo@4 | |
| 199 | DisplayConfigSetDeviceInfo@4 | |
| 200 | DisplayExitWindowsWarnings@4 | |
| 201 | DlgDirListA@20 | |
| 202 | DlgDirListComboBoxA@20 | |
| 203 | DlgDirListComboBoxW@20 | |
| 204 | DlgDirListW@20 | |
| 205 | DlgDirSelectComboBoxExA@16 | |
| 206 | DlgDirSelectComboBoxExW@16 | |
| 207 | DlgDirSelectExA@16 | |
| 208 | DlgDirSelectExW@16 | |
| 209 | DoSoundConnect@0 | |
| 210 | DoSoundDisconnect@0 | |
| 211 | DragDetect@12 | |
| 212 | DragObject@20 | |
| 213 | DrawAnimatedRects@16 | |
| 214 | DrawCaption@16 | |
| 215 | DrawCaptionTempA@28 | |
| 216 | DrawCaptionTempW@28 | |
| 217 | DrawEdge@16 | |
| 218 | DrawFocusRect@8 | |
| 219 | DrawFrame@16 | |
| 220 | DrawFrameControl@16 | |
| 221 | DrawIcon@16 | |
| 222 | DrawIconEx@36 | |
| 223 | DrawMenuBar@4 | |
| 224 | DrawMenuBarTemp@20 | |
| 225 | DrawStateA@40 | |
| 226 | DrawStateW@40 | |
| 227 | DrawTextA@20 | |
| 228 | DrawTextExA@24 | |
| 229 | DrawTextExW@24 | |
| 230 | DrawTextW@20 | |
| 231 | DwmGetDxSharedSurface@24 | |
| 232 | DwmGetRemoteSessionOcclusionEvent@0 | |
| 233 | DwmGetRemoteSessionOcclusionState@0 | |
| 234 | DwmLockScreenUpdates@4 | |
| 235 | DwmStartRedirection@8 ; Mentioned on http://habrahabr.ru/post/145174/ , enables GDI virtualization (for security purposes) | |
| 236 | DwmStopRedirection@0 | |
| 237 | DwmValidateWindow@8 | |
| 238 | EditWndProc@16 | |
| 239 | EmptyClipboard@0 | |
| 240 | EnableMenuItem@12 | |
| 241 | EnableMouseInPointer@4 | |
| 242 | EnableScrollBar@12 | |
| 243 | EnableSessionForMMCSS@4 | |
| 244 | EnableWindow@8 | |
| 245 | EndDeferWindowPos@4 | |
| 246 | EndDeferWindowPosEx@8 | |
| 247 | EndDialog@8 | |
| 248 | EndMenu@0 | |
| 249 | EndPaint@8 | |
| 250 | EndTask@12 | |
| 251 | EnterReaderModeHelper@4 | |
| 252 | EnumChildWindows@12 | |
| 253 | EnumClipboardFormats@4 | |
| 254 | EnumDesktopWindows@12 | |
| 255 | EnumDesktopsA@12 | |
| 256 | EnumDesktopsW@12 | |
| 257 | EnumDisplayDevicesA@16 | |
| 258 | EnumDisplayDevicesW@16 | |
| 259 | EnumDisplayMonitors@16 | |
| 260 | EnumDisplaySettingsA@12 | |
| 261 | EnumDisplaySettingsExA@16 | |
| 262 | EnumDisplaySettingsExW@16 | |
| 263 | EnumDisplaySettingsW@12 | |
| 264 | EnumPropsA@8 | |
| 265 | EnumPropsExA@12 | |
| 266 | EnumPropsExW@12 | |
| 267 | EnumPropsW@8 | |
| 268 | EnumThreadWindows@12 | |
| 269 | EnumWindowStationsA@8 | |
| 270 | EnumWindowStationsW@8 | |
| 271 | EnumWindows@8 | |
| 272 | EqualRect@8 | |
| 273 | EvaluateProximityToPolygon@16 | |
| 274 | EvaluateProximityToRect@12 | |
| 275 | ExcludeUpdateRgn@8 | |
| 276 | ExitWindowsEx@8 | |
| 277 | FillRect@12 | |
| 278 | FindWindowA@8 | |
| 279 | FindWindowExA@16 | |
| 280 | FindWindowExW@16 | |
| 281 | FindWindowW@8 | |
| 282 | FlashWindow@8 | |
| 283 | FlashWindowEx@4 | |
| 284 | FrameRect@12 | |
| 285 | FreeDDElParam@8 | |
| 286 | FrostCrashedWindow@8 | |
| 287 | GetActiveWindow@0 | |
| 288 | GetAltTabInfo@20 | |
| 289 | GetAltTabInfoA@20 | |
| 290 | GetAltTabInfoW@20 | |
| 291 | GetAncestor@8 | |
| 292 | GetAppCompatFlags2@4 | |
| 293 | GetAppCompatFlags@8 ; ReactOS has @4 version http://doxygen.reactos.org/d9/d71/undocuser_8h_a9b76cdc68c523a061c86a40367049ed2.html | |
| 294 | GetAsyncKeyState@4 | |
| 295 | GetAutoRotationState@4 | |
| 296 | GetCIMSSM@4 | |
| 297 | GetCapture@0 | |
| 298 | GetCaretBlinkTime@0 | |
| 299 | GetCaretPos@4 | |
| 300 | GetClassInfoA@12 | |
| 301 | GetClassInfoExA@12 | |
| 302 | GetClassInfoExW@12 | |
| 303 | GetClassInfoW@12 | |
| 304 | GetClassLongA@8 | |
| 305 | GetClassLongW@8 | |
| 306 | GetClassNameA@12 | |
| 307 | GetClassNameW@12 | |
| 308 | GetClassWord@8 | |
| 309 | GetClientRect@8 | |
| 310 | GetClipCursor@4 | |
| 311 | GetClipboardAccessToken@8 | |
| 312 | GetClipboardData@4 | |
| 313 | GetClipboardFormatNameA@12 | |
| 314 | GetClipboardFormatNameW@12 | |
| 315 | GetClipboardOwner@0 | |
| 316 | GetClipboardSequenceNumber@0 | |
| 317 | GetClipboardViewer@0 | |
| 318 | GetComboBoxInfo@8 | |
| 319 | GetCurrentInputMessageSource@4 | |
| 320 | GetCursor@0 | |
| 321 | GetCursorFrameInfo@20 | |
| 322 | GetCursorInfo@4 | |
| 323 | GetCursorPos@4 | |
| 324 | GetDC@4 | |
| 325 | GetDCEx@12 | |
| 326 | GetDesktopID@8 | |
| 327 | GetDesktopWindow@0 | |
| 328 | GetDialogBaseUnits@0 | |
| 329 | GetDisplayAutoRotationPreferences@4 | |
| 330 | GetDisplayConfigBufferSizes@12 | |
| 331 | GetDlgCtrlID@4 | |
| 332 | GetDlgItem@8 | |
| 333 | GetDlgItemInt@16 | |
| 334 | GetDlgItemTextA@16 | |
| 335 | GetDlgItemTextW@16 | |
| 336 | GetDoubleClickTime@0 | |
| 337 | GetDpiForMonitorInternal@16 | |
| 338 | GetFocus@0 | |
| 339 | GetForegroundWindow@0 | |
| 340 | GetGUIThreadInfo@8 | |
| 341 | GetGestureConfig@24 | |
| 342 | GetGestureExtraArgs@12 | |
| 343 | GetGestureInfo@8 | |
| 344 | GetGuiResources@8 | |
| 345 | GetIconInfo@8 | |
| 346 | GetIconInfoExA@8 | |
| 347 | GetIconInfoExW@8 | |
| 348 | GetInputDesktop@0 | |
| 349 | GetInputLocaleInfo@8 | |
| 350 | GetInputState@0 | |
| 351 | GetInternalWindowPos@12 | |
| 352 | GetKBCodePage@0 | |
| 353 | GetKeyNameTextA@12 | |
| 354 | GetKeyNameTextW@12 | |
| 355 | GetKeyState@4 | |
| 356 | GetKeyboardLayout@4 | |
| 357 | GetKeyboardLayoutList@8 | |
| 358 | GetKeyboardLayoutNameA@4 | |
| 359 | GetKeyboardLayoutNameW@4 | |
| 360 | GetKeyboardState@4 | |
| 361 | GetKeyboardType@4 | |
| 362 | GetLastActivePopup@4 | |
| 363 | GetLastInputInfo@4 | |
| 364 | GetLayeredWindowAttributes@16 | |
| 365 | GetListBoxInfo@4 | |
| 366 | GetMagnificationDesktopColorEffect@4 | |
| 367 | GetMagnificationDesktopMagnification@12 | |
| 368 | GetMagnificationLensCtxInformation@16 | |
| 369 | GetMenu@4 | |
| 370 | GetMenuBarInfo@16 | |
| 371 | GetMenuCheckMarkDimensions@0 | |
| 372 | GetMenuContextHelpId@4 | |
| 373 | GetMenuDefaultItem@12 | |
| 374 | GetMenuInfo@8 | |
| 375 | GetMenuItemCount@4 | |
| 376 | GetMenuItemID@8 | |
| 377 | GetMenuItemInfoA@16 | |
| 378 | GetMenuItemInfoW@16 | |
| 379 | GetMenuItemRect@16 | |
| 380 | GetMenuState@12 | |
| 381 | GetMenuStringA@20 | |
| 382 | GetMenuStringW@20 | |
| 383 | GetMessageA@16 | |
| 384 | GetMessageExtraInfo@0 | |
| 385 | GetMessagePos@0 | |
| 386 | GetMessageTime@0 | |
| 387 | GetMessageW@16 | |
| 388 | GetMonitorInfoA@8 | |
| 389 | GetMonitorInfoW@8 | |
| 390 | GetMouseMovePointsEx@20 | |
| 391 | GetNextDlgGroupItem@12 | |
| 392 | GetNextDlgTabItem@12 | |
| 393 | GetOpenClipboardWindow@0 | |
| 394 | GetParent@4 | |
| 395 | GetPhysicalCursorPos@4 | |
| 396 | GetPointerCursorId@8 | |
| 397 | GetPointerDevice@8 | |
| 398 | GetPointerDeviceCursors@12 | |
| 399 | GetPointerDeviceProperties@12 | |
| 400 | GetPointerDeviceRects@12 | |
| 401 | GetPointerDevices@8 | |
| 402 | GetPointerFrameInfo@12 | |
| 403 | GetPointerFrameInfoHistory@16 | |
| 404 | GetPointerFramePenInfo@12 | |
| 405 | GetPointerFramePenInfoHistory@16 | |
| 406 | GetPointerFrameTouchInfo@12 | |
| 407 | GetPointerFrameTouchInfoHistory@16 | |
| 408 | GetPointerInfo@8 | |
| 409 | GetPointerInfoHistory@12 | |
| 410 | GetPointerInputTransform@12 | |
| 411 | GetPointerPenInfo@8 | |
| 412 | GetPointerPenInfoHistory@12 | |
| 413 | GetPointerTouchInfo@8 | |
| 414 | GetPointerTouchInfoHistory@12 | |
| 415 | GetPointerType@8 | |
| 416 | GetPriorityClipboardFormat@8 | |
| 417 | GetProcessDefaultLayout@4 | |
| 418 | GetProcessDpiAwarenessInternal@8 | |
| 419 | GetProcessWindowStation@0 | |
| 420 | GetProgmanWindow@0 | |
| 421 | GetPropA@8 | |
| 422 | GetPropW@8 | |
| 423 | GetQueueStatus@4 | |
| 424 | GetRawInputBuffer@12 | |
| 425 | GetRawInputData@20 | |
| 426 | GetRawInputDeviceInfoA@16 | |
| 427 | GetRawInputDeviceInfoW@16 | |
| 428 | GetRawInputDeviceList@12 | |
| 429 | GetRawPointerDeviceData@20 | |
| 430 | GetReasonTitleFromReasonCode@12 | |
| 431 | GetRegisteredRawInputDevices@12 | |
| 432 | GetQueueStatus@4 | |
| 433 | GetScrollBarInfo@12 | |
| 434 | GetScrollInfo@12 | |
| 435 | GetScrollPos@8 | |
| 436 | GetScrollRange@16 | |
| 437 | GetSendMessageReceiver@4 | |
| 438 | GetShellWindow@0 | |
| 439 | GetSubMenu@8 | |
| 440 | GetSysColor@4 | |
| 441 | GetSysColorBrush@4 | |
| 442 | GetSystemMenu@8 | |
| 443 | GetSystemMetrics@4 | |
| 444 | GetTabbedTextExtentA@20 | |
| 445 | GetTabbedTextExtentW@20 | |
| 446 | GetTaskmanWindow@0 | |
| 447 | GetThreadDesktop@4 | |
| 448 | GetTitleBarInfo@8 | |
| 449 | GetTopLevelWindow@4 | |
| 450 | GetTopWindow@4 | |
| 451 | GetTouchInputInfo@16 | |
| 452 | GetUnpredictedMessagePos@0 | |
| 453 | GetUpdateRect@12 | |
| 454 | GetUpdateRgn@12 | |
| 455 | GetUpdatedClipboardFormats@12 | |
| 456 | GetUserObjectInformationA@20 | |
| 457 | GetUserObjectInformationW@20 | |
| 458 | GetUserObjectSecurity@20 | |
| 459 | GetWinStationInfo@4 | |
| 460 | GetWindow@8 | |
| 461 | GetWindowBand@8 | |
| 462 | GetWindowCompositionAttribute@8 | |
| 463 | GetWindowCompositionInfo@8 | |
| 464 | GetWindowContextHelpId@4 | |
| 465 | GetWindowDC@4 | |
| 466 | GetWindowDisplayAffinity@8 | |
| 467 | GetWindowFeedbackSetting@20 | |
| 468 | GetWindowInfo@8 | |
| 469 | GetWindowLongA@8 | |
| 470 | GetWindowLongW@8 | |
| 471 | GetWindowMinimizeRect@8 | |
| 472 | GetWindowModuleFileName@12 | |
| 473 | GetWindowModuleFileNameA@12 | |
| 474 | GetWindowModuleFileNameW@12 | |
| 475 | GetWindowPlacement@8 | |
| 476 | GetWindowRect@8 | |
| 477 | GetWindowRgn@8 | |
| 478 | GetWindowRgnBox@8 | |
| 479 | GetWindowRgnEx@12 | |
| 480 | GetWindowTextA@12 | |
| 481 | GetWindowTextLengthA@4 | |
| 482 | GetWindowTextLengthW@4 | |
| 483 | GetWindowTextW@12 | |
| 484 | GetWindowThreadProcessId@8 | |
| 485 | GetWindowWord@8 | |
| 486 | GhostWindowFromHungWindow@4 | |
| 487 | GrayStringA@36 | |
| 488 | GrayStringW@36 | |
| 489 | HideCaret@4 | |
| 490 | HiliteMenuItem@16 | |
| 491 | HungWindowFromGhostWindow@4 | |
| 492 | IMPGetIMEA@8 | |
| 493 | IMPGetIMEW@8 | |
| 494 | IMPQueryIMEA@4 | |
| 495 | IMPQueryIMEW@4 | |
| 496 | IMPSetIMEA@8 | |
| 497 | IMPSetIMEW@8 | |
| 498 | ImpersonateDdeClientWindow@8 | |
| 499 | InSendMessage@0 | |
| 500 | InSendMessageEx@4 | |
| 501 | InflateRect@12 | |
| 502 | InitializeLpkHooks@4 | |
| 503 | InitializeWin32EntryTable@4 | |
| 504 | InitializeTouchInjection@8 | |
| 505 | InjectTouchInput@8 | |
| 506 | InsertMenuA@20 | |
| 507 | InsertMenuItemA@16 | |
| 508 | InsertMenuItemW@16 | |
| 509 | InsertMenuW@20 | |
| 510 | InternalGetWindowIcon@8 | |
| 511 | ;ord_2001@4 @2001 | |
| 512 | ;ord_2002@4 @2002 | |
| 513 | InternalGetWindowText@12 | |
| 514 | IntersectRect@12 | |
| 515 | ;ord_2005@4 @2005 | |
| 516 | InvalidateRect@12 | |
| 517 | InvalidateRgn@12 | |
| 518 | InvertRect@8 | |
| 519 | IsCharAlphaA@4 | |
| 520 | ;ord_2010@16 @2010 | |
| 521 | IsCharAlphaNumericA@4 | |
| 522 | IsCharAlphaNumericW@4 | |
| 523 | IsCharAlphaW@4 | |
| 524 | IsCharLowerA@4 | |
| 525 | IsCharLowerW@4 | |
| 526 | IsCharUpperA@4 | |
| 527 | IsCharUpperW@4 | |
| 528 | IsChild@8 | |
| 529 | IsClipboardFormatAvailable@4 | |
| 530 | IsDialogMessage@8 | |
| 531 | IsDialogMessageA@8 | |
| 532 | IsDialogMessageW@8 | |
| 533 | IsDlgButtonChecked@8 | |
| 534 | IsGUIThread@4 | |
| 535 | IsHungAppWindow@4 | |
| 536 | IsIconic@4 | |
| 537 | IsImmersiveProcess@4 | |
| 538 | IsInDesktopWindowBand@4 | |
| 539 | IsMenu@4 | |
| 540 | IsProcess16Bit@0 | |
| 541 | IsMouseInPointerEnabled@0 | |
| 542 | IsProcessDPIAware@0 | |
| 543 | IsQueueAttached@0 | |
| 544 | IsRectEmpty@4 | |
| 545 | IsSETEnabled@0 | |
| 546 | IsServerSideWindow@4 | |
| 547 | IsThreadDesktopComposited@0 | |
| 548 | IsTopLevelWindow@4 | |
| 549 | IsTouchWindow@8 | |
| 550 | IsWinEventHookInstalled@4 | |
| 551 | IsWindow@4 | |
| 552 | IsWindowEnabled@4 | |
| 553 | IsWindowInDestroy@4 | |
| 554 | IsWindowRedirectedForPrint@4 | |
| 555 | IsWindowUnicode@4 | |
| 556 | IsWindowVisible@4 | |
| 557 | IsWow64Message@0 | |
| 558 | IsZoomed@4 | |
| 559 | KillSystemTimer@8 | |
| 560 | KillTimer@8 | |
| 561 | LoadAcceleratorsA@8 | |
| 562 | LoadAcceleratorsW@8 | |
| 563 | LoadBitmapA@8 | |
| 564 | LoadBitmapW@8 | |
| 565 | LoadCursorA@8 | |
| 566 | LoadCursorFromFileA@4 | |
| 567 | LoadCursorFromFileW@4 | |
| 568 | ;ord_2000@0 @2000 | |
| 569 | ;ord_2001@4 @2001 | |
| 570 | ;ord_2002@4 @2002 | |
| 571 | LoadCursorW@8 | |
| 572 | LoadIconA@8 | |
| 573 | ;ord_2005@4 @2005 | |
| 574 | LoadIconW@8 | |
| 575 | LoadImageA@24 | |
| 576 | LoadImageW@24 | |
| 577 | LoadKeyboardLayoutA@8 | |
| 578 | LoadKeyboardLayoutEx@12 | |
| 579 | LoadKeyboardLayoutW@8 | |
| 580 | LoadLocalFonts@0 | |
| 581 | LoadMenuA@8 | |
| 582 | LoadMenuIndirectA@4 | |
| 583 | LoadMenuIndirectW@4 | |
| 584 | LoadMenuW@8 | |
| 585 | LoadRemoteFonts@0 | |
| 586 | LoadStringA@16 | |
| 587 | LoadStringW@16 | |
| 588 | LockSetForegroundWindow@4 | |
| 589 | LockWindowStation@4 | |
| 590 | LockWindowUpdate@4 | |
| 591 | LockWorkStation@0 | |
| 592 | LogicalToPhysicalPoint@8 | |
| 593 | LogicalToPhysicalPointForPerMonitorDPI@8 | |
| 594 | LookupIconIdFromDirectory@8 | |
| 595 | LookupIconIdFromDirectoryEx@20 | |
| 596 | MBToWCSEx@24 | |
| 597 | MBToWCSExt@20 | |
| 598 | MB_GetString@4 | |
| 599 | MapDialogRect@8 | |
| 600 | MapVirtualKeyA@8 | |
| 601 | MapVirtualKeyExA@12 | |
| 602 | MapVirtualKeyExW@12 | |
| 603 | MapVirtualKeyW@8 | |
| 604 | MapWindowPoints@16 | |
| 605 | MenuItemFromPoint@16 | |
| 606 | MenuWindowProcA@20 | |
| 607 | MenuWindowProcW@20 | |
| 608 | MessageBeep@4 | |
| 609 | MessageBoxA@16 | |
| 610 | MessageBoxExA@20 | |
| 611 | MessageBoxExW@20 | |
| 612 | MessageBoxIndirectA@4 | |
| 613 | MessageBoxIndirectW@4 | |
| 614 | MessageBoxTimeoutA@24 | |
| 615 | MessageBoxTimeoutW@24 | |
| 616 | MessageBoxW@16 | |
| 617 | ModifyMenuA@20 | |
| 618 | ModifyMenuW@20 | |
| 619 | MonitorFromPoint@12 | |
| 620 | MonitorFromRect@8 | |
| 621 | MonitorFromWindow@8 | |
| 622 | MoveWindow@24 | |
| 623 | MsgWaitForMultipleObjects@20 | |
| 624 | MsgWaitForMultipleObjectsEx@20 | |
| 625 | NotifyOverlayWindow@8 | |
| 626 | NotifyWinEvent@16 | |
| 627 | OemKeyScan@4 | |
| 628 | OemToCharA@8 | |
| 629 | OemToCharBuffA@12 | |
| 630 | OemToCharBuffW@12 | |
| 631 | OemToCharW@8 | |
| 632 | OffsetRect@12 | |
| 633 | OpenClipboard@4 | |
| 634 | OpenDesktopA@16 | |
| 635 | OpenDesktopW@16 | |
| 636 | OpenIcon@4 | |
| 637 | OpenInputDesktop@12 | |
| 638 | OpenThreadDesktop@16 | |
| 639 | OpenWindowStationA@12 | |
| 640 | OpenWindowStationW@12 | |
| 641 | PackDDElParam@12 | |
| 642 | PackTouchHitTestingProximityEvaluation@8 | |
| 643 | PaintDesktop@4 | |
| 644 | PaintMenuBar@24 | |
| 645 | PaintMonitor@12 | |
| 646 | PeekMessageA@20 | |
| 647 | PeekMessageW@20 | |
| 648 | PhysicalToLogicalPoint@8 | |
| 649 | PhysicalToLogicalPointForPerMonitorDPI@8 | |
| 650 | PostMessageA@16 | |
| 651 | PostMessageW@16 | |
| 652 | PostQuitMessage@4 | |
| 653 | PostThreadMessageA@16 | |
| 654 | PostThreadMessageW@16 | |
| 655 | PrintWindow@12 | |
| 656 | PrivateExtractIconExA@20 | |
| 657 | PrivateExtractIconExW@20 | |
| 658 | PrivateExtractIconsA@32 | |
| 659 | PrivateExtractIconsW@32 | |
| 660 | PrivateSetDbgTag@8 | |
| 661 | PrivateSetRipFlags@8 | |
| 662 | PrivateRegisterICSProc@4 | |
| 663 | PtInRect@12 | |
| 664 | QueryBSDRWindow@0 | |
| 665 | QueryDisplayConfig@24 | |
| 666 | QuerySendMessage@4 | |
| 667 | QueryUserCounters@20 | |
| 668 | RealChildWindowFromPoint@12 | |
| 669 | RealGetWindowClass@12 | |
| 670 | RealGetWindowClassA@12 | |
| 671 | RealGetWindowClassW@12 | |
| 672 | ReasonCodeNeedsBugID@4 | |
| 673 | ReasonCodeNeedsComment@4 | |
| 674 | RecordShutdownReason@4 | |
| 675 | RedrawWindow@16 | |
| 676 | RegisterBSDRWindow@8 | |
| 677 | RegisterClassA@4 | |
| 678 | RegisterClassExA@4 | |
| 679 | RegisterClassExW@4 | |
| 680 | RegisterClassW@4 | |
| 681 | RegisterClipboardFormatA@4 | |
| 682 | RegisterClipboardFormatW@4 | |
| 683 | RegisterDeviceNotificationA@12 | |
| 684 | RegisterDeviceNotificationW@12 | |
| 685 | RegisterErrorReportingDialog@8 | |
| 686 | RegisterFrostWindow@8 | |
| 687 | RegisterGhostWindow@8 | |
| 688 | RegisterHotKey@16 | |
| 689 | RegisterPowerSettingNotification@12 | |
| 690 | RegisterLogonProcess@8 | |
| 691 | RegisterMessagePumpHook@4 | |
| 692 | RegisterPointerDeviceNotifications@8 | |
| 693 | RegisterPointerInputTarget@8 | |
| 694 | RegisterPowerSettingNotification@12 | |
| 695 | RegisterRawInputDevices@12 | |
| 696 | RegisterServicesProcess@4 | |
| 697 | RegisterSessionPort@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 | |
| 698 | RegisterShellHookWindow@4 | |
| 699 | RegisterSuspendResumeNotification@8 | |
| 700 | RegisterSystemThread@8 | |
| 701 | RegisterTasklist@4 | |
| 702 | RegisterTouchHitTestingWindow@8 | |
| 703 | RegisterTouchWindow@8 | |
| 704 | RegisterUserApiHook@4 ; Prototype changed in 2003 - https://www.reactos.org/wiki/Techwiki:RegisterUserApiHook | |
| 705 | RegisterWindowMessageA@4 | |
| 706 | RegisterWindowMessageW@4 | |
| 707 | ReleaseCapture@0 | |
| 708 | ReleaseDC@8 | |
| 709 | RemoveClipboardFormatListener@4 | |
| 710 | RemoveMenu@12 | |
| 711 | RemovePropA@8 | |
| 712 | RemovePropW@8 | |
| 713 | ReplyMessage@4 | |
| 714 | ResolveDesktopForWOW@4 | |
| 715 | ReuseDDElParam@20 | |
| 716 | ScreenToClient@8 | |
| 717 | ScrollChildren@12 | |
| 718 | ScrollDC@28 | |
| 719 | ScrollWindow@20 | |
| 720 | ScrollWindowEx@32 | |
| 721 | SendDlgItemMessageA@20 | |
| 722 | SendDlgItemMessageW@20 | |
| 723 | SendIMEMessageExA@8 | |
| 724 | SendIMEMessageExW@8 | |
| 725 | SendInput@12 | |
| 726 | SendMessageA@16 | |
| 727 | SendMessageCallbackA@24 | |
| 728 | SendMessageCallbackW@24 | |
| 729 | SendMessageTimeoutA@28 | |
| 730 | SendMessageTimeoutW@28 | |
| 731 | SendMessageW@16 | |
| 732 | SendNotifyMessageA@16 | |
| 733 | SendNotifyMessageW@16 | |
| 734 | SetActiveWindow@4 | |
| 735 | SetCapture@4 | |
| 736 | SetCaretBlinkTime@4 | |
| 737 | SetCaretPos@8 | |
| 738 | SetClassLongA@12 | |
| 739 | SetClassLongW@12 | |
| 740 | SetClassWord@12 | |
| 741 | SetClipboardData@8 | |
| 742 | SetClipboardViewer@4 | |
| 743 | SetConsoleReserveKeys@8 | |
| 744 | SetCoalescableTimer@20 | |
| 745 | SetCursor@4 | |
| 746 | SetCursorContents@8 | |
| 747 | SetCursorPos@8 | |
| 748 | SetDebugErrorLevel@4 | |
| 749 | SetDeskWallpaper@4 | |
| 750 | SetDisplayAutoRotationPreferences@4 | |
| 751 | SetDisplayConfig@20 | |
| 752 | SetDlgItemInt@16 | |
| 753 | SetDlgItemTextA@12 | |
| 754 | SetDlgItemTextW@12 | |
| 755 | SetDoubleClickTime@4 | |
| 756 | SetFocus@4 | |
| 757 | SetForegroundWindow@4 | |
| 758 | SetGestureConfig@20 | |
| 759 | SetImmersiveBackgroundWindow@4 | |
| 760 | SetInternalWindowPos@16 | |
| 761 | SetKeyboardState@4 | |
| 762 | SetLastErrorEx@8 | |
| 763 | SetLayeredWindowAttributes@16 | |
| 764 | SetLogonNotifyWindow@4 | |
| 765 | SetMagnificationDesktopColorEffect@4 | |
| 766 | SetMagnificationDesktopMagnification@16 | |
| 767 | SetMagnificationLensCtxInformation@16 | |
| 768 | SetMenu@8 | |
| 769 | SetMenuContextHelpId@8 | |
| 770 | SetMenuDefaultItem@12 | |
| 771 | SetMenuInfo@8 | |
| 772 | SetMenuItemBitmaps@20 | |
| 773 | SetMenuItemInfoA@16 | |
| 774 | SetMenuItemInfoW@16 | |
| 775 | SetMessageExtraInfo@4 | |
| 776 | SetMessageQueue@4 | |
| 777 | SetMirrorRendering@8 | |
| 778 | SetParent@8 | |
| 779 | SetPhysicalCursorPos@8 | |
| 780 | SetProcessDPIAware@0 | |
| 781 | SetProcessDefaultLayout@4 | |
| 782 | SetProcessDpiAwarenessInternal@4 | |
| 783 | SetProcessRestrictionExemption@4 | |
| 784 | SetProcessWindowStation@4 | |
| 785 | SetProgmanWindow@4 | |
| 786 | SetPropA@12 | |
| 787 | SetPropW@12 | |
| 788 | SetRect@20 | |
| 789 | SetRectEmpty@4 | |
| 790 | SetScrollInfo@16 | |
| 791 | SetScrollPos@16 | |
| 792 | SetScrollRange@20 | |
| 793 | SetShellWindow@4 | |
| 794 | SetShellWindowEx@8 | |
| 795 | SetSysColors@12 | |
| 796 | SetSysColorsTemp@12 | |
| 797 | SetSystemCursor@8 | |
| 798 | SetSystemMenu@8 | |
| 799 | SetSystemTimer@16 | |
| 800 | SetTaskmanWindow@4 | |
| 801 | SetThreadDesktop@4 | |
| 802 | SetThreadInputBlocked@8 | |
| 803 | SetTimer@16 | |
| 804 | SetUserObjectInformationA@16 | |
| 805 | SetUserObjectInformationW@16 | |
| 806 | SetUserObjectSecurity@12 | |
| 807 | SetWinEventHook@28 | |
| 808 | SetWindowBand@12 | |
| 809 | SetWindowCompositionAttribute@8 | |
| 810 | SetWindowCompositionTransition@28 | |
| 811 | SetWindowContextHelpId@8 | |
| 812 | SetWindowDisplayAffinity@8 | |
| 813 | SetWindowFeedbackSetting@20 | |
| 814 | SetWindowLongA@12 | |
| 815 | SetWindowLongW@12 | |
| 816 | SetWindowPlacement@8 | |
| 817 | SetWindowPos@28 | |
| 818 | SetWindowRgn@12 | |
| 819 | SetWindowRgnEx@12 | |
| 820 | SetWindowStationUser@16 | |
| 821 | SetWindowTextA@8 | |
| 822 | SetWindowTextW@8 | |
| 823 | SetWindowWord@12 | |
| 824 | SetWindowsHookA@8 | |
| 825 | SetWindowsHookExA@16 | |
| 826 | SetWindowsHookExW@16 | |
| 827 | SetWindowsHookW@8 | |
| 828 | SfmDxBindSwapChain@12 | |
| 829 | SfmDxGetSwapChainStats@8 | |
| 830 | SfmDxOpenSwapChain@16 | |
| 831 | SfmDxQuerySwapChainBindingStatus@12 | |
| 832 | SfmDxReleaseSwapChain@8 | |
| 833 | SfmDxReportPendingBindingsToDwm@0 | |
| 834 | SfmDxSetSwapChainBindingStatus@8 | |
| 835 | SfmDxSetSwapChainStats@8 | |
| 836 | ShowCaret@4 | |
| 837 | ShowCursor@4 | |
| 838 | ShowOwnedPopups@8 | |
| 839 | ShowScrollBar@12 | |
| 840 | ShowStartGlass@4 | |
| 841 | ShowSystemCursor@4 | |
| 842 | ShowWindow@8 | |
| 843 | ShowWindowAsync@8 | |
| 844 | ShutdownBlockReasonCreate@8 | |
| 845 | ShutdownBlockReasonDestroy@4 | |
| 846 | ShutdownBlockReasonQuery@12 | |
| 847 | SignalRedirectionStartComplete@0 | |
| 848 | SkipPointerFrameMessages@4 | |
| 849 | SoftModalMessageBox@4 | |
| 850 | SoundSentry@0 | |
| 851 | SubtractRect@12 | |
| 852 | SwapMouseButton@4 | |
| 853 | SwitchDesktop@4 | |
| 854 | SwitchDesktopWithFade@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/ | |
| 855 | SwitchToThisWindow@8 | |
| 856 | SystemParametersInfoA@16 | |
| 857 | SystemParametersInfoW@16 | |
| 858 | TabbedTextOutA@32 | |
| 859 | TabbedTextOutW@32 | |
| 860 | TileChildWindows@8 | |
| 861 | TileWindows@20 | |
| 862 | ToAscii@20 | |
| 863 | ToAsciiEx@24 | |
| 864 | ToUnicode@24 | |
| 865 | ToUnicodeEx@28 | |
| 866 | TrackMouseEvent@4 | |
| 867 | TrackPopupMenu@28 | |
| 868 | TrackPopupMenuEx@24 | |
| 869 | TranslateAccelerator@12 | |
| 870 | TranslateAcceleratorA@12 | |
| 871 | TranslateAcceleratorW@12 | |
| 872 | TranslateMDISysAccel@8 | |
| 873 | TranslateMessage@4 | |
| 874 | TranslateMessageEx@8 | |
| 875 | UnhookWinEvent@4 | |
| 876 | UnhookWindowsHook@8 | |
| 877 | UnhookWindowsHookEx@4 | |
| 878 | UnionRect@12 | |
| 879 | UnloadKeyboardLayout@4 | |
| 880 | UnlockWindowStation@4 | |
| 881 | UnpackDDElParam@16 | |
| 882 | UnregisterClassA@8 | |
| 883 | UnregisterClassW@8 | |
| 884 | UnregisterDeviceNotification@4 | |
| 885 | UnregisterHotKey@8 | |
| 886 | UnregisterMessagePumpHook@0 | |
| 887 | UnregisterPointerInputTarget@8 | |
| 888 | UnregisterPowerSettingNotification@4 | |
| 889 | UnregisterSessionPort@0 | |
| 890 | UnregisterSuspendResumeNotification@4 | |
| 891 | UnregisterTouchWindow@4 | |
| 892 | UnregisterUserApiHook@0 | |
| 893 | UpdateDefaultDesktopThumbnail@20 | |
| 894 | UpdateLayeredWindow@36 | |
| 895 | UpdateLayeredWindowIndirect@8 | |
| 896 | UpdatePerUserSystemParameters@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 | |
| 897 | UpdateWindow@4 | |
| 898 | UpdateWindowInputSinkHints@8 | |
| 899 | UpdateWindowTransform@12 | |
| 900 | User32InitializeImmEntryTable@4 | |
| 901 | UserClientDllInitialize@12 | |
| 902 | UserHandleGrantAccess@12 | |
| 903 | UserLpkPSMTextOut@24 | |
| 904 | UserLpkTabbedTextOut@48 | |
| 905 | UserRealizePalette@4 | |
| 906 | UserRegisterWowHandlers@8 | |
| 907 | VRipOutput@0 | |
| 908 | VTagOutput@0 | |
| 909 | ValidateRect@8 | |
| 910 | ValidateRgn@8 | |
| 911 | VkKeyScanA@4 | |
| 912 | VkKeyScanExA@8 | |
| 913 | VkKeyScanExW@8 | |
| 914 | VkKeyScanW@4 | |
| 915 | WCSToMBEx@24 | |
| 916 | WINNLSEnableIME@8 | |
| 917 | WINNLSGetEnableStatus@4 | |
| 918 | WINNLSGetIMEHotkey@4 | |
| 919 | WaitForInputIdle@8 | |
| 920 | WaitForRedirectionStartComplete@0 | |
| 921 | WaitMessage@0 | |
| 922 | Win32PoolAllocationStats@24 | |
| 923 | WinHelpA@16 | |
| 924 | WinHelpW@16 | |
| 925 | WindowFromDC@4 | |
| 926 | WindowFromPhysicalPoint@8 | |
| 927 | WindowFromPoint@8 | |
| 928 | _UserTestTokenForInteractive@8 | |
| 929 | gSharedInfo DATA | |
| 930 | gapfnScSendMessage DATA | |
| 931 | keybd_event@16 | |
| 932 | mouse_event@20 | |
| 933 | wsprintfA | |
| 934 | wsprintfW | |
| 935 | wvsprintfA@12 | |
| 936 | wvsprintfW@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 | |
| 965 | IsThreadMessageQueueAttached@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 | 371 | pub fn initCapacity(allocator: *Allocator, num: usize) !Self { |
| 372 | 372 | var self = Self{}; |
| 373 | 373 | |
| 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 | 375 | self.items.ptr = new_memory.ptr; |
| 376 | 376 | self.capacity = new_memory.len; |
| 377 | 377 | |
| ... | ... | @@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 419 | 419 | /// Replace range of elements `list[start..start+len]` with `new_items` |
| 420 | 420 | /// grows list if `len < new_items.len`. may allocate |
| 421 | 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 | 423 | var managed = self.toManaged(allocator); |
| 424 | 424 | try managed.replaceRange(start, len, new_items); |
| 425 | 425 | self.* = managed.toUnmanaged(); |
| ... | ... | @@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 617 | 617 | }; |
| 618 | 618 | } |
| 619 | 619 | |
| 620 | test "std.ArrayList.init" { | |
| 621 | var list = ArrayList(i32).init(testing.allocator); | |
| 622 | defer list.deinit(); | |
| 620 | test "std.ArrayList/ArrayListUnmanaged.init" { | |
| 621 | { | |
| 622 | var list = ArrayList(i32).init(testing.allocator); | |
| 623 | defer list.deinit(); | |
| 623 | 624 | |
| 624 | testing.expect(list.items.len == 0); | |
| 625 | testing.expect(list.capacity == 0); | |
| 626 | } | |
| 625 | testing.expect(list.items.len == 0); | |
| 626 | testing.expect(list.capacity == 0); | |
| 627 | } | |
| 627 | 628 | |
| 628 | test "std.ArrayList.initCapacity" { | |
| 629 | var list = try ArrayList(i8).initCapacity(testing.allocator, 200); | |
| 630 | defer list.deinit(); | |
| 631 | testing.expect(list.items.len == 0); | |
| 632 | testing.expect(list.capacity >= 200); | |
| 633 | } | |
| 629 | { | |
| 630 | var list = ArrayListUnmanaged(i32){}; | |
| 634 | 631 | |
| 635 | test "std.ArrayList.basic" { | |
| 636 | var list = ArrayList(i32).init(testing.allocator); | |
| 637 | defer list.deinit(); | |
| 632 | testing.expect(list.items.len == 0); | |
| 633 | testing.expect(list.capacity == 0); | |
| 634 | } | |
| 635 | } | |
| 638 | 636 | |
| 637 | test "std.ArrayList/ArrayListUnmanaged.initCapacity" { | |
| 638 | const a = testing.allocator; | |
| 639 | 639 | { |
| 640 | var i: usize = 0; | |
| 641 | while (i < 10) : (i += 1) { | |
| 642 | list.append(@intCast(i32, i + 1)) catch unreachable; | |
| 643 | } | |
| 640 | var list = try ArrayList(i8).initCapacity(a, 200); | |
| 641 | defer list.deinit(); | |
| 642 | testing.expect(list.items.len == 0); | |
| 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 | } | |
| 645 | 652 | |
| 653 | test "std.ArrayList/ArrayListUnmanaged.basic" { | |
| 654 | const a = testing.allocator; | |
| 646 | 655 | { |
| 647 | var i: usize = 0; | |
| 648 | while (i < 10) : (i += 1) { | |
| 649 | testing.expect(list.items[i] == @intCast(i32, i + 1)); | |
| 656 | var list = ArrayList(i32).init(a); | |
| 657 | defer list.deinit(); | |
| 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 | } | |
| 652 | 676 | |
| 653 | for (list.items) |v, i| { | |
| 654 | testing.expect(v == @intCast(i32, i + 1)); | |
| 677 | testing.expect(list.pop() == 10); | |
| 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 | } | |
| 656 | 718 | |
| 657 | testing.expect(list.pop() == 10); | |
| 658 | testing.expect(list.items.len == 9); | |
| 719 | testing.expect(list.pop() == 10); | |
| 720 | testing.expect(list.items.len == 9); | |
| 659 | 721 | |
| 660 | list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable; | |
| 661 | testing.expect(list.items.len == 12); | |
| 662 | testing.expect(list.pop() == 3); | |
| 663 | testing.expect(list.pop() == 2); | |
| 664 | testing.expect(list.pop() == 1); | |
| 665 | testing.expect(list.items.len == 9); | |
| 722 | list.appendSlice(a, &[_]i32{ 1, 2, 3 }) catch unreachable; | |
| 723 | testing.expect(list.items.len == 12); | |
| 724 | testing.expect(list.pop() == 3); | |
| 725 | testing.expect(list.pop() == 2); | |
| 726 | testing.expect(list.pop() == 1); | |
| 727 | testing.expect(list.items.len == 9); | |
| 666 | 728 | |
| 667 | list.appendSlice(&[_]i32{}) catch unreachable; | |
| 668 | testing.expect(list.items.len == 9); | |
| 729 | list.appendSlice(a, &[_]i32{}) catch unreachable; | |
| 730 | testing.expect(list.items.len == 9); | |
| 669 | 731 | |
| 670 | // can only set on indices < self.items.len | |
| 671 | list.items[7] = 33; | |
| 672 | list.items[8] = 42; | |
| 732 | // can only set on indices < self.items.len | |
| 733 | list.items[7] = 33; | |
| 734 | list.items[8] = 42; | |
| 673 | 735 | |
| 674 | testing.expect(list.pop() == 42); | |
| 675 | testing.expect(list.pop() == 33); | |
| 736 | testing.expect(list.pop() == 42); | |
| 737 | testing.expect(list.pop() == 33); | |
| 738 | } | |
| 676 | 739 | } |
| 677 | 740 | |
| 678 | test "std.ArrayList.appendNTimes" { | |
| 679 | var list = ArrayList(i32).init(testing.allocator); | |
| 680 | defer list.deinit(); | |
| 741 | test "std.ArrayList/ArrayListUnmanaged.appendNTimes" { | |
| 742 | const a = testing.allocator; | |
| 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); | |
| 681 | 756 | |
| 682 | try list.appendNTimes(2, 10); | |
| 683 | testing.expectEqual(@as(usize, 10), list.items.len); | |
| 684 | for (list.items) |element| { | |
| 685 | testing.expectEqual(@as(i32, 2), element); | |
| 757 | try list.appendNTimes(a, 2, 10); | |
| 758 | testing.expectEqual(@as(usize, 10), list.items.len); | |
| 759 | for (list.items) |element| { | |
| 760 | testing.expectEqual(@as(i32, 2), element); | |
| 761 | } | |
| 686 | 762 | } |
| 687 | 763 | } |
| 688 | 764 | |
| 689 | test "std.ArrayList.appendNTimes with failing allocator" { | |
| 690 | var list = ArrayList(i32).init(testing.failing_allocator); | |
| 691 | defer list.deinit(); | |
| 692 | testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10)); | |
| 765 | test "std.ArrayList/ArrayListUnmanaged.appendNTimes with failing allocator" { | |
| 766 | const a = testing.failing_allocator; | |
| 767 | { | |
| 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 | } |
| 694 | 778 | |
| 695 | test "std.ArrayList.orderedRemove" { | |
| 696 | var list = ArrayList(i32).init(testing.allocator); | |
| 697 | defer list.deinit(); | |
| 779 | test "std.ArrayList/ArrayListUnmanaged.orderedRemove" { | |
| 780 | const a = testing.allocator; | |
| 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); | |
| 698 | 810 | |
| 699 | try list.append(1); | |
| 700 | try list.append(2); | |
| 701 | try list.append(3); | |
| 702 | try list.append(4); | |
| 703 | try list.append(5); | |
| 704 | try list.append(6); | |
| 705 | try list.append(7); | |
| 706 | ||
| 707 | //remove from middle | |
| 708 | testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); | |
| 709 | testing.expectEqual(@as(i32, 5), list.items[3]); | |
| 710 | testing.expectEqual(@as(usize, 6), list.items.len); | |
| 711 | ||
| 712 | //remove from end | |
| 713 | testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); | |
| 714 | testing.expectEqual(@as(usize, 5), list.items.len); | |
| 715 | ||
| 716 | //remove from front | |
| 717 | testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); | |
| 718 | testing.expectEqual(@as(i32, 2), list.items[0]); | |
| 719 | testing.expectEqual(@as(usize, 4), list.items.len); | |
| 811 | try list.append(a, 1); | |
| 812 | try list.append(a, 2); | |
| 813 | try list.append(a, 3); | |
| 814 | try list.append(a, 4); | |
| 815 | try list.append(a, 5); | |
| 816 | try list.append(a, 6); | |
| 817 | try list.append(a, 7); | |
| 818 | ||
| 819 | //remove from middle | |
| 820 | testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); | |
| 821 | testing.expectEqual(@as(i32, 5), list.items[3]); | |
| 822 | testing.expectEqual(@as(usize, 6), list.items.len); | |
| 823 | ||
| 824 | //remove from end | |
| 825 | testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); | |
| 826 | testing.expectEqual(@as(usize, 5), list.items.len); | |
| 827 | ||
| 828 | //remove from front | |
| 829 | testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); | |
| 830 | testing.expectEqual(@as(i32, 2), list.items[0]); | |
| 831 | testing.expectEqual(@as(usize, 4), list.items.len); | |
| 832 | } | |
| 720 | 833 | } |
| 721 | 834 | |
| 722 | test "std.ArrayList.swapRemove" { | |
| 723 | var list = ArrayList(i32).init(testing.allocator); | |
| 724 | defer list.deinit(); | |
| 835 | test "std.ArrayList/ArrayListUnmanaged.swapRemove" { | |
| 836 | const a = testing.allocator; | |
| 837 | { | |
| 838 | var list = ArrayList(i32).init(a); | |
| 839 | defer list.deinit(); | |
| 725 | 840 | |
| 726 | try list.append(1); | |
| 727 | try list.append(2); | |
| 728 | try list.append(3); | |
| 729 | try list.append(4); | |
| 730 | try list.append(5); | |
| 731 | try list.append(6); | |
| 732 | try list.append(7); | |
| 733 | ||
| 734 | //remove from middle | |
| 735 | testing.expect(list.swapRemove(3) == 4); | |
| 736 | testing.expect(list.items[3] == 7); | |
| 737 | testing.expect(list.items.len == 6); | |
| 738 | ||
| 739 | //remove from end | |
| 740 | testing.expect(list.swapRemove(5) == 6); | |
| 741 | testing.expect(list.items.len == 5); | |
| 742 | ||
| 743 | //remove from front | |
| 744 | testing.expect(list.swapRemove(0) == 1); | |
| 745 | testing.expect(list.items[0] == 5); | |
| 746 | testing.expect(list.items.len == 4); | |
| 841 | try list.append(1); | |
| 842 | try list.append(2); | |
| 843 | try list.append(3); | |
| 844 | try list.append(4); | |
| 845 | try list.append(5); | |
| 846 | try list.append(6); | |
| 847 | try list.append(7); | |
| 848 | ||
| 849 | //remove from middle | |
| 850 | testing.expect(list.swapRemove(3) == 4); | |
| 851 | testing.expect(list.items[3] == 7); | |
| 852 | testing.expect(list.items.len == 6); | |
| 853 | ||
| 854 | //remove from end | |
| 855 | testing.expect(list.swapRemove(5) == 6); | |
| 856 | testing.expect(list.items.len == 5); | |
| 857 | ||
| 858 | //remove from front | |
| 859 | testing.expect(list.swapRemove(0) == 1); | |
| 860 | testing.expect(list.items[0] == 5); | |
| 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 | } |
| 748 | 890 | |
| 749 | test "std.ArrayList.insert" { | |
| 750 | var list = ArrayList(i32).init(testing.allocator); | |
| 751 | defer list.deinit(); | |
| 891 | test "std.ArrayList/ArrayListUnmanaged.insert" { | |
| 892 | const a = testing.allocator; | |
| 893 | { | |
| 894 | var list = ArrayList(i32).init(a); | |
| 895 | defer list.deinit(); | |
| 752 | 896 | |
| 753 | try list.append(1); | |
| 754 | try list.append(2); | |
| 755 | try list.append(3); | |
| 756 | try list.insert(0, 5); | |
| 757 | testing.expect(list.items[0] == 5); | |
| 758 | testing.expect(list.items[1] == 1); | |
| 759 | testing.expect(list.items[2] == 2); | |
| 760 | testing.expect(list.items[3] == 3); | |
| 897 | try list.append(1); | |
| 898 | try list.append(2); | |
| 899 | try list.append(3); | |
| 900 | try list.insert(0, 5); | |
| 901 | testing.expect(list.items[0] == 5); | |
| 902 | testing.expect(list.items[1] == 1); | |
| 903 | testing.expect(list.items[2] == 2); | |
| 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 | } |
| 762 | 920 | |
| 763 | test "std.ArrayList.insertSlice" { | |
| 764 | var list = ArrayList(i32).init(testing.allocator); | |
| 765 | defer list.deinit(); | |
| 921 | test "std.ArrayList/ArrayListUnmanaged.insertSlice" { | |
| 922 | const a = testing.allocator; | |
| 923 | { | |
| 924 | var list = ArrayList(i32).init(a); | |
| 925 | defer list.deinit(); | |
| 766 | 926 | |
| 767 | try list.append(1); | |
| 768 | try list.append(2); | |
| 769 | try list.append(3); | |
| 770 | try list.append(4); | |
| 771 | try list.insertSlice(1, &[_]i32{ 9, 8 }); | |
| 772 | testing.expect(list.items[0] == 1); | |
| 773 | testing.expect(list.items[1] == 9); | |
| 774 | testing.expect(list.items[2] == 8); | |
| 775 | testing.expect(list.items[3] == 2); | |
| 776 | testing.expect(list.items[4] == 3); | |
| 777 | testing.expect(list.items[5] == 4); | |
| 778 | ||
| 779 | const items = [_]i32{1}; | |
| 780 | try list.insertSlice(0, items[0..0]); | |
| 781 | testing.expect(list.items.len == 6); | |
| 782 | testing.expect(list.items[0] == 1); | |
| 927 | try list.append(1); | |
| 928 | try list.append(2); | |
| 929 | try list.append(3); | |
| 930 | try list.append(4); | |
| 931 | try list.insertSlice(1, &[_]i32{ 9, 8 }); | |
| 932 | testing.expect(list.items[0] == 1); | |
| 933 | testing.expect(list.items[1] == 9); | |
| 934 | testing.expect(list.items[2] == 8); | |
| 935 | testing.expect(list.items[3] == 2); | |
| 936 | testing.expect(list.items[4] == 3); | |
| 937 | testing.expect(list.items[5] == 4); | |
| 938 | ||
| 939 | const items = [_]i32{1}; | |
| 940 | try list.insertSlice(0, items[0..0]); | |
| 941 | testing.expect(list.items.len == 6); | |
| 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 | } |
| 784 | 966 | |
| 785 | test "std.ArrayList.replaceRange" { | |
| 967 | test "std.ArrayList/ArrayListUnmanaged.replaceRange" { | |
| 786 | 968 | var arena = std.heap.ArenaAllocator.init(testing.allocator); |
| 787 | 969 | defer arena.deinit(); |
| 970 | const a = &arena.allocator; | |
| 788 | 971 | |
| 789 | const alloc = &arena.allocator; | |
| 790 | 972 | const init = [_]i32{ 1, 2, 3, 4, 5 }; |
| 791 | 973 | const new = [_]i32{ 0, 0, 0 }; |
| 792 | 974 | |
| 793 | var list_zero = ArrayList(i32).init(alloc); | |
| 794 | var list_eq = ArrayList(i32).init(alloc); | |
| 795 | var list_lt = ArrayList(i32).init(alloc); | |
| 796 | var list_gt = ArrayList(i32).init(alloc); | |
| 975 | const result_zero = [_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 }; | |
| 976 | const result_eq = [_]i32{ 1, 0, 0, 0, 5 }; | |
| 977 | const result_le = [_]i32{ 1, 0, 0, 0, 4, 5 }; | |
| 978 | const result_gt = [_]i32{ 1, 0, 0, 0 }; | |
| 797 | 979 | |
| 798 | try list_zero.appendSlice(&init); | |
| 799 | try list_eq.appendSlice(&init); | |
| 800 | try list_lt.appendSlice(&init); | |
| 801 | try list_gt.appendSlice(&init); | |
| 802 | ||
| 803 | try list_zero.replaceRange(1, 0, &new); | |
| 804 | try list_eq.replaceRange(1, 3, &new); | |
| 805 | try list_lt.replaceRange(1, 2, &new); | |
| 806 | ||
| 807 | // after_range > new_items.len in function body | |
| 808 | testing.expect(1 + 4 > new.len); | |
| 809 | try list_gt.replaceRange(1, 4, &new); | |
| 810 | ||
| 811 | testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 }); | |
| 812 | testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 }); | |
| 813 | testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 }); | |
| 814 | testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 }); | |
| 980 | { | |
| 981 | var list_zero = ArrayList(i32).init(a); | |
| 982 | var list_eq = ArrayList(i32).init(a); | |
| 983 | var list_lt = ArrayList(i32).init(a); | |
| 984 | var list_gt = ArrayList(i32).init(a); | |
| 985 | ||
| 986 | try list_zero.appendSlice(&init); | |
| 987 | try list_eq.appendSlice(&init); | |
| 988 | try list_lt.appendSlice(&init); | |
| 989 | try list_gt.appendSlice(&init); | |
| 990 | ||
| 991 | try list_zero.replaceRange(1, 0, &new); | |
| 992 | try list_eq.replaceRange(1, 3, &new); | |
| 993 | try list_lt.replaceRange(1, 2, &new); | |
| 994 | ||
| 995 | // after_range > new_items.len in function body | |
| 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 | } |
| 816 | 1029 | |
| 817 | 1030 | const Item = struct { |
| ... | ... | @@ -819,11 +1032,25 @@ const Item = struct { |
| 819 | 1032 | sub_items: ArrayList(Item), |
| 820 | 1033 | }; |
| 821 | 1034 | |
| 822 | test "std.ArrayList: ArrayList(T) of struct T" { | |
| 823 | var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) }; | |
| 824 | defer root.sub_items.deinit(); | |
| 825 | try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) }); | |
| 826 | testing.expect(root.sub_items.items[0].integer == 42); | |
| 1035 | const ItemUnmanaged = struct { | |
| 1036 | integer: i32, | |
| 1037 | sub_items: ArrayListUnmanaged(ItemUnmanaged), | |
| 1038 | }; | |
| 1039 | ||
| 1040 | test "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 | } |
| 828 | 1055 | |
| 829 | 1056 | test "std.ArrayList(u8) implements outStream" { |
| ... | ... | @@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" { |
| 837 | 1064 | testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span()); |
| 838 | 1065 | } |
| 839 | 1066 | |
| 840 | test "std.ArrayList.shrink still sets length on error.OutOfMemory" { | |
| 1067 | test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" { | |
| 841 | 1068 | // use an arena allocator to make sure realloc returns error.OutOfMemory |
| 842 | 1069 | var arena = std.heap.ArenaAllocator.init(testing.allocator); |
| 843 | 1070 | defer arena.deinit(); |
| 1071 | const a = &arena.allocator; | |
| 844 | 1072 | |
| 845 | var list = ArrayList(i32).init(&arena.allocator); | |
| 1073 | { | |
| 1074 | var list = ArrayList(i32).init(a); | |
| 846 | 1075 | |
| 847 | try list.append(1); | |
| 848 | try list.append(2); | |
| 849 | try list.append(3); | |
| 1076 | try list.append(1); | |
| 1077 | try list.append(2); | |
| 1078 | try list.append(3); | |
| 850 | 1079 | |
| 851 | list.shrink(1); | |
| 852 | testing.expect(list.items.len == 1); | |
| 1080 | list.shrink(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 | } |
| 854 | 1094 | |
| 855 | 1095 | test "std.ArrayList.writer" { |
| ... | ... | @@ -864,7 +1104,7 @@ test "std.ArrayList.writer" { |
| 864 | 1104 | testing.expectEqualSlices(u8, list.items, "abcdefg"); |
| 865 | 1105 | } |
| 866 | 1106 | |
| 867 | test "addManyAsArray" { | |
| 1107 | test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { | |
| 868 | 1108 | const a = std.testing.allocator; |
| 869 | 1109 | { |
| 870 | 1110 | var list = ArrayList(u8).init(a); |
lib/std/build.zig+6-2| ... | ... | @@ -1239,6 +1239,7 @@ pub const LibExeObjStep = struct { |
| 1239 | 1239 | /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF |
| 1240 | 1240 | /// file. |
| 1241 | 1241 | link_eh_frame_hdr: bool = false, |
| 1242 | link_emit_relocs: bool = false, | |
| 1242 | 1243 | |
| 1243 | 1244 | /// Place every function in its own section so that unused ones may be |
| 1244 | 1245 | /// safely garbage-collected during the linking phase. |
| ... | ... | @@ -2075,6 +2076,9 @@ pub const LibExeObjStep = struct { |
| 2075 | 2076 | if (self.link_eh_frame_hdr) { |
| 2076 | 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 | 2082 | if (self.link_function_sections) { |
| 2079 | 2083 | try zig_args.append("-ffunction-sections"); |
| 2080 | 2084 | } |
| ... | ... | @@ -2168,8 +2172,8 @@ pub const LibExeObjStep = struct { |
| 2168 | 2172 | } |
| 2169 | 2173 | |
| 2170 | 2174 | if (self.linker_script) |linker_script| { |
| 2171 | zig_args.append("--linker-script") catch unreachable; | |
| 2172 | zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable; | |
| 2175 | try zig_args.append("--script"); | |
| 2176 | try zig_args.append(builder.pathFromRoot(linker_script)); | |
| 2173 | 2177 | } |
| 2174 | 2178 | |
| 2175 | 2179 | if (self.version_script) |version_script| { |
lib/std/builtin.zig+3| ... | ... | @@ -262,6 +262,7 @@ pub const TypeInfo = union(enum) { |
| 262 | 262 | field_type: type, |
| 263 | 263 | default_value: anytype, |
| 264 | 264 | is_comptime: bool, |
| 265 | alignment: comptime_int, | |
| 265 | 266 | }; |
| 266 | 267 | |
| 267 | 268 | /// This data structure is used by the Zig language code generation and |
| ... | ... | @@ -318,6 +319,7 @@ pub const TypeInfo = union(enum) { |
| 318 | 319 | pub const UnionField = struct { |
| 319 | 320 | name: []const u8, |
| 320 | 321 | field_type: type, |
| 322 | alignment: comptime_int, | |
| 321 | 323 | }; |
| 322 | 324 | |
| 323 | 325 | /// This data structure is used by the Zig language code generation and |
| ... | ... | @@ -341,6 +343,7 @@ pub const TypeInfo = union(enum) { |
| 341 | 343 | /// therefore must be kept in sync with the compiler implementation. |
| 342 | 344 | pub const Fn = struct { |
| 343 | 345 | calling_convention: CallingConvention, |
| 346 | alignment: comptime_int, | |
| 344 | 347 | is_generic: bool, |
| 345 | 348 | is_var_args: bool, |
| 346 | 349 | return_type: ?type, |
lib/std/c/darwin.zig+1-1| ... | ... | @@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig"); |
| 12 | 12 | |
| 13 | 13 | extern "c" fn __error() *c_int; |
| 14 | 14 | pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32; |
| 15 | pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int; | |
| 15 | pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int; | |
| 16 | 16 | pub extern "c" fn _dyld_image_count() u32; |
| 17 | 17 | pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header; |
| 18 | 18 | pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize; |
lib/std/crypto.zig+46-40| ... | ... | @@ -4,6 +4,48 @@ |
| 4 | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | 5 | // and substantial portions of the software. |
| 6 | 6 | |
| 7 | /// Authenticated Encryption with Associated Data | |
| 8 | pub 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. | |
| 19 | pub 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. | |
| 25 | pub 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. | |
| 38 | pub const dh = struct { | |
| 39 | pub const X25519 = @import("crypto/25519/x25519.zig").X25519; | |
| 40 | }; | |
| 41 | ||
| 42 | /// Elliptic-curve arithmetic. | |
| 43 | pub 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 | 49 | /// Hash functions. |
| 8 | 50 | pub const hash = struct { |
| 9 | 51 | pub const Md5 = @import("crypto/md5.zig").Md5; |
| ... | ... | @@ -15,26 +57,15 @@ pub const hash = struct { |
| 15 | 57 | pub const Gimli = @import("crypto/gimli.zig").Hash; |
| 16 | 58 | }; |
| 17 | 59 | |
| 18 | /// Authentication (MAC) functions. | |
| 19 | pub const auth = struct { | |
| 20 | pub const hmac = @import("crypto/hmac.zig"); | |
| 21 | pub const siphash = @import("crypto/siphash.zig"); | |
| 22 | }; | |
| 23 | ||
| 24 | /// Authenticated Encryption with Associated Data | |
| 25 | pub 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; | |
| 60 | /// Key derivation functions. | |
| 61 | pub const kdf = struct { | |
| 62 | pub const hkdf = @import("crypto/hkdf.zig"); | |
| 33 | 63 | }; |
| 34 | 64 | |
| 35 | 65 | /// MAC functions requiring single-use secret keys. |
| 36 | 66 | pub const onetimeauth = struct { |
| 37 | 67 | pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305; |
| 68 | pub const Ghash = @import("crypto/ghash.zig").Ghash; | |
| 38 | 69 | }; |
| 39 | 70 | |
| 40 | 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 | 88 | pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2; |
| 58 | 89 | }; |
| 59 | 90 | |
| 60 | /// Core functions, that should rarely be used directly by applications. | |
| 61 | pub 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. | |
| 74 | pub 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. | |
| 81 | pub const dh = struct { | |
| 82 | pub const X25519 = @import("crypto/25519/x25519.zig").X25519; | |
| 83 | }; | |
| 84 | ||
| 85 | 91 | /// Digital signature functions. |
| 86 | 92 | pub const sign = struct { |
| 87 | 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 | 57 | } |
| 58 | 58 | |
| 59 | 59 | const macs = [_]Crypto{ |
| 60 | Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" }, | |
| 60 | 61 | Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" }, |
| 61 | 62 | Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" }, |
| 62 | 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 | ||
| 9 | const std = @import("../std.zig"); | |
| 10 | const assert = std.debug.assert; | |
| 11 | const math = std.math; | |
| 12 | const 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. | |
| 20 | pub 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 | ||
| 293 | const htest = @import("test.zig"); | |
| 294 | ||
| 295 | test "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 @@ |
| 1 | const std = @import("../std.zig"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const hmac = std.crypto.auth.hmac; | |
| 4 | const mem = std.mem; | |
| 5 | ||
| 6 | /// HKDF-SHA256 | |
| 7 | pub const HkdfSha256 = Hkdf(hmac.sha2.HmacSha256); | |
| 8 | ||
| 9 | /// HKDF-SHA512 | |
| 10 | pub 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. | |
| 14 | pub 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 | ||
| 54 | const htest = @import("test.zig"); | |
| 55 | ||
| 56 | test "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 | 22 | // partial block buffer |
| 23 | 23 | buf: [block_size]u8 align(16) = undefined, |
| 24 | 24 | |
| 25 | pub fn init(key: []const u8) Poly1305 { | |
| 26 | std.debug.assert(key.len >= minimum_key_length); | |
| 25 | pub fn init(key: *const [minimum_key_length]u8) Poly1305 { | |
| 27 | 26 | const t0 = mem.readIntLittle(u64, key[0..8]); |
| 28 | 27 | const t1 = mem.readIntLittle(u64, key[8..16]); |
| 29 | 28 | return Poly1305{ |
| ... | ... | @@ -115,8 +114,7 @@ pub const Poly1305 = struct { |
| 115 | 114 | } |
| 116 | 115 | } |
| 117 | 116 | |
| 118 | pub fn final(st: *Poly1305, out: []u8) void { | |
| 119 | std.debug.assert(out.len >= mac_length); | |
| 117 | pub fn final(st: *Poly1305, out: *[mac_length]u8) void { | |
| 120 | 118 | if (st.leftover > 0) { |
| 121 | 119 | var i = st.leftover; |
| 122 | 120 | st.buf[i] = 1; |
| ... | ... | @@ -187,10 +185,7 @@ pub const Poly1305 = struct { |
| 187 | 185 | std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]); |
| 188 | 186 | } |
| 189 | 187 | |
| 190 | pub fn create(out: []u8, msg: []const u8, key: []const u8) void { | |
| 191 | std.debug.assert(out.len >= mac_length); | |
| 192 | std.debug.assert(key.len >= minimum_key_length); | |
| 193 | ||
| 188 | pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void { | |
| 194 | 189 | var st = Poly1305.init(key); |
| 195 | 190 | st.update(msg); |
| 196 | 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 | 1181 | return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; |
| 1182 | 1182 | } |
| 1183 | 1183 | |
| 1184 | pub 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 | ||
| 1190 | test "comptimePrint" { | |
| 1191 | std.testing.expectEqualSlices(u8, "100", comptime comptimePrint("{}", .{100})); | |
| 1192 | } | |
| 1193 | ||
| 1184 | 1194 | test "parse u64 digit too big" { |
| 1185 | 1195 | _ = parseUnsigned(u64, "123a", 10) catch |err| { |
| 1186 | 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 | 2162 | return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags); |
| 2163 | 2163 | } |
| 2164 | 2164 | |
| 2165 | pub const SelfExePathError = os.ReadLinkError || os.SysCtlError; | |
| 2165 | pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError; | |
| 2166 | 2166 | |
| 2167 | 2167 | /// `selfExePath` except allocates the result on the heap. |
| 2168 | 2168 | /// Caller owns returned memory. |
| ... | ... | @@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 { |
| 2190 | 2190 | /// TODO make the return type of this a null terminated pointer |
| 2191 | 2191 | pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { |
| 2192 | 2192 | if (is_darwin) { |
| 2193 | var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32))); | |
| 2194 | const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len); | |
| 2193 | // Note that _NSGetExecutablePath() will return "a path" to | |
| 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 | 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 | 2206 | switch (builtin.os.tag) { |
| 2199 | 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 | 58 | return (string_len + (limb_bits / base - 1)) / (limb_bits / base); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | pub 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 | 66 | /// a + b * c + *carry, sets carry to the overflow bits |
| 62 | 67 | pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb { |
| 63 | 68 | @setRuntimeSafety(debug_safety); |
| ... | ... | @@ -597,6 +602,52 @@ pub const Mutable = struct { |
| 597 | 602 | return gcdLehmer(rma, x_copy, y_copy, limbs_buffer); |
| 598 | 603 | } |
| 599 | 604 | |
| 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 | 651 | /// rma may not alias x or y. |
| 601 | 652 | /// x and y may alias each other. |
| 602 | 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 | 1826 | try m.gcd(x.toConst(), y.toConst(), &limbs_buffer); |
| 1776 | 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 | }; |
| 1779 | 1853 | |
| 1780 | 1854 | /// Knuth 4.3.1, Algorithm M. |
| ... | ... | @@ -2129,6 +2203,52 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void { |
| 2129 | 2203 | } |
| 2130 | 2204 | } |
| 2131 | 2205 | |
| 2206 | /// Knuth 4.6.3 | |
| 2207 | fn 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 | 2252 | // Storage must live for the lifetime of the returned value |
| 2133 | 2253 | fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable { |
| 2134 | 2254 | assert(storage.len >= 2); |
lib/std/math/big/int_test.zig+45| ... | ... | @@ -1480,3 +1480,48 @@ test "big.int const to managed" { |
| 1480 | 1480 | |
| 1481 | 1481 | testing.expect(a.toConst().eq(b.toConst())); |
| 1482 | 1482 | } |
| 1483 | ||
| 1484 | test "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 | 854 | .field_type = arg.arg_type.?, |
| 855 | 855 | .default_value = @as(?(arg.arg_type.?), null), |
| 856 | 856 | .is_comptime = false, |
| 857 | .alignment = @alignOf(arg.arg_type.?), | |
| 857 | 858 | }; |
| 858 | 859 | } |
| 859 | 860 | |
| ... | ... | @@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type { |
| 884 | 885 | .field_type = T, |
| 885 | 886 | .default_value = @as(?T, null), |
| 886 | 887 | .is_comptime = false, |
| 888 | .alignment = @alignOf(T), | |
| 887 | 889 | }; |
| 888 | 890 | } |
| 889 | 891 |
lib/std/meta/trailer_flags.zig+1| ... | ... | @@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type { |
| 47 | 47 | @as(?struct_field.field_type, null), |
| 48 | 48 | ), |
| 49 | 49 | .is_comptime = false, |
| 50 | .alignment = @alignOf(?struct_field.field_type), | |
| 50 | 51 | }; |
| 51 | 52 | } |
| 52 | 53 | break :blk @Type(.{ |
lib/std/os.zig+1-1| ... | ... | @@ -3993,7 +3993,7 @@ pub const RealPathError = error{ |
| 3993 | 3993 | /// Expands all symbolic links and resolves references to `.`, `..`, and |
| 3994 | 3994 | /// extra `/` characters in `pathname`. |
| 3995 | 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`. | |
| 3997 | 3997 | pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 3998 | 3998 | if (builtin.os.tag == .windows) { |
| 3999 | 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 | 318 | }; |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true; | |
| 322 | ||
| 321 | 323 | test "PackedIntArray" { |
| 322 | 324 | // TODO @setEvalBranchQuota generates panics in wasm32. Investigate. |
| 323 | 325 | if (builtin.arch == .wasm32) return error.SkipZigTest; |
| 326 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 324 | 327 | |
| 325 | 328 | @setEvalBranchQuota(10000); |
| 326 | 329 | const max_bits = 256; |
| ... | ... | @@ -358,6 +361,7 @@ test "PackedIntArray" { |
| 358 | 361 | } |
| 359 | 362 | |
| 360 | 363 | test "PackedIntArray init" { |
| 364 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 361 | 365 | const PackedArray = PackedIntArray(u3, 8); |
| 362 | 366 | var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 }); |
| 363 | 367 | var i = @as(usize, 0); |
| ... | ... | @@ -367,6 +371,7 @@ test "PackedIntArray init" { |
| 367 | 371 | test "PackedIntSlice" { |
| 368 | 372 | // TODO @setEvalBranchQuota generates panics in wasm32. Investigate. |
| 369 | 373 | if (builtin.arch == .wasm32) return error.SkipZigTest; |
| 374 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 370 | 375 | |
| 371 | 376 | @setEvalBranchQuota(10000); |
| 372 | 377 | const max_bits = 256; |
| ... | ... | @@ -405,6 +410,7 @@ test "PackedIntSlice" { |
| 405 | 410 | } |
| 406 | 411 | |
| 407 | 412 | test "PackedIntSlice of PackedInt(Array/Slice)" { |
| 413 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 408 | 414 | const max_bits = 16; |
| 409 | 415 | const int_count = 19; |
| 410 | 416 | |
| ... | ... | @@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" { |
| 470 | 476 | } |
| 471 | 477 | |
| 472 | 478 | test "PackedIntSlice accumulating bit offsets" { |
| 479 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 473 | 480 | //bit_offset is u3, so standard debugging asserts should catch |
| 474 | 481 | // anything |
| 475 | 482 | { |
| ... | ... | @@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" { |
| 497 | 504 | //@NOTE: As I do not have a big endian system to test this on, |
| 498 | 505 | // big endian values were not tested |
| 499 | 506 | test "PackedInt(Array/Slice) sliceCast" { |
| 507 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 508 | ||
| 500 | 509 | const PackedArray = PackedIntArray(u1, 16); |
| 501 | 510 | var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }); |
| 502 | 511 | const packed_slice_cast_2 = packed_array.sliceCast(u2); |
| ... | ... | @@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" { |
| 537 | 546 | } |
| 538 | 547 | |
| 539 | 548 | test "PackedInt(Array/Slice)Endian" { |
| 549 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 550 | ||
| 540 | 551 | { |
| 541 | 552 | const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8); |
| 542 | 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 | 615 | // after this one is not mapped and will cause a segfault if we |
| 605 | 616 | // don't account for the bounds. |
| 606 | 617 | test "PackedIntArray at end of available memory" { |
| 618 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 619 | ||
| 607 | 620 | switch (builtin.os.tag) { |
| 608 | 621 | .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {}, |
| 609 | 622 | else => return, |
| ... | ... | @@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" { |
| 623 | 636 | } |
| 624 | 637 | |
| 625 | 638 | test "PackedIntSlice at end of available memory" { |
| 639 | if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest; | |
| 640 | ||
| 626 | 641 | switch (builtin.os.tag) { |
| 627 | 642 | .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {}, |
| 628 | 643 | else => return, |
src/Compilation.zig+22-9| ... | ... | @@ -352,6 +352,7 @@ pub const InitOptions = struct { |
| 352 | 352 | time_report: bool = false, |
| 353 | 353 | stack_report: bool = false, |
| 354 | 354 | link_eh_frame_hdr: bool = false, |
| 355 | link_emit_relocs: bool = false, | |
| 355 | 356 | linker_script: ?[]const u8 = null, |
| 356 | 357 | version_script: ?[]const u8 = null, |
| 357 | 358 | override_soname: ?[]const u8 = null, |
| ... | ... | @@ -447,6 +448,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 447 | 448 | options.system_libs.len != 0 or |
| 448 | 449 | options.link_libc or options.link_libcpp or |
| 449 | 450 | options.link_eh_frame_hdr or |
| 451 | options.link_emit_relocs or | |
| 450 | 452 | options.output_mode == .Lib or |
| 451 | 453 | options.lld_argv.len != 0 or |
| 452 | 454 | options.linker_script != null or options.version_script != null) |
| ... | ... | @@ -769,6 +771,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 769 | 771 | .version_script = options.version_script, |
| 770 | 772 | .gc_sections = options.linker_gc_sections, |
| 771 | 773 | .eh_frame_hdr = options.link_eh_frame_hdr, |
| 774 | .emit_relocs = options.link_emit_relocs, | |
| 772 | 775 | .rdynamic = options.rdynamic, |
| 773 | 776 | .extra_lld_args = options.lld_argv, |
| 774 | 777 | .override_soname = options.override_soname, |
| ... | ... | @@ -1146,7 +1149,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 1146 | 1149 | }; |
| 1147 | 1150 | } |
| 1148 | 1151 | |
| 1149 | pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { | |
| 1152 | pub 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 | 1161 | while (self.work_queue.readItem()) |work_item| switch (work_item) { |
| 1151 | 1162 | .codegen_decl => |decl| switch (decl.analysis) { |
| 1152 | 1163 | .unreferenced => unreachable, |
| ... | ... | @@ -1223,7 +1234,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { |
| 1223 | 1234 | }; |
| 1224 | 1235 | }, |
| 1225 | 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 | 1238 | error.AnalysisFail => continue, |
| 1228 | 1239 | else => { |
| 1229 | 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 | 1320 | if (!build_options.is_stage1) |
| 1310 | 1321 | unreachable; |
| 1311 | 1322 | |
| 1312 | self.updateStage1Module() catch |err| { | |
| 1323 | self.updateStage1Module(main_progress_node) catch |err| { | |
| 1313 | 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 | 1481 | }; |
| 1471 | 1482 | } |
| 1472 | 1483 | |
| 1473 | fn updateCObject(comp: *Compilation, c_object: *CObject) !void { | |
| 1484 | fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *std.Progress.Node) !void { | |
| 1474 | 1485 | if (!build_options.have_llvm) { |
| 1475 | 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 | 1524 | const arena = &arena_allocator.allocator; |
| 1514 | 1525 | |
| 1515 | 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 | 1533 | // Special case when doing build-obj for just one C file. When there are more than one object |
| 1517 | 1534 | // file and building an object we need to link them together, but with just one it should go |
| 1518 | 1535 | // directly to the output file. |
| ... | ... | @@ -2506,7 +2523,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2506 | 2523 | }; |
| 2507 | 2524 | } |
| 2508 | 2525 | |
| 2509 | fn updateStage1Module(comp: *Compilation) !void { | |
| 2526 | fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void { | |
| 2510 | 2527 | const tracy = trace(@src()); |
| 2511 | 2528 | defer tracy.end(); |
| 2512 | 2529 | |
| ... | ... | @@ -2612,10 +2629,6 @@ fn updateStage1Module(comp: *Compilation) !void { |
| 2612 | 2629 | .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null, |
| 2613 | 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; | |
| 2619 | 2632 | |
| 2620 | 2633 | comp.stage1_cache_manifest = &man; |
| 2621 | 2634 |
src/link.zig+1| ... | ... | @@ -60,6 +60,7 @@ pub const Options = struct { |
| 60 | 60 | link_libcpp: bool, |
| 61 | 61 | function_sections: bool, |
| 62 | 62 | eh_frame_hdr: bool, |
| 63 | emit_relocs: bool, | |
| 63 | 64 | rdynamic: bool, |
| 64 | 65 | z_nodelete: bool, |
| 65 | 66 | z_defs: bool, |
src/link/Elf.zig+5| ... | ... | @@ -1286,6 +1286,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1286 | 1286 | man.hash.add(stack_size); |
| 1287 | 1287 | man.hash.add(gc_sections); |
| 1288 | 1288 | man.hash.add(self.base.options.eh_frame_hdr); |
| 1289 | man.hash.add(self.base.options.emit_relocs); | |
| 1289 | 1290 | man.hash.add(self.base.options.rdynamic); |
| 1290 | 1291 | man.hash.addListOfBytes(self.base.options.extra_lld_args); |
| 1291 | 1292 | man.hash.addListOfBytes(self.base.options.lib_dirs); |
| ... | ... | @@ -1364,6 +1365,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1364 | 1365 | if (self.base.options.eh_frame_hdr) { |
| 1365 | 1366 | try argv.append("--eh-frame-hdr"); |
| 1366 | 1367 | } |
| 1368 | ||
| 1369 | if (self.base.options.emit_relocs) { | |
| 1370 | try argv.append("--emit-relocs"); | |
| 1371 | } | |
| 1367 | 1372 | |
| 1368 | 1373 | if (self.base.options.rdynamic) { |
| 1369 | 1374 | try argv.append("--export-dynamic"); |
src/main.zig+9| ... | ... | @@ -273,6 +273,7 @@ const usage_build_generic = |
| 273 | 273 | \\ -rdynamic Add all symbols to the dynamic symbol table |
| 274 | 274 | \\ -rpath [path] Add directory to the runtime library search path |
| 275 | 275 | \\ --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 | 277 | \\ -dynamic Force output to be dynamically linked |
| 277 | 278 | \\ -static Force output to be statically linked |
| 278 | 279 | \\ -Bsymbolic Bind global references locally |
| ... | ... | @@ -438,6 +439,7 @@ fn buildOutputType( |
| 438 | 439 | var use_lld: ?bool = null; |
| 439 | 440 | var use_clang: ?bool = null; |
| 440 | 441 | var link_eh_frame_hdr = false; |
| 442 | var link_emit_relocs = false; | |
| 441 | 443 | var each_lib_rpath = false; |
| 442 | 444 | var libc_paths_file: ?[]const u8 = null; |
| 443 | 445 | var machine_code_model: std.builtin.CodeModel = .default; |
| ... | ... | @@ -838,6 +840,8 @@ fn buildOutputType( |
| 838 | 840 | function_sections = true; |
| 839 | 841 | } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { |
| 840 | 842 | link_eh_frame_hdr = true; |
| 843 | } else if (mem.eql(u8, arg, "--emit-relocs")) { | |
| 844 | link_emit_relocs = true; | |
| 841 | 845 | } else if (mem.eql(u8, arg, "-Bsymbolic")) { |
| 842 | 846 | linker_bind_global_refs_locally = true; |
| 843 | 847 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| ... | ... | @@ -1206,6 +1210,10 @@ fn buildOutputType( |
| 1206 | 1210 | fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len}); |
| 1207 | 1211 | } |
| 1208 | 1212 | |
| 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 | 1217 | const root_name = if (provided_name) |n| n else blk: { |
| 1210 | 1218 | if (arg_mode == .zig_test) { |
| 1211 | 1219 | break :blk "test"; |
| ... | ... | @@ -1580,6 +1588,7 @@ fn buildOutputType( |
| 1580 | 1588 | .linker_z_nodelete = linker_z_nodelete, |
| 1581 | 1589 | .linker_z_defs = linker_z_defs, |
| 1582 | 1590 | .link_eh_frame_hdr = link_eh_frame_hdr, |
| 1591 | .link_emit_relocs = link_emit_relocs, | |
| 1583 | 1592 | .stack_size_override = stack_size_override, |
| 1584 | 1593 | .strip = strip, |
| 1585 | 1594 | .single_threaded = single_threaded, |
src/mingw.zig+6-5| ... | ... | @@ -32,6 +32,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 32 | 32 | var args = std.ArrayList([]const u8).init(arena); |
| 33 | 33 | try add_cc_args(comp, arena, &args); |
| 34 | 34 | try args.appendSlice(&[_][]const u8{ |
| 35 | "-D_SYSCRT=1", | |
| 36 | "-DCRTDLL=1", | |
| 35 | 37 | "-U__CRTDLL__", |
| 36 | 38 | "-D__MSVCRT__", |
| 37 | 39 | // Uncomment these 3 things for crtu |
| ... | ... | @@ -53,6 +55,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 53 | 55 | var args = std.ArrayList([]const u8).init(arena); |
| 54 | 56 | try add_cc_args(comp, arena, &args); |
| 55 | 57 | try args.appendSlice(&[_][]const u8{ |
| 58 | "-D_SYSCRT=1", | |
| 59 | "-DCRTDLL=1", | |
| 56 | 60 | "-U__CRTDLL__", |
| 57 | 61 | "-D__MSVCRT__", |
| 58 | 62 | }); |
| ... | ... | @@ -437,11 +441,8 @@ fn findDef(comp: *Compilation, allocator: *Allocator, lib_name: []const u8) ![]u |
| 437 | 441 | const lib_path = switch (target.cpu.arch) { |
| 438 | 442 | .i386 => "lib32", |
| 439 | 443 | .x86_64 => "lib64", |
| 440 | .arm, .armeb => switch (target.cpu.arch.ptrBitWidth()) { | |
| 441 | 32 => "libarm32", | |
| 442 | 64 => "libarm64", | |
| 443 | else => unreachable, | |
| 444 | }, | |
| 444 | .arm, .armeb, .thumb, .thumbeb, .aarch64_32 => "libarm32", | |
| 445 | .aarch64, .aarch64_be => "libarm64", | |
| 445 | 446 | else => unreachable, |
| 446 | 447 | }; |
| 447 | 448 |
src/stage1.zig+5-1| ... | ... | @@ -39,7 +39,11 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int { |
| 39 | 39 | for (args) |*arg, i| { |
| 40 | 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 | 47 | return 0; |
| 44 | 48 | } |
| 45 | 49 |
src/stage1/all_types.hpp+1-5| ... | ... | @@ -18,11 +18,6 @@ |
| 18 | 18 | #include "target.hpp" |
| 19 | 19 | #include "tokenizer.hpp" |
| 20 | 20 | |
| 21 | #ifndef NDEBUG | |
| 22 | #define DBG_MACRO_NO_WARNING | |
| 23 | #include <dbg.h> | |
| 24 | #endif | |
| 25 | ||
| 26 | 21 | struct AstNode; |
| 27 | 22 | struct ZigFn; |
| 28 | 23 | struct Scope; |
| ... | ... | @@ -1456,6 +1451,7 @@ struct ZigTypeEnum { |
| 1456 | 1451 | ContainerLayout layout; |
| 1457 | 1452 | ResolveStatus resolve_status; |
| 1458 | 1453 | |
| 1454 | bool has_explicit_tag_type; | |
| 1459 | 1455 | bool non_exhaustive; |
| 1460 | 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 | 1802 | } |
| 1803 | 1803 | return type_allowed_in_extern(g, child_type, result); |
| 1804 | 1804 | } |
| 1805 | case ZigTypeIdEnum: | |
| 1806 | *result = type_entry->data.enumeration.layout == ContainerLayoutExtern || | |
| 1807 | type_entry->data.enumeration.layout == ContainerLayoutPacked; | |
| 1808 | return ErrorNone; | |
| 1805 | case ZigTypeIdEnum: { | |
| 1806 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | |
| 1807 | return err; | |
| 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 | 1817 | case ZigTypeIdUnion: |
| 1810 | 1818 | *result = type_entry->data.unionation.layout == ContainerLayoutExtern || |
| 1811 | 1819 | type_entry->data.unionation.layout == ContainerLayoutPacked; |
| ... | ... | @@ -2639,9 +2647,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { |
| 2639 | 2647 | if (decl_node->type == NodeTypeContainerDecl) { |
| 2640 | 2648 | if (decl_node->data.container_decl.init_arg_expr != nullptr) { |
| 2641 | 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 | 2652 | } else { |
| 2644 | 2653 | wanted_tag_int_type = enum_type->data.enumeration.tag_int_type; |
| 2654 | enum_type->data.enumeration.has_explicit_tag_type = true; | |
| 2645 | 2655 | } |
| 2646 | 2656 | |
| 2647 | 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 | 8837 | buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n"); |
| 8838 | 8838 | buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n"); |
| 8839 | 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 | 8841 | buf_appendf(contents, "pub const is_test = false;\n"); |
| 8842 | 8842 | buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); |
| 8843 | 8843 | buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); |
src/stage1/config.h.in+1| ... | ... | @@ -21,5 +21,6 @@ |
| 21 | 21 | #define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@" |
| 22 | 22 | #define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@" |
| 23 | 23 | #define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@" |
| 24 | #define ZIG_LINK_MODE "@ZIG_LINK_MODE@" | |
| 24 | 25 | |
| 25 | 26 | #endif |
src/stage1/ir.cpp+154-27| ... | ... | @@ -25034,7 +25034,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, IrInst *source_instr, |
| 25034 | 25034 | fields[2]->special = ConstValSpecialStatic; |
| 25035 | 25035 | fields[2]->type = ira->codegen->builtin_types.entry_bool; |
| 25036 | 25036 | fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile; |
| 25037 | // alignment: u32 | |
| 25037 | // alignment: comptime_int | |
| 25038 | 25038 | ensure_field_index(result->type, "alignment", 3); |
| 25039 | 25039 | fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int; |
| 25040 | 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 | 25438 | union_field_val->special = ConstValSpecialStatic; |
| 25439 | 25439 | union_field_val->type = type_info_union_field_type; |
| 25440 | 25440 | |
| 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 | 25443 | inner_fields[1]->special = ConstValSpecialStatic; |
| 25443 | 25444 | inner_fields[1]->type = ira->codegen->builtin_types.entry_type; |
| 25444 | 25445 | inner_fields[1]->data.x_type = union_field->type_entry; |
| 25445 | 25446 | |
| 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 | 25452 | ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee; |
| 25447 | 25453 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true); |
| 25448 | 25454 | |
| ... | ... | @@ -25509,7 +25515,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25509 | 25515 | struct_field_val->special = ConstValSpecialStatic; |
| 25510 | 25516 | struct_field_val->type = type_info_struct_field_type; |
| 25511 | 25517 | |
| 25512 | ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4); | |
| 25518 | ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 5); | |
| 25513 | 25519 | |
| 25514 | 25520 | inner_fields[1]->special = ConstValSpecialStatic; |
| 25515 | 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 | 25531 | } |
| 25526 | 25532 | set_optional_payload(inner_fields[2], struct_field->init_val); |
| 25527 | 25533 | |
| 25534 | // is_comptime: bool | |
| 25528 | 25535 | inner_fields[3]->special = ConstValSpecialStatic; |
| 25529 | 25536 | inner_fields[3]->type = ira->codegen->builtin_types.entry_bool; |
| 25530 | 25537 | inner_fields[3]->data.x_bool = struct_field->is_comptime; |
| 25531 | 25538 | |
| 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 | 25544 | ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; |
| 25533 | 25545 | init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); |
| 25534 | 25546 | |
| ... | ... | @@ -25559,7 +25571,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25559 | 25571 | result->special = ConstValSpecialStatic; |
| 25560 | 25572 | result->type = ir_type_info_get_type(ira, "Fn", nullptr); |
| 25561 | 25573 | |
| 25562 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5); | |
| 25574 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 6); | |
| 25563 | 25575 | result->data.x_struct.fields = fields; |
| 25564 | 25576 | |
| 25565 | 25577 | // calling_convention: TypeInfo.CallingConvention |
| ... | ... | @@ -25567,38 +25579,42 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25567 | 25579 | fields[0]->special = ConstValSpecialStatic; |
| 25568 | 25580 | fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention"); |
| 25569 | 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 | 25587 | // is_generic: bool |
| 25571 | ensure_field_index(result->type, "is_generic", 1); | |
| 25588 | ensure_field_index(result->type, "is_generic", 2); | |
| 25572 | 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 | 25590 | fields[2]->special = ConstValSpecialStatic; |
| 25580 | 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; | |
| 25582 | // return_type: ?type | |
| 25583 | ensure_field_index(result->type, "return_type", 3); | |
| 25592 | fields[2]->data.x_bool = is_generic; | |
| 25593 | // is_varargs: bool | |
| 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 | 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 | 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 | 25605 | else { |
| 25589 | 25606 | ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>(); |
| 25590 | 25607 | return_type->special = ConstValSpecialStatic; |
| 25591 | 25608 | return_type->type = ira->codegen->builtin_types.entry_type; |
| 25592 | 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 | 25612 | // args: []TypeInfo.FnArg |
| 25596 | 25613 | ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr); |
| 25597 | 25614 | if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) { |
| 25598 | 25615 | zig_unreachable(); |
| 25599 | 25616 | } |
| 25600 | 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); | |
| 25617 | size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count; | |
| 25602 | 25618 | |
| 25603 | 25619 | ZigValue *fn_arg_array = ira->codegen->pass1_arena->create<ZigValue>(); |
| 25604 | 25620 | fn_arg_array->special = ConstValSpecialStatic; |
| ... | ... | @@ -25606,7 +25622,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25606 | 25622 | fn_arg_array->data.x_array.special = ConstArraySpecialNone; |
| 25607 | 25623 | fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count); |
| 25608 | 25624 | |
| 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); | |
| 25610 | 25626 | |
| 25611 | 25627 | for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { |
| 25612 | 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 | 25891 | buf_sprintf("sentinels are only allowed on slices and unknown-length pointers")); |
| 25876 | 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); | |
| 25879 | if (bi == nullptr) | |
| 25894 | ||
| 25895 | BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3); | |
| 25896 | if (alignment == nullptr) | |
| 25880 | 25897 | return ira->codegen->invalid_inst_gen->value->type; |
| 25881 | 25898 | |
| 25882 | 25899 | bool is_const; |
| ... | ... | @@ -25903,7 +25920,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 25903 | 25920 | is_const, |
| 25904 | 25921 | is_volatile, |
| 25905 | 25922 | ptr_len, |
| 25906 | bigint_as_u32(bi), | |
| 25923 | bigint_as_u32(alignment), | |
| 25907 | 25924 | 0, // bit_offset_in_host |
| 25908 | 25925 | 0, // host_int_bytes |
| 25909 | 25926 | is_allowzero, |
| ... | ... | @@ -26140,6 +26157,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26140 | 26157 | } |
| 26141 | 26158 | if ((err = get_const_field_bool(ira, source_instr->source_node, field_value, "is_comptime", 3, &field->is_comptime))) |
| 26142 | 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 | } |
| 26144 | 26165 | |
| 26145 | 26166 | return entry; |
| ... | ... | @@ -26157,6 +26178,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26157 | 26178 | ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag); |
| 26158 | 26179 | |
| 26159 | 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 | } | |
| 26160 | 26188 | |
| 26161 | 26189 | ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2); |
| 26162 | 26190 | if (fields_value == nullptr) |
| ... | ... | @@ -26302,14 +26330,113 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 26302 | 26330 | return ira->codegen->invalid_inst_gen->value->type; |
| 26303 | 26331 | field->type_val = type_value; |
| 26304 | 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 | 26338 | return entry; |
| 26307 | 26339 | } |
| 26308 | 26340 | case ZigTypeIdFn: |
| 26309 | case ZigTypeIdBoundFn: | |
| 26310 | ir_add_error(ira, source_instr, buf_sprintf( | |
| 26311 | "@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId))); | |
| 26312 | return ira->codegen->invalid_inst_gen->value->type; | |
| 26341 | case ZigTypeIdBoundFn: { | |
| 26342 | assert(payload->special == ConstValSpecialStatic); | |
| 26343 | assert(payload->type == ir_type_info_get_type(ira, "Fn", nullptr)); | |
| 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 | 26441 | zig_unreachable(); |
| 26315 | 26442 | } |
src/stage1/os.cpp+21-1053| ... | ... | @@ -94,106 +94,6 @@ static clock_serv_t macos_monotonic_clock; |
| 94 | 94 | extern char **environ; |
| 95 | 95 | #endif |
| 96 | 96 | |
| 97 | #if defined(ZIG_OS_POSIX) | |
| 98 | static 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 | ||
| 114 | static 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 | ||
| 136 | static 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 | ||
| 154 | static 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 | ||
| 187 | void 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 | ||
| 197 | 97 | void os_path_dirname(Buf *full_path, Buf *out_dirname) { |
| 198 | 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 | 181 | buf_append_buf(out_full_path, basename); |
| 282 | 182 | } |
| 283 | 183 | |
| 284 | Error 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 | |
| 318 | static 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 | ||
| 338 | bool 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 | } | |
| 347 | 184 | |
| 348 | #if defined(ZIG_OS_WINDOWS) | |
| 185 | #if defined(ZIG_OS_WINDOWS)		 | |
| 186 | // Ported from std/os/path.zig		 | |
| 187 | static 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 | }		 | |
| 349 | 205 | |
| 350 | 206 | enum WindowsPathKind { |
| 351 | 207 | WindowsPathKindNone, |
| ... | ... | @@ -688,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { |
| 688 | 544 | size_t max_size = 0; |
| 689 | 545 | for (size_t i = 0; i < paths_len; i += 1) { |
| 690 | 546 | Buf *p = paths_ptr[i]; |
| 691 | if (os_path_is_absolute(p)) { | |
| 547 | if (buf_ptr(p)[0] == '/') { | |
| 692 | 548 | first_index = i; |
| 693 | 549 | have_abs = true; |
| 694 | 550 | max_size = 0; |
| ... | ... | @@ -788,256 +644,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) { |
| 788 | 644 | zig_unreachable(); |
| 789 | 645 | } |
| 790 | 646 | |
| 791 | Error 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) | |
| 803 | static 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 | ||
| 897 | static 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 | ||
| 1013 | Error 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 | ||
| 1029 | Error 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 | ||
| 1041 | 647 | Error os_write_file(Buf *full_path, Buf *contents) { |
| 1042 | 648 | #if defined(ZIG_OS_WINDOWS) |
| 1043 | 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 | 682 | } |
| 1077 | 683 | } |
| 1078 | 684 | |
| 1079 | Error 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 | 685 | #if defined(ZIG_OS_WINDOWS) |
| 1109 | 686 | static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) { |
| 1110 | 687 | mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime; |
| ... | ... | @@ -1118,88 +695,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) { |
| 1118 | 695 | } |
| 1119 | 696 | #endif |
| 1120 | 697 | |
| 1121 | static 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 | ||
| 1145 | Error 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 | ||
| 1203 | 698 | Error os_copy_file(Buf *src_path, Buf *dest_path) { |
| 1204 | 699 | #if defined(ZIG_OS_WINDOWS) |
| 1205 | 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 | 855 | #endif |
| 1361 | 856 | } |
| 1362 | 857 | |
| 1363 | Error os_delete_file(Buf *path) { | |
| 1364 | if (remove(buf_ptr(path))) { | |
| 1365 | return ErrorFileSystem; | |
| 1366 | } else { | |
| 1367 | return ErrorNone; | |
| 1368 | } | |
| 1369 | } | |
| 1370 | ||
| 1371 | 858 | Error os_rename(Buf *src_path, Buf *dest_path) { |
| 1372 | 859 | if (buf_eql_buf(src_path, dest_path)) { |
| 1373 | 860 | return ErrorNone; |
| ... | ... | @@ -1386,30 +873,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) { |
| 1386 | 873 | return ErrorNone; |
| 1387 | 874 | } |
| 1388 | 875 | |
| 1389 | OsTimeStamp 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 | ||
| 1413 | 876 | OsTimeStamp os_timestamp_monotonic(void) { |
| 1414 | 877 | OsTimeStamp result; |
| 1415 | 878 | #if defined(ZIG_OS_WINDOWS) |
| ... | ... | @@ -1503,49 +966,8 @@ Error os_make_dir(Buf *path) { |
| 1503 | 966 | #endif |
| 1504 | 967 | } |
| 1505 | 968 | |
| 1506 | static 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 | } | |
| 1546 | 969 | |
| 1547 | 970 | int os_init(void) { |
| 1548 | init_rand(); | |
| 1549 | 971 | #if defined(ZIG_OS_WINDOWS) |
| 1550 | 972 | _setmode(fileno(stdout), _O_BINARY); |
| 1551 | 973 | _setmode(fileno(stderr), _O_BINARY); |
| ... | ... | @@ -1582,71 +1004,6 @@ int os_init(void) { |
| 1582 | 1004 | return 0; |
| 1583 | 1005 | } |
| 1584 | 1006 | |
| 1585 | Error 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 | 1007 | #define VT_RED "\x1b[31;1m" |
| 1651 | 1008 | #define VT_GREEN "\x1b[32;1m" |
| 1652 | 1009 | #define VT_CYAN "\x1b[36;1m" |
| ... | ... | @@ -1956,392 +1313,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) { |
| 1956 | 1313 | return path_space; |
| 1957 | 1314 | } |
| 1958 | 1315 | #endif |
| 1959 | ||
| 1960 | // Ported from std.os.getAppDataDir | |
| 1961 | Error 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) | |
| 2017 | static 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 | ||
| 2026 | Error 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 | ||
| 2048 | Error 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 | ||
| 2145 | Error 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 | ||
| 2149 | Error 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 | ||
| 2153 | Error 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 | ||
| 2241 | Error 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 | ||
| 2271 | Error 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 | ||
| 2294 | Error 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 | ||
| 2339 | void 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 | 70 | TermColorReset, |
| 71 | 71 | }; |
| 72 | 72 | |
| 73 | enum TerminationId { | |
| 74 | TerminationIdClean, | |
| 75 | TerminationIdSignaled, | |
| 76 | TerminationIdStopped, | |
| 77 | TerminationIdUnknown, | |
| 78 | }; | |
| 79 | ||
| 80 | struct 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 | ||
| 91 | 73 | struct OsTimeStamp { |
| 92 | 74 | int64_t sec; |
| 93 | 75 | int64_t nsec; |
| 94 | 76 | }; |
| 95 | 77 | |
| 96 | struct OsFileAttr { | |
| 97 | OsTimeStamp mtime; | |
| 98 | uint64_t size; | |
| 99 | uint64_t inode; | |
| 100 | uint32_t mode; | |
| 101 | }; | |
| 102 | ||
| 103 | 78 | int os_init(void); |
| 104 | 79 | |
| 105 | void os_spawn_process(ZigList<const char *> &args, Termination *term); | |
| 106 | Error os_exec_process(ZigList<const char *> &args, | |
| 107 | Termination *term, Buf *out_stderr, Buf *out_stdout); | |
| 108 | Error os_execv(const char *exe, const char **argv); | |
| 109 | ||
| 110 | 80 | void os_path_dirname(Buf *full_path, Buf *out_dirname); |
| 111 | 81 | void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename); |
| 112 | 82 | void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname); |
| 113 | 83 | void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path); |
| 114 | Error os_path_real(Buf *rel_path, Buf *out_abs_path); | |
| 115 | 84 | Buf os_path_resolve(Buf **paths_ptr, size_t paths_len); |
| 116 | 85 | bool os_path_is_absolute(Buf *path); |
| 117 | 86 | |
| 118 | 87 | Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); |
| 119 | 88 | Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); |
| 120 | 89 | |
| 121 | Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr); | |
| 122 | Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode); | |
| 123 | Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file); | |
| 124 | Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len); | |
| 125 | Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); | |
| 126 | Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents); | |
| 127 | void os_file_close(OsFile *file); | |
| 128 | ||
| 129 | 90 | Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents); |
| 130 | 91 | Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path); |
| 131 | Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path); | |
| 132 | Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file); | |
| 133 | 92 | |
| 134 | 93 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents); |
| 135 | 94 | Error 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 | 98 | bool os_stderr_tty(void); |
| 140 | 99 | void os_stderr_set_color(TermColor color); |
| 141 | 100 | |
| 142 | Error os_delete_file(Buf *path); | |
| 143 | ||
| 144 | Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result); | |
| 145 | ||
| 146 | 101 | Error os_rename(Buf *src_path, Buf *dest_path); |
| 147 | 102 | OsTimeStamp os_timestamp_monotonic(void); |
| 148 | OsTimeStamp os_timestamp_calendar(void); | |
| 149 | 103 | |
| 150 | 104 | bool os_is_sep(uint8_t c); |
| 151 | 105 | |
| 152 | Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path); | |
| 153 | ||
| 154 | Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname); | |
| 155 | ||
| 156 | Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths); | |
| 157 | ||
| 158 | 106 | const size_t PATH_MAX_WIDE = 32767; |
| 159 | 107 | |
| 160 | 108 | struct PathSpace { |
src/stage1/zig0.cpp+10| ... | ... | @@ -430,6 +430,16 @@ int main(int argc, char **argv) { |
| 430 | 430 | return print_error_usage(arg0); |
| 431 | 431 | } |
| 432 | 432 | |
| 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 | 443 | ZigStage1 *stage1 = zig_stage1_create(optimize_mode, |
| 434 | 444 | nullptr, 0, |
| 435 | 445 | in_file, strlen(in_file), |
src/target.zig+1-1| ... | ... | @@ -130,7 +130,6 @@ pub fn osRequiresLibC(target: std.Target) bool { |
| 130 | 130 | |
| 131 | 131 | pub fn libcNeedsLibUnwind(target: std.Target) bool { |
| 132 | 132 | return switch (target.os.tag) { |
| 133 | .windows, | |
| 134 | 133 | .macosx, |
| 135 | 134 | .ios, |
| 136 | 135 | .watchos, |
| ... | ... | @@ -138,6 +137,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool { |
| 138 | 137 | .freestanding, |
| 139 | 138 | => false, |
| 140 | 139 | |
| 140 | .windows => target.abi != .msvc, | |
| 141 | 141 | else => true, |
| 142 | 142 | }; |
| 143 | 143 | } |
test/compile_errors.zig+182-47| ... | ... | @@ -2,20 +2,175 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | |
| 4 | 4 | pub 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 | 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 | 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 | }); |
| 12 | 22 | |
| 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 | 28 | \\export fn entry() void { |
| 15 | \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 }; | |
| 29 | \\ const s: S = undefined; | |
| 16 | 30 | \\} |
| 17 | 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 | }); |
| 20 | 175 | |
| 21 | 176 | cases.add("@Type for union with opaque field", |
| ... | ... | @@ -25,7 +180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 25 | 180 | \\ .layout = .Auto, |
| 26 | 181 | \\ .tag_type = null, |
| 27 | 182 | \\ .fields = &[_]TypeInfo.UnionField{ |
| 28 | \\ .{ .name = "foo", .field_type = @Type(.Opaque) }, | |
| 183 | \\ .{ .name = "foo", .field_type = @Type(.Opaque), .alignment = 1 }, | |
| 29 | 184 | \\ }, |
| 30 | 185 | \\ .decls = &[_]TypeInfo.Declaration{}, |
| 31 | 186 | \\ }, |
| ... | ... | @@ -38,6 +193,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 38 | 193 | "tmp.zig:13:17: note: referenced here", |
| 39 | 194 | }); |
| 40 | 195 | |
| 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 | 212 | cases.add("@Type for union with zero fields", |
| 42 | 213 | \\const TypeInfo = @import("builtin").TypeInfo; |
| 43 | 214 | \\const Untagged = @Type(.{ |
| ... | ... | @@ -94,9 +265,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 94 | 265 | \\ .layout = .Auto, |
| 95 | 266 | \\ .tag_type = Tag, |
| 96 | 267 | \\ .fields = &[_]TypeInfo.UnionField{ |
| 97 | \\ .{ .name = "signed", .field_type = i32 }, | |
| 98 | \\ .{ .name = "unsigned", .field_type = u32 }, | |
| 99 | \\ .{ .name = "arst", .field_type = f32 }, | |
| 268 | \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, | |
| 269 | \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, | |
| 270 | \\ .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) }, | |
| 100 | 271 | \\ }, |
| 101 | 272 | \\ .decls = &[_]TypeInfo.Declaration{}, |
| 102 | 273 | \\ }, |
| ... | ... | @@ -111,42 +282,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 111 | 282 | "tmp.zig:27:24: note: referenced here", |
| 112 | 283 | }); |
| 113 | 284 | |
| 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 | 285 | cases.add("@Type with undefined", |
| 151 | 286 | \\comptime { |
| 152 | 287 | \\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } }); |
| ... | ... | @@ -7556,7 +7691,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 7556 | 7691 | }); |
| 7557 | 7692 | |
| 7558 | 7693 | cases.add( // fixed bug #2032 |
| 7559 | "compile diagnostic string for top level decl type", | |
| 7694 | "compile diagnostic string for top level decl type", | |
| 7560 | 7695 | \\export fn entry() void { |
| 7561 | 7696 | \\ var foo: u32 = @This(){}; |
| 7562 | 7697 | \\} |
test/stage1/behavior/bugs/1467.zig created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | pub const E = enum(u32) { A, B, C }; | |
| 2 | pub const S = extern struct { | |
| 3 | e: E, | |
| 4 | }; | |
| 5 | test "bug 1467" { | |
| 6 | const s: S = undefined; | |
| 7 | } |
test/stage1/behavior/type.zig+35-8| ... | ... | @@ -320,8 +320,8 @@ test "Type.Union" { |
| 320 | 320 | .layout = .Auto, |
| 321 | 321 | .tag_type = null, |
| 322 | 322 | .fields = &[_]TypeInfo.UnionField{ |
| 323 | .{ .name = "int", .field_type = i32 }, | |
| 324 | .{ .name = "float", .field_type = f32 }, | |
| 323 | .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) }, | |
| 324 | .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) }, | |
| 325 | 325 | }, |
| 326 | 326 | .decls = &[_]TypeInfo.Declaration{}, |
| 327 | 327 | }, |
| ... | ... | @@ -336,8 +336,8 @@ test "Type.Union" { |
| 336 | 336 | .layout = .Packed, |
| 337 | 337 | .tag_type = null, |
| 338 | 338 | .fields = &[_]TypeInfo.UnionField{ |
| 339 | .{ .name = "signed", .field_type = i32 }, | |
| 340 | .{ .name = "unsigned", .field_type = u32 }, | |
| 339 | .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, | |
| 340 | .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, | |
| 341 | 341 | }, |
| 342 | 342 | .decls = &[_]TypeInfo.Declaration{}, |
| 343 | 343 | }, |
| ... | ... | @@ -363,8 +363,8 @@ test "Type.Union" { |
| 363 | 363 | .layout = .Auto, |
| 364 | 364 | .tag_type = Tag, |
| 365 | 365 | .fields = &[_]TypeInfo.UnionField{ |
| 366 | .{ .name = "signed", .field_type = i32 }, | |
| 367 | .{ .name = "unsigned", .field_type = u32 }, | |
| 366 | .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, | |
| 367 | .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, | |
| 368 | 368 | }, |
| 369 | 369 | .decls = &[_]TypeInfo.Declaration{}, |
| 370 | 370 | }, |
| ... | ... | @@ -392,7 +392,7 @@ test "Type.Union from Type.Enum" { |
| 392 | 392 | .layout = .Auto, |
| 393 | 393 | .tag_type = Tag, |
| 394 | 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 | 397 | .decls = &[_]TypeInfo.Declaration{}, |
| 398 | 398 | }, |
| ... | ... | @@ -408,7 +408,7 @@ test "Type.Union from regular enum" { |
| 408 | 408 | .layout = .Auto, |
| 409 | 409 | .tag_type = E, |
| 410 | 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 | 413 | .decls = &[_]TypeInfo.Declaration{}, |
| 414 | 414 | }, |
| ... | ... | @@ -416,3 +416,30 @@ test "Type.Union from regular enum" { |
| 416 | 416 | _ = T; |
| 417 | 417 | _ = @typeInfo(T).Union; |
| 418 | 418 | } |
| 419 | ||
| 420 | test "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 | ||
| 433 | test "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 | 211 | expect(notag_union_info.Union.tag_type == null); |
| 212 | 212 | expect(notag_union_info.Union.layout == .Auto); |
| 213 | 213 | expect(notag_union_info.Union.fields.len == 2); |
| 214 | expect(notag_union_info.Union.fields[0].alignment == @alignOf(void)); | |
| 214 | 215 | expect(notag_union_info.Union.fields[1].field_type == u32); |
| 216 | expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32)); | |
| 215 | 217 | |
| 216 | 218 | const TestExternUnion = extern union { |
| 217 | 219 | foo: *c_void, |
| ... | ... | @@ -229,13 +231,18 @@ test "type info: struct info" { |
| 229 | 231 | } |
| 230 | 232 | |
| 231 | 233 | fn testStruct() void { |
| 234 | const unpacked_struct_info = @typeInfo(TestUnpackedStruct); | |
| 235 | expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32)); | |
| 236 | ||
| 232 | 237 | const struct_info = @typeInfo(TestStruct); |
| 233 | 238 | expect(struct_info == .Struct); |
| 234 | 239 | expect(struct_info.Struct.layout == .Packed); |
| 235 | 240 | expect(struct_info.Struct.fields.len == 4); |
| 241 | expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize)); | |
| 236 | 242 | expect(struct_info.Struct.fields[2].field_type == *TestStruct); |
| 237 | 243 | expect(struct_info.Struct.fields[2].default_value == null); |
| 238 | 244 | expect(struct_info.Struct.fields[3].default_value.? == 4); |
| 245 | expect(struct_info.Struct.fields[3].alignment == 1); | |
| 239 | 246 | expect(struct_info.Struct.decls.len == 2); |
| 240 | 247 | expect(struct_info.Struct.decls[0].is_pub); |
| 241 | 248 | expect(!struct_info.Struct.decls[0].data.Fn.is_extern); |
| ... | ... | @@ -244,8 +251,12 @@ fn testStruct() void { |
| 244 | 251 | expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void); |
| 245 | 252 | } |
| 246 | 253 | |
| 254 | const TestUnpackedStruct = struct { | |
| 255 | fieldA: u32 = 4, | |
| 256 | }; | |
| 257 | ||
| 247 | 258 | const TestStruct = packed struct { |
| 248 | fieldA: usize, | |
| 259 | fieldA: usize align(2 * @alignOf(usize)), | |
| 249 | 260 | fieldB: void, |
| 250 | 261 | fieldC: *Self, |
| 251 | 262 | fieldD: u32 = 4, |
| ... | ... | @@ -255,6 +266,8 @@ const TestStruct = packed struct { |
| 255 | 266 | }; |
| 256 | 267 | |
| 257 | 268 | test "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 | 271 | testFunction(); |
| 259 | 272 | comptime testFunction(); |
| 260 | 273 | } |
| ... | ... | @@ -262,11 +275,14 @@ test "type info: function type info" { |
| 262 | 275 | fn testFunction() void { |
| 263 | 276 | const fn_info = @typeInfo(@TypeOf(foo)); |
| 264 | 277 | expect(fn_info == .Fn); |
| 278 | expect(fn_info.Fn.alignment == 0); | |
| 265 | 279 | expect(fn_info.Fn.calling_convention == .C); |
| 266 | 280 | expect(!fn_info.Fn.is_generic); |
| 267 | 281 | expect(fn_info.Fn.args.len == 2); |
| 268 | 282 | expect(fn_info.Fn.is_var_args); |
| 269 | 283 | expect(fn_info.Fn.return_type.? == usize); |
| 284 | const fn_aligned_info = @typeInfo(@TypeOf(fooAligned)); | |
| 285 | expect(fn_aligned_info.Fn.alignment == 4); | |
| 270 | 286 | |
| 271 | 287 | const test_instance: TestStruct = undefined; |
| 272 | 288 | const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo)); |
| ... | ... | @@ -274,7 +290,8 @@ fn testFunction() void { |
| 274 | 290 | expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); |
| 275 | 291 | } |
| 276 | 292 | |
| 277 | extern fn foo(a: usize, b: bool, ...) usize; | |
| 293 | extern fn foo(a: usize, b: bool, ...) callconv(.C) usize; | |
| 294 | extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize; | |
| 278 | 295 | |
| 279 | 296 | test "typeInfo with comptime parameter in struct fn def" { |
| 280 | 297 | const S = struct { |