commit 23cd3b33312ea5fcae32dcb6cd53cbd502361ce9 (tree)
parent 82f0ede3ad4150a80ab745419664f1dce4a6be9c
Author: Alexandros Naskos <alex_naskos@hotmail.com>
Date: Sun, 4 Oct 2020 10:39:26 +0300
Merge branch 'master' of https://github.com/ziglang/zig into add_some_frees
Diffstat:
43 files changed, 2551 insertions(+), 2349 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -63,6 +63,9 @@ endif()
if(ZIG_STATIC)
set(ZIG_STATIC_LLVM "on")
+ set(ZIG_LINK_MODE "Static")
+else()
+ set(ZIG_LINK_MODE "Dynamic")
endif()
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)
set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")
set(ZIG_TARGET_MCPU "baseline" CACHE STRING "-mcpu parameter to output binaries for")
set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")
+set(ZIG_PREFER_LLVM_CONFIG off CACHE BOOL "(when cross compiling) use llvm-config to find target llvm dependencies if needed")
find_package(llvm)
find_package(clang)
@@ -257,7 +261,6 @@ target_include_directories(embedded_softfloat PUBLIC
)
include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include")
set(SOFTFLOAT_LIBRARIES embedded_softfloat)
-include_directories("${CMAKE_SOURCE_DIR}/deps/dbg-macro")
find_package(Threads)
diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml
@@ -41,7 +41,7 @@ jobs:
steps:
- powershell: |
- (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")
+ (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")
.\sfx.exe -y -o\
del sfx.exe
displayName: Download/Extract/Install MSYS2
diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake
@@ -32,7 +32,7 @@ if(ZIG_PREFER_CLANG_CPP_DYLIB)
/usr/local/llvm10/lib
/usr/local/llvm100/lib
)
-elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
+elseif(("${ZIG_TARGET_TRIPLE}" STREQUAL "native") OR ZIG_PREFER_LLVM_CONFIG)
find_program(LLVM_CONFIG_EXE
NAMES llvm-config-10 llvm-config-10.0 llvm-config100 llvm-config10 llvm-config
PATHS
@@ -55,13 +55,13 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
OUTPUT_STRIP_TRAILING_WHITESPACE)
if("${LLVM_CONFIG_VERSION}" VERSION_LESS 10)
- message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")
+ message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
endif()
if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 11)
- message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")
+ message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
endif()
if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 11)
- message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION}")
+ message(FATAL_ERROR "expected LLVM 10.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}")
endif()
execute_process(
@@ -72,7 +72,7 @@ elseif("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
function(NEED_TARGET TARGET_NAME)
list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)
if (${_index} EQUAL -1)
- message(FATAL_ERROR "LLVM is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
+ 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.")
endif()
endfunction(NEED_TARGET)
NEED_TARGET("AArch64")
diff --git a/deps/dbg-macro/LICENSE b/deps/dbg-macro/LICENSE
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 David Peter <mail@david-peter.de>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/deps/dbg-macro/README.md b/deps/dbg-macro/README.md
@@ -1,172 +0,0 @@
-# `dbg(…)`
-
-[](https://travis-ci.org/sharkdp/dbg-macro) [](https://ci.appveyor.com/project/sharkdp/dbg-macro) [](https://repl.it/@sharkdp/dbg-macro-demo) [](dbg.h)
-
-*A macro for `printf`-style debugging fans.*
-
-Debuggers are great. But sometimes you just don't have the time or patience to set
-up everything correctly and just want a quick way to inspect some values at runtime.
-
-This projects provides a [single header file](dbg.h) with a `dbg(…)`
-macro that can be used in all circumstances where you would typically write
-`printf("…", …)` or `std::cout << …`. But it comes with a few extras.
-
-## Examples
-
-``` c++
-#include <vector>
-#include <dbg.h>
-
-// You can use "dbg(..)" in expressions:
-int factorial(int n) {
- if (dbg(n <= 1)) {
- return dbg(1);
- } else {
- return dbg(n * factorial(n - 1));
- }
-}
-
-int main() {
- std::string message = "hello";
- dbg(message); // [example.cpp:15 (main)] message = "hello" (std::string)
-
- const int a = 2;
- const int b = dbg(3 * a) + 1; // [example.cpp:18 (main)] 3 * a = 6 (int)
-
- std::vector<int> numbers{b, 13, 42};
- dbg(numbers); // [example.cpp:21 (main)] numbers = {7, 13, 42} (size: 3) (std::vector<int>)
-
- dbg("this line is executed"); // [example.cpp:23 (main)] this line is executed
-
- factorial(4);
-
- return 0;
-}
-```
-
-The code above produces this output ([try it yourself](https://repl.it/@sharkdp/dbg-macro-demo)):
-
-
-
-## Features
-
- * Easy to read, colorized output (colors auto-disable when the output is not an interactive terminal)
- * Prints file name, line number, function name and the original expression
- * Adds type information for the printed-out value
- * Specialized pretty-printers for containers, pointers, string literals, enums, `std::optional`, etc.
- * Can be used inside expressions (passing through the original value)
- * The `dbg.h` header issues a compiler warning when included (so you don't forget to remove it).
- * Compatible and tested with C++11, C++14 and C++17.
-
-## Installation
-
-To make this practical, the `dbg.h` header should to be readily available from all kinds of different
-places and in all kinds of environments. The quick & dirty way is to actually copy the header file
-to `/usr/include` or to clone the repository and symlink `dbg.h` to `/usr/include/dbg.h`.
-``` bash
-git clone https://github.com/sharkdp/dbg-macro
-sudo ln -s $(readlink -f dbg-macro/dbg.h) /usr/include/dbg.h
-```
-If you don't want to make untracked changes to your filesystem, check below if there is a package for
-your operating system or package manager.
-
-### On Arch Linux
-
-You can install [`dbg-macro` from the AUR](https://aur.archlinux.org/packages/dbg-macro/):
-``` bash
-yay -S dbg-macro
-```
-
-### With vcpkg
-
-You can install the [`dbg-macro` port](https://github.com/microsoft/vcpkg/tree/master/ports/dbg-macro) via:
-``` bash
-vcpkg install dbg-macro
-```
-
-## Configuration
-
-* Set the `DBG_MACRO_DISABLE` flag to disable the `dbg(…)` macro (i.e. to make it a no-op).
-* Set the `DBG_MACRO_NO_WARNING` flag to disable the *"'dbg.h' header is included in your code base"* warnings.
-
-## Advanced features
-
-### Hexadecimal, octal and binary format
-
-If you want to format integers in hexadecimal, octal or binary representation, you can
-simply wrap them in `dbg::hex(…)`, `dbg::oct(…)` or `dbg::bin(…)`:
-```c++
-const uint32_t secret = 12648430;
-dbg(dbg::hex(secret));
-```
-
-### Printing type names
-
-`dbg(…)` already prints the type for each value in parenthesis (see screenshot above). But
-sometimes you just want to print a type (maybe because you don't have a value for that type).
-In this case, you can use the `dbg::type<T>()` helper to pretty-print a given type `T`.
-For example:
-```c++
-template <typename T>
-void my_function_template() {
- using MyDependentType = typename std::remove_reference<T>::type&&;
- dbg(dbg::type<MyDependentType>());
-}
-```
-
-### Print the current time
-
-To print a timestamp, you can use the `dbg::time()` helper:
-```c++
-dbg(dbg::time());
-```
-
-### Customization
-
-If you want `dbg(…)` to work for your custom datatype, you can simply overload `operator<<` for
-`std::ostream&`:
-```c++
-std::ostream& operator<<(std::ostream& out, const user_defined_type& v) {
- out << "…";
- return out;
-}
-```
-
-If you want to modify the type name that is printed by `dbg(…)`, you can add a custom
-`get_type_name` overload:
-```c++
-// Customization point for type information
-namespace dbg {
- std::string get_type_name(type_tag<bool>) {
- return "truth value";
- }
-}
-```
-
-## Development
-
-If you want to contribute to `dbg-macro`, here is how you can build the tests and demos:
-
-Make sure that the submodule(s) are up to date:
-```bash
-git submodule update --init
-```
-
-Then, use the typical `cmake` workflow. Usage of `-DCMAKE_CXX_STANDARD=17` is optional,
-but recommended in order to have the largest set of features enabled:
-```bash
-mkdir build
-cd build
-cmake .. -DCMAKE_CXX_STANDARD=17
-make
-```
-
-To run the tests, simply call:
-```bash
-make test
-```
-You can find the unit tests in `tests/basic.cpp`.
-
-## Acknowledgement
-
-This project is inspired by Rusts [`dbg!(…)` macro](https://doc.rust-lang.org/std/macro.dbg.html).
diff --git a/deps/dbg-macro/dbg.h b/deps/dbg-macro/dbg.h
@@ -1,711 +0,0 @@
-/*****************************************************************************
-
- dbg(...) macro
-
-License (MIT):
-
- Copyright (c) 2019 David Peter <mail@david-peter.de>
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-
-*****************************************************************************/
-
-#ifndef DBG_MACRO_DBG_H
-#define DBG_MACRO_DBG_H
-
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-#define DBG_MACRO_UNIX
-#elif defined(_MSC_VER)
-#define DBG_MACRO_WINDOWS
-#endif
-
-#ifndef DBG_MACRO_NO_WARNING
-#pragma message("WARNING: the 'dbg.h' header is included in your code base")
-#endif // DBG_MACRO_NO_WARNING
-
-#include <algorithm>
-#include <chrono>
-#include <ctime>
-#include <iomanip>
-#include <ios>
-#include <iostream>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <type_traits>
-#include <vector>
-
-#ifdef DBG_MACRO_UNIX
-#include <unistd.h>
-#endif
-
-#if __cplusplus >= 201703L || defined(_MSC_VER)
-#define DBG_MACRO_CXX_STANDARD 17
-#elif __cplusplus >= 201402L
-#define DBG_MACRO_CXX_STANDARD 14
-#else
-#define DBG_MACRO_CXX_STANDARD 11
-#endif
-
-#if DBG_MACRO_CXX_STANDARD >= 17
-#include <optional>
-#include <variant>
-#endif
-
-namespace dbg {
-
-#ifdef DBG_MACRO_UNIX
-inline bool isColorizedOutputEnabled() {
- return isatty(fileno(stderr));
-}
-#else
-inline bool isColorizedOutputEnabled() {
- return true;
-}
-#endif
-
-struct time {};
-
-namespace pretty_function {
-
-// Compiler-agnostic version of __PRETTY_FUNCTION__ and constants to
-// extract the template argument in `type_name_impl`
-
-#if defined(__clang__)
-#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
-static constexpr size_t PREFIX_LENGTH =
- sizeof("const char *dbg::type_name_impl() [T = ") - 1;
-static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
-#elif defined(__GNUC__) && !defined(__clang__)
-#define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__
-static constexpr size_t PREFIX_LENGTH =
- sizeof("const char* dbg::type_name_impl() [with T = ") - 1;
-static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1;
-#elif defined(_MSC_VER)
-#define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__
-static constexpr size_t PREFIX_LENGTH =
- sizeof("const char *__cdecl dbg::type_name_impl<") - 1;
-static constexpr size_t SUFFIX_LENGTH = sizeof(">(void)") - 1;
-#else
-#error "This compiler is currently not supported by dbg_macro."
-#endif
-
-} // namespace pretty_function
-
-// Formatting helpers
-
-template <typename T>
-struct print_formatted {
- static_assert(std::is_integral<T>::value,
- "Only integral types are supported.");
-
- print_formatted(T value, int numeric_base)
- : inner(value), base(numeric_base) {}
-
- operator T() const { return inner; }
-
- const char* prefix() const {
- switch (base) {
- case 8:
- return "0o";
- case 16:
- return "0x";
- case 2:
- return "0b";
- default:
- return "";
- }
- }
-
- T inner;
- int base;
-};
-
-template <typename T>
-print_formatted<T> hex(T value) {
- return print_formatted<T>{value, 16};
-}
-
-template <typename T>
-print_formatted<T> oct(T value) {
- return print_formatted<T>{value, 8};
-}
-
-template <typename T>
-print_formatted<T> bin(T value) {
- return print_formatted<T>{value, 2};
-}
-
-// Implementation of 'type_name<T>()'
-
-template <typename T>
-const char* type_name_impl() {
- return DBG_MACRO_PRETTY_FUNCTION;
-}
-
-template <typename T>
-struct type_tag {};
-
-template <int&... ExplicitArgumentBarrier, typename T>
-std::string get_type_name(type_tag<T>) {
- namespace pf = pretty_function;
-
- std::string type = type_name_impl<T>();
- return type.substr(pf::PREFIX_LENGTH,
- type.size() - pf::PREFIX_LENGTH - pf::SUFFIX_LENGTH);
-}
-
-template <typename T>
-std::string type_name() {
- if (std::is_volatile<T>::value) {
- if (std::is_pointer<T>::value) {
- return type_name<typename std::remove_volatile<T>::type>() + " volatile";
- } else {
- return "volatile " + type_name<typename std::remove_volatile<T>::type>();
- }
- }
- if (std::is_const<T>::value) {
- if (std::is_pointer<T>::value) {
- return type_name<typename std::remove_const<T>::type>() + " const";
- } else {
- return "const " + type_name<typename std::remove_const<T>::type>();
- }
- }
- if (std::is_pointer<T>::value) {
- return type_name<typename std::remove_pointer<T>::type>() + "*";
- }
- if (std::is_lvalue_reference<T>::value) {
- return type_name<typename std::remove_reference<T>::type>() + "&";
- }
- if (std::is_rvalue_reference<T>::value) {
- return type_name<typename std::remove_reference<T>::type>() + "&&";
- }
- return get_type_name(type_tag<T>{});
-}
-
-inline std::string get_type_name(type_tag<short>) {
- return "short";
-}
-
-inline std::string get_type_name(type_tag<unsigned short>) {
- return "unsigned short";
-}
-
-inline std::string get_type_name(type_tag<long>) {
- return "long";
-}
-
-inline std::string get_type_name(type_tag<unsigned long>) {
- return "unsigned long";
-}
-
-inline std::string get_type_name(type_tag<std::string>) {
- return "std::string";
-}
-
-template <typename T>
-std::string get_type_name(type_tag<std::vector<T, std::allocator<T>>>) {
- return "std::vector<" + type_name<T>() + ">";
-}
-
-template <typename T1, typename T2>
-std::string get_type_name(type_tag<std::pair<T1, T2>>) {
- return "std::pair<" + type_name<T1>() + ", " + type_name<T2>() + ">";
-}
-
-template <typename... T>
-std::string type_list_to_string() {
- std::string result;
- auto unused = {(result += type_name<T>() + ", ", 0)..., 0};
- static_cast<void>(unused);
-
- if (sizeof...(T) > 0) {
- result.pop_back();
- result.pop_back();
- }
- return result;
-}
-
-template <typename... T>
-std::string get_type_name(type_tag<std::tuple<T...>>) {
- return "std::tuple<" + type_list_to_string<T...>() + ">";
-}
-
-template <typename T>
-inline std::string get_type_name(type_tag<print_formatted<T>>) {
- return type_name<T>();
-}
-
-// Implementation of 'is_detected' to specialize for container-like types
-
-namespace detail_detector {
-
-struct nonesuch {
- nonesuch() = delete;
- ~nonesuch() = delete;
- nonesuch(nonesuch const&) = delete;
- void operator=(nonesuch const&) = delete;
-};
-
-template <typename...>
-using void_t = void;
-
-template <class Default,
- class AlwaysVoid,
- template <class...>
- class Op,
- class... Args>
-struct detector {
- using value_t = std::false_type;
- using type = Default;
-};
-
-template <class Default, template <class...> class Op, class... Args>
-struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
- using value_t = std::true_type;
- using type = Op<Args...>;
-};
-
-} // namespace detail_detector
-
-template <template <class...> class Op, class... Args>
-using is_detected = typename detail_detector::
- detector<detail_detector::nonesuch, void, Op, Args...>::value_t;
-
-namespace detail {
-
-namespace {
-using std::begin;
-using std::end;
-#if DBG_MACRO_CXX_STANDARD < 17
-template <typename T>
-constexpr auto size(const T& c) -> decltype(c.size()) {
- return c.size();
-}
-template <typename T, std::size_t N>
-constexpr std::size_t size(const T (&)[N]) {
- return N;
-}
-#else
-using std::size;
-#endif
-} // namespace
-
-template <typename T>
-using detect_begin_t = decltype(detail::begin(std::declval<T>()));
-
-template <typename T>
-using detect_end_t = decltype(detail::end(std::declval<T>()));
-
-template <typename T>
-using detect_size_t = decltype(detail::size(std::declval<T>()));
-
-template <typename T>
-struct is_container {
- static constexpr bool value =
- is_detected<detect_begin_t, T>::value &&
- is_detected<detect_end_t, T>::value &&
- is_detected<detect_size_t, T>::value &&
- !std::is_same<std::string,
- typename std::remove_cv<
- typename std::remove_reference<T>::type>::type>::value;
-};
-
-template <typename T>
-using ostream_operator_t =
- decltype(std::declval<std::ostream&>() << std::declval<T>());
-
-template <typename T>
-struct has_ostream_operator : is_detected<ostream_operator_t, T> {};
-
-} // namespace detail
-
-// Helper to dbg(…)-print types
-template <typename T>
-struct print_type {};
-
-template <typename T>
-print_type<T> type() {
- return print_type<T>{};
-}
-
-// Specializations of "pretty_print"
-
-template <typename T>
-inline void pretty_print(std::ostream& stream, const T& value, std::true_type) {
- stream << value;
-}
-
-template <typename T>
-inline void pretty_print(std::ostream&, const T&, std::false_type) {
- static_assert(detail::has_ostream_operator<const T&>::value,
- "Type does not support the << ostream operator");
-}
-
-template <typename T>
-inline typename std::enable_if<!detail::is_container<const T&>::value &&
- !std::is_enum<T>::value,
- bool>::type
-pretty_print(std::ostream& stream, const T& value) {
- pretty_print(stream, value,
- typename detail::has_ostream_operator<const T&>::type{});
- return true;
-}
-
-inline bool pretty_print(std::ostream& stream, const bool& value) {
- stream << std::boolalpha << value;
- return true;
-}
-
-inline bool pretty_print(std::ostream& stream, const char& value) {
- const bool printable = value >= 0x20 && value <= 0x7E;
-
- if (printable) {
- stream << "'" << value << "'";
- } else {
- stream << "'\\x" << std::setw(2) << std::setfill('0') << std::hex
- << std::uppercase << (0xFF & value) << "'";
- }
- return true;
-}
-
-template <typename P>
-inline bool pretty_print(std::ostream& stream, P* const& value) {
- if (value == nullptr) {
- stream << "nullptr";
- } else {
- stream << value;
- }
- return true;
-}
-
-template <typename T, typename Deleter>
-inline bool pretty_print(std::ostream& stream,
- std::unique_ptr<T, Deleter>& value) {
- pretty_print(stream, value.get());
- return true;
-}
-
-template <typename T>
-inline bool pretty_print(std::ostream& stream, std::shared_ptr<T>& value) {
- pretty_print(stream, value.get());
- stream << " (use_count = " << value.use_count() << ")";
-
- return true;
-}
-
-template <size_t N>
-inline bool pretty_print(std::ostream& stream, const char (&value)[N]) {
- stream << value;
- return false;
-}
-
-template <>
-inline bool pretty_print(std::ostream& stream, const char* const& value) {
- stream << '"' << value << '"';
- return true;
-}
-
-template <size_t Idx>
-struct pretty_print_tuple {
- template <typename... Ts>
- static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
- pretty_print_tuple<Idx - 1>::print(stream, tuple);
- stream << ", ";
- pretty_print(stream, std::get<Idx>(tuple));
- }
-};
-
-template <>
-struct pretty_print_tuple<0> {
- template <typename... Ts>
- static void print(std::ostream& stream, const std::tuple<Ts...>& tuple) {
- pretty_print(stream, std::get<0>(tuple));
- }
-};
-
-template <typename... Ts>
-inline bool pretty_print(std::ostream& stream, const std::tuple<Ts...>& value) {
- stream << "{";
- pretty_print_tuple<sizeof...(Ts) - 1>::print(stream, value);
- stream << "}";
-
- return true;
-}
-
-template <>
-inline bool pretty_print(std::ostream& stream, const std::tuple<>&) {
- stream << "{}";
-
- return true;
-}
-
-template <>
-inline bool pretty_print(std::ostream& stream, const time&) {
- using namespace std::chrono;
-
- const auto now = system_clock::now();
- const auto us =
- duration_cast<microseconds>(now.time_since_epoch()).count() % 1000000;
- const auto hms = system_clock::to_time_t(now);
- const std::tm* tm = std::localtime(&hms);
- stream << "current time = " << std::put_time(tm, "%H:%M:%S") << '.'
- << std::setw(6) << std::setfill('0') << us;
-
- return false;
-}
-
-// Converts decimal integer to binary string
-template <typename T>
-std::string decimalToBinary(T n) {
- const size_t length = 8 * sizeof(T);
- std::string toRet;
- toRet.resize(length);
-
- for (size_t i = 0; i < length; ++i) {
- const auto bit_at_index_i = (n >> i) & 1;
- toRet[length - 1 - i] = bit_at_index_i + '0';
- }
-
- return toRet;
-}
-
-template <typename T>
-inline bool pretty_print(std::ostream& stream,
- const print_formatted<T>& value) {
- if (value.inner < 0) {
- stream << "-";
- }
- stream << value.prefix();
-
- // Print using setbase
- if (value.base != 2) {
- stream << std::setw(sizeof(T)) << std::setfill('0')
- << std::setbase(value.base) << std::uppercase;
-
- if (value.inner >= 0) {
- // The '+' sign makes sure that a uint_8 is printed as a number
- stream << +value.inner;
- } else {
- using unsigned_type = typename std::make_unsigned<T>::type;
- stream << +(static_cast<unsigned_type>(-(value.inner + 1)) + 1);
- }
- } else {
- // Print for binary
- if (value.inner >= 0) {
- stream << decimalToBinary(value.inner);
- } else {
- using unsigned_type = typename std::make_unsigned<T>::type;
- stream << decimalToBinary<unsigned_type>(
- static_cast<unsigned_type>(-(value.inner + 1)) + 1);
- }
- }
-
- return true;
-}
-
-template <typename T>
-inline bool pretty_print(std::ostream& stream, const print_type<T>&) {
- stream << type_name<T>();
-
- stream << " [sizeof: " << sizeof(T) << " byte, ";
-
- stream << "trivial: ";
- if (std::is_trivial<T>::value) {
- stream << "yes";
- } else {
- stream << "no";
- }
-
- stream << ", standard layout: ";
- if (std::is_standard_layout<T>::value) {
- stream << "yes";
- } else {
- stream << "no";
- }
- stream << "]";
-
- return false;
-}
-
-template <typename Container>
-inline typename std::enable_if<detail::is_container<const Container&>::value,
- bool>::type
-pretty_print(std::ostream& stream, const Container& value) {
- stream << "{";
- const size_t size = detail::size(value);
- const size_t n = std::min(size_t{10}, size);
- size_t i = 0;
- using std::begin;
- using std::end;
- for (auto it = begin(value); it != end(value) && i < n; ++it, ++i) {
- pretty_print(stream, *it);
- if (i != n - 1) {
- stream << ", ";
- }
- }
-
- if (size > n) {
- stream << ", ...";
- stream << " size:" << size;
- }
-
- stream << "}";
- return true;
-}
-
-template <typename Enum>
-inline typename std::enable_if<std::is_enum<Enum>::value, bool>::type
-pretty_print(std::ostream& stream, Enum const& value) {
- using UnderlyingType = typename std::underlying_type<Enum>::type;
- stream << static_cast<UnderlyingType>(value);
-
- return true;
-}
-
-inline bool pretty_print(std::ostream& stream, const std::string& value) {
- stream << '"' << value << '"';
- return true;
-}
-
-template <typename T1, typename T2>
-inline bool pretty_print(std::ostream& stream, const std::pair<T1, T2>& value) {
- stream << "{";
- pretty_print(stream, value.first);
- stream << ", ";
- pretty_print(stream, value.second);
- stream << "}";
- return true;
-}
-
-#if DBG_MACRO_CXX_STANDARD >= 17
-
-template <typename T>
-inline bool pretty_print(std::ostream& stream, const std::optional<T>& value) {
- if (value) {
- stream << '{';
- pretty_print(stream, *value);
- stream << '}';
- } else {
- stream << "nullopt";
- }
-
- return true;
-}
-
-template <typename... Ts>
-inline bool pretty_print(std::ostream& stream,
- const std::variant<Ts...>& value) {
- stream << "{";
- std::visit([&stream](auto&& arg) { pretty_print(stream, arg); }, value);
- stream << "}";
-
- return true;
-}
-
-#endif
-
-class DebugOutput {
- public:
- DebugOutput(const char* filepath,
- int line,
- const char* function_name,
- const char* expression)
- : m_use_colorized_output(isColorizedOutputEnabled()),
- m_filepath(filepath),
- m_line(line),
- m_function_name(function_name),
- m_expression(expression) {
- const std::size_t path_length = m_filepath.length();
- if (path_length > MAX_PATH_LENGTH) {
- m_filepath = ".." + m_filepath.substr(path_length - MAX_PATH_LENGTH,
- MAX_PATH_LENGTH);
- }
- }
-
- template <typename T>
- T&& print(const std::string& type, T&& value) const {
- const T& ref = value;
- std::stringstream stream_value;
- const bool print_expr_and_type = pretty_print(stream_value, ref);
-
- std::stringstream output;
- output << ansi(ANSI_DEBUG) << "[" << m_filepath << ":" << m_line << " ("
- << m_function_name << ")] " << ansi(ANSI_RESET);
- if (print_expr_and_type) {
- output << ansi(ANSI_EXPRESSION) << m_expression << ansi(ANSI_RESET)
- << " = ";
- }
- output << ansi(ANSI_VALUE) << stream_value.str() << ansi(ANSI_RESET);
- if (print_expr_and_type) {
- output << " (" << ansi(ANSI_TYPE) << type << ansi(ANSI_RESET) << ")";
- }
- output << std::endl;
- std::cerr << output.str();
-
- return std::forward<T>(value);
- }
-
- private:
- const char* ansi(const char* code) const {
- if (m_use_colorized_output) {
- return code;
- } else {
- return ANSI_EMPTY;
- }
- }
-
- const bool m_use_colorized_output;
-
- std::string m_filepath;
- const int m_line;
- const std::string m_function_name;
- const std::string m_expression;
-
- static constexpr std::size_t MAX_PATH_LENGTH = 20;
-
- static constexpr const char* const ANSI_EMPTY = "";
- static constexpr const char* const ANSI_DEBUG = "\x1b[02m";
- static constexpr const char* const ANSI_EXPRESSION = "\x1b[36m";
- static constexpr const char* const ANSI_VALUE = "\x1b[01m";
- static constexpr const char* const ANSI_TYPE = "\x1b[32m";
- static constexpr const char* const ANSI_RESET = "\x1b[0m";
-};
-
-// Identity function to suppress "-Wunused-value" warnings in DBG_MACRO_DISABLE
-// mode
-template <typename T>
-T&& identity(T&& t) {
- return std::forward<T>(t);
-}
-
-} // namespace dbg
-
-#ifndef DBG_MACRO_DISABLE
-// We use a variadic macro to support commas inside expressions (e.g.
-// initializer lists):
-#define dbg(...) \
- dbg::DebugOutput(__FILE__, __LINE__, __func__, #__VA_ARGS__) \
- .print(dbg::type_name<decltype(__VA_ARGS__)>(), (__VA_ARGS__))
-#else
-#define dbg(...) dbg::identity(__VA_ARGS__)
-#endif // DBG_MACRO_DISABLE
-
-#endif // DBG_MACRO_DBG_H
diff --git a/lib/libc/mingw/lib32/user32.def b/lib/libc/mingw/lib32/user32.def
@@ -0,0 +1,998 @@
+LIBRARY USER32.dll
+EXPORTS
+;ord_1500@16 @1500
+;ord_1501@4 @1501
+;ord_1502@12 @1502
+ActivateKeyboardLayout@8
+AddClipboardFormatListener@4
+AdjustWindowRect@12
+AdjustWindowRectEx@16
+AlignRects@16
+AllowForegroundActivation@0
+AllowSetForegroundWindow@4
+AnimateWindow@12
+AnyPopup@0
+AppendMenuA@16
+AppendMenuW@16
+ArrangeIconicWindows@4
+AttachThreadInput@12
+BeginDeferWindowPos@4
+BeginPaint@8
+BlockInput@4
+BringWindowToTop@4
+BroadcastSystemMessage@20
+BroadcastSystemMessageA@20
+BroadcastSystemMessageExA@24
+BroadcastSystemMessageExW@24
+BroadcastSystemMessageW@20
+BuildReasonArray@12
+CalcChildScroll@8
+CalcMenuBar@20
+CalculatePopupWindowPosition@20
+CallMsgFilter@8
+CallMsgFilterA@8
+CallMsgFilterW@8
+CallNextHookEx@16
+CallWindowProcA@20
+CallWindowProcW@20
+CancelShutdown@0
+CascadeChildWindows@8
+CascadeWindows@20
+ChangeClipboardChain@8
+ChangeDisplaySettingsA@8
+ChangeDisplaySettingsExA@20
+ChangeDisplaySettingsExW@20
+ChangeDisplaySettingsW@8
+ChangeMenuA@20
+ChangeMenuW@20
+ChangeWindowMessageFilter@8
+ChangeWindowMessageFilterEx@16
+CharLowerA@4
+CharLowerBuffA@8
+CharLowerBuffW@8
+CharLowerW@4
+CharNextA@4
+;ord_1550@12 @1550
+;ord_1551@8 @1551
+;ord_1552@8 @1552
+;ord_1553@12 @1553
+;ord_1554@8 @1554
+;ord_1555@16 @1555
+;ord_1556@4 @1556
+CharNextExA@12
+CharNextW@4
+CharPrevA@8
+CharPrevExA@16
+CharPrevW@8
+CharToOemA@8
+CharToOemBuffA@12
+CharToOemBuffW@12
+CharToOemW@8
+CharUpperA@4
+CharUpperBuffA@8
+CharUpperBuffW@8
+CharUpperW@4
+CheckDesktopByThreadId@4
+CheckDBCSEnabledExt@0
+CheckDlgButton@12
+CheckMenuItem@12
+CheckMenuRadioItem@20
+CheckProcessForClipboardAccess@8
+CheckProcessSession@4
+CheckRadioButton@16
+CheckWindowThreadDesktop@8
+ChildWindowFromPoint@12
+ChildWindowFromPointEx@16
+CliImmSetHotKey@16
+ClientThreadSetup@0
+ClientToScreen@8
+ClipCursor@4
+CloseClipboard@0
+CloseDesktop@4
+CloseGestureInfoHandle@4
+CloseTouchInputHandle@4
+CloseWindow@4
+CloseWindowStation@4
+ConsoleControl@12
+ControlMagnification@8
+CopyAcceleratorTableA@12
+CopyAcceleratorTableW@12
+CopyIcon@4
+CopyImage@20
+CopyRect@8
+CountClipboardFormats@0
+CreateAcceleratorTableA@8
+CreateAcceleratorTableW@8
+CreateCaret@16
+CreateCursor@28
+CreateDCompositionHwndTarget@12
+CreateDesktopA@24
+CreateDesktopExA@32
+CreateDesktopExW@32
+CreateDesktopW@24
+CreateDialogIndirectParamA@20
+CreateDialogIndirectParamAorW@24
+CreateDialogIndirectParamW@20
+CreateDialogParamA@20
+CreateDialogParamW@20
+CreateIcon@28
+CreateIconFromResource@16
+CreateIconFromResourceEx@28
+CreateIconIndirect@4
+CreateMDIWindowA@40
+CreateMDIWindowW@40
+CreateMenu@0
+CreatePopupMenu@0
+CreateSystemThreads@16 ; ReactOS has the @8 variant
+CreateWindowExA@48
+CreateWindowExW@48
+CreateWindowInBand@52
+CreateWindowIndirect@4
+CreateWindowStationA@16
+CreateWindowStationW@16
+CsrBroadcastSystemMessageExW@24
+CtxInitUser32@0
+DdeAbandonTransaction@12
+DdeAccessData@8
+DdeAddData@16
+DdeClientTransaction@32
+DdeCmpStringHandles@8
+DdeConnect@16
+DdeConnectList@20
+DdeCreateDataHandle@28
+DdeCreateStringHandleA@12
+DdeCreateStringHandleW@12
+DdeDisconnect@4
+DdeDisconnectList@4
+DdeEnableCallback@12
+DdeFreeDataHandle@4
+DdeFreeStringHandle@8
+DdeGetData@16
+DdeGetLastError@4
+DdeGetQualityOfService@12
+DdeImpersonateClient@4
+DdeInitializeA@16
+DdeInitializeW@16
+DdeKeepStringHandle@8
+DdeNameService@16
+DdePostAdvise@12
+DdeQueryConvInfo@12
+DdeQueryNextServer@8
+DdeQueryStringA@20
+DdeQueryStringW@20
+DdeReconnect@4
+DdeSetQualityOfService@12
+DdeSetUserHandle@12
+DdeUnaccessData@4
+DdeUninitialize@4
+DefDlgProcA@16
+DefDlgProcW@16
+DefFrameProcA@20
+DefFrameProcW@20
+DefMDIChildProcA@16
+DefMDIChildProcW@16
+DefRawInputProc@12
+DefWindowProcA@16
+DefWindowProcW@16
+DeferWindowPos@32
+DeferWindowPosAndBand@36
+DeleteMenu@12
+DeregisterShellHookWindow@4
+DestroyAcceleratorTable@4
+DestroyCaret@0
+DestroyCursor@4
+DestroyDCompositionHwndTarget@8
+DestroyIcon@4
+DestroyMenu@4
+DestroyReasons@4
+DestroyWindow@4
+DeviceEventWorker@24 ; No documentation whatsoever, ReactOS has a stub with @20 - https://www.reactos.org/archives/public/ros-diffs/2011-February/040308.html
+DialogBoxIndirectParamA@20
+DialogBoxIndirectParamAorW@24
+DialogBoxIndirectParamW@20
+DialogBoxParamA@20
+DialogBoxParamW@20
+DisableProcessWindowsGhosting@0
+DispatchMessageA@4
+DispatchMessageW@4
+DisplayConfigGetDeviceInfo@4
+DisplayConfigSetDeviceInfo@4
+DisplayExitWindowsWarnings@4
+DlgDirListA@20
+DlgDirListComboBoxA@20
+DlgDirListComboBoxW@20
+DlgDirListW@20
+DlgDirSelectComboBoxExA@16
+DlgDirSelectComboBoxExW@16
+DlgDirSelectExA@16
+DlgDirSelectExW@16
+DoSoundConnect@0
+DoSoundDisconnect@0
+DragDetect@12
+DragObject@20
+DrawAnimatedRects@16
+DrawCaption@16
+DrawCaptionTempA@28
+DrawCaptionTempW@28
+DrawEdge@16
+DrawFocusRect@8
+DrawFrame@16
+DrawFrameControl@16
+DrawIcon@16
+DrawIconEx@36
+DrawMenuBar@4
+DrawMenuBarTemp@20
+DrawStateA@40
+DrawStateW@40
+DrawTextA@20
+DrawTextExA@24
+DrawTextExW@24
+DrawTextW@20
+DwmGetDxSharedSurface@24
+DwmGetRemoteSessionOcclusionEvent@0
+DwmGetRemoteSessionOcclusionState@0
+DwmLockScreenUpdates@4
+DwmStartRedirection@8 ; Mentioned on http://habrahabr.ru/post/145174/ , enables GDI virtualization (for security purposes)
+DwmStopRedirection@0
+DwmValidateWindow@8
+EditWndProc@16
+EmptyClipboard@0
+EnableMenuItem@12
+EnableMouseInPointer@4
+EnableScrollBar@12
+EnableSessionForMMCSS@4
+EnableWindow@8
+EndDeferWindowPos@4
+EndDeferWindowPosEx@8
+EndDialog@8
+EndMenu@0
+EndPaint@8
+EndTask@12
+EnterReaderModeHelper@4
+EnumChildWindows@12
+EnumClipboardFormats@4
+EnumDesktopWindows@12
+EnumDesktopsA@12
+EnumDesktopsW@12
+EnumDisplayDevicesA@16
+EnumDisplayDevicesW@16
+EnumDisplayMonitors@16
+EnumDisplaySettingsA@12
+EnumDisplaySettingsExA@16
+EnumDisplaySettingsExW@16
+EnumDisplaySettingsW@12
+EnumPropsA@8
+EnumPropsExA@12
+EnumPropsExW@12
+EnumPropsW@8
+EnumThreadWindows@12
+EnumWindowStationsA@8
+EnumWindowStationsW@8
+EnumWindows@8
+EqualRect@8
+EvaluateProximityToPolygon@16
+EvaluateProximityToRect@12
+ExcludeUpdateRgn@8
+ExitWindowsEx@8
+FillRect@12
+FindWindowA@8
+FindWindowExA@16
+FindWindowExW@16
+FindWindowW@8
+FlashWindow@8
+FlashWindowEx@4
+FrameRect@12
+FreeDDElParam@8
+FrostCrashedWindow@8
+GetActiveWindow@0
+GetAltTabInfo@20
+GetAltTabInfoA@20
+GetAltTabInfoW@20
+GetAncestor@8
+GetAppCompatFlags2@4
+GetAppCompatFlags@8 ; ReactOS has @4 version http://doxygen.reactos.org/d9/d71/undocuser_8h_a9b76cdc68c523a061c86a40367049ed2.html
+GetAsyncKeyState@4
+GetAutoRotationState@4
+GetCIMSSM@4
+GetCapture@0
+GetCaretBlinkTime@0
+GetCaretPos@4
+GetClassInfoA@12
+GetClassInfoExA@12
+GetClassInfoExW@12
+GetClassInfoW@12
+GetClassLongA@8
+GetClassLongW@8
+GetClassNameA@12
+GetClassNameW@12
+GetClassWord@8
+GetClientRect@8
+GetClipCursor@4
+GetClipboardAccessToken@8
+GetClipboardData@4
+GetClipboardFormatNameA@12
+GetClipboardFormatNameW@12
+GetClipboardOwner@0
+GetClipboardSequenceNumber@0
+GetClipboardViewer@0
+GetComboBoxInfo@8
+GetCurrentInputMessageSource@4
+GetCursor@0
+GetCursorFrameInfo@20
+GetCursorInfo@4
+GetCursorPos@4
+GetDC@4
+GetDCEx@12
+GetDesktopID@8
+GetDesktopWindow@0
+GetDialogBaseUnits@0
+GetDisplayAutoRotationPreferences@4
+GetDisplayConfigBufferSizes@12
+GetDlgCtrlID@4
+GetDlgItem@8
+GetDlgItemInt@16
+GetDlgItemTextA@16
+GetDlgItemTextW@16
+GetDoubleClickTime@0
+GetDpiForMonitorInternal@16
+GetFocus@0
+GetForegroundWindow@0
+GetGUIThreadInfo@8
+GetGestureConfig@24
+GetGestureExtraArgs@12
+GetGestureInfo@8
+GetGuiResources@8
+GetIconInfo@8
+GetIconInfoExA@8
+GetIconInfoExW@8
+GetInputDesktop@0
+GetInputLocaleInfo@8
+GetInputState@0
+GetInternalWindowPos@12
+GetKBCodePage@0
+GetKeyNameTextA@12
+GetKeyNameTextW@12
+GetKeyState@4
+GetKeyboardLayout@4
+GetKeyboardLayoutList@8
+GetKeyboardLayoutNameA@4
+GetKeyboardLayoutNameW@4
+GetKeyboardState@4
+GetKeyboardType@4
+GetLastActivePopup@4
+GetLastInputInfo@4
+GetLayeredWindowAttributes@16
+GetListBoxInfo@4
+GetMagnificationDesktopColorEffect@4
+GetMagnificationDesktopMagnification@12
+GetMagnificationLensCtxInformation@16
+GetMenu@4
+GetMenuBarInfo@16
+GetMenuCheckMarkDimensions@0
+GetMenuContextHelpId@4
+GetMenuDefaultItem@12
+GetMenuInfo@8
+GetMenuItemCount@4
+GetMenuItemID@8
+GetMenuItemInfoA@16
+GetMenuItemInfoW@16
+GetMenuItemRect@16
+GetMenuState@12
+GetMenuStringA@20
+GetMenuStringW@20
+GetMessageA@16
+GetMessageExtraInfo@0
+GetMessagePos@0
+GetMessageTime@0
+GetMessageW@16
+GetMonitorInfoA@8
+GetMonitorInfoW@8
+GetMouseMovePointsEx@20
+GetNextDlgGroupItem@12
+GetNextDlgTabItem@12
+GetOpenClipboardWindow@0
+GetParent@4
+GetPhysicalCursorPos@4
+GetPointerCursorId@8
+GetPointerDevice@8
+GetPointerDeviceCursors@12
+GetPointerDeviceProperties@12
+GetPointerDeviceRects@12
+GetPointerDevices@8
+GetPointerFrameInfo@12
+GetPointerFrameInfoHistory@16
+GetPointerFramePenInfo@12
+GetPointerFramePenInfoHistory@16
+GetPointerFrameTouchInfo@12
+GetPointerFrameTouchInfoHistory@16
+GetPointerInfo@8
+GetPointerInfoHistory@12
+GetPointerInputTransform@12
+GetPointerPenInfo@8
+GetPointerPenInfoHistory@12
+GetPointerTouchInfo@8
+GetPointerTouchInfoHistory@12
+GetPointerType@8
+GetPriorityClipboardFormat@8
+GetProcessDefaultLayout@4
+GetProcessDpiAwarenessInternal@8
+GetProcessWindowStation@0
+GetProgmanWindow@0
+GetPropA@8
+GetPropW@8
+GetQueueStatus@4
+GetRawInputBuffer@12
+GetRawInputData@20
+GetRawInputDeviceInfoA@16
+GetRawInputDeviceInfoW@16
+GetRawInputDeviceList@12
+GetRawPointerDeviceData@20
+GetReasonTitleFromReasonCode@12
+GetRegisteredRawInputDevices@12
+GetQueueStatus@4
+GetScrollBarInfo@12
+GetScrollInfo@12
+GetScrollPos@8
+GetScrollRange@16
+GetSendMessageReceiver@4
+GetShellWindow@0
+GetSubMenu@8
+GetSysColor@4
+GetSysColorBrush@4
+GetSystemMenu@8
+GetSystemMetrics@4
+GetTabbedTextExtentA@20
+GetTabbedTextExtentW@20
+GetTaskmanWindow@0
+GetThreadDesktop@4
+GetTitleBarInfo@8
+GetTopLevelWindow@4
+GetTopWindow@4
+GetTouchInputInfo@16
+GetUnpredictedMessagePos@0
+GetUpdateRect@12
+GetUpdateRgn@12
+GetUpdatedClipboardFormats@12
+GetUserObjectInformationA@20
+GetUserObjectInformationW@20
+GetUserObjectSecurity@20
+GetWinStationInfo@4
+GetWindow@8
+GetWindowBand@8
+GetWindowCompositionAttribute@8
+GetWindowCompositionInfo@8
+GetWindowContextHelpId@4
+GetWindowDC@4
+GetWindowDisplayAffinity@8
+GetWindowFeedbackSetting@20
+GetWindowInfo@8
+GetWindowLongA@8
+GetWindowLongW@8
+GetWindowMinimizeRect@8
+GetWindowModuleFileName@12
+GetWindowModuleFileNameA@12
+GetWindowModuleFileNameW@12
+GetWindowPlacement@8
+GetWindowRect@8
+GetWindowRgn@8
+GetWindowRgnBox@8
+GetWindowRgnEx@12
+GetWindowTextA@12
+GetWindowTextLengthA@4
+GetWindowTextLengthW@4
+GetWindowTextW@12
+GetWindowThreadProcessId@8
+GetWindowWord@8
+GhostWindowFromHungWindow@4
+GrayStringA@36
+GrayStringW@36
+HideCaret@4
+HiliteMenuItem@16
+HungWindowFromGhostWindow@4
+IMPGetIMEA@8
+IMPGetIMEW@8
+IMPQueryIMEA@4
+IMPQueryIMEW@4
+IMPSetIMEA@8
+IMPSetIMEW@8
+ImpersonateDdeClientWindow@8
+InSendMessage@0
+InSendMessageEx@4
+InflateRect@12
+InitializeLpkHooks@4
+InitializeWin32EntryTable@4
+InitializeTouchInjection@8
+InjectTouchInput@8
+InsertMenuA@20
+InsertMenuItemA@16
+InsertMenuItemW@16
+InsertMenuW@20
+InternalGetWindowIcon@8
+;ord_2001@4 @2001
+;ord_2002@4 @2002
+InternalGetWindowText@12
+IntersectRect@12
+;ord_2005@4 @2005
+InvalidateRect@12
+InvalidateRgn@12
+InvertRect@8
+IsCharAlphaA@4
+;ord_2010@16 @2010
+IsCharAlphaNumericA@4
+IsCharAlphaNumericW@4
+IsCharAlphaW@4
+IsCharLowerA@4
+IsCharLowerW@4
+IsCharUpperA@4
+IsCharUpperW@4
+IsChild@8
+IsClipboardFormatAvailable@4
+IsDialogMessage@8
+IsDialogMessageA@8
+IsDialogMessageW@8
+IsDlgButtonChecked@8
+IsGUIThread@4
+IsHungAppWindow@4
+IsIconic@4
+IsImmersiveProcess@4
+IsInDesktopWindowBand@4
+IsMenu@4
+IsProcess16Bit@0
+IsMouseInPointerEnabled@0
+IsProcessDPIAware@0
+IsQueueAttached@0
+IsRectEmpty@4
+IsSETEnabled@0
+IsServerSideWindow@4
+IsThreadDesktopComposited@0
+IsTopLevelWindow@4
+IsTouchWindow@8
+IsWinEventHookInstalled@4
+IsWindow@4
+IsWindowEnabled@4
+IsWindowInDestroy@4
+IsWindowRedirectedForPrint@4
+IsWindowUnicode@4
+IsWindowVisible@4
+IsWow64Message@0
+IsZoomed@4
+KillSystemTimer@8
+KillTimer@8
+LoadAcceleratorsA@8
+LoadAcceleratorsW@8
+LoadBitmapA@8
+LoadBitmapW@8
+LoadCursorA@8
+LoadCursorFromFileA@4
+LoadCursorFromFileW@4
+;ord_2000@0 @2000
+;ord_2001@4 @2001
+;ord_2002@4 @2002
+LoadCursorW@8
+LoadIconA@8
+;ord_2005@4 @2005
+LoadIconW@8
+LoadImageA@24
+LoadImageW@24
+LoadKeyboardLayoutA@8
+LoadKeyboardLayoutEx@12
+LoadKeyboardLayoutW@8
+LoadLocalFonts@0
+LoadMenuA@8
+LoadMenuIndirectA@4
+LoadMenuIndirectW@4
+LoadMenuW@8
+LoadRemoteFonts@0
+LoadStringA@16
+LoadStringW@16
+LockSetForegroundWindow@4
+LockWindowStation@4
+LockWindowUpdate@4
+LockWorkStation@0
+LogicalToPhysicalPoint@8
+LogicalToPhysicalPointForPerMonitorDPI@8
+LookupIconIdFromDirectory@8
+LookupIconIdFromDirectoryEx@20
+MBToWCSEx@24
+MBToWCSExt@20
+MB_GetString@4
+MapDialogRect@8
+MapVirtualKeyA@8
+MapVirtualKeyExA@12
+MapVirtualKeyExW@12
+MapVirtualKeyW@8
+MapWindowPoints@16
+MenuItemFromPoint@16
+MenuWindowProcA@20
+MenuWindowProcW@20
+MessageBeep@4
+MessageBoxA@16
+MessageBoxExA@20
+MessageBoxExW@20
+MessageBoxIndirectA@4
+MessageBoxIndirectW@4
+MessageBoxTimeoutA@24
+MessageBoxTimeoutW@24
+MessageBoxW@16
+ModifyMenuA@20
+ModifyMenuW@20
+MonitorFromPoint@12
+MonitorFromRect@8
+MonitorFromWindow@8
+MoveWindow@24
+MsgWaitForMultipleObjects@20
+MsgWaitForMultipleObjectsEx@20
+NotifyOverlayWindow@8
+NotifyWinEvent@16
+OemKeyScan@4
+OemToCharA@8
+OemToCharBuffA@12
+OemToCharBuffW@12
+OemToCharW@8
+OffsetRect@12
+OpenClipboard@4
+OpenDesktopA@16
+OpenDesktopW@16
+OpenIcon@4
+OpenInputDesktop@12
+OpenThreadDesktop@16
+OpenWindowStationA@12
+OpenWindowStationW@12
+PackDDElParam@12
+PackTouchHitTestingProximityEvaluation@8
+PaintDesktop@4
+PaintMenuBar@24
+PaintMonitor@12
+PeekMessageA@20
+PeekMessageW@20
+PhysicalToLogicalPoint@8
+PhysicalToLogicalPointForPerMonitorDPI@8
+PostMessageA@16
+PostMessageW@16
+PostQuitMessage@4
+PostThreadMessageA@16
+PostThreadMessageW@16
+PrintWindow@12
+PrivateExtractIconExA@20
+PrivateExtractIconExW@20
+PrivateExtractIconsA@32
+PrivateExtractIconsW@32
+PrivateSetDbgTag@8
+PrivateSetRipFlags@8
+PrivateRegisterICSProc@4
+PtInRect@12
+QueryBSDRWindow@0
+QueryDisplayConfig@24
+QuerySendMessage@4
+QueryUserCounters@20
+RealChildWindowFromPoint@12
+RealGetWindowClass@12
+RealGetWindowClassA@12
+RealGetWindowClassW@12
+ReasonCodeNeedsBugID@4
+ReasonCodeNeedsComment@4
+RecordShutdownReason@4
+RedrawWindow@16
+RegisterBSDRWindow@8
+RegisterClassA@4
+RegisterClassExA@4
+RegisterClassExW@4
+RegisterClassW@4
+RegisterClipboardFormatA@4
+RegisterClipboardFormatW@4
+RegisterDeviceNotificationA@12
+RegisterDeviceNotificationW@12
+RegisterErrorReportingDialog@8
+RegisterFrostWindow@8
+RegisterGhostWindow@8
+RegisterHotKey@16
+RegisterPowerSettingNotification@12
+RegisterLogonProcess@8
+RegisterMessagePumpHook@4
+RegisterPointerDeviceNotifications@8
+RegisterPointerInputTarget@8
+RegisterPowerSettingNotification@12
+RegisterRawInputDevices@12
+RegisterServicesProcess@4
+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
+RegisterShellHookWindow@4
+RegisterSuspendResumeNotification@8
+RegisterSystemThread@8
+RegisterTasklist@4
+RegisterTouchHitTestingWindow@8
+RegisterTouchWindow@8
+RegisterUserApiHook@4 ; Prototype changed in 2003 - https://www.reactos.org/wiki/Techwiki:RegisterUserApiHook
+RegisterWindowMessageA@4
+RegisterWindowMessageW@4
+ReleaseCapture@0
+ReleaseDC@8
+RemoveClipboardFormatListener@4
+RemoveMenu@12
+RemovePropA@8
+RemovePropW@8
+ReplyMessage@4
+ResolveDesktopForWOW@4
+ReuseDDElParam@20
+ScreenToClient@8
+ScrollChildren@12
+ScrollDC@28
+ScrollWindow@20
+ScrollWindowEx@32
+SendDlgItemMessageA@20
+SendDlgItemMessageW@20
+SendIMEMessageExA@8
+SendIMEMessageExW@8
+SendInput@12
+SendMessageA@16
+SendMessageCallbackA@24
+SendMessageCallbackW@24
+SendMessageTimeoutA@28
+SendMessageTimeoutW@28
+SendMessageW@16
+SendNotifyMessageA@16
+SendNotifyMessageW@16
+SetActiveWindow@4
+SetCapture@4
+SetCaretBlinkTime@4
+SetCaretPos@8
+SetClassLongA@12
+SetClassLongW@12
+SetClassWord@12
+SetClipboardData@8
+SetClipboardViewer@4
+SetConsoleReserveKeys@8
+SetCoalescableTimer@20
+SetCursor@4
+SetCursorContents@8
+SetCursorPos@8
+SetDebugErrorLevel@4
+SetDeskWallpaper@4
+SetDisplayAutoRotationPreferences@4
+SetDisplayConfig@20
+SetDlgItemInt@16
+SetDlgItemTextA@12
+SetDlgItemTextW@12
+SetDoubleClickTime@4
+SetFocus@4
+SetForegroundWindow@4
+SetGestureConfig@20
+SetImmersiveBackgroundWindow@4
+SetInternalWindowPos@16
+SetKeyboardState@4
+SetLastErrorEx@8
+SetLayeredWindowAttributes@16
+SetLogonNotifyWindow@4
+SetMagnificationDesktopColorEffect@4
+SetMagnificationDesktopMagnification@16
+SetMagnificationLensCtxInformation@16
+SetMenu@8
+SetMenuContextHelpId@8
+SetMenuDefaultItem@12
+SetMenuInfo@8
+SetMenuItemBitmaps@20
+SetMenuItemInfoA@16
+SetMenuItemInfoW@16
+SetMessageExtraInfo@4
+SetMessageQueue@4
+SetMirrorRendering@8
+SetParent@8
+SetPhysicalCursorPos@8
+SetProcessDPIAware@0
+SetProcessDefaultLayout@4
+SetProcessDpiAwarenessInternal@4
+SetProcessRestrictionExemption@4
+SetProcessWindowStation@4
+SetProgmanWindow@4
+SetPropA@12
+SetPropW@12
+SetRect@20
+SetRectEmpty@4
+SetScrollInfo@16
+SetScrollPos@16
+SetScrollRange@20
+SetShellWindow@4
+SetShellWindowEx@8
+SetSysColors@12
+SetSysColorsTemp@12
+SetSystemCursor@8
+SetSystemMenu@8
+SetSystemTimer@16
+SetTaskmanWindow@4
+SetThreadDesktop@4
+SetThreadInputBlocked@8
+SetTimer@16
+SetUserObjectInformationA@16
+SetUserObjectInformationW@16
+SetUserObjectSecurity@12
+SetWinEventHook@28
+SetWindowBand@12
+SetWindowCompositionAttribute@8
+SetWindowCompositionTransition@28
+SetWindowContextHelpId@8
+SetWindowDisplayAffinity@8
+SetWindowFeedbackSetting@20
+SetWindowLongA@12
+SetWindowLongW@12
+SetWindowPlacement@8
+SetWindowPos@28
+SetWindowRgn@12
+SetWindowRgnEx@12
+SetWindowStationUser@16
+SetWindowTextA@8
+SetWindowTextW@8
+SetWindowWord@12
+SetWindowsHookA@8
+SetWindowsHookExA@16
+SetWindowsHookExW@16
+SetWindowsHookW@8
+SfmDxBindSwapChain@12
+SfmDxGetSwapChainStats@8
+SfmDxOpenSwapChain@16
+SfmDxQuerySwapChainBindingStatus@12
+SfmDxReleaseSwapChain@8
+SfmDxReportPendingBindingsToDwm@0
+SfmDxSetSwapChainBindingStatus@8
+SfmDxSetSwapChainStats@8
+ShowCaret@4
+ShowCursor@4
+ShowOwnedPopups@8
+ShowScrollBar@12
+ShowStartGlass@4
+ShowSystemCursor@4
+ShowWindow@8
+ShowWindowAsync@8
+ShutdownBlockReasonCreate@8
+ShutdownBlockReasonDestroy@4
+ShutdownBlockReasonQuery@12
+SignalRedirectionStartComplete@0
+SkipPointerFrameMessages@4
+SoftModalMessageBox@4
+SoundSentry@0
+SubtractRect@12
+SwapMouseButton@4
+SwitchDesktop@4
+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/
+SwitchToThisWindow@8
+SystemParametersInfoA@16
+SystemParametersInfoW@16
+TabbedTextOutA@32
+TabbedTextOutW@32
+TileChildWindows@8
+TileWindows@20
+ToAscii@20
+ToAsciiEx@24
+ToUnicode@24
+ToUnicodeEx@28
+TrackMouseEvent@4
+TrackPopupMenu@28
+TrackPopupMenuEx@24
+TranslateAccelerator@12
+TranslateAcceleratorA@12
+TranslateAcceleratorW@12
+TranslateMDISysAccel@8
+TranslateMessage@4
+TranslateMessageEx@8
+UnhookWinEvent@4
+UnhookWindowsHook@8
+UnhookWindowsHookEx@4
+UnionRect@12
+UnloadKeyboardLayout@4
+UnlockWindowStation@4
+UnpackDDElParam@16
+UnregisterClassA@8
+UnregisterClassW@8
+UnregisterDeviceNotification@4
+UnregisterHotKey@8
+UnregisterMessagePumpHook@0
+UnregisterPointerInputTarget@8
+UnregisterPowerSettingNotification@4
+UnregisterSessionPort@0
+UnregisterSuspendResumeNotification@4
+UnregisterTouchWindow@4
+UnregisterUserApiHook@0
+UpdateDefaultDesktopThumbnail@20
+UpdateLayeredWindow@36
+UpdateLayeredWindowIndirect@8
+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
+UpdateWindow@4
+UpdateWindowInputSinkHints@8
+UpdateWindowTransform@12
+User32InitializeImmEntryTable@4
+UserClientDllInitialize@12
+UserHandleGrantAccess@12
+UserLpkPSMTextOut@24
+UserLpkTabbedTextOut@48
+UserRealizePalette@4
+UserRegisterWowHandlers@8
+VRipOutput@0
+VTagOutput@0
+ValidateRect@8
+ValidateRgn@8
+VkKeyScanA@4
+VkKeyScanExA@8
+VkKeyScanExW@8
+VkKeyScanW@4
+WCSToMBEx@24
+WINNLSEnableIME@8
+WINNLSGetEnableStatus@4
+WINNLSGetIMEHotkey@4
+WaitForInputIdle@8
+WaitForRedirectionStartComplete@0
+WaitMessage@0
+Win32PoolAllocationStats@24
+WinHelpA@16
+WinHelpW@16
+WindowFromDC@4
+WindowFromPhysicalPoint@8
+WindowFromPoint@8
+_UserTestTokenForInteractive@8
+gSharedInfo DATA
+gapfnScSendMessage DATA
+keybd_event@16
+mouse_event@20
+wsprintfA
+wsprintfW
+wvsprintfA@12
+wvsprintfW@12
+;ord_2500@16 @2500
+;ord_2501@12 @2501
+;ord_2502@8 @2502
+;ord_2503@24 @2503
+;ord_2504@8 @2504
+;ord_2505@8 @2505
+;ord_2506@12 @2506
+;ord_2507@4 @2507
+;ord_2508@8 @2508
+;ord_2509@4 @2509
+;ord_2510@12 @2510
+;ord_2511@8 @2511
+;ord_2512@12 @2512
+;ord_2513@4 @2513
+;ord_2514@8 @2514
+;ord_2515@8 @2515
+;ord_2516@12 @2516
+;ord_2517@4 @2517
+;ord_2518@0 @2518
+;ord_2519@4 @2519
+;ord_2520@0 @2520
+;ord_2521@8 @2521
+;ord_2522@4 @2522
+;ord_2523@8 @2523
+;ord_2524@8 @2524
+;ord_2525@12 @2525
+;ord_2526@12 @2526
+;ord_2527@12 @2527
+IsThreadMessageQueueAttached@4
+;ord_2529@4 @2529
+;ord_2530@8 @2530
+;ord_2531@16 @2531
+;ord_2532@8 @2532
+;ord_2533@4 @2533
+;ord_2534@8 @2534
+;ord_2535@0 @2535
+;ord_2536@8 @2536
+;ord_2537@16 @2537
+;ord_2538@4 @2538
+;ord_2539@4 @2539
+;ord_2540@4 @2540
+;ord_2541@0 @2541
+;ord_2544@4 @2544
+;ord_2545@8 @2545
+;ord_2546@4 @2546
+;ord_2547@4 @2547
+;ord_2548@4 @2548
+;ord_2549@4 @2549
+;ord_2550@8 @2550
+;ord_2551@20 @2551
+;ord_2552@8 @2552
+;ord_2553@32 @2553
+;ord_2554@12 @2554
+;ord_2555@16 @2555
+;ord_2556@8 @2556
+;ord_2557@12 @2557
+;ord_2558@12 @2558
+;ord_2559@16 @2559
+;ord_2560@20 @2560
+;ord_2561@0 @2561
+;ord_2562@0 @2562
+;ord_2563@0 @2563
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
@@ -371,7 +371,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
var self = Self{};
- const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
+ const new_memory = try allocator.allocAdvanced(T, alignment, num, .at_least);
self.items.ptr = new_memory.ptr;
self.capacity = new_memory.len;
@@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Replace range of elements `list[start..start+len]` with `new_items`
/// grows list if `len < new_items.len`. may allocate
/// shrinks list if `len > new_items.len`
- pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {
+ pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void {
var managed = self.toManaged(allocator);
try managed.replaceRange(start, len, new_items);
self.* = managed.toUnmanaged();
@@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
};
}
-test "std.ArrayList.init" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.init" {
+ {
+ var list = ArrayList(i32).init(testing.allocator);
+ defer list.deinit();
- testing.expect(list.items.len == 0);
- testing.expect(list.capacity == 0);
-}
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity == 0);
+ }
-test "std.ArrayList.initCapacity" {
- var list = try ArrayList(i8).initCapacity(testing.allocator, 200);
- defer list.deinit();
- testing.expect(list.items.len == 0);
- testing.expect(list.capacity >= 200);
-}
+ {
+ var list = ArrayListUnmanaged(i32){};
-test "std.ArrayList.basic" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity == 0);
+ }
+}
+test "std.ArrayList/ArrayListUnmanaged.initCapacity" {
+ const a = testing.allocator;
{
- var i: usize = 0;
- while (i < 10) : (i += 1) {
- list.append(@intCast(i32, i + 1)) catch unreachable;
- }
+ var list = try ArrayList(i8).initCapacity(a, 200);
+ defer list.deinit();
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity >= 200);
+ }
+ {
+ var list = try ArrayListUnmanaged(i8).initCapacity(a, 200);
+ defer list.deinit(a);
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity >= 200);
}
+}
+test "std.ArrayList/ArrayListUnmanaged.basic" {
+ const a = testing.allocator;
{
- var i: usize = 0;
- while (i < 10) : (i += 1) {
- testing.expect(list.items[i] == @intCast(i32, i + 1));
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ list.append(@intCast(i32, i + 1)) catch unreachable;
+ }
+ }
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ testing.expect(list.items[i] == @intCast(i32, i + 1));
+ }
+ }
+
+ for (list.items) |v, i| {
+ testing.expect(v == @intCast(i32, i + 1));
}
- }
- for (list.items) |v, i| {
- testing.expect(v == @intCast(i32, i + 1));
+ testing.expect(list.pop() == 10);
+ testing.expect(list.items.len == 9);
+
+ list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;
+ testing.expect(list.items.len == 12);
+ testing.expect(list.pop() == 3);
+ testing.expect(list.pop() == 2);
+ testing.expect(list.pop() == 1);
+ testing.expect(list.items.len == 9);
+
+ list.appendSlice(&[_]i32{}) catch unreachable;
+ testing.expect(list.items.len == 9);
+
+ // can only set on indices < self.items.len
+ list.items[7] = 33;
+ list.items[8] = 42;
+
+ testing.expect(list.pop() == 42);
+ testing.expect(list.pop() == 33);
}
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ list.append(a, @intCast(i32, i + 1)) catch unreachable;
+ }
+ }
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ testing.expect(list.items[i] == @intCast(i32, i + 1));
+ }
+ }
+
+ for (list.items) |v, i| {
+ testing.expect(v == @intCast(i32, i + 1));
+ }
- testing.expect(list.pop() == 10);
- testing.expect(list.items.len == 9);
+ testing.expect(list.pop() == 10);
+ testing.expect(list.items.len == 9);
- list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;
- testing.expect(list.items.len == 12);
- testing.expect(list.pop() == 3);
- testing.expect(list.pop() == 2);
- testing.expect(list.pop() == 1);
- testing.expect(list.items.len == 9);
+ list.appendSlice(a, &[_]i32{ 1, 2, 3 }) catch unreachable;
+ testing.expect(list.items.len == 12);
+ testing.expect(list.pop() == 3);
+ testing.expect(list.pop() == 2);
+ testing.expect(list.pop() == 1);
+ testing.expect(list.items.len == 9);
- list.appendSlice(&[_]i32{}) catch unreachable;
- testing.expect(list.items.len == 9);
+ list.appendSlice(a, &[_]i32{}) catch unreachable;
+ testing.expect(list.items.len == 9);
- // can only set on indices < self.items.len
- list.items[7] = 33;
- list.items[8] = 42;
+ // can only set on indices < self.items.len
+ list.items[7] = 33;
+ list.items[8] = 42;
- testing.expect(list.pop() == 42);
- testing.expect(list.pop() == 33);
+ testing.expect(list.pop() == 42);
+ testing.expect(list.pop() == 33);
+ }
}
-test "std.ArrayList.appendNTimes" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.appendNTimes" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ try list.appendNTimes(2, 10);
+ testing.expectEqual(@as(usize, 10), list.items.len);
+ for (list.items) |element| {
+ testing.expectEqual(@as(i32, 2), element);
+ }
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
- try list.appendNTimes(2, 10);
- testing.expectEqual(@as(usize, 10), list.items.len);
- for (list.items) |element| {
- testing.expectEqual(@as(i32, 2), element);
+ try list.appendNTimes(a, 2, 10);
+ testing.expectEqual(@as(usize, 10), list.items.len);
+ for (list.items) |element| {
+ testing.expectEqual(@as(i32, 2), element);
+ }
}
}
-test "std.ArrayList.appendNTimes with failing allocator" {
- var list = ArrayList(i32).init(testing.failing_allocator);
- defer list.deinit();
- testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
+test "std.ArrayList/ArrayListUnmanaged.appendNTimes with failing allocator" {
+ const a = testing.failing_allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+ testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+ testing.expectError(error.OutOfMemory, list.appendNTimes(a, 2, 10));
+ }
}
-test "std.ArrayList.orderedRemove" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.orderedRemove" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.append(5);
+ try list.append(6);
+ try list.append(7);
+
+ //remove from middle
+ testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
+ testing.expectEqual(@as(i32, 5), list.items[3]);
+ testing.expectEqual(@as(usize, 6), list.items.len);
+
+ //remove from end
+ testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
+ testing.expectEqual(@as(usize, 5), list.items.len);
+
+ //remove from front
+ testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
+ testing.expectEqual(@as(i32, 2), list.items[0]);
+ testing.expectEqual(@as(usize, 4), list.items.len);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.append(5);
- try list.append(6);
- try list.append(7);
-
- //remove from middle
- testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
- testing.expectEqual(@as(i32, 5), list.items[3]);
- testing.expectEqual(@as(usize, 6), list.items.len);
-
- //remove from end
- testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
- testing.expectEqual(@as(usize, 5), list.items.len);
-
- //remove from front
- testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
- testing.expectEqual(@as(i32, 2), list.items[0]);
- testing.expectEqual(@as(usize, 4), list.items.len);
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.append(a, 5);
+ try list.append(a, 6);
+ try list.append(a, 7);
+
+ //remove from middle
+ testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
+ testing.expectEqual(@as(i32, 5), list.items[3]);
+ testing.expectEqual(@as(usize, 6), list.items.len);
+
+ //remove from end
+ testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
+ testing.expectEqual(@as(usize, 5), list.items.len);
+
+ //remove from front
+ testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
+ testing.expectEqual(@as(i32, 2), list.items[0]);
+ testing.expectEqual(@as(usize, 4), list.items.len);
+ }
}
-test "std.ArrayList.swapRemove" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.swapRemove" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.append(5);
- try list.append(6);
- try list.append(7);
-
- //remove from middle
- testing.expect(list.swapRemove(3) == 4);
- testing.expect(list.items[3] == 7);
- testing.expect(list.items.len == 6);
-
- //remove from end
- testing.expect(list.swapRemove(5) == 6);
- testing.expect(list.items.len == 5);
-
- //remove from front
- testing.expect(list.swapRemove(0) == 1);
- testing.expect(list.items[0] == 5);
- testing.expect(list.items.len == 4);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.append(5);
+ try list.append(6);
+ try list.append(7);
+
+ //remove from middle
+ testing.expect(list.swapRemove(3) == 4);
+ testing.expect(list.items[3] == 7);
+ testing.expect(list.items.len == 6);
+
+ //remove from end
+ testing.expect(list.swapRemove(5) == 6);
+ testing.expect(list.items.len == 5);
+
+ //remove from front
+ testing.expect(list.swapRemove(0) == 1);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items.len == 4);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.append(a, 5);
+ try list.append(a, 6);
+ try list.append(a, 7);
+
+ //remove from middle
+ testing.expect(list.swapRemove(3) == 4);
+ testing.expect(list.items[3] == 7);
+ testing.expect(list.items.len == 6);
+
+ //remove from end
+ testing.expect(list.swapRemove(5) == 6);
+ testing.expect(list.items.len == 5);
+
+ //remove from front
+ testing.expect(list.swapRemove(0) == 1);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items.len == 4);
+ }
}
-test "std.ArrayList.insert" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.insert" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.insert(0, 5);
- testing.expect(list.items[0] == 5);
- testing.expect(list.items[1] == 1);
- testing.expect(list.items[2] == 2);
- testing.expect(list.items[3] == 3);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.insert(0, 5);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items[1] == 1);
+ testing.expect(list.items[2] == 2);
+ testing.expect(list.items[3] == 3);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.insert(a, 0, 5);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items[1] == 1);
+ testing.expect(list.items[2] == 2);
+ testing.expect(list.items[3] == 3);
+ }
}
-test "std.ArrayList.insertSlice" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.insertSlice" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.insertSlice(1, &[_]i32{ 9, 8 });
- testing.expect(list.items[0] == 1);
- testing.expect(list.items[1] == 9);
- testing.expect(list.items[2] == 8);
- testing.expect(list.items[3] == 2);
- testing.expect(list.items[4] == 3);
- testing.expect(list.items[5] == 4);
-
- const items = [_]i32{1};
- try list.insertSlice(0, items[0..0]);
- testing.expect(list.items.len == 6);
- testing.expect(list.items[0] == 1);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.insertSlice(1, &[_]i32{ 9, 8 });
+ testing.expect(list.items[0] == 1);
+ testing.expect(list.items[1] == 9);
+ testing.expect(list.items[2] == 8);
+ testing.expect(list.items[3] == 2);
+ testing.expect(list.items[4] == 3);
+ testing.expect(list.items[5] == 4);
+
+ const items = [_]i32{1};
+ try list.insertSlice(0, items[0..0]);
+ testing.expect(list.items.len == 6);
+ testing.expect(list.items[0] == 1);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.insertSlice(a, 1, &[_]i32{ 9, 8 });
+ testing.expect(list.items[0] == 1);
+ testing.expect(list.items[1] == 9);
+ testing.expect(list.items[2] == 8);
+ testing.expect(list.items[3] == 2);
+ testing.expect(list.items[4] == 3);
+ testing.expect(list.items[5] == 4);
+
+ const items = [_]i32{1};
+ try list.insertSlice(a, 0, items[0..0]);
+ testing.expect(list.items.len == 6);
+ testing.expect(list.items[0] == 1);
+ }
}
-test "std.ArrayList.replaceRange" {
+test "std.ArrayList/ArrayListUnmanaged.replaceRange" {
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
+ const a = &arena.allocator;
- const alloc = &arena.allocator;
const init = [_]i32{ 1, 2, 3, 4, 5 };
const new = [_]i32{ 0, 0, 0 };
- var list_zero = ArrayList(i32).init(alloc);
- var list_eq = ArrayList(i32).init(alloc);
- var list_lt = ArrayList(i32).init(alloc);
- var list_gt = ArrayList(i32).init(alloc);
+ const result_zero = [_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 };
+ const result_eq = [_]i32{ 1, 0, 0, 0, 5 };
+ const result_le = [_]i32{ 1, 0, 0, 0, 4, 5 };
+ const result_gt = [_]i32{ 1, 0, 0, 0 };
- try list_zero.appendSlice(&init);
- try list_eq.appendSlice(&init);
- try list_lt.appendSlice(&init);
- try list_gt.appendSlice(&init);
-
- try list_zero.replaceRange(1, 0, &new);
- try list_eq.replaceRange(1, 3, &new);
- try list_lt.replaceRange(1, 2, &new);
-
- // after_range > new_items.len in function body
- testing.expect(1 + 4 > new.len);
- try list_gt.replaceRange(1, 4, &new);
-
- testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 });
- testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 });
- testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 });
- testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 });
+ {
+ var list_zero = ArrayList(i32).init(a);
+ var list_eq = ArrayList(i32).init(a);
+ var list_lt = ArrayList(i32).init(a);
+ var list_gt = ArrayList(i32).init(a);
+
+ try list_zero.appendSlice(&init);
+ try list_eq.appendSlice(&init);
+ try list_lt.appendSlice(&init);
+ try list_gt.appendSlice(&init);
+
+ try list_zero.replaceRange(1, 0, &new);
+ try list_eq.replaceRange(1, 3, &new);
+ try list_lt.replaceRange(1, 2, &new);
+
+ // after_range > new_items.len in function body
+ testing.expect(1 + 4 > new.len);
+ try list_gt.replaceRange(1, 4, &new);
+
+ testing.expectEqualSlices(i32, list_zero.items, &result_zero);
+ testing.expectEqualSlices(i32, list_eq.items, &result_eq);
+ testing.expectEqualSlices(i32, list_lt.items, &result_le);
+ testing.expectEqualSlices(i32, list_gt.items, &result_gt);
+ }
+ {
+ var list_zero = ArrayListUnmanaged(i32){};
+ var list_eq = ArrayListUnmanaged(i32){};
+ var list_lt = ArrayListUnmanaged(i32){};
+ var list_gt = ArrayListUnmanaged(i32){};
+
+ try list_zero.appendSlice(a, &init);
+ try list_eq.appendSlice(a, &init);
+ try list_lt.appendSlice(a, &init);
+ try list_gt.appendSlice(a, &init);
+
+ try list_zero.replaceRange(a, 1, 0, &new);
+ try list_eq.replaceRange(a, 1, 3, &new);
+ try list_lt.replaceRange(a, 1, 2, &new);
+
+ // after_range > new_items.len in function body
+ testing.expect(1 + 4 > new.len);
+ try list_gt.replaceRange(a, 1, 4, &new);
+
+ testing.expectEqualSlices(i32, list_zero.items, &result_zero);
+ testing.expectEqualSlices(i32, list_eq.items, &result_eq);
+ testing.expectEqualSlices(i32, list_lt.items, &result_le);
+ testing.expectEqualSlices(i32, list_gt.items, &result_gt);
+ }
}
const Item = struct {
@@ -819,11 +1032,25 @@ const Item = struct {
sub_items: ArrayList(Item),
};
-test "std.ArrayList: ArrayList(T) of struct T" {
- var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) };
- defer root.sub_items.deinit();
- try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) });
- testing.expect(root.sub_items.items[0].integer == 42);
+const ItemUnmanaged = struct {
+ integer: i32,
+ sub_items: ArrayListUnmanaged(ItemUnmanaged),
+};
+
+test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" {
+ const a = std.testing.allocator;
+ {
+ var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(a) };
+ defer root.sub_items.deinit();
+ try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(a) });
+ testing.expect(root.sub_items.items[0].integer == 42);
+ }
+ {
+ var root = ItemUnmanaged{ .integer = 1, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} };
+ defer root.sub_items.deinit(a);
+ try root.sub_items.append(a, ItemUnmanaged{ .integer = 42, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} });
+ testing.expect(root.sub_items.items[0].integer == 42);
+ }
}
test "std.ArrayList(u8) implements outStream" {
@@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" {
testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span());
}
-test "std.ArrayList.shrink still sets length on error.OutOfMemory" {
+test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" {
// use an arena allocator to make sure realloc returns error.OutOfMemory
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
+ const a = &arena.allocator;
- var list = ArrayList(i32).init(&arena.allocator);
+ {
+ var list = ArrayList(i32).init(a);
- try list.append(1);
- try list.append(2);
- try list.append(3);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
- list.shrink(1);
- testing.expect(list.items.len == 1);
+ list.shrink(1);
+ testing.expect(list.items.len == 1);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+
+ list.shrink(a, 1);
+ testing.expect(list.items.len == 1);
+ }
}
test "std.ArrayList.writer" {
@@ -864,7 +1104,7 @@ test "std.ArrayList.writer" {
testing.expectEqualSlices(u8, list.items, "abcdefg");
}
-test "addManyAsArray" {
+test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
const a = std.testing.allocator;
{
var list = ArrayList(u8).init(a);
diff --git a/lib/std/build.zig b/lib/std/build.zig
@@ -1239,6 +1239,7 @@ pub const LibExeObjStep = struct {
/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
/// file.
link_eh_frame_hdr: bool = false,
+ link_emit_relocs: bool = false,
/// Place every function in its own section so that unused ones may be
/// safely garbage-collected during the linking phase.
@@ -2075,6 +2076,9 @@ pub const LibExeObjStep = struct {
if (self.link_eh_frame_hdr) {
try zig_args.append("--eh-frame-hdr");
}
+ if (self.link_emit_relocs) {
+ try zig_args.append("--emit-relocs");
+ }
if (self.link_function_sections) {
try zig_args.append("-ffunction-sections");
}
@@ -2168,8 +2172,8 @@ pub const LibExeObjStep = struct {
}
if (self.linker_script) |linker_script| {
- zig_args.append("--linker-script") catch unreachable;
- zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;
+ try zig_args.append("--script");
+ try zig_args.append(builder.pathFromRoot(linker_script));
}
if (self.version_script) |version_script| {
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
@@ -262,6 +262,7 @@ pub const TypeInfo = union(enum) {
field_type: type,
default_value: anytype,
is_comptime: bool,
+ alignment: comptime_int,
};
/// This data structure is used by the Zig language code generation and
@@ -318,6 +319,7 @@ pub const TypeInfo = union(enum) {
pub const UnionField = struct {
name: []const u8,
field_type: type,
+ alignment: comptime_int,
};
/// This data structure is used by the Zig language code generation and
@@ -341,6 +343,7 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Fn = struct {
calling_convention: CallingConvention,
+ alignment: comptime_int,
is_generic: bool,
is_var_args: bool,
return_type: ?type,
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
@@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig");
extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
-pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
+pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
pub extern "c" fn _dyld_image_count() u32;
pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig
@@ -4,6 +4,48 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
+/// Authenticated Encryption with Associated Data
+pub const aead = struct {
+ const chacha20 = @import("crypto/chacha20.zig");
+
+ pub const Gimli = @import("crypto/gimli.zig").Aead;
+ pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
+ pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
+ pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
+ pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
+};
+
+/// Authentication (MAC) functions.
+pub const auth = struct {
+ pub const hmac = @import("crypto/hmac.zig");
+ pub const siphash = @import("crypto/siphash.zig");
+};
+
+/// Core functions, that should rarely be used directly by applications.
+pub const core = struct {
+ pub const aes = @import("crypto/aes.zig");
+ pub const Gimli = @import("crypto/gimli.zig").State;
+
+ /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
+ ///
+ /// 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.
+ ///
+ /// Most applications may want to use AEADs instead.
+ pub const modes = @import("crypto/modes.zig");
+};
+
+/// Diffie-Hellman key exchange functions.
+pub const dh = struct {
+ pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
+};
+
+/// Elliptic-curve arithmetic.
+pub const ecc = struct {
+ pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
+ pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
+ pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
+};
+
/// Hash functions.
pub const hash = struct {
pub const Md5 = @import("crypto/md5.zig").Md5;
@@ -15,26 +57,15 @@ pub const hash = struct {
pub const Gimli = @import("crypto/gimli.zig").Hash;
};
-/// Authentication (MAC) functions.
-pub const auth = struct {
- pub const hmac = @import("crypto/hmac.zig");
- pub const siphash = @import("crypto/siphash.zig");
-};
-
-/// Authenticated Encryption with Associated Data
-pub const aead = struct {
- const chacha20 = @import("crypto/chacha20.zig");
-
- pub const Gimli = @import("crypto/gimli.zig").Aead;
- pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
- pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
- pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
- pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
+/// Key derivation functions.
+pub const kdf = struct {
+ pub const hkdf = @import("crypto/hkdf.zig");
};
/// MAC functions requiring single-use secret keys.
pub const onetimeauth = struct {
pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
+ pub const Ghash = @import("crypto/ghash.zig").Ghash;
};
/// A password hashing function derives a uniform key from low-entropy input material such as passwords.
@@ -57,31 +88,6 @@ pub const pwhash = struct {
pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;
};
-/// Core functions, that should rarely be used directly by applications.
-pub const core = struct {
- pub const aes = @import("crypto/aes.zig");
- pub const Gimli = @import("crypto/gimli.zig").State;
-
- /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
- ///
- /// 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.
- ///
- /// Most applications may want to use AEADs instead.
- pub const modes = @import("crypto/modes.zig");
-};
-
-/// Elliptic-curve arithmetic.
-pub const ecc = struct {
- pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
- pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
- pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
-};
-
-/// Diffie-Hellman key exchange functions.
-pub const dh = struct {
- pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
-};
-
/// Digital signature functions.
pub const sign = struct {
pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig
@@ -57,6 +57,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
}
const macs = [_]Crypto{
+ Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" },
Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },
Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },
diff --git a/lib/std/crypto/ghash.zig b/lib/std/crypto/ghash.zig
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2020 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+//
+// Adapted from BearSSL's ctmul64 implementation originally written by Thomas Pornin <pornin@bolet.org>
+
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const math = std.math;
+const mem = std.mem;
+
+/// GHASH is a universal hash function that features multiplication
+/// by a fixed parameter within a Galois field.
+///
+/// It is not a general purpose hash function - The key must be secret, unpredictable and never reused.
+///
+/// GHASH is typically used to compute the authentication tag in the AES-GCM construction.
+pub const Ghash = struct {
+ pub const block_size: usize = 16;
+ pub const mac_length = 16;
+ pub const minimum_key_length = 16;
+
+ y0: u64 = 0,
+ y1: u64 = 0,
+ h0: u64,
+ h1: u64,
+ h2: u64,
+ h0r: u64,
+ h1r: u64,
+ h2r: u64,
+
+ hh0: u64 = undefined,
+ hh1: u64 = undefined,
+ hh2: u64 = undefined,
+ hh0r: u64 = undefined,
+ hh1r: u64 = undefined,
+ hh2r: u64 = undefined,
+
+ leftover: usize = 0,
+ buf: [block_size]u8 align(16) = undefined,
+
+ pub fn init(key: *const [minimum_key_length]u8) Ghash {
+ const h1 = mem.readIntBig(u64, key[0..8]);
+ const h0 = mem.readIntBig(u64, key[8..16]);
+ const h1r = @bitReverse(u64, h1);
+ const h0r = @bitReverse(u64, h0);
+ const h2 = h0 ^ h1;
+ const h2r = h0r ^ h1r;
+
+ if (std.builtin.mode == .ReleaseSmall) {
+ return Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+ };
+ } else {
+ // Precompute H^2
+ var hh = Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+ };
+ hh.update(key);
+ const hh1 = hh.y1;
+ const hh0 = hh.y0;
+ const hh1r = @bitReverse(u64, hh1);
+ const hh0r = @bitReverse(u64, hh0);
+ const hh2 = hh0 ^ hh1;
+ const hh2r = hh0r ^ hh1r;
+
+ return Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+
+ .hh0 = hh0,
+ .hh1 = hh1,
+ .hh2 = hh2,
+ .hh0r = hh0r,
+ .hh1r = hh1r,
+ .hh2r = hh2r,
+ };
+ }
+ }
+
+ inline fn clmul_pclmul(x: u64, y: u64) u64 {
+ const Vector = std.meta.Vector;
+ const product = asm (
+ \\ vpclmulqdq $0x00, %[x], %[y], %[out]
+ : [out] "=x" (-> Vector(2, u64))
+ : [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))),
+ [y] "x" (@bitCast(Vector(2, u64), @as(u128, y)))
+ );
+ return product[0];
+ }
+
+ fn clmul_soft(x: u64, y: u64) u64 {
+ const x0 = x & 0x1111111111111111;
+ const x1 = x & 0x2222222222222222;
+ const x2 = x & 0x4444444444444444;
+ const x3 = x & 0x8888888888888888;
+ const y0 = y & 0x1111111111111111;
+ const y1 = y & 0x2222222222222222;
+ const y2 = y & 0x4444444444444444;
+ const y3 = y & 0x8888888888888888;
+ var z0 = (x0 *% y0) ^ (x1 *% y3) ^ (x2 *% y2) ^ (x3 *% y1);
+ var z1 = (x0 *% y1) ^ (x1 *% y0) ^ (x2 *% y3) ^ (x3 *% y2);
+ var z2 = (x0 *% y2) ^ (x1 *% y1) ^ (x2 *% y0) ^ (x3 *% y3);
+ var z3 = (x0 *% y3) ^ (x1 *% y2) ^ (x2 *% y1) ^ (x3 *% y0);
+ z0 &= 0x1111111111111111;
+ z1 &= 0x2222222222222222;
+ z2 &= 0x4444444444444444;
+ z3 &= 0x8888888888888888;
+ return z0 | z1 | z2 | z3;
+ }
+
+ const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul);
+ const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);
+ const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft;
+
+ fn blocks(st: *Ghash, msg: []const u8) void {
+ assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks
+ var y1 = st.y1;
+ var y0 = st.y0;
+
+ var i: usize = 0;
+
+ // 2-blocks aggregated reduction
+ if (std.builtin.mode != .ReleaseSmall) {
+ while (i + 32 <= msg.len) : (i += 32) {
+ // B0 * H^2 unreduced
+ y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
+ y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
+
+ const y1r = @bitReverse(u64, y1);
+ const y0r = @bitReverse(u64, y0);
+ const y2 = y0 ^ y1;
+ const y2r = y0r ^ y1r;
+
+ var z0 = clmul(y0, st.hh0);
+ var z1 = clmul(y1, st.hh1);
+ var z2 = clmul(y2, st.hh2) ^ z0 ^ z1;
+ var z0h = clmul(y0r, st.hh0r);
+ var z1h = clmul(y1r, st.hh1r);
+ var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h;
+
+ // B1 * H unreduced
+ const sy1 = mem.readIntBig(u64, msg[i..][16..24]);
+ const sy0 = mem.readIntBig(u64, msg[i..][24..32]);
+
+ const sy1r = @bitReverse(u64, sy1);
+ const sy0r = @bitReverse(u64, sy0);
+ const sy2 = sy0 ^ sy1;
+ const sy2r = sy0r ^ sy1r;
+
+ const sz0 = clmul(sy0, st.h0);
+ const sz1 = clmul(sy1, st.h1);
+ const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1;
+ const sz0h = clmul(sy0r, st.h0r);
+ const sz1h = clmul(sy1r, st.h1r);
+ const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h;
+
+ // ((B0 * H^2) + B1 * H) (mod M)
+ z0 ^= sz0;
+ z1 ^= sz1;
+ z2 ^= sz2;
+ z0h ^= sz0h;
+ z1h ^= sz1h;
+ z2h ^= sz2h;
+ z0h = @bitReverse(u64, z0h) >> 1;
+ z1h = @bitReverse(u64, z1h) >> 1;
+ z2h = @bitReverse(u64, z2h) >> 1;
+
+ var v3 = z1h;
+ var v2 = z1 ^ z2h;
+ var v1 = z0h ^ z2;
+ var v0 = z0;
+
+ v3 = (v3 << 1) | (v2 >> 63);
+ v2 = (v2 << 1) | (v1 >> 63);
+ v1 = (v1 << 1) | (v0 >> 63);
+ v0 = (v0 << 1);
+
+ v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
+ v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
+ y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
+ y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
+ }
+ }
+
+ // single block
+ while (i + 16 <= msg.len) : (i += 16) {
+ y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
+ y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
+
+ const y1r = @bitReverse(u64, y1);
+ const y0r = @bitReverse(u64, y0);
+ const y2 = y0 ^ y1;
+ const y2r = y0r ^ y1r;
+
+ const z0 = clmul(y0, st.h0);
+ const z1 = clmul(y1, st.h1);
+ var z2 = clmul(y2, st.h2) ^ z0 ^ z1;
+ var z0h = clmul(y0r, st.h0r);
+ var z1h = clmul(y1r, st.h1r);
+ var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h;
+ z0h = @bitReverse(u64, z0h) >> 1;
+ z1h = @bitReverse(u64, z1h) >> 1;
+ z2h = @bitReverse(u64, z2h) >> 1;
+
+ // shift & reduce
+ var v3 = z1h;
+ var v2 = z1 ^ z2h;
+ var v1 = z0h ^ z2;
+ var v0 = z0;
+
+ v3 = (v3 << 1) | (v2 >> 63);
+ v2 = (v2 << 1) | (v1 >> 63);
+ v1 = (v1 << 1) | (v0 >> 63);
+ v0 = (v0 << 1);
+
+ v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
+ v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
+ y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
+ y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
+ }
+ st.y1 = y1;
+ st.y0 = y0;
+ }
+
+ pub fn update(st: *Ghash, m: []const u8) void {
+ var mb = m;
+
+ if (st.leftover > 0) {
+ const want = math.min(block_size - st.leftover, mb.len);
+ const mc = mb[0..want];
+ for (mc) |x, i| {
+ st.buf[st.leftover + i] = x;
+ }
+ mb = mb[want..];
+ st.leftover += want;
+ if (st.leftover > block_size) {
+ return;
+ }
+ st.blocks(&st.buf);
+ st.leftover = 0;
+ }
+ if (mb.len >= block_size) {
+ const want = mb.len & ~(block_size - 1);
+ st.blocks(mb[0..want]);
+ mb = mb[want..];
+ }
+ if (mb.len > 0) {
+ for (mb) |x, i| {
+ st.buf[st.leftover + i] = x;
+ }
+ st.leftover += mb.len;
+ }
+ }
+
+ pub fn final(st: *Ghash, out: *[mac_length]u8) void {
+ if (st.leftover > 0) {
+ var i = st.leftover;
+ while (i < block_size) : (i += 1) {
+ st.buf[i] = 0;
+ }
+ st.blocks(&st.buf);
+ }
+ mem.writeIntBig(u64, out[0..8], st.y1);
+ mem.writeIntBig(u64, out[8..16], st.y0);
+
+ mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Ghash)]);
+ }
+
+ pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
+ var st = Ghash.init(key);
+ st.update(msg);
+ st.final(out);
+ }
+};
+
+const htest = @import("test.zig");
+
+test "ghash" {
+ const key = [_]u8{0x42} ** 16;
+ const m = [_]u8{0x69} ** 256;
+
+ var st = Ghash.init(&key);
+ st.update(&m);
+ var out: [16]u8 = undefined;
+ st.final(&out);
+ htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
+
+ st = Ghash.init(&key);
+ st.update(m[0..100]);
+ st.update(m[100..]);
+ st.final(&out);
+ htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
+}
diff --git a/lib/std/crypto/hkdf.zig b/lib/std/crypto/hkdf.zig
@@ -0,0 +1,66 @@
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const hmac = std.crypto.auth.hmac;
+const mem = std.mem;
+
+/// HKDF-SHA256
+pub const HkdfSha256 = Hkdf(hmac.sha2.HmacSha256);
+
+/// HKDF-SHA512
+pub const HkdfSha512 = Hkdf(hmac.sha2.HmacSha512);
+
+/// The Hkdf construction takes some source of initial keying material and
+/// derives one or more uniform keys from it.
+pub fn Hkdf(comptime Hmac: type) type {
+ return struct {
+ /// Return a master key from a salt and initial keying material.
+ fn extract(salt: []const u8, ikm: []const u8) [Hmac.mac_length]u8 {
+ var prk: [Hmac.mac_length]u8 = undefined;
+ Hmac.create(&prk, ikm, salt);
+ return prk;
+ }
+
+ /// Derive a subkey from a master key `prk` and a subkey description `ctx`.
+ fn expand(out: []u8, ctx: []const u8, prk: [Hmac.mac_length]u8) void {
+ assert(out.len < Hmac.mac_length * 255); // output size is too large for the Hkdf construction
+ var i: usize = 0;
+ var counter = [1]u8{1};
+ while (i + Hmac.mac_length <= out.len) : (i += Hmac.mac_length) {
+ var st = Hmac.init(&prk);
+ if (i != 0) {
+ st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
+ }
+ st.update(ctx);
+ st.update(&counter);
+ st.final(out[i..][0..Hmac.mac_length]);
+ counter[0] += 1;
+ }
+ const left = out.len % Hmac.mac_length;
+ if (left > 0) {
+ var st = Hmac.init(&prk);
+ if (i != 0) {
+ st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
+ }
+ st.update(ctx);
+ st.update(&counter);
+ var tmp: [Hmac.mac_length]u8 = undefined;
+ st.final(tmp[0..Hmac.mac_length]);
+ mem.copy(u8, out[i..][0..left], tmp[0..left]);
+ }
+ }
+ };
+}
+
+const htest = @import("test.zig");
+
+test "Hkdf" {
+ const ikm = [_]u8{0x0b} ** 22;
+ const salt = [_]u8{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+ const context = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
+ const kdf = HkdfSha256;
+ const prk = kdf.extract(&salt, &ikm);
+ htest.assertEqual("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", &prk);
+ var out: [42]u8 = undefined;
+ kdf.expand(&out, &context, prk);
+ htest.assertEqual("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", &out);
+}
diff --git a/lib/std/crypto/poly1305.zig b/lib/std/crypto/poly1305.zig
@@ -22,8 +22,7 @@ pub const Poly1305 = struct {
// partial block buffer
buf: [block_size]u8 align(16) = undefined,
- pub fn init(key: []const u8) Poly1305 {
- std.debug.assert(key.len >= minimum_key_length);
+ pub fn init(key: *const [minimum_key_length]u8) Poly1305 {
const t0 = mem.readIntLittle(u64, key[0..8]);
const t1 = mem.readIntLittle(u64, key[8..16]);
return Poly1305{
@@ -115,8 +114,7 @@ pub const Poly1305 = struct {
}
}
- pub fn final(st: *Poly1305, out: []u8) void {
- std.debug.assert(out.len >= mac_length);
+ pub fn final(st: *Poly1305, out: *[mac_length]u8) void {
if (st.leftover > 0) {
var i = st.leftover;
st.buf[i] = 1;
@@ -187,10 +185,7 @@ pub const Poly1305 = struct {
std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]);
}
- pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
- std.debug.assert(out.len >= mac_length);
- std.debug.assert(key.len >= minimum_key_length);
-
+ pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
var st = Poly1305.init(key);
st.update(msg);
st.final(out);
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
@@ -1181,6 +1181,16 @@ fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, uppercase: bool, opti
return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
}
+pub fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args)]u8 {
+ comptime var buf: [count(fmt, args)]u8 = undefined;
+ _ = bufPrint(&buf, fmt, args) catch unreachable;
+ return &buf;
+}
+
+test "comptimePrint" {
+ std.testing.expectEqualSlices(u8, "100", comptime comptimePrint("{}", .{100}));
+}
+
test "parse u64 digit too big" {
_ = parseUnsigned(u64, "123a", 10) catch |err| {
if (err == error.InvalidCharacter) return;
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
@@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags);
}
-pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
+pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError;
/// `selfExePath` except allocates the result on the heap.
/// Caller owns returned memory.
@@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {
/// TODO make the return type of this a null terminated pointer
pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
if (is_darwin) {
- var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32)));
- const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len);
+ // Note that _NSGetExecutablePath() will return "a path" to
+ // the executable not a "real path" to the executable.
+ var symlink_path_buf: [MAX_PATH_BYTES:0]u8 = undefined;
+ var u32_len: u32 = MAX_PATH_BYTES + 1; // include the sentinel
+ const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len);
if (rc != 0) return error.NameTooLong;
- return mem.spanZ(@ptrCast([*:0]u8, out_buffer));
+
+ var real_path_buf: [MAX_PATH_BYTES]u8 = undefined;
+ const real_path = try std.os.realpathZ(&symlink_path_buf, &real_path_buf);
+ if (real_path.len > out_buffer.len) return error.NameTooLong;
+ std.mem.copy(u8, out_buffer, real_path);
+ return out_buffer[0..real_path.len];
}
switch (builtin.os.tag) {
.linux => return os.readlinkZ("/proc/self/exe", out_buffer),
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
@@ -58,6 +58,11 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {
return (string_len + (limb_bits / base - 1)) / (limb_bits / base);
}
+pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize {
+ // The 1 accounts for the multiplication carry
+ return 1 + (a_bit_count * y + (limb_bits - 1)) / limb_bits;
+}
+
/// a + b * c + *carry, sets carry to the overflow bits
pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {
@setRuntimeSafety(debug_safety);
@@ -597,6 +602,52 @@ pub const Mutable = struct {
return gcdLehmer(rma, x_copy, y_copy, limbs_buffer);
}
+ /// q = a ^ b
+ ///
+ /// r may not alias a.
+ ///
+ /// Asserts that `r` has enough limbs to store the result. Upper bound is
+ /// `calcPowLimbsBufferLen(a.bitCountAbs(), b)`.
+ ///
+ /// `limbs_buffer` is used for temporary storage.
+ /// The amount required is given by `calcPowLimbsBufferLen`.
+ pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void {
+ assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing
+
+ // Handle all the trivial cases first
+ switch (b) {
+ 0 => {
+ // a^0 = 1
+ return r.set(1);
+ },
+ 1 => {
+ // a^1 = a
+ return r.copy(a);
+ },
+ else => {},
+ }
+
+ if (a.eqZero()) {
+ // 0^b = 0
+ return r.set(0);
+ } else if (a.limbs.len == 1 and a.limbs[0] == 1) {
+ // 1^b = 1 and -1^b = ±1
+ r.set(1);
+ r.positive = a.positive or (b & 1) == 0;
+ return;
+ }
+
+ // Here a>1 and b>1
+ const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
+ assert(r.limbs.len >= needed_limbs);
+ assert(limbs_buffer.len >= needed_limbs);
+
+ llpow(r.limbs, a.limbs, b, limbs_buffer);
+
+ r.normalize(needed_limbs);
+ r.positive = a.positive or (b & 1) == 0;
+ }
+
/// rma may not alias x or y.
/// x and y may alias each other.
/// Asserts that `rma` has enough limbs to store the result. Upper bound is given by `calcGcdNoAliasLimbLen`.
@@ -1775,6 +1826,29 @@ pub const Managed = struct {
try m.gcd(x.toConst(), y.toConst(), &limbs_buffer);
rma.setMetadata(m.positive, m.len);
}
+
+ pub fn pow(rma: *Managed, a: Managed, b: u32) !void {
+ const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
+
+ const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs);
+ defer rma.allocator.free(limbs_buffer);
+
+ if (rma.limbs.ptr == a.limbs.ptr) {
+ var m = try Managed.initCapacity(rma.allocator, needed_limbs);
+ errdefer m.deinit();
+ var m_mut = m.toMutable();
+ try m_mut.pow(a.toConst(), b, limbs_buffer);
+ m.setMetadata(m_mut.positive, m_mut.len);
+
+ rma.deinit();
+ rma.swap(&m);
+ } else {
+ try rma.ensureCapacity(needed_limbs);
+ var rma_mut = rma.toMutable();
+ try rma_mut.pow(a.toConst(), b, limbs_buffer);
+ rma.setMetadata(rma_mut.positive, rma_mut.len);
+ }
+ }
};
/// Knuth 4.3.1, Algorithm M.
@@ -2129,6 +2203,52 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void {
}
}
+/// Knuth 4.6.3
+fn llpow(r: []Limb, a: []const Limb, b: u32, tmp_limbs: []Limb) void {
+ mem.copy(Limb, r, a);
+ mem.set(Limb, r[a.len..], 0);
+
+ // Multiplication requires no aliasing between the operand and the result
+ // variable, use the output limbs and another temporary set to overcome this
+ // limit.
+ // Note that the order is important in the code below.
+ var list = [_][]Limb{ r, tmp_limbs };
+ var index: usize = 0;
+
+ // Scan the exponent as a binary number, from left to right, dropping the
+ // most significant bit set
+ var exp = @bitReverse(u32, b) >> (1 + @intCast(u5, @clz(u32, b)));
+ while (exp != 0) : (exp >>= 1) {
+ // Square
+ {
+ const cur_buf = list[index];
+ const cur_buf_len = llnormalize(cur_buf);
+ const cur_buf_out = list[index ^ 1];
+
+ mem.set(Limb, cur_buf_out, 0);
+ llmulacc(null, cur_buf_out, cur_buf[0..cur_buf_len], cur_buf[0..cur_buf_len]);
+
+ index ^= 1;
+ }
+
+ if ((exp & 1) != 0) {
+ // Multiply
+ const cur_buf = list[index];
+ const cur_buf_len = llnormalize(cur_buf);
+ const cur_buf_out = list[index ^ 1];
+
+ mem.set(Limb, cur_buf_out, 0);
+ llmulacc(null, cur_buf_out, cur_buf, a);
+
+ index ^= 1;
+ }
+ }
+
+ if (index != 0) {
+ mem.copy(Limb, r, tmp_limbs);
+ }
+}
+
// Storage must live for the lifetime of the returned value
fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {
assert(storage.len >= 2);
diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig
@@ -1480,3 +1480,48 @@ test "big.int const to managed" {
testing.expect(a.toConst().eq(b.toConst()));
}
+
+test "big.int pow" {
+ {
+ var a = try Managed.initSet(testing.allocator, 10);
+ defer a.deinit();
+
+ var y = try Managed.init(testing.allocator);
+ defer y.deinit();
+
+ // y and a are not aliased
+ try y.pow(a, 123);
+ // y and a are aliased
+ try a.pow(a, 123);
+
+ testing.expect(a.eq(y));
+
+ const ys = try y.toString(testing.allocator, 16, false);
+ defer testing.allocator.free(ys);
+ testing.expectEqualSlices(
+ u8,
+ "183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++
+ "4933f60e8000000000000000000000000000000",
+ ys,
+ );
+ }
+ // Special cases
+ {
+ var a = try Managed.initSet(testing.allocator, 0);
+ defer a.deinit();
+
+ try a.pow(a, 100);
+ testing.expectEqual(@as(i32, 0), try a.to(i32));
+
+ try a.set(1);
+ try a.pow(a, 0);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ try a.pow(a, 100);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ try a.set(-1);
+ try a.pow(a, 15);
+ testing.expectEqual(@as(i32, -1), try a.to(i32));
+ try a.pow(a, 16);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ }
+}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
@@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type {
.field_type = arg.arg_type.?,
.default_value = @as(?(arg.arg_type.?), null),
.is_comptime = false,
+ .alignment = @alignOf(arg.arg_type.?),
};
}
@@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type {
.field_type = T,
.default_value = @as(?T, null),
.is_comptime = false,
+ .alignment = @alignOf(T),
};
}
diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig
@@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
@as(?struct_field.field_type, null),
),
.is_comptime = false,
+ .alignment = @alignOf(?struct_field.field_type),
};
}
break :blk @Type(.{
diff --git a/lib/std/os.zig b/lib/std/os.zig
@@ -3993,7 +3993,7 @@ pub const RealPathError = error{
/// Expands all symbolic links and resolves references to `.`, `..`, and
/// extra `/` characters in `pathname`.
/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
-/// See also `realpathC` and `realpathW`.
+/// See also `realpathZ` and `realpathW`.
pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
if (builtin.os.tag == .windows) {
const pathname_w = try windows.sliceToPrefixedFileW(pathname);
diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig
@@ -318,9 +318,12 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)
};
}
+const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true;
+
test "PackedIntArray" {
// TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
if (builtin.arch == .wasm32) return error.SkipZigTest;
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
@setEvalBranchQuota(10000);
const max_bits = 256;
@@ -358,6 +361,7 @@ test "PackedIntArray" {
}
test "PackedIntArray init" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
const PackedArray = PackedIntArray(u3, 8);
var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
var i = @as(usize, 0);
@@ -367,6 +371,7 @@ test "PackedIntArray init" {
test "PackedIntSlice" {
// TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
if (builtin.arch == .wasm32) return error.SkipZigTest;
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
@setEvalBranchQuota(10000);
const max_bits = 256;
@@ -405,6 +410,7 @@ test "PackedIntSlice" {
}
test "PackedIntSlice of PackedInt(Array/Slice)" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
const max_bits = 16;
const int_count = 19;
@@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {
}
test "PackedIntSlice accumulating bit offsets" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
//bit_offset is u3, so standard debugging asserts should catch
// anything
{
@@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" {
//@NOTE: As I do not have a big endian system to test this on,
// big endian values were not tested
test "PackedInt(Array/Slice) sliceCast" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
const PackedArray = PackedIntArray(u1, 16);
var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
const packed_slice_cast_2 = packed_array.sliceCast(u2);
@@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" {
}
test "PackedInt(Array/Slice)Endian" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
{
const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
var packed_array_be = PackedArrayBe.init([_]u4{ 0, 1, 2, 3, 4, 5, 6, 7 });
@@ -604,6 +615,8 @@ test "PackedInt(Array/Slice)Endian" {
// after this one is not mapped and will cause a segfault if we
// don't account for the bounds.
test "PackedIntArray at end of available memory" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
switch (builtin.os.tag) {
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
@@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" {
}
test "PackedIntSlice at end of available memory" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
switch (builtin.os.tag) {
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
diff --git a/src/Compilation.zig b/src/Compilation.zig
@@ -352,6 +352,7 @@ pub const InitOptions = struct {
time_report: bool = false,
stack_report: bool = false,
link_eh_frame_hdr: bool = false,
+ link_emit_relocs: bool = false,
linker_script: ?[]const u8 = null,
version_script: ?[]const u8 = null,
override_soname: ?[]const u8 = null,
@@ -447,6 +448,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
options.system_libs.len != 0 or
options.link_libc or options.link_libcpp or
options.link_eh_frame_hdr or
+ options.link_emit_relocs or
options.output_mode == .Lib or
options.lld_argv.len != 0 or
options.linker_script != null or options.version_script != null)
@@ -769,6 +771,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.version_script = options.version_script,
.gc_sections = options.linker_gc_sections,
.eh_frame_hdr = options.link_eh_frame_hdr,
+ .emit_relocs = options.link_emit_relocs,
.rdynamic = options.rdynamic,
.extra_lld_args = options.lld_argv,
.override_soname = options.override_soname,
@@ -1146,7 +1149,15 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
};
}
-pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
+pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemory }!void {
+ var progress: std.Progress = .{};
+ var main_progress_node = try progress.start("", null);
+ defer main_progress_node.end();
+ if (self.color == .Off) progress.terminal = null;
+
+ var c_comp_progress_node = main_progress_node.start("Compile C Objects", self.c_source_files.len);
+ defer c_comp_progress_node.end();
+
while (self.work_queue.readItem()) |work_item| switch (work_item) {
.codegen_decl => |decl| switch (decl.analysis) {
.unreferenced => unreachable,
@@ -1223,7 +1234,7 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
};
},
.c_object => |c_object| {
- self.updateCObject(c_object) catch |err| switch (err) {
+ self.updateCObject(c_object, &c_comp_progress_node) catch |err| switch (err) {
error.AnalysisFail => continue,
else => {
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 {
if (!build_options.is_stage1)
unreachable;
- self.updateStage1Module() catch |err| {
+ self.updateStage1Module(main_progress_node) catch |err| {
fatal("unable to build stage1 zig object: {}", .{@errorName(err)});
};
},
@@ -1470,7 +1481,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
};
}
-fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
+fn updateCObject(comp: *Compilation, c_object: *CObject, c_comp_progress_node: *std.Progress.Node) !void {
if (!build_options.have_llvm) {
return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
}
@@ -1513,6 +1524,12 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
const arena = &arena_allocator.allocator;
const c_source_basename = std.fs.path.basename(c_object.src.src_path);
+
+ c_comp_progress_node.activate();
+ var child_progress_node = c_comp_progress_node.start(c_source_basename, null);
+ child_progress_node.activate();
+ defer child_progress_node.end();
+
// Special case when doing build-obj for just one C file. When there are more than one object
// file and building an object we need to link them together, but with just one it should go
// directly to the output file.
@@ -2506,7 +2523,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
};
}
-fn updateStage1Module(comp: *Compilation) !void {
+fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -2612,10 +2629,6 @@ fn updateStage1Module(comp: *Compilation) !void {
.llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
.llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?,
};
- var progress: std.Progress = .{};
- var main_progress_node = try progress.start("", null);
- defer main_progress_node.end();
- if (comp.color == .Off) progress.terminal = null;
comp.stage1_cache_manifest = &man;
diff --git a/src/link.zig b/src/link.zig
@@ -60,6 +60,7 @@ pub const Options = struct {
link_libcpp: bool,
function_sections: bool,
eh_frame_hdr: bool,
+ emit_relocs: bool,
rdynamic: bool,
z_nodelete: bool,
z_defs: bool,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -1286,6 +1286,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
man.hash.add(stack_size);
man.hash.add(gc_sections);
man.hash.add(self.base.options.eh_frame_hdr);
+ man.hash.add(self.base.options.emit_relocs);
man.hash.add(self.base.options.rdynamic);
man.hash.addListOfBytes(self.base.options.extra_lld_args);
man.hash.addListOfBytes(self.base.options.lib_dirs);
@@ -1364,6 +1365,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
if (self.base.options.eh_frame_hdr) {
try argv.append("--eh-frame-hdr");
}
+
+ if (self.base.options.emit_relocs) {
+ try argv.append("--emit-relocs");
+ }
if (self.base.options.rdynamic) {
try argv.append("--export-dynamic");
diff --git a/src/main.zig b/src/main.zig
@@ -273,6 +273,7 @@ const usage_build_generic =
\\ -rdynamic Add all symbols to the dynamic symbol table
\\ -rpath [path] Add directory to the runtime library search path
\\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
+ \\ --emit-relocs Enable output of relocation sections for post build tools
\\ -dynamic Force output to be dynamically linked
\\ -static Force output to be statically linked
\\ -Bsymbolic Bind global references locally
@@ -438,6 +439,7 @@ fn buildOutputType(
var use_lld: ?bool = null;
var use_clang: ?bool = null;
var link_eh_frame_hdr = false;
+ var link_emit_relocs = false;
var each_lib_rpath = false;
var libc_paths_file: ?[]const u8 = null;
var machine_code_model: std.builtin.CodeModel = .default;
@@ -838,6 +840,8 @@ fn buildOutputType(
function_sections = true;
} else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
link_eh_frame_hdr = true;
+ } else if (mem.eql(u8, arg, "--emit-relocs")) {
+ link_emit_relocs = true;
} else if (mem.eql(u8, arg, "-Bsymbolic")) {
linker_bind_global_refs_locally = true;
} else if (mem.eql(u8, arg, "--verbose-link")) {
@@ -1206,6 +1210,10 @@ fn buildOutputType(
fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});
}
+ if (root_src_file == null and arg_mode == .zig_test) {
+ fatal("one zig source file is required to run `zig test`", .{});
+ }
+
const root_name = if (provided_name) |n| n else blk: {
if (arg_mode == .zig_test) {
break :blk "test";
@@ -1580,6 +1588,7 @@ fn buildOutputType(
.linker_z_nodelete = linker_z_nodelete,
.linker_z_defs = linker_z_defs,
.link_eh_frame_hdr = link_eh_frame_hdr,
+ .link_emit_relocs = link_emit_relocs,
.stack_size_override = stack_size_override,
.strip = strip,
.single_threaded = single_threaded,
diff --git a/src/mingw.zig b/src/mingw.zig
@@ -32,6 +32,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
var args = std.ArrayList([]const u8).init(arena);
try add_cc_args(comp, arena, &args);
try args.appendSlice(&[_][]const u8{
+ "-D_SYSCRT=1",
+ "-DCRTDLL=1",
"-U__CRTDLL__",
"-D__MSVCRT__",
// Uncomment these 3 things for crtu
@@ -53,6 +55,8 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
var args = std.ArrayList([]const u8).init(arena);
try add_cc_args(comp, arena, &args);
try args.appendSlice(&[_][]const u8{
+ "-D_SYSCRT=1",
+ "-DCRTDLL=1",
"-U__CRTDLL__",
"-D__MSVCRT__",
});
@@ -437,11 +441,8 @@ fn findDef(comp: *Compilation, allocator: *Allocator, lib_name: []const u8) ![]u
const lib_path = switch (target.cpu.arch) {
.i386 => "lib32",
.x86_64 => "lib64",
- .arm, .armeb => switch (target.cpu.arch.ptrBitWidth()) {
- 32 => "libarm32",
- 64 => "libarm64",
- else => unreachable,
- },
+ .arm, .armeb, .thumb, .thumbeb, .aarch64_32 => "libarm32",
+ .aarch64, .aarch64_be => "libarm64",
else => unreachable,
};
diff --git a/src/stage1.zig b/src/stage1.zig
@@ -39,7 +39,11 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
for (args) |*arg, i| {
arg.* = mem.spanZ(argv[i]);
}
- stage2.mainArgs(gpa, arena, args) catch |err| fatal("{}", .{@errorName(err)});
+ if (std.builtin.mode == .Debug) {
+ stage2.mainArgs(gpa, arena, args) catch unreachable;
+ } else {
+ stage2.mainArgs(gpa, arena, args) catch |err| fatal("{}", .{@errorName(err)});
+ }
return 0;
}
diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp
@@ -18,11 +18,6 @@
#include "target.hpp"
#include "tokenizer.hpp"
-#ifndef NDEBUG
-#define DBG_MACRO_NO_WARNING
-#include <dbg.h>
-#endif
-
struct AstNode;
struct ZigFn;
struct Scope;
@@ -1456,6 +1451,7 @@ struct ZigTypeEnum {
ContainerLayout layout;
ResolveStatus resolve_status;
+ bool has_explicit_tag_type;
bool non_exhaustive;
bool resolve_loop_flag;
};
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp
@@ -1802,10 +1802,18 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
}
return type_allowed_in_extern(g, child_type, result);
}
- case ZigTypeIdEnum:
- *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
- type_entry->data.enumeration.layout == ContainerLayoutPacked;
- return ErrorNone;
+ case ZigTypeIdEnum: {
+ if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
+ return err;
+ ZigType *tag_int_type = type_entry->data.enumeration.tag_int_type;
+ if (type_entry->data.enumeration.has_explicit_tag_type) {
+ return type_allowed_in_extern(g, tag_int_type, result);
+ } else {
+ *result = type_entry->data.enumeration.layout == ContainerLayoutExtern ||
+ type_entry->data.enumeration.layout == ContainerLayoutPacked;
+ return ErrorNone;
+ }
+ }
case ZigTypeIdUnion:
*result = type_entry->data.unionation.layout == ContainerLayoutExtern ||
type_entry->data.unionation.layout == ContainerLayoutPacked;
@@ -2639,9 +2647,11 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
if (decl_node->type == NodeTypeContainerDecl) {
if (decl_node->data.container_decl.init_arg_expr != nullptr) {
wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
+ enum_type->data.enumeration.has_explicit_tag_type = true;
}
} else {
wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
+ enum_type->data.enumeration.has_explicit_tag_type = true;
}
if (wanted_tag_int_type != nullptr) {
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
@@ -8837,7 +8837,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
- buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n");
+ buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", ZIG_LINK_MODE);
buf_appendf(contents, "pub const is_test = false;\n");
buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
diff --git a/src/stage1/config.h.in b/src/stage1/config.h.in
@@ -21,5 +21,6 @@
#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
#define ZIG_LLVM_CONFIG_EXE "@LLVM_CONFIG_EXE@"
#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
+#define ZIG_LINK_MODE "@ZIG_LINK_MODE@"
#endif
diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp
@@ -25034,7 +25034,7 @@ static ZigValue *create_ptr_like_type_info(IrAnalyze *ira, IrInst *source_instr,
fields[2]->special = ConstValSpecialStatic;
fields[2]->type = ira->codegen->builtin_types.entry_bool;
fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile;
- // alignment: u32
+ // alignment: comptime_int
ensure_field_index(result->type, "alignment", 3);
fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int;
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
union_field_val->special = ConstValSpecialStatic;
union_field_val->type = type_info_union_field_type;
- ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 2);
+ ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 3);
+ // field_type: type
inner_fields[1]->special = ConstValSpecialStatic;
inner_fields[1]->type = ira->codegen->builtin_types.entry_type;
inner_fields[1]->data.x_type = union_field->type_entry;
+ // alignment: comptime_int
+ inner_fields[2]->special = ConstValSpecialStatic;
+ inner_fields[2]->type = ira->codegen->builtin_types.entry_num_lit_int;
+ bigint_init_unsigned(&inner_fields[2]->data.x_bigint, union_field->align);
+
ZigValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
@@ -25509,7 +25515,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
struct_field_val->special = ConstValSpecialStatic;
struct_field_val->type = type_info_struct_field_type;
- ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 4);
+ ZigValue **inner_fields = alloc_const_vals_ptrs(ira->codegen, 5);
inner_fields[1]->special = ConstValSpecialStatic;
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
}
set_optional_payload(inner_fields[2], struct_field->init_val);
+ // is_comptime: bool
inner_fields[3]->special = ConstValSpecialStatic;
inner_fields[3]->type = ira->codegen->builtin_types.entry_bool;
inner_fields[3]->data.x_bool = struct_field->is_comptime;
+ // alignment: comptime_int
+ inner_fields[4]->special = ConstValSpecialStatic;
+ inner_fields[4]->type = ira->codegen->builtin_types.entry_num_lit_int;
+ bigint_init_unsigned(&inner_fields[4]->data.x_bigint, struct_field->align);
+
ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
@@ -25559,7 +25571,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
result->special = ConstValSpecialStatic;
result->type = ir_type_info_get_type(ira, "Fn", nullptr);
- ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 5);
+ ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 6);
result->data.x_struct.fields = fields;
// calling_convention: TypeInfo.CallingConvention
@@ -25567,38 +25579,42 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
fields[0]->special = ConstValSpecialStatic;
fields[0]->type = get_builtin_type(ira->codegen, "CallingConvention");
bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc);
+ // alignment: u29
+ ensure_field_index(result->type, "alignment", 1);
+ fields[1]->special = ConstValSpecialStatic;
+ fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
+ bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.fn.fn_type_id.alignment);
// is_generic: bool
- ensure_field_index(result->type, "is_generic", 1);
+ ensure_field_index(result->type, "is_generic", 2);
bool is_generic = type_entry->data.fn.is_generic;
- fields[1]->special = ConstValSpecialStatic;
- fields[1]->type = ira->codegen->builtin_types.entry_bool;
- fields[1]->data.x_bool = is_generic;
- // is_varargs: bool
- ensure_field_index(result->type, "is_var_args", 2);
- bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
fields[2]->special = ConstValSpecialStatic;
fields[2]->type = ira->codegen->builtin_types.entry_bool;
- fields[2]->data.x_bool = type_entry->data.fn.fn_type_id.is_var_args;
- // return_type: ?type
- ensure_field_index(result->type, "return_type", 3);
+ fields[2]->data.x_bool = is_generic;
+ // is_varargs: bool
+ ensure_field_index(result->type, "is_var_args", 3);
+ bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args;
fields[3]->special = ConstValSpecialStatic;
- fields[3]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
+ fields[3]->type = ira->codegen->builtin_types.entry_bool;
+ fields[3]->data.x_bool = is_varargs;
+ // return_type: ?type
+ ensure_field_index(result->type, "return_type", 4);
+ fields[4]->special = ConstValSpecialStatic;
+ fields[4]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
if (type_entry->data.fn.fn_type_id.return_type == nullptr)
- fields[3]->data.x_optional = nullptr;
+ fields[4]->data.x_optional = nullptr;
else {
ZigValue *return_type = ira->codegen->pass1_arena->create<ZigValue>();
return_type->special = ConstValSpecialStatic;
return_type->type = ira->codegen->builtin_types.entry_type;
return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type;
- fields[3]->data.x_optional = return_type;
+ fields[4]->data.x_optional = return_type;
}
// args: []TypeInfo.FnArg
ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr);
if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) {
zig_unreachable();
}
- size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count -
- (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC);
+ size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count;
ZigValue *fn_arg_array = ira->codegen->pass1_arena->create<ZigValue>();
fn_arg_array->special = ConstValSpecialStatic;
@@ -25606,7 +25622,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy
fn_arg_array->data.x_array.special = ConstArraySpecialNone;
fn_arg_array->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(fn_arg_count);
- init_const_slice(ira->codegen, fields[4], fn_arg_array, 0, fn_arg_count, false);
+ init_const_slice(ira->codegen, fields[5], fn_arg_array, 0, fn_arg_count, false);
for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
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
buf_sprintf("sentinels are only allowed on slices and unknown-length pointers"));
return ira->codegen->invalid_inst_gen->value->type;
}
- BigInt *bi = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
- if (bi == nullptr)
+
+ BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 3);
+ if (alignment == nullptr)
return ira->codegen->invalid_inst_gen->value->type;
bool is_const;
@@ -25903,7 +25920,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
is_const,
is_volatile,
ptr_len,
- bigint_as_u32(bi),
+ bigint_as_u32(alignment),
0, // bit_offset_in_host
0, // host_int_bytes
is_allowzero,
@@ -26140,6 +26157,10 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
}
if ((err = get_const_field_bool(ira, source_instr->source_node, field_value, "is_comptime", 3, &field->is_comptime)))
return ira->codegen->invalid_inst_gen->value->type;
+ BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 4);
+ if (alignment == nullptr)
+ return ira->codegen->invalid_inst_gen->value->type;
+ field->align = bigint_as_u32(alignment);
}
return entry;
@@ -26157,6 +26178,13 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
ZigType *tag_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "tag_type", 1);
+ if (type_is_invalid(tag_type))
+ return ira->codegen->invalid_inst_gen->value->type;
+ if (tag_type->id != ZigTypeIdInt) {
+ ir_add_error(ira, source_instr, buf_sprintf(
+ "TypeInfo.Enum.tag_type must be an integer type, not '%s'", buf_ptr(&tag_type->name)));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);
if (fields_value == nullptr)
@@ -26302,14 +26330,113 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
return ira->codegen->invalid_inst_gen->value->type;
field->type_val = type_value;
field->type_entry = type_value->data.x_type;
+ BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, field_value, "alignment", 2);
+ if (alignment == nullptr)
+ return ira->codegen->invalid_inst_gen->value->type;
+ field->align = bigint_as_u32(alignment);
}
return entry;
}
case ZigTypeIdFn:
- case ZigTypeIdBoundFn:
- ir_add_error(ira, source_instr, buf_sprintf(
- "@Type not available for 'TypeInfo.%s'", type_id_name(tagTypeId)));
- return ira->codegen->invalid_inst_gen->value->type;
+ case ZigTypeIdBoundFn: {
+ assert(payload->special == ConstValSpecialStatic);
+ assert(payload->type == ir_type_info_get_type(ira, "Fn", nullptr));
+
+ ZigValue *cc_value = get_const_field(ira, source_instr->source_node, payload, "calling_convention", 0);
+ if (cc_value == nullptr)
+ return ira->codegen->invalid_inst_gen->value->type;
+ assert(cc_value->special == ConstValSpecialStatic);
+ assert(cc_value->type == get_builtin_type(ira->codegen, "CallingConvention"));
+ CallingConvention cc = (CallingConvention)bigint_as_u32(&cc_value->data.x_enum_tag);
+
+ BigInt *alignment = get_const_field_lit_int(ira, source_instr->source_node, payload, "alignment", 1);
+ if (alignment == nullptr)
+ return ira->codegen->invalid_inst_gen->value->type;
+
+ Error err;
+ bool is_generic;
+ if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_generic", 2, &is_generic)))
+ return ira->codegen->invalid_inst_gen->value->type;
+ if (is_generic) {
+ ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.Fn.is_generic must be false for @Type"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
+
+ bool is_var_args;
+ if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_var_args", 3, &is_var_args)))
+ return ira->codegen->invalid_inst_gen->value->type;
+ if (is_var_args && cc != CallingConventionC) {
+ ir_add_error(ira, source_instr, buf_sprintf("varargs functions must have C calling convention"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
+
+ ZigType *return_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "return_type", 4);
+ if (return_type == nullptr) {
+ ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.Fn.return_type must be non-null for @Type"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
+
+ ZigValue *args_value = get_const_field(ira, source_instr->source_node, payload, "args", 5);
+ if (args_value == nullptr)
+ return ira->codegen->invalid_inst_gen->value->type;
+ assert(args_value->special == ConstValSpecialStatic);
+ assert(is_slice(args_value->type));
+ ZigValue *args_ptr = args_value->data.x_struct.fields[slice_ptr_index];
+ ZigValue *args_len_value = args_value->data.x_struct.fields[slice_len_index];
+ size_t args_len = bigint_as_usize(&args_len_value->data.x_bigint);
+
+ FnTypeId fn_type_id = {};
+ fn_type_id.return_type = return_type;
+ fn_type_id.param_info = heap::c_allocator.allocate<FnTypeParamInfo>(args_len);
+ fn_type_id.param_count = args_len;
+ fn_type_id.next_param_index = args_len;
+ fn_type_id.is_var_args = is_var_args;
+ fn_type_id.cc = cc;
+ fn_type_id.alignment = bigint_as_u32(alignment);
+
+ assert(args_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ assert(args_ptr->data.x_ptr.data.base_array.elem_index == 0);
+ ZigValue *args_arr = args_ptr->data.x_ptr.data.base_array.array_val;
+ assert(args_arr->special == ConstValSpecialStatic);
+ assert(args_arr->data.x_array.special == ConstArraySpecialNone);
+ for (size_t i = 0; i < args_len; i++) {
+ ZigValue *arg_value = &args_arr->data.x_array.data.s_none.elements[i];
+ assert(arg_value->type == ir_type_info_get_type(ira, "FnArg", nullptr));
+ FnTypeParamInfo *info = &fn_type_id.param_info[i];
+ Error err;
+ bool is_generic;
+ if ((err = get_const_field_bool(ira, source_instr->source_node, arg_value, "is_generic", 0, &is_generic)))
+ return ira->codegen->invalid_inst_gen->value->type;
+ if (is_generic) {
+ ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.FnArg.is_generic must be false for @Type"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
+ if ((err = get_const_field_bool(ira, source_instr->source_node, arg_value, "is_noalias", 1, &info->is_noalias)))
+ return ira->codegen->invalid_inst_gen->value->type;
+ ZigType *type = get_const_field_meta_type_optional(
+ ira, source_instr->source_node, arg_value, "arg_type", 2);
+ if (type == nullptr) {
+ ir_add_error(ira, source_instr, buf_sprintf("TypeInfo.FnArg.arg_type must be non-null for @Type"));
+ return ira->codegen->invalid_inst_gen->value->type;
+ }
+ info->type = type;
+ }
+
+ ZigType *entry = get_fn_type(ira->codegen, &fn_type_id);
+
+ switch (tagTypeId) {
+ case ZigTypeIdFn:
+ return entry;
+ case ZigTypeIdBoundFn: {
+ ZigType *bound_fn_entry = new_type_table_entry(ZigTypeIdBoundFn);
+ bound_fn_entry->name = *buf_sprintf("(bound %s)", buf_ptr(&entry->name));
+ bound_fn_entry->data.bound_fn.fn_type = entry;
+ return bound_fn_entry;
+ }
+ default:
+ zig_unreachable();
+ }
+ }
}
zig_unreachable();
}
diff --git a/src/stage1/os.cpp b/src/stage1/os.cpp
@@ -94,106 +94,6 @@ static clock_serv_t macos_monotonic_clock;
extern char **environ;
#endif
-#if defined(ZIG_OS_POSIX)
-static void populate_termination(Termination *term, int status) {
- if (WIFEXITED(status)) {
- term->how = TerminationIdClean;
- term->code = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- term->how = TerminationIdSignaled;
- term->code = WTERMSIG(status);
- } else if (WIFSTOPPED(status)) {
- term->how = TerminationIdStopped;
- term->code = WSTOPSIG(status);
- } else {
- term->how = TerminationIdUnknown;
- term->code = status;
- }
-}
-
-static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) {
- const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
- for (size_t i = 0; i < args.length; i += 1) {
- argv[i] = args.at(i);
- }
- argv[args.length] = nullptr;
-
- pid_t pid;
- int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ);
- if (rc != 0) {
- zig_panic("unable to spawn %s: %s", args.at(0), strerror(rc));
- }
-
- int status;
- waitpid(pid, &status, 0);
- populate_termination(term, status);
- heap::c_allocator.deallocate(argv, args.length + 1);
-}
-#endif
-
-#if defined(ZIG_OS_WINDOWS)
-
-static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) {
- buf_resize(command_line, 0);
- const char *prefix = "\"";
- for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) {
- const char *arg = args.at(arg_i);
- buf_append_str(command_line, prefix);
- prefix = " \"";
- size_t arg_len = strlen(arg);
- for (size_t c_i = 0; c_i < arg_len; c_i += 1) {
- if (arg[c_i] == '\"') {
- zig_panic("TODO");
- }
- buf_append_char(command_line, arg[c_i]);
- }
- buf_append_char(command_line, '\"');
- }
-}
-
-static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) {
- Buf command_line = BUF_INIT;
- os_windows_create_command_line(&command_line, args);
-
- PROCESS_INFORMATION piProcInfo = {0};
- STARTUPINFOW siStartInfo = {0};
- siStartInfo.cb = sizeof(STARTUPINFOW);
-
- Slice<uint8_t> exe_slice = str(args.at(0));
- auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1);
- exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0;
-
- auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1);
- command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0;
-
- BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr,
- &siStartInfo, &piProcInfo);
-
- if (!success) {
- zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line));
- }
-
- WaitForSingleObject(piProcInfo.hProcess, INFINITE);
-
- DWORD exit_code;
- if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
- zig_panic("GetExitCodeProcess failed");
- }
- term->how = TerminationIdClean;
- term->code = exit_code;
-}
-#endif
-
-void os_spawn_process(ZigList<const char *> &args, Termination *term) {
-#if defined(ZIG_OS_WINDOWS)
- os_spawn_process_windows(args, term);
-#elif defined(ZIG_OS_POSIX)
- os_spawn_process_posix(args, term);
-#else
-#error "missing os_spawn_process implementation"
-#endif
-}
-
void os_path_dirname(Buf *full_path, Buf *out_dirname) {
return os_path_split(full_path, out_dirname, nullptr);
}
@@ -281,71 +181,27 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
buf_append_buf(out_full_path, basename);
}
-Error os_path_real(Buf *rel_path, Buf *out_abs_path) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path));
- PathSpace out_abs_path_space;
-
- if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) {
- zig_panic("_wfullpath failed");
- }
- utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]);
- return ErrorNone;
-#elif defined(ZIG_OS_POSIX)
- buf_resize(out_abs_path, PATH_MAX + 1);
- char *result = realpath(buf_ptr(rel_path), buf_ptr(out_abs_path));
- if (!result) {
- int err = errno;
- if (err == EACCES) {
- return ErrorAccess;
- } else if (err == ENOENT) {
- return ErrorFileNotFound;
- } else if (err == ENOMEM) {
- return ErrorNoMem;
- } else {
- return ErrorFileSystem;
- }
- }
- buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));
- return ErrorNone;
-#else
-#error "missing os_path_real implementation"
-#endif
-}
-
-#if defined(ZIG_OS_WINDOWS)
-// Ported from std/os/path.zig
-static bool isAbsoluteWindows(Slice<uint8_t> path) {
- if (path.ptr[0] == '/')
- return true;
-
- if (path.ptr[0] == '\\') {
- return true;
- }
- if (path.len < 3) {
- return false;
- }
- if (path.ptr[1] == ':') {
- if (path.ptr[2] == '/')
- return true;
- if (path.ptr[2] == '\\')
- return true;
- }
- return false;
-}
-#endif
-
-bool os_path_is_absolute(Buf *path) {
-#if defined(ZIG_OS_WINDOWS)
- return isAbsoluteWindows(buf_to_slice(path));
-#elif defined(ZIG_OS_POSIX)
- return buf_ptr(path)[0] == '/';
-#else
-#error "missing os_path_is_absolute implementation"
-#endif
-}
-#if defined(ZIG_OS_WINDOWS)
+#if defined(ZIG_OS_WINDOWS)
+// Ported from std/os/path.zig
+static bool isAbsoluteWindows(Slice<uint8_t> path) {
+ if (path.ptr[0] == '/')
+ return true;
+
+ if (path.ptr[0] == '\\') {
+ return true;
+ }
+ if (path.len < 3) {
+ return false;
+ }
+ if (path.ptr[1] == ':') {
+ if (path.ptr[2] == '/')
+ return true;
+ if (path.ptr[2] == '\\')
+ return true;
+ }
+ return false;
+}
enum WindowsPathKind {
WindowsPathKindNone,
@@ -688,7 +544,7 @@ static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
size_t max_size = 0;
for (size_t i = 0; i < paths_len; i += 1) {
Buf *p = paths_ptr[i];
- if (os_path_is_absolute(p)) {
+ if (buf_ptr(p)[0] == '/') {
first_index = i;
have_abs = true;
max_size = 0;
@@ -788,256 +644,6 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {
zig_unreachable();
}
-Error os_file_exists(Buf *full_path, bool *result) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
- *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES;
- return ErrorNone;
-#else
- *result = access(buf_ptr(full_path), F_OK) != -1;
- return ErrorNone;
-#endif
-}
-
-#if defined(ZIG_OS_POSIX)
-static Error os_exec_process_posix(ZigList<const char *> &args,
- Termination *term, Buf *out_stderr, Buf *out_stdout)
-{
- int stdin_pipe[2];
- int stdout_pipe[2];
- int stderr_pipe[2];
- int err_pipe[2];
-
- int err;
- if ((err = pipe(stdin_pipe)))
- zig_panic("pipe failed");
- if ((err = pipe(stdout_pipe)))
- zig_panic("pipe failed");
- if ((err = pipe(stderr_pipe)))
- zig_panic("pipe failed");
- if ((err = pipe(err_pipe)))
- zig_panic("pipe failed");
-
- pid_t pid = fork();
- if (pid == -1)
- zig_panic("fork failed: %s", strerror(errno));
- if (pid == 0) {
- // child
- if (dup2(stdin_pipe[0], STDIN_FILENO) == -1)
- zig_panic("dup2 failed");
-
- if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1)
- zig_panic("dup2 failed");
-
- if (dup2(stderr_pipe[1], STDERR_FILENO) == -1)
- zig_panic("dup2 failed");
-
- const char **argv = heap::c_allocator.allocate<const char *>(args.length + 1);
- argv[args.length] = nullptr;
- for (size_t i = 0; i < args.length; i += 1) {
- argv[i] = args.at(i);
- }
- execvp(argv[0], const_cast<char * const *>(argv));
- Error report_err = ErrorUnexpected;
- if (errno == ENOENT) {
- report_err = ErrorFileNotFound;
- }
- if (write(err_pipe[1], &report_err, sizeof(Error)) == -1) {
- zig_panic("write failed");
- }
- exit(1);
- } else {
- // parent
- close(stdin_pipe[0]);
- close(stdin_pipe[1]);
- close(stdout_pipe[1]);
- close(stderr_pipe[1]);
-
- int status;
- waitpid(pid, &status, 0);
- populate_termination(term, status);
-
- FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
- FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
- Error err1 = os_fetch_file(stdout_f, out_stdout);
- Error err2 = os_fetch_file(stderr_f, out_stderr);
-
- fclose(stdout_f);
- fclose(stderr_f);
-
- if (err1) return err1;
- if (err2) return err2;
-
- Error child_err = ErrorNone;
- if (write(err_pipe[1], &child_err, sizeof(Error)) == -1) {
- zig_panic("write failed");
- }
- close(err_pipe[1]);
- if (read(err_pipe[0], &child_err, sizeof(Error)) == -1) {
- zig_panic("write failed");
- }
- close(err_pipe[0]);
- return child_err;
- }
-}
-#endif
-
-#if defined(ZIG_OS_WINDOWS)
-
-//static void win32_panic(const char *str) {
-// DWORD err = GetLastError();
-// LPSTR messageBuffer = nullptr;
-// FormatMessageA(
-// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-// NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
-// zig_panic(str, messageBuffer);
-// LocalFree(messageBuffer);
-//}
-
-static Error os_exec_process_windows(ZigList<const char *> &args,
- Termination *term, Buf *out_stderr, Buf *out_stdout)
-{
- Buf command_line = BUF_INIT;
- os_windows_create_command_line(&command_line, args);
-
- HANDLE g_hChildStd_IN_Rd = NULL;
- HANDLE g_hChildStd_IN_Wr = NULL;
- HANDLE g_hChildStd_OUT_Rd = NULL;
- HANDLE g_hChildStd_OUT_Wr = NULL;
- HANDLE g_hChildStd_ERR_Rd = NULL;
- HANDLE g_hChildStd_ERR_Wr = NULL;
-
- SECURITY_ATTRIBUTES saAttr;
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = NULL;
-
- if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) {
- zig_panic("StdoutRd CreatePipe");
- }
-
- if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
- zig_panic("Stdout SetHandleInformation");
- }
-
- if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) {
- zig_panic("stderr CreatePipe");
- }
-
- if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) {
- zig_panic("stderr SetHandleInformation");
- }
-
- if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) {
- zig_panic("Stdin CreatePipe");
- }
-
- if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) {
- zig_panic("Stdin SetHandleInformation");
- }
-
-
- PROCESS_INFORMATION piProcInfo = {0};
- STARTUPINFO siStartInfo = {0};
- siStartInfo.cb = sizeof(STARTUPINFO);
- siStartInfo.hStdError = g_hChildStd_ERR_Wr;
- siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
- siStartInfo.hStdInput = g_hChildStd_IN_Rd;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- const char *exe = args.at(0);
- BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
- &siStartInfo, &piProcInfo);
-
- if (!success) {
- if (GetLastError() == ERROR_FILE_NOT_FOUND) {
- CloseHandle(piProcInfo.hProcess);
- CloseHandle(piProcInfo.hThread);
- return ErrorFileNotFound;
- }
- zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));
- }
-
- if (!CloseHandle(g_hChildStd_IN_Wr)) {
- zig_panic("stdinwr closehandle");
- }
-
- CloseHandle(g_hChildStd_IN_Rd);
- CloseHandle(g_hChildStd_ERR_Wr);
- CloseHandle(g_hChildStd_OUT_Wr);
-
- static const size_t BUF_SIZE = 4 * 1024;
- {
- DWORD dwRead;
- char chBuf[BUF_SIZE];
-
- buf_resize(out_stdout, 0);
- for (;;) {
- success = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
- if (!success || dwRead == 0) break;
-
- buf_append_mem(out_stdout, chBuf, dwRead);
- }
- CloseHandle(g_hChildStd_OUT_Rd);
- }
- {
- DWORD dwRead;
- char chBuf[BUF_SIZE];
-
- buf_resize(out_stderr, 0);
- for (;;) {
- success = ReadFile( g_hChildStd_ERR_Rd, chBuf, BUF_SIZE, &dwRead, NULL);
- if (!success || dwRead == 0) break;
-
- buf_append_mem(out_stderr, chBuf, dwRead);
- }
- CloseHandle(g_hChildStd_ERR_Rd);
- }
-
- WaitForSingleObject(piProcInfo.hProcess, INFINITE);
-
- DWORD exit_code;
- if (!GetExitCodeProcess(piProcInfo.hProcess, &exit_code)) {
- zig_panic("GetExitCodeProcess failed");
- }
- term->how = TerminationIdClean;
- term->code = exit_code;
-
- CloseHandle(piProcInfo.hProcess);
- CloseHandle(piProcInfo.hThread);
-
- return ErrorNone;
-}
-#endif
-
-Error os_execv(const char *exe, const char **argv) {
-#if defined(ZIG_OS_WINDOWS)
- return ErrorUnsupportedOperatingSystem;
-#else
- execv(exe, (char *const *)argv);
- switch (errno) {
- case ENOMEM:
- return ErrorSystemResources;
- case EIO:
- return ErrorFileSystem;
- default:
- return ErrorUnexpected;
- }
-#endif
-}
-
-Error os_exec_process(ZigList<const char *> &args,
- Termination *term, Buf *out_stderr, Buf *out_stdout)
-{
-#if defined(ZIG_OS_WINDOWS)
- return os_exec_process_windows(args, term, out_stderr, out_stdout);
-#elif defined(ZIG_OS_POSIX)
- return os_exec_process_posix(args, term, out_stderr, out_stdout);
-#else
-#error "missing os_exec_process implementation"
-#endif
-}
-
Error os_write_file(Buf *full_path, Buf *contents) {
#if defined(ZIG_OS_WINDOWS)
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) {
}
}
-Error os_dump_file(Buf *src_path, FILE *dest_file) {
- Error err;
-
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
- FILE *src_f = _wfopen(&path_space.data.items[0], L"rb");
-#else
- FILE *src_f = fopen(buf_ptr(src_path), "rb");
-#endif
- if (!src_f) {
- int err = errno;
- if (err == ENOENT) {
- return ErrorFileNotFound;
- } else if (err == EACCES || err == EPERM) {
- return ErrorAccess;
- } else {
- return ErrorFileSystem;
- }
- }
- copy_open_files(src_f, dest_file);
- if ((err = copy_open_files(src_f, dest_file))) {
- fclose(src_f);
- return err;
- }
-
- fclose(src_f);
- return ErrorNone;
-}
-
#if defined(ZIG_OS_WINDOWS)
static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
@@ -1118,88 +695,6 @@ static FILETIME windows_os_timestamp_to_filetime(OsTimeStamp mtime) {
}
#endif
-static Error set_file_times(OsFile file, OsTimeStamp ts) {
-#if defined(ZIG_OS_WINDOWS)
- FILETIME ft = windows_os_timestamp_to_filetime(ts);
- if (SetFileTime(file, nullptr, &ft, &ft) == 0) {
- return ErrorUnexpected;
- }
- return ErrorNone;
-#else
- struct timespec times[2] = {
- { (time_t)ts.sec, (long)ts.nsec },
- { (time_t)ts.sec, (long)ts.nsec },
- };
- if (futimens(file, times) == -1) {
- switch (errno) {
- case EBADF:
- zig_panic("futimens EBADF");
- default:
- return ErrorUnexpected;
- }
- }
- return ErrorNone;
-#endif
-}
-
-Error os_update_file(Buf *src_path, Buf *dst_path) {
- Error err;
-
- OsFile src_file;
- OsFileAttr src_attr;
- if ((err = os_file_open_r(src_path, &src_file, &src_attr))) {
- return err;
- }
-
- OsFile dst_file;
- OsFileAttr dst_attr;
- if ((err = os_file_open_w(dst_path, &dst_file, &dst_attr, src_attr.mode))) {
- os_file_close(&src_file);
- return err;
- }
-
- if (src_attr.size == dst_attr.size &&
- src_attr.mode == dst_attr.mode &&
- src_attr.mtime.sec == dst_attr.mtime.sec &&
- src_attr.mtime.nsec == dst_attr.mtime.nsec)
- {
- os_file_close(&src_file);
- os_file_close(&dst_file);
- return ErrorNone;
- }
-#if defined(ZIG_OS_WINDOWS)
- if (SetEndOfFile(dst_file) == 0) {
- return ErrorUnexpected;
- }
-#else
- if (ftruncate(dst_file, 0) == -1) {
- return ErrorUnexpected;
- }
-#endif
-#if defined(ZIG_OS_WINDOWS)
- FILE *src_libc_file = _fdopen(_open_osfhandle((intptr_t)src_file, _O_RDONLY), "rb");
- FILE *dst_libc_file = _fdopen(_open_osfhandle((intptr_t)dst_file, 0), "wb");
-#else
- FILE *src_libc_file = fdopen(src_file, "rb");
- FILE *dst_libc_file = fdopen(dst_file, "wb");
-#endif
- assert(src_libc_file);
- assert(dst_libc_file);
-
- if ((err = copy_open_files(src_libc_file, dst_libc_file))) {
- fclose(src_libc_file);
- fclose(dst_libc_file);
- return err;
- }
- if (fflush(dst_libc_file) == -1) {
- return ErrorUnexpected;
- }
- err = set_file_times(dst_file, src_attr.mtime);
- fclose(src_libc_file);
- fclose(dst_libc_file);
- return err;
-}
-
Error os_copy_file(Buf *src_path, Buf *dest_path) {
#if defined(ZIG_OS_WINDOWS)
PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
@@ -1360,14 +855,6 @@ bool os_stderr_tty(void) {
#endif
}
-Error os_delete_file(Buf *path) {
- if (remove(buf_ptr(path))) {
- return ErrorFileSystem;
- } else {
- return ErrorNone;
- }
-}
-
Error os_rename(Buf *src_path, Buf *dest_path) {
if (buf_eql_buf(src_path, dest_path)) {
return ErrorNone;
@@ -1386,30 +873,6 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
return ErrorNone;
}
-OsTimeStamp os_timestamp_calendar(void) {
- OsTimeStamp result;
-#if defined(ZIG_OS_WINDOWS)
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- windows_filetime_to_os_timestamp(&ft, &result);
-#elif defined(__MACH__)
- mach_timespec_t mts;
-
- kern_return_t err = clock_get_time(macos_calendar_clock, &mts);
- assert(!err);
-
- result.sec = mts.tv_sec;
- result.nsec = mts.tv_nsec;
-#else
- struct timespec tms;
- clock_gettime(CLOCK_REALTIME, &tms);
-
- result.sec = tms.tv_sec;
- result.nsec = tms.tv_nsec;
-#endif
- return result;
-}
-
OsTimeStamp os_timestamp_monotonic(void) {
OsTimeStamp result;
#if defined(ZIG_OS_WINDOWS)
@@ -1503,49 +966,8 @@ Error os_make_dir(Buf *path) {
#endif
}
-static void init_rand() {
-#if defined(ZIG_OS_WINDOWS)
- char bytes[sizeof(unsigned)];
- unsigned seed;
- RtlGenRandom(bytes, sizeof(unsigned));
- memcpy(&seed, bytes, sizeof(unsigned));
- srand(seed);
-#elif defined(ZIG_OS_LINUX)
- unsigned char *ptr_random = (unsigned char*)getauxval(AT_RANDOM);
- unsigned seed;
- memcpy(&seed, ptr_random, sizeof(seed));
- srand(seed);
-#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
- unsigned seed;
- size_t len = sizeof(seed);
- int mib[2] = { CTL_KERN, KERN_ARND };
- if (sysctl(mib, 2, &seed, &len, NULL, 0) != 0) {
- zig_panic("unable to query random data from sysctl");
- }
- srand(seed);
-#else
- int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
- if (fd == -1) {
- zig_panic("unable to open /dev/urandom");
- }
- char bytes[sizeof(unsigned)];
- ssize_t amt_read;
- while ((amt_read = read(fd, bytes, sizeof(unsigned))) == -1) {
- if (errno == EINTR) continue;
- zig_panic("unable to read /dev/urandom");
- }
- if (amt_read != sizeof(unsigned)) {
- zig_panic("unable to read enough bytes from /dev/urandom");
- }
- close(fd);
- unsigned seed;
- memcpy(&seed, bytes, sizeof(unsigned));
- srand(seed);
-#endif
-}
int os_init(void) {
- init_rand();
#if defined(ZIG_OS_WINDOWS)
_setmode(fileno(stdout), _O_BINARY);
_setmode(fileno(stderr), _O_BINARY);
@@ -1582,71 +1004,6 @@ int os_init(void) {
return 0;
}
-Error os_self_exe_path(Buf *out_path) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space;
- DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE);
- if (copied_amt <= 0) {
- return ErrorFileNotFound;
- }
- utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]);
- return ErrorNone;
-
-#elif defined(ZIG_OS_DARWIN)
- // How long is the executable's path?
- uint32_t u32_len = 0;
- int ret1 = _NSGetExecutablePath(nullptr, &u32_len);
- assert(ret1 != 0);
-
- Buf *tmp = buf_alloc_fixed(u32_len);
-
- // Fill the executable path.
- int ret2 = _NSGetExecutablePath(buf_ptr(tmp), &u32_len);
- assert(ret2 == 0);
-
- // According to libuv project, PATH_MAX*2 works around a libc bug where
- // the resolved path is sometimes bigger than PATH_MAX.
- buf_resize(out_path, PATH_MAX*2);
- char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
- if (!real_path) {
- buf_init_from_buf(out_path, tmp);
- return ErrorNone;
- }
-
- // Resize out_path for the correct length.
- buf_resize(out_path, strlen(buf_ptr(out_path)));
-
- return ErrorNone;
-#elif defined(ZIG_OS_LINUX)
- buf_resize(out_path, PATH_MAX);
- ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
- if (amt == -1) {
- return ErrorUnexpected;
- }
- buf_resize(out_path, amt);
- return ErrorNone;
-#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_DRAGONFLY)
- buf_resize(out_path, PATH_MAX);
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
- size_t cb = PATH_MAX;
- if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
- return ErrorUnexpected;
- }
- buf_resize(out_path, cb - 1);
- return ErrorNone;
-#elif defined(ZIG_OS_NETBSD)
- buf_resize(out_path, PATH_MAX);
- int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
- size_t cb = PATH_MAX;
- if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
- return ErrorUnexpected;
- }
- buf_resize(out_path, cb - 1);
- return ErrorNone;
-#endif
- return ErrorFileNotFound;
-}
-
#define VT_RED "\x1b[31;1m"
#define VT_GREEN "\x1b[32;1m"
#define VT_CYAN "\x1b[36;1m"
@@ -1956,392 +1313,3 @@ PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
return path_space;
}
#endif
-
-// Ported from std.os.getAppDataDir
-Error os_get_app_data_dir(Buf *out_path, const char *appname) {
-#if defined(ZIG_OS_WINDOWS)
- WCHAR *dir_path_ptr;
- switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
- case S_OK:
- // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
- utf16le_ptr_to_utf8(out_path, dir_path_ptr);
- CoTaskMemFree(dir_path_ptr);
- buf_appendf(out_path, "\\%s", appname);
- return ErrorNone;
- case E_OUTOFMEMORY:
- return ErrorNoMem;
- default:
- return ErrorUnexpected;
- }
- zig_unreachable();
-#elif defined(ZIG_OS_DARWIN)
- const char *home_dir = getenv("HOME");
- if (home_dir == nullptr) {
- // TODO use /etc/passwd
- return ErrorFileNotFound;
- }
- buf_resize(out_path, 0);
- buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
- return ErrorNone;
-#elif defined(ZIG_OS_POSIX)
- const char *cache_dir = getenv("XDG_CACHE_HOME");
- if (cache_dir == nullptr) {
- cache_dir = getenv("HOME");
- if (cache_dir == nullptr) {
- // TODO use /etc/passwd
- return ErrorFileNotFound;
- }
- if (cache_dir[0] == 0) {
- return ErrorFileNotFound;
- }
- buf_init_from_str(out_path, cache_dir);
- if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
- buf_append_char(out_path, '/');
- }
- buf_appendf(out_path, ".cache/%s", appname);
- } else {
- if (cache_dir[0] == 0) {
- return ErrorFileNotFound;
- }
- buf_init_from_str(out_path, cache_dir);
- if (buf_ptr(out_path)[buf_len(out_path) - 1] != '/') {
- buf_append_char(out_path, '/');
- }
- buf_appendf(out_path, "%s", appname);
- }
- return ErrorNone;
-#endif
-}
-
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
-static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
- ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
- if (info->dlpi_name[0] == '/') {
- libs->append(buf_create_from_str(info->dlpi_name));
- }
- return 0;
-}
-#endif
-
-Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) || defined(ZIG_OS_DRAGONFLY)
- paths.resize(0);
- dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
- return ErrorNone;
-#elif defined(ZIG_OS_DARWIN)
- paths.resize(0);
- uint32_t img_count = _dyld_image_count();
- for (uint32_t i = 0; i != img_count; i += 1) {
- const char *name = _dyld_get_image_name(i);
- paths.append(buf_create_from_str(name));
- }
- return ErrorNone;
-#elif defined(ZIG_OS_WINDOWS)
- // zig is built statically on windows, so we can return an empty list
- paths.resize(0);
- return ErrorNone;
-#else
-#error unimplemented
-#endif
-}
-
-Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
- HANDLE result = CreateFileW(&path_space.data.items[0],
- need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
- need_write ? 0 : FILE_SHARE_READ,
- nullptr,
- need_write ? OPEN_ALWAYS : OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, nullptr);
-
- if (result == INVALID_HANDLE_VALUE) {
- DWORD err = GetLastError();
- switch (err) {
- case ERROR_SHARING_VIOLATION:
- return ErrorSharingViolation;
- case ERROR_ALREADY_EXISTS:
- return ErrorPathAlreadyExists;
- case ERROR_FILE_EXISTS:
- return ErrorPathAlreadyExists;
- case ERROR_FILE_NOT_FOUND:
- return ErrorFileNotFound;
- case ERROR_PATH_NOT_FOUND:
- return ErrorFileNotFound;
- case ERROR_ACCESS_DENIED:
- return ErrorAccess;
- case ERROR_PIPE_BUSY:
- return ErrorPipeBusy;
- default:
- return ErrorUnexpected;
- }
- }
- *out_file = result;
-
- if (attr != nullptr) {
- BY_HANDLE_FILE_INFORMATION file_info;
- if (!GetFileInformationByHandle(result, &file_info)) {
- CloseHandle(result);
- return ErrorUnexpected;
- }
- windows_filetime_to_os_timestamp(&file_info.ftLastWriteTime, &attr->mtime);
- attr->inode = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
- attr->mode = 0;
- attr->size = (((uint64_t)file_info.nFileSizeHigh) << 32) | file_info.nFileSizeLow;
- }
-
- return ErrorNone;
-#else
- for (;;) {
- int fd = open(buf_ptr(full_path),
- need_write ? (O_RDWR|O_CLOEXEC|O_CREAT) : (O_RDONLY|O_CLOEXEC), mode);
- if (fd == -1) {
- switch (errno) {
- case EINTR:
- continue;
- case EINVAL:
- zig_unreachable();
- case EFAULT:
- zig_unreachable();
- case EACCES:
- case EPERM:
- return ErrorAccess;
- case EISDIR:
- return ErrorIsDir;
- case ENOENT:
- return ErrorFileNotFound;
- default:
- return ErrorFileSystem;
- }
- }
- struct stat statbuf;
- if (fstat(fd, &statbuf) == -1) {
- close(fd);
- return ErrorFileSystem;
- }
- if (S_ISDIR(statbuf.st_mode)) {
- close(fd);
- return ErrorIsDir;
- }
- *out_file = fd;
-
- if (attr != nullptr) {
- attr->inode = statbuf.st_ino;
-#if defined(ZIG_OS_DARWIN)
- attr->mtime.sec = statbuf.st_mtimespec.tv_sec;
- attr->mtime.nsec = statbuf.st_mtimespec.tv_nsec;
-#else
- attr->mtime.sec = statbuf.st_mtim.tv_sec;
- attr->mtime.nsec = statbuf.st_mtim.tv_nsec;
-#endif
- attr->mode = statbuf.st_mode;
- attr->size = statbuf.st_size;
- }
- return ErrorNone;
- }
-#endif
-}
-
-Error os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr) {
- return os_file_open_rw(full_path, out_file, attr, false, 0);
-}
-
-Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode) {
- return os_file_open_rw(full_path, out_file, attr, true, mode);
-}
-
-Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
-#if defined(ZIG_OS_WINDOWS)
- PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
- for (;;) {
- HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE,
- 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
-
- if (result == INVALID_HANDLE_VALUE) {
- DWORD err = GetLastError();
- switch (err) {
- case ERROR_SHARING_VIOLATION:
- // TODO wait for the lock instead of sleeping
- Sleep(10);
- continue;
- case ERROR_ALREADY_EXISTS:
- return ErrorPathAlreadyExists;
- case ERROR_FILE_EXISTS:
- return ErrorPathAlreadyExists;
- case ERROR_FILE_NOT_FOUND:
- return ErrorFileNotFound;
- case ERROR_PATH_NOT_FOUND:
- return ErrorFileNotFound;
- case ERROR_ACCESS_DENIED:
- return ErrorAccess;
- case ERROR_PIPE_BUSY:
- return ErrorPipeBusy;
- default:
- return ErrorUnexpected;
- }
- }
- *out_file = result;
- return ErrorNone;
- }
-#else
- int fd;
- for (;;) {
- fd = open(buf_ptr(full_path), O_RDWR|O_CLOEXEC|O_CREAT, 0666);
- if (fd == -1) {
- switch (errno) {
- case EINTR:
- continue;
- case EINVAL:
- zig_unreachable();
- case EFAULT:
- zig_unreachable();
- case EACCES:
- case EPERM:
- return ErrorAccess;
- case EISDIR:
- return ErrorIsDir;
- case ENOENT:
- return ErrorFileNotFound;
- case ENOTDIR:
- return ErrorNotDir;
- default:
- return ErrorFileSystem;
- }
- }
- break;
- }
- for (;;) {
- struct flock lock;
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- if (fcntl(fd, F_SETLKW, &lock) == -1) {
- switch (errno) {
- case EINTR:
- continue;
- case EBADF:
- zig_unreachable();
- case EFAULT:
- zig_unreachable();
- case EINVAL:
- zig_unreachable();
- default:
- close(fd);
- return ErrorFileSystem;
- }
- }
- break;
- }
- *out_file = fd;
- return ErrorNone;
-#endif
-}
-
-Error os_file_read(OsFile file, void *ptr, size_t *len) {
-#if defined(ZIG_OS_WINDOWS)
- DWORD amt_read;
- if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0)
- return ErrorUnexpected;
- *len = amt_read;
- return ErrorNone;
-#else
- for (;;) {
- ssize_t rc = read(file, ptr, *len);
- if (rc == -1) {
- switch (errno) {
- case EINTR:
- continue;
- case EBADF:
- zig_unreachable();
- case EFAULT:
- zig_unreachable();
- case EISDIR:
- return ErrorIsDir;
- default:
- return ErrorFileSystem;
- }
- }
- *len = rc;
- return ErrorNone;
- }
-#endif
-}
-
-Error os_file_read_all(OsFile file, Buf *contents) {
- Error err;
- size_t index = 0;
- for (;;) {
- size_t amt = buf_len(contents) - index;
-
- if (amt < 4096) {
- buf_resize(contents, buf_len(contents) + (4096 - amt));
- amt = buf_len(contents) - index;
- }
-
- if ((err = os_file_read(file, buf_ptr(contents) + index, &amt)))
- return err;
-
- if (amt == 0) {
- buf_resize(contents, index);
- return ErrorNone;
- }
-
- index += amt;
- }
-}
-
-Error os_file_overwrite(OsFile file, Buf *contents) {
-#if defined(ZIG_OS_WINDOWS)
- if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- return ErrorFileSystem;
- if (!SetEndOfFile(file))
- return ErrorFileSystem;
- DWORD bytes_written;
- if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr))
- return ErrorFileSystem;
- return ErrorNone;
-#else
- if (lseek(file, 0, SEEK_SET) == -1)
- return ErrorUnexpectedSeekFailure;
- if (ftruncate(file, 0) == -1)
- return ErrorUnexpectedFileTruncationFailure;
- for (;;) {
- if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {
- switch (errno) {
- case EINTR:
- continue;
- case EINVAL:
- zig_unreachable();
- case EBADF:
- zig_unreachable();
- case EFAULT:
- zig_unreachable();
- case EDQUOT:
- return ErrorDiskQuota;
- case ENOSPC:
- return ErrorDiskSpace;
- case EFBIG:
- return ErrorFileTooBig;
- case EIO:
- return ErrorFileSystem;
- case EPERM:
- return ErrorAccess;
- default:
- return ErrorUnexpectedWriteFailure;
- }
- }
- return ErrorNone;
- }
-#endif
-}
-
-void os_file_close(OsFile *file) {
-#if defined(ZIG_OS_WINDOWS)
- CloseHandle(*file);
- *file = NULL;
-#else
- close(*file);
- *file = -1;
-#endif
-}
diff --git a/src/stage1/os.hpp b/src/stage1/os.hpp
@@ -70,66 +70,25 @@ enum TermColor {
TermColorReset,
};
-enum TerminationId {
- TerminationIdClean,
- TerminationIdSignaled,
- TerminationIdStopped,
- TerminationIdUnknown,
-};
-
-struct Termination {
- TerminationId how;
- int code;
-};
-
-#if defined(ZIG_OS_WINDOWS)
-#define OsFile void *
-#else
-#define OsFile int
-#endif
-
struct OsTimeStamp {
int64_t sec;
int64_t nsec;
};
-struct OsFileAttr {
- OsTimeStamp mtime;
- uint64_t size;
- uint64_t inode;
- uint32_t mode;
-};
-
int os_init(void);
-void os_spawn_process(ZigList<const char *> &args, Termination *term);
-Error os_exec_process(ZigList<const char *> &args,
- Termination *term, Buf *out_stderr, Buf *out_stdout);
-Error os_execv(const char *exe, const char **argv);
-
void os_path_dirname(Buf *full_path, Buf *out_dirname);
void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
-Error os_path_real(Buf *rel_path, Buf *out_abs_path);
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
bool os_path_is_absolute(Buf *path);
Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
-Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsFileAttr *attr);
-Error ATTRIBUTE_MUST_USE os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_t mode);
-Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
-Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
-Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
-Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
-void os_file_close(OsFile *file);
-
Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
-Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
-Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
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);
bool os_stderr_tty(void);
void os_stderr_set_color(TermColor color);
-Error os_delete_file(Buf *path);
-
-Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
-
Error os_rename(Buf *src_path, Buf *dest_path);
OsTimeStamp os_timestamp_monotonic(void);
-OsTimeStamp os_timestamp_calendar(void);
bool os_is_sep(uint8_t c);
-Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
-
-Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
-
-Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
-
const size_t PATH_MAX_WIDE = 32767;
struct PathSpace {
diff --git a/src/stage1/zig0.cpp b/src/stage1/zig0.cpp
@@ -430,6 +430,16 @@ int main(int argc, char **argv) {
return print_error_usage(arg0);
}
+ if (override_lib_dir == nullptr) {
+ fprintf(stderr, "missing --override-lib-dir\n");
+ return print_error_usage(arg0);
+ }
+
+ if (emit_bin_path == nullptr) {
+ fprintf(stderr, "missing -femit-bin=\n");
+ return print_error_usage(arg0);
+ }
+
ZigStage1 *stage1 = zig_stage1_create(optimize_mode,
nullptr, 0,
in_file, strlen(in_file),
diff --git a/src/target.zig b/src/target.zig
@@ -130,7 +130,6 @@ pub fn osRequiresLibC(target: std.Target) bool {
pub fn libcNeedsLibUnwind(target: std.Target) bool {
return switch (target.os.tag) {
- .windows,
.macosx,
.ios,
.watchos,
@@ -138,6 +137,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool {
.freestanding,
=> false,
+ .windows => target.abi != .msvc,
else => true,
};
}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
@@ -2,20 +2,175 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
- cases.add("slice sentinel mismatch",
+ cases.add("@Type for exhaustive enum with undefined tag type",
+ \\const TypeInfo = @import("builtin").TypeInfo;
+ \\const Tag = @Type(.{
+ \\ .Enum = .{
+ \\ .layout = .Auto,
+ \\ .tag_type = undefined,
+ \\ .fields = &[_]TypeInfo.EnumField{},
+ \\ .decls = &[_]TypeInfo.Declaration{},
+ \\ .is_exhaustive = false,
+ \\ },
+ \\});
\\export fn entry() void {
- \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };
+ \\ _ = @intToEnum(Tag, 0);
\\}
, &[_][]const u8{
- "tmp.zig:2:62: error: index 3 outside vector of size 3",
+ "tmp.zig:2:20: error: use of undefined value here causes undefined behavior",
});
- cases.add("slice sentinel mismatch",
+ cases.add("extern struct with non-extern-compatible integer tag type",
+ \\pub const E = enum(u31) { A, B, C };
+ \\pub const S = extern struct {
+ \\ e: E,
+ \\};
\\export fn entry() void {
- \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
+ \\ const s: S = undefined;
\\}
, &[_][]const u8{
- "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
+ "tmp.zig:3:5: error: extern structs cannot contain fields of type 'E'",
+ });
+
+ cases.add("@Type for exhaustive enum with non-integer tag type",
+ \\const TypeInfo = @import("builtin").TypeInfo;
+ \\const Tag = @Type(.{
+ \\ .Enum = .{
+ \\ .layout = .Auto,
+ \\ .tag_type = bool,
+ \\ .fields = &[_]TypeInfo.EnumField{},
+ \\ .decls = &[_]TypeInfo.Declaration{},
+ \\ .is_exhaustive = false,
+ \\ },
+ \\});
+ \\export fn entry() void {
+ \\ _ = @intToEnum(Tag, 0);
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:20: error: TypeInfo.Enum.tag_type must be an integer type, not 'bool'",
+ });
+
+ cases.add("extern struct with extern-compatible but inferred integer tag type",
+ \\pub const E = enum {
+ \\@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12",
+ \\@"13",@"14",@"15",@"16",@"17",@"18",@"19",@"20",@"21",@"22",@"23",
+ \\@"24",@"25",@"26",@"27",@"28",@"29",@"30",@"31",@"32",@"33",@"34",
+ \\@"35",@"36",@"37",@"38",@"39",@"40",@"41",@"42",@"43",@"44",@"45",
+ \\@"46",@"47",@"48",@"49",@"50",@"51",@"52",@"53",@"54",@"55",@"56",
+ \\@"57",@"58",@"59",@"60",@"61",@"62",@"63",@"64",@"65",@"66",@"67",
+ \\@"68",@"69",@"70",@"71",@"72",@"73",@"74",@"75",@"76",@"77",@"78",
+ \\@"79",@"80",@"81",@"82",@"83",@"84",@"85",@"86",@"87",@"88",@"89",
+ \\@"90",@"91",@"92",@"93",@"94",@"95",@"96",@"97",@"98",@"99",@"100",
+ \\@"101",@"102",@"103",@"104",@"105",@"106",@"107",@"108",@"109",
+ \\@"110",@"111",@"112",@"113",@"114",@"115",@"116",@"117",@"118",
+ \\@"119",@"120",@"121",@"122",@"123",@"124",@"125",@"126",@"127",
+ \\@"128",@"129",@"130",@"131",@"132",@"133",@"134",@"135",@"136",
+ \\@"137",@"138",@"139",@"140",@"141",@"142",@"143",@"144",@"145",
+ \\@"146",@"147",@"148",@"149",@"150",@"151",@"152",@"153",@"154",
+ \\@"155",@"156",@"157",@"158",@"159",@"160",@"161",@"162",@"163",
+ \\@"164",@"165",@"166",@"167",@"168",@"169",@"170",@"171",@"172",
+ \\@"173",@"174",@"175",@"176",@"177",@"178",@"179",@"180",@"181",
+ \\@"182",@"183",@"184",@"185",@"186",@"187",@"188",@"189",@"190",
+ \\@"191",@"192",@"193",@"194",@"195",@"196",@"197",@"198",@"199",
+ \\@"200",@"201",@"202",@"203",@"204",@"205",@"206",@"207",@"208",
+ \\@"209",@"210",@"211",@"212",@"213",@"214",@"215",@"216",@"217",
+ \\@"218",@"219",@"220",@"221",@"222",@"223",@"224",@"225",@"226",
+ \\@"227",@"228",@"229",@"230",@"231",@"232",@"233",@"234",@"235",
+ \\@"236",@"237",@"238",@"239",@"240",@"241",@"242",@"243",@"244",
+ \\@"245",@"246",@"247",@"248",@"249",@"250",@"251",@"252",@"253",
+ \\@"254",@"255"
+ \\};
+ \\pub const S = extern struct {
+ \\ e: E,
+ \\};
+ \\export fn entry() void {
+ \\ if (@TagType(E) != u8) @compileError("did not infer u8 tag type");
+ \\ const s: S = undefined;
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:31:5: error: extern structs cannot contain fields of type 'E'",
+ });
+
+ cases.add("@Type for tagged union with extra enum field",
+ \\const TypeInfo = @import("builtin").TypeInfo;
+ \\const Tag = @Type(.{
+ \\ .Enum = .{
+ \\ .layout = .Auto,
+ \\ .tag_type = u2,
+ \\ .fields = &[_]TypeInfo.EnumField{
+ \\ .{ .name = "signed", .value = 0 },
+ \\ .{ .name = "unsigned", .value = 1 },
+ \\ .{ .name = "arst", .value = 2 },
+ \\ },
+ \\ .decls = &[_]TypeInfo.Declaration{},
+ \\ .is_exhaustive = true,
+ \\ },
+ \\});
+ \\const Tagged = @Type(.{
+ \\ .Union = .{
+ \\ .layout = .Auto,
+ \\ .tag_type = Tag,
+ \\ .fields = &[_]TypeInfo.UnionField{
+ \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+ \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
+ \\ },
+ \\ .decls = &[_]TypeInfo.Declaration{},
+ \\ },
+ \\});
+ \\export fn entry() void {
+ \\ var tagged = Tagged{ .signed = -1 };
+ \\ tagged = .{ .unsigned = 1 };
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:15:23: error: enum field missing: 'arst'",
+ "tmp.zig:27:24: note: referenced here",
+ });
+ cases.add("@Type(.Fn) with is_generic = true",
+ \\const Foo = @Type(.{
+ \\ .Fn = .{
+ \\ .calling_convention = .Unspecified,
+ \\ .alignment = 0,
+ \\ .is_generic = true,
+ \\ .is_var_args = false,
+ \\ .return_type = u0,
+ \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
+ \\ },
+ \\});
+ \\comptime { _ = Foo; }
+ , &[_][]const u8{
+ "tmp.zig:1:20: error: TypeInfo.Fn.is_generic must be false for @Type",
+ });
+
+ cases.add("@Type(.Fn) with is_var_args = true and non-C callconv",
+ \\const Foo = @Type(.{
+ \\ .Fn = .{
+ \\ .calling_convention = .Unspecified,
+ \\ .alignment = 0,
+ \\ .is_generic = false,
+ \\ .is_var_args = true,
+ \\ .return_type = u0,
+ \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
+ \\ },
+ \\});
+ \\comptime { _ = Foo; }
+ , &[_][]const u8{
+ "tmp.zig:1:20: error: varargs functions must have C calling convention",
+ });
+
+ cases.add("@Type(.Fn) with return_type = null",
+ \\const Foo = @Type(.{
+ \\ .Fn = .{
+ \\ .calling_convention = .Unspecified,
+ \\ .alignment = 0,
+ \\ .is_generic = false,
+ \\ .is_var_args = false,
+ \\ .return_type = null,
+ \\ .args = &[_]@import("builtin").TypeInfo.FnArg{},
+ \\ },
+ \\});
+ \\comptime { _ = Foo; }
+ , &[_][]const u8{
+ "tmp.zig:1:20: error: TypeInfo.Fn.return_type must be non-null for @Type",
});
cases.add("@Type for union with opaque field",
@@ -25,7 +180,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ .layout = .Auto,
\\ .tag_type = null,
\\ .fields = &[_]TypeInfo.UnionField{
- \\ .{ .name = "foo", .field_type = @Type(.Opaque) },
+ \\ .{ .name = "foo", .field_type = @Type(.Opaque), .alignment = 1 },
\\ },
\\ .decls = &[_]TypeInfo.Declaration{},
\\ },
@@ -38,6 +193,22 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:13:17: note: referenced here",
});
+ cases.add("slice sentinel mismatch",
+ \\export fn entry() void {
+ \\ const x = @import("std").meta.Vector(3, f32){ 25, 75, 5, 0 };
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:62: error: index 3 outside vector of size 3",
+ });
+
+ cases.add("slice sentinel mismatch",
+ \\export fn entry() void {
+ \\ const y: [:1]const u8 = &[_:2]u8{ 1, 2 };
+ \\}
+ , &[_][]const u8{
+ "tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
+ });
+
cases.add("@Type for union with zero fields",
\\const TypeInfo = @import("builtin").TypeInfo;
\\const Untagged = @Type(.{
@@ -94,9 +265,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ .layout = .Auto,
\\ .tag_type = Tag,
\\ .fields = &[_]TypeInfo.UnionField{
- \\ .{ .name = "signed", .field_type = i32 },
- \\ .{ .name = "unsigned", .field_type = u32 },
- \\ .{ .name = "arst", .field_type = f32 },
+ \\ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+ \\ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
+ \\ .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) },
\\ },
\\ .decls = &[_]TypeInfo.Declaration{},
\\ },
@@ -111,42 +282,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:27:24: note: referenced here",
});
- cases.add("@Type for tagged union with extra enum field",
- \\const TypeInfo = @import("builtin").TypeInfo;
- \\const Tag = @Type(.{
- \\ .Enum = .{
- \\ .layout = .Auto,
- \\ .tag_type = u2,
- \\ .fields = &[_]TypeInfo.EnumField{
- \\ .{ .name = "signed", .value = 0 },
- \\ .{ .name = "unsigned", .value = 1 },
- \\ .{ .name = "arst", .field_type = 2 },
- \\ },
- \\ .decls = &[_]TypeInfo.Declaration{},
- \\ .is_exhaustive = true,
- \\ },
- \\});
- \\const Tagged = @Type(.{
- \\ .Union = .{
- \\ .layout = .Auto,
- \\ .tag_type = Tag,
- \\ .fields = &[_]TypeInfo.UnionField{
- \\ .{ .name = "signed", .field_type = i32 },
- \\ .{ .name = "unsigned", .field_type = u32 },
- \\ },
- \\ .decls = &[_]TypeInfo.Declaration{},
- \\ },
- \\});
- \\export fn entry() void {
- \\ var tagged = Tagged{ .signed = -1 };
- \\ tagged = .{ .unsigned = 1 };
- \\}
- , &[_][]const u8{
- "tmp.zig:9:32: error: no member named 'field_type' in struct 'std.builtin.EnumField'",
- "tmp.zig:18:21: note: referenced here",
- "tmp.zig:27:18: note: referenced here",
- });
-
cases.add("@Type with undefined",
\\comptime {
\\ _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } });
@@ -7556,7 +7691,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
});
cases.add( // fixed bug #2032
- "compile diagnostic string for top level decl type",
+ "compile diagnostic string for top level decl type",
\\export fn entry() void {
\\ var foo: u32 = @This(){};
\\}
diff --git a/test/stage1/behavior/bugs/1467.zig b/test/stage1/behavior/bugs/1467.zig
@@ -0,0 +1,7 @@
+pub const E = enum(u32) { A, B, C };
+pub const S = extern struct {
+ e: E,
+};
+test "bug 1467" {
+ const s: S = undefined;
+}
diff --git a/test/stage1/behavior/type.zig b/test/stage1/behavior/type.zig
@@ -320,8 +320,8 @@ test "Type.Union" {
.layout = .Auto,
.tag_type = null,
.fields = &[_]TypeInfo.UnionField{
- .{ .name = "int", .field_type = i32 },
- .{ .name = "float", .field_type = f32 },
+ .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
+ .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
},
.decls = &[_]TypeInfo.Declaration{},
},
@@ -336,8 +336,8 @@ test "Type.Union" {
.layout = .Packed,
.tag_type = null,
.fields = &[_]TypeInfo.UnionField{
- .{ .name = "signed", .field_type = i32 },
- .{ .name = "unsigned", .field_type = u32 },
+ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
},
.decls = &[_]TypeInfo.Declaration{},
},
@@ -363,8 +363,8 @@ test "Type.Union" {
.layout = .Auto,
.tag_type = Tag,
.fields = &[_]TypeInfo.UnionField{
- .{ .name = "signed", .field_type = i32 },
- .{ .name = "unsigned", .field_type = u32 },
+ .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
+ .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
},
.decls = &[_]TypeInfo.Declaration{},
},
@@ -392,7 +392,7 @@ test "Type.Union from Type.Enum" {
.layout = .Auto,
.tag_type = Tag,
.fields = &[_]TypeInfo.UnionField{
- .{ .name = "working_as_expected", .field_type = u32 },
+ .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
},
.decls = &[_]TypeInfo.Declaration{},
},
@@ -408,7 +408,7 @@ test "Type.Union from regular enum" {
.layout = .Auto,
.tag_type = E,
.fields = &[_]TypeInfo.UnionField{
- .{ .name = "working_as_expected", .field_type = u32 },
+ .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
},
.decls = &[_]TypeInfo.Declaration{},
},
@@ -416,3 +416,30 @@ test "Type.Union from regular enum" {
_ = T;
_ = @typeInfo(T).Union;
}
+
+test "Type.Fn" {
+ // wasm doesn't support align attributes on functions
+ if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
+
+ const foo = struct {
+ fn func(a: usize, b: bool) align(4) callconv(.C) usize {
+ return 0;
+ }
+ }.func;
+ const Foo = @Type(@typeInfo(@TypeOf(foo)));
+ const foo_2: Foo = foo;
+}
+
+test "Type.BoundFn" {
+ // wasm doesn't support align attributes on functions
+ if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
+
+ const TestStruct = packed struct {
+ pub fn foo(self: *const @This()) align(4) callconv(.Unspecified) void {}
+ };
+ const test_instance: TestStruct = undefined;
+ testing.expect(std.meta.eql(
+ @typeName(@TypeOf(test_instance.foo)),
+ @typeName(@Type(@typeInfo(@TypeOf(test_instance.foo)))),
+ ));
+}
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
@@ -211,7 +211,9 @@ fn testUnion() void {
expect(notag_union_info.Union.tag_type == null);
expect(notag_union_info.Union.layout == .Auto);
expect(notag_union_info.Union.fields.len == 2);
+ expect(notag_union_info.Union.fields[0].alignment == @alignOf(void));
expect(notag_union_info.Union.fields[1].field_type == u32);
+ expect(notag_union_info.Union.fields[1].alignment == @alignOf(u32));
const TestExternUnion = extern union {
foo: *c_void,
@@ -229,13 +231,18 @@ test "type info: struct info" {
}
fn testStruct() void {
+ const unpacked_struct_info = @typeInfo(TestUnpackedStruct);
+ expect(unpacked_struct_info.Struct.fields[0].alignment == @alignOf(u32));
+
const struct_info = @typeInfo(TestStruct);
expect(struct_info == .Struct);
expect(struct_info.Struct.layout == .Packed);
expect(struct_info.Struct.fields.len == 4);
+ expect(struct_info.Struct.fields[0].alignment == 2 * @alignOf(usize));
expect(struct_info.Struct.fields[2].field_type == *TestStruct);
expect(struct_info.Struct.fields[2].default_value == null);
expect(struct_info.Struct.fields[3].default_value.? == 4);
+ expect(struct_info.Struct.fields[3].alignment == 1);
expect(struct_info.Struct.decls.len == 2);
expect(struct_info.Struct.decls[0].is_pub);
expect(!struct_info.Struct.decls[0].data.Fn.is_extern);
@@ -244,8 +251,12 @@ fn testStruct() void {
expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
}
+const TestUnpackedStruct = struct {
+ fieldA: u32 = 4,
+};
+
const TestStruct = packed struct {
- fieldA: usize,
+ fieldA: usize align(2 * @alignOf(usize)),
fieldB: void,
fieldC: *Self,
fieldD: u32 = 4,
@@ -255,6 +266,8 @@ const TestStruct = packed struct {
};
test "type info: function type info" {
+ // wasm doesn't support align attributes on functions
+ if (builtin.arch == .wasm32 or builtin.arch == .wasm64) return error.SkipZigTest;
testFunction();
comptime testFunction();
}
@@ -262,11 +275,14 @@ test "type info: function type info" {
fn testFunction() void {
const fn_info = @typeInfo(@TypeOf(foo));
expect(fn_info == .Fn);
+ expect(fn_info.Fn.alignment == 0);
expect(fn_info.Fn.calling_convention == .C);
expect(!fn_info.Fn.is_generic);
expect(fn_info.Fn.args.len == 2);
expect(fn_info.Fn.is_var_args);
expect(fn_info.Fn.return_type.? == usize);
+ const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
+ expect(fn_aligned_info.Fn.alignment == 4);
const test_instance: TestStruct = undefined;
const bound_fn_info = @typeInfo(@TypeOf(test_instance.foo));
@@ -274,7 +290,8 @@ fn testFunction() void {
expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
}
-extern fn foo(a: usize, b: bool, ...) usize;
+extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
+extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
test "typeInfo with comptime parameter in struct fn def" {
const S = struct {