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

This commit is contained in:
Alexandros Naskos
2020-10-04 10:39:26 +03:00
43 changed files with 2568 additions and 2366 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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")

View File

@@ -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.

View File

@@ -1,172 +0,0 @@
# `dbg(…)`
[![Build Status](https://travis-ci.org/sharkdp/dbg-macro.svg?branch=master)](https://travis-ci.org/sharkdp/dbg-macro) [![Build status](https://ci.appveyor.com/api/projects/status/vmo9rw4te2wifkul/branch/master?svg=true)](https://ci.appveyor.com/project/sharkdp/dbg-macro) [![Try it online](https://img.shields.io/badge/try-online-f34b7d.svg)](https://repl.it/@sharkdp/dbg-macro-demo) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](dbg.h)
*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)):
![dbg(…) macro output](https://i.imgur.com/NHEYk9A.png)
## 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).

711
deps/dbg-macro/dbg.h vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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();
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);
}
test "std.ArrayList.basic" {
var list = ArrayList(i32).init(testing.allocator);
defer list.deinit();
test "std.ArrayList/ArrayListUnmanaged.init" {
{
var i: usize = 0;
while (i < 10) : (i += 1) {
list.append(@intCast(i32, i + 1)) catch unreachable;
}
var list = ArrayList(i32).init(testing.allocator);
defer list.deinit();
testing.expect(list.items.len == 0);
testing.expect(list.capacity == 0);
}
{
var i: usize = 0;
while (i < 10) : (i += 1) {
testing.expect(list.items[i] == @intCast(i32, i + 1));
var list = ArrayListUnmanaged(i32){};
testing.expect(list.items.len == 0);
testing.expect(list.capacity == 0);
}
}
test "std.ArrayList/ArrayListUnmanaged.initCapacity" {
const a = testing.allocator;
{
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 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));
}
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);
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(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;
testing.expect(list.pop() == 42);
testing.expect(list.pop() == 33);
}
}
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);
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);
}
test "std.ArrayList.appendNTimes" {
var list = ArrayList(i32).init(testing.allocator);
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);
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);
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 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 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);
//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(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);
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 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 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);
//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);
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);
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);
{
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.replaceRange(1, 0, &new);
try list_eq.replaceRange(1, 3, &new);
try list_lt.replaceRange(1, 2, &new);
try list_zero.appendSlice(&init);
try list_eq.appendSlice(&init);
try list_lt.appendSlice(&init);
try list_gt.appendSlice(&init);
// after_range > new_items.len in function body
testing.expect(1 + 4 > new.len);
try list_gt.replaceRange(1, 4, &new);
try list_zero.replaceRange(1, 0, &new);
try list_eq.replaceRange(1, 3, &new);
try list_lt.replaceRange(1, 2, &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 });
// 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);

View File

@@ -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| {

View File

@@ -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,

View File

@@ -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;

View File

@@ -4,23 +4,6 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
/// Hash functions.
pub const hash = struct {
pub const Md5 = @import("crypto/md5.zig").Md5;
pub const Sha1 = @import("crypto/sha1.zig").Sha1;
pub const sha2 = @import("crypto/sha2.zig");
pub const sha3 = @import("crypto/sha3.zig");
pub const blake2 = @import("crypto/blake2.zig");
pub const Blake3 = @import("crypto/blake3.zig").Blake3;
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");
@@ -32,9 +15,57 @@ pub const aead = struct {
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;
pub const Sha1 = @import("crypto/sha1.zig").Sha1;
pub const sha2 = @import("crypto/sha2.zig");
pub const sha3 = @import("crypto/sha3.zig");
pub const blake2 = @import("crypto/blake2.zig");
pub const Blake3 = @import("crypto/blake3.zig").Blake3;
pub const Gimli = @import("crypto/gimli.zig").Hash;
};
/// 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;

View File

@@ -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" },

310
lib/std/crypto/ghash.zig Normal file
View File

@@ -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);
}

66
lib/std/crypto/hkdf.zig Normal file
View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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),

View File

@@ -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);

View File

@@ -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));
}
}

View File

@@ -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),
};
}

View File

@@ -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(.{

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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,

View File

@@ -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");

View File

@@ -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,

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
// is_generic: bool
ensure_field_index(result->type, "is_generic", 1);
bool is_generic = type_entry->data.fn.is_generic;
// alignment: u29
ensure_field_index(result->type, "alignment", 1);
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[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", 2);
bool is_generic = type_entry->data.fn.is_generic;
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();
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 {

View File

@@ -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),

View File

@@ -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,
};
}

View File

@@ -2,6 +2,197 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
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 {
\\ _ = @intToEnum(Tag, 0);
\\}
, &[_][]const u8{
"tmp.zig:2:20: error: use of undefined value here causes undefined behavior",
});
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 s: S = undefined;
\\}
, &[_][]const 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",
\\const TypeInfo = @import("builtin").TypeInfo;
\\const Untagged = @Type(.{
\\ .Union = .{
\\ .layout = .Auto,
\\ .tag_type = null,
\\ .fields = &[_]TypeInfo.UnionField{
\\ .{ .name = "foo", .field_type = @Type(.Opaque), .alignment = 1 },
\\ },
\\ .decls = &[_]TypeInfo.Declaration{},
\\ },
\\});
\\export fn entry() void {
\\ _ = Untagged{};
\\}
, &[_][]const u8{
"tmp.zig:2:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
"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 };
@@ -18,26 +209,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:2:37: error: expected type '[:1]const u8', found '*const [2:2]u8'",
});
cases.add("@Type for union with opaque field",
\\const TypeInfo = @import("builtin").TypeInfo;
\\const Untagged = @Type(.{
\\ .Union = .{
\\ .layout = .Auto,
\\ .tag_type = null,
\\ .fields = &[_]TypeInfo.UnionField{
\\ .{ .name = "foo", .field_type = @Type(.Opaque) },
\\ },
\\ .decls = &[_]TypeInfo.Declaration{},
\\ },
\\});
\\export fn entry() void {
\\ _ = Untagged{};
\\}
, &[_][]const u8{
"tmp.zig:2:25: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
"tmp.zig:13:17: note: referenced here",
});
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(){};
\\}

View File

@@ -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;
}

View File

@@ -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)))),
));
}

View File

@@ -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 {