diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000..86b8f6f471
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+github: [andrewrk]
+patreon: andrewrk
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 985216ed7b..d77b6f09ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -630,9 +630,11 @@ set(ZIG_STD_FILES
"os/windows/bits.zig"
"os/windows/error.zig"
"os/windows/kernel32.zig"
+ "os/windows/lang.zig"
"os/windows/ntdll.zig"
"os/windows/ole32.zig"
"os/windows/shell32.zig"
+ "os/windows/sublang.zig"
"os/zen.zig"
"packed_int_array.zig"
"pdb.zig"
@@ -6066,6 +6068,8 @@ set(ZIG_LIBC_FILES
"include/x86_64-linux-musl/bits/stat.h"
"include/x86_64-linux-musl/bits/syscall.h"
"include/x86_64-linux-musl/bits/user.h"
+ "include/wasm32-freestanding-musl/bits/alltypes.h"
+ "include/wasm32-freestanding-musl/errno.h"
"musl/arch/aarch64/atomic_arch.h"
"musl/arch/aarch64/bits/alltypes.h.in"
"musl/arch/aarch64/bits/endian.h"
@@ -6726,9 +6730,13 @@ add_custom_command(
"-Doutput-dir=${CMAKE_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
DEPENDS
+ "${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
"${CMAKE_SOURCE_DIR}/build.zig"
+ "${CMAKE_SOURCE_DIR}/std/zig/parse.zig"
+ "${CMAKE_SOURCE_DIR}/std/zig/render.zig"
+ "${CMAKE_SOURCE_DIR}/std/zig/tokenizer.zig"
)
add_custom_target(userland_target DEPENDS "${LIBUSERLAND}")
add_executable(zig "${ZIG_MAIN_SRC}")
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..c19ef48829
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,91 @@
+## Contributing
+
+### Start a Project Using Zig
+
+One of the best ways you can contribute to Zig is to start using it for a
+personal project. Here are some great examples:
+
+ * [Oxid](https://github.com/dbandstra/oxid) - arcade style game
+ * [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games
+ * [trOS](https://github.com/sjdh02/trOS) - tiny aarch64 baremetal OS thingy
+
+Without fail, these projects lead to discovering bugs and helping flesh out use
+cases, which lead to further design iterations of Zig. Importantly, each issue
+found this way comes with real world motivations, so it is easy to explain
+your reasoning behind proposals and feature requests.
+
+Ideally, such a project will help you to learn new skills and add something
+to your personal portfolio at the same time.
+
+### Spread the Word
+
+Another way to contribute is to write about Zig, or speak about Zig at a
+conference, or do either of those things for your project which uses Zig.
+Here are some examples:
+
+ * [Iterative Replacement of C with Zig](http://tiehuis.github.io/blog/zig1.html)
+ * [The Right Tool for the Right Job: Redis Modules & Zig](https://www.youtube.com/watch?v=eCHM8-_poZY)
+
+Zig is a brand new language, with no advertising budget. Word of mouth is the
+only way people find out about the project, and the more people hear about it,
+the more people will use it, and the better chance we have to take over the
+world.
+
+### Finding Contributor Friendly Issues
+
+Please note that issues labeled
+[Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal)
+but do not also have the
+[Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted)
+label are still under consideration, and efforts to implement such a proposal
+have a high risk of being wasted. If you are interested in a proposal which is
+still under consideration, please express your interest in the issue tracker,
+providing extra insights and considerations that others have not yet expressed.
+The most highly regarded argument in such a discussion is a real world use case.
+
+The issue label
+[Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22)
+exists to help contributors find issues that are "limited in scope and/or
+knowledge of Zig internals."
+
+### Editing Source Code
+
+First, build the Stage 1 compiler as described in [the Building section](#building).
+
+When making changes to the standard library, be sure to edit the files in the
+`std` directory and not the installed copy in the build directory. If you add a
+new file to the standard library, you must also add the file path in
+CMakeLists.txt.
+
+To test changes, do the following from the build directory:
+
+1. Run `make install` (on POSIX) or
+ `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
+2. `bin/zig build --build-file ../build.zig test` (on POSIX) or
+ `bin\zig.exe build --build-file ..\build.zig test` (on Windows).
+
+That runs the whole test suite, which does a lot of extra testing that you
+likely won't always need, and can take upwards of 2 hours. This is what the
+CI server runs when you make a pull request.
+
+To save time, you can add the `--help` option to the `zig build` command and
+see what options are available. One of the most helpful ones is
+`-Dskip-release`. Adding this option to the command in step 2 above will take
+the time down from around 2 hours to about 6 minutes, and this is a good
+enough amount of testing before making a pull request.
+
+Another example is choosing a different set of things to test. For example,
+`test-std` instead of `test` will only run the standard library tests, and
+not the other ones. Combining this suggestion with the previous one, you could
+do this:
+
+`bin/zig build --build-file ../build.zig test-std -Dskip-release` (on POSIX) or
+`bin\zig.exe build --build-file ..\build.zig test-std -Dskip-release` (on Windows).
+
+This will run only the standard library tests, in debug mode only, for all
+targets (it will cross-compile the tests for non-native targets but not run
+them).
+
+When making changes to the compiler source code, the most helpful test step to
+run is `test-behavior`. When editing documentation it is `docs`. You can find
+this information and more in the `--help` menu.
diff --git a/README.md b/README.md
index 4ca79232d8..92ad435f5b 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@ Zig is an open-source programming language designed for **robustness**,
* [Introduction](https://ziglang.org/#Introduction)
* [Download & Documentation](https://ziglang.org/download)
* [Community](https://github.com/ziglang/zig/wiki/Community)
+ * [Contributing](https://github.com/ziglang/zig/blob/master/CONTRIBUTING.md)
## Building from Source
@@ -96,95 +97,3 @@ use stage 1.
```
./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
```
-
-## Contributing
-
-### Start a Project Using Zig
-
-One of the best ways you can contribute to Zig is to start using it for a
-personal project. Here are some great examples:
-
- * [Oxid](https://github.com/dbandstra/oxid) - arcade style game
- * [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games
- * [trOS](https://github.com/sjdh02/trOS) - tiny aarch64 baremetal OS thingy
-
-Without fail, these projects lead to discovering bugs and helping flesh out use
-cases, which lead to further design iterations of Zig. Importantly, each issue
-found this way comes with real world motivations, so it is easy to explain
-your reasoning behind proposals and feature requests.
-
-Ideally, such a project will help you to learn new skills and add something
-to your personal portfolio at the same time.
-
-### Spread the Word
-
-Another way to contribute is to write about Zig, or speak about Zig at a
-conference, or do either of those things for your project which uses Zig.
-Here are some examples:
-
- * [Iterative Replacement of C with Zig](http://tiehuis.github.io/blog/zig1.html)
- * [The Right Tool for the Right Job: Redis Modules & Zig](https://www.youtube.com/watch?v=eCHM8-_poZY)
-
-Zig is a brand new language, with no advertising budget. Word of mouth is the
-only way people find out about the project, and the more people hear about it,
-the more people will use it, and the better chance we have to take over the
-world.
-
-### Finding Contributor Friendly Issues
-
-Please note that issues labeled
-[Proposal](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aproposal)
-but do not also have the
-[Accepted](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted)
-label are still under consideration, and efforts to implement such a proposal
-have a high risk of being wasted. If you are interested in a proposal which is
-still under consideration, please express your interest in the issue tracker,
-providing extra insights and considerations that others have not yet expressed.
-The most highly regarded argument in such a discussion is a real world use case.
-
-The issue label
-[Contributor Friendly](https://github.com/ziglang/zig/issues?q=is%3Aissue+is%3Aopen+label%3A%22contributor+friendly%22)
-exists to help contributors find issues that are "limited in scope and/or
-knowledge of Zig internals."
-
-### Editing Source Code
-
-First, build the Stage 1 compiler as described in [the Building section](#building).
-
-When making changes to the standard library, be sure to edit the files in the
-`std` directory and not the installed copy in the build directory. If you add a
-new file to the standard library, you must also add the file path in
-CMakeLists.txt.
-
-To test changes, do the following from the build directory:
-
-1. Run `make install` (on POSIX) or
- `msbuild -p:Configuration=Release INSTALL.vcxproj` (on Windows).
-2. `bin/zig build --build-file ../build.zig test` (on POSIX) or
- `bin\zig.exe build --build-file ..\build.zig test` (on Windows).
-
-That runs the whole test suite, which does a lot of extra testing that you
-likely won't always need, and can take upwards of 2 hours. This is what the
-CI server runs when you make a pull request.
-
-To save time, you can add the `--help` option to the `zig build` command and
-see what options are available. One of the most helpful ones is
-`-Dskip-release`. Adding this option to the command in step 2 above will take
-the time down from around 2 hours to about 6 minutes, and this is a good
-enough amount of testing before making a pull request.
-
-Another example is choosing a different set of things to test. For example,
-`test-std` instead of `test` will only run the standard library tests, and
-not the other ones. Combining this suggestion with the previous one, you could
-do this:
-
-`bin/zig build --build-file ../build.zig test-std -Dskip-release` (on POSIX) or
-`bin\zig.exe build --build-file ..\build.zig test-std -Dskip-release` (on Windows).
-
-This will run only the standard library tests, in debug mode only, for all
-targets (it will cross-compile the tests for non-native targets but not run
-them).
-
-When making changes to the compiler source code, the most helpful test step to
-run is `test-behavior`. When editing documentation it is `docs`. You can find
-this information and more in the `--help` menu.
diff --git a/ci/azure/linux_script b/ci/azure/linux_script
index aaa75d6fce..20373f3a49 100755
--- a/ci/azure/linux_script
+++ b/ci/azure/linux_script
@@ -28,7 +28,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
docker run -i --mount type=bind,source="$ARTIFACTSDIR",target=/z ziglang/static-base:llvm8-1 -j2 $BUILD_SOURCEVERSION
TARBALL="$(ls $ARTIFACTSDIR)"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
- s3cmd put -P "$ARTIFACTSDIR/$TARBALL" s3://ziglang.org/builds/
+ s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$ARTIFACTSDIR/$TARBALL" s3://ziglang.org/builds/
SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)
diff --git a/ci/azure/macos_script b/ci/azure/macos_script
index 1b1d8741fa..7a7f1d1bce 100755
--- a/ci/azure/macos_script
+++ b/ci/azure/macos_script
@@ -6,7 +6,7 @@ set -e
brew install s3cmd gcc@8
ZIGDIR="$(pwd)"
-CACHE_BASENAME="llvm+clang-8.0.0-macos-x86_64-gcc8-release-static"
+CACHE_BASENAME="llvm+clang-8.0.0-macos-x86_64-gcc8-release"
PREFIX="$HOME/$CACHE_BASENAME"
TMPDIR="$HOME/tmpz"
JOBS="-j2"
@@ -62,7 +62,7 @@ else
cd $HOME
tar cfJ "$CACHE_BASENAME.tar.xz" "$CACHE_BASENAME"
cp "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
- s3cmd put -P "$CACHE_BASENAME.tar.xz" "s3://ziglang.org/builds/$CACHE_BASENAME.tar.xz"
+ s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$CACHE_BASENAME.tar.xz" "s3://ziglang.org/builds/$CACHE_BASENAME.tar.xz"
fi
cd $ZIGDIR
@@ -85,7 +85,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
tar cfJ "$TARBALL" "$DIRNAME"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
- s3cmd put -P "$TARBALL" s3://ziglang.org/builds/
+ s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml
index 37fce2a27a..8e6fcde636 100644
--- a/ci/azure/pipelines.yml
+++ b/ci/azure/pipelines.yml
@@ -1,7 +1,7 @@
jobs:
- job: BuildMacOS
pool:
- vmImage: 'macOS 10.13'
+ vmImage: 'macOS 10.14'
timeoutInMinutes: 360
diff --git a/ci/azure/update_download_page b/ci/azure/update_download_page
index c1e816a309..c6a690e8e6 100755
--- a/ci/azure/update_download_page
+++ b/ci/azure/update_download_page
@@ -35,7 +35,7 @@ env
"../$ZIG" run update-download-page.zig
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
-s3cmd put -P "../$SRC_TARBALL" s3://ziglang.org/builds/
+s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "../$SRC_TARBALL" s3://ziglang.org/builds/
s3cmd put -P "../$LANGREF" s3://ziglang.org/documentation/master/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
s3cmd put -P www/download/index.html s3://ziglang.org/download/index.html --add-header="Cache-Control: max-age=0, must-revalidate"
s3cmd put -P www/download/index.json s3://ziglang.org/download/index.json --add-header="Cache-Control: max-age=0, must-revalidate"
diff --git a/ci/azure/windows_upload b/ci/azure/windows_upload
index 8478be0e0b..266d1b57dd 100755
--- a/ci/azure/windows_upload
+++ b/ci/azure/windows_upload
@@ -19,7 +19,7 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
7z a "$TARBALL" "$DIRNAME"
mv "$DOWNLOADSECUREFILE_SECUREFILEPATH" "$HOME/.s3cfg"
- s3cmd put -P "$TARBALL" s3://ziglang.org/builds/
+ s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/
SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script
index 0ff66aaec5..9edf076c53 100755
--- a/ci/srht/freebsd_script
+++ b/ci/srht/freebsd_script
@@ -36,7 +36,7 @@ if [ -f ~/.s3cfg ]; then
mv release "$DIRNAME"
tar cfJ "$TARBALL" "$DIRNAME"
- s3cmd put -P "$TARBALL" s3://ziglang.org/builds/
+ s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
BYTESIZE=$(wc -c < $TARBALL)
diff --git a/doc/docgen.zig b/doc/docgen.zig
index 998db54bbc..461ff5cac2 100644
--- a/doc/docgen.zig
+++ b/doc/docgen.zig
@@ -788,7 +788,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
std.zig.Token.Id.Keyword_try,
std.zig.Token.Id.Keyword_union,
std.zig.Token.Id.Keyword_unreachable,
- std.zig.Token.Id.Keyword_use,
+ std.zig.Token.Id.Keyword_usingnamespace,
std.zig.Token.Id.Keyword_var,
std.zig.Token.Id.Keyword_volatile,
std.zig.Token.Id.Keyword_allowzero,
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 61db4ed598..ba093881ab 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -2026,9 +2026,9 @@ fn foo(bytes: []u8) u32 {
{#header_open|allowzero#}
This pointer attribute allows a pointer to have address zero. This is only ever needed on the
- freestanding OS target, where the address zero is mappable. In this code example, if the pointer
- did not have the {#syntax#}allowzero{#endsyntax#} attribute, this would be a
- {#link|Pointer Cast Invalid Null#} panic:
+ freestanding OS target, where the address zero is mappable. If you want to represent null pointers, use
+ {#link|Optional Pointers#} instead. In this code example, if the pointer did not have the
+ {#syntax#}allowzero{#endsyntax#} attribute, this would be a {#link|Pointer Cast Invalid Null#} panic:
{#code_begin|test|allowzero#}
const std = @import("std");
@@ -2263,6 +2263,28 @@ test "linked list" {
}
{#code_end#}
+ {#header_open|Default Field Values#}
+
+ Each struct field may have an expression indicating the default field value. Such expressions
+ are executed at {#link|comptime#}, and allow the field to be omitted in a struct literal expression:
+
+ {#code_begin|test#}
+const Foo = struct {
+ a: i32 = 1234,
+ b: i32,
+};
+
+test "default struct initialization fields" {
+ const x = Foo{
+ .b = 5,
+ };
+ if (x.a + x.b != 1239) {
+ @compileError("it's even comptime known!");
+ }
+}
+ {#code_end#}
+ {#header_close#}
+
{#header_open|extern struct#}
An {#syntax#}extern struct{#endsyntax#} has in-memory layout guaranteed to match the
C ABI for the target.
@@ -3271,6 +3293,7 @@ test "for else" {
var items = []?i32 { 3, 4, null, 5 };
// For loops can also be used as expressions.
+ // Similar to while loops, when you break from a for loop, the else branch is not evaluated.
var sum: i32 = 0;
const result = for (items) |value| {
if (value == null) {
@@ -7545,7 +7568,7 @@ pub const TypeInfo = union(TypeId) {
pub const Struct = struct {
layout: ContainerLayout,
fields: []StructField,
- defs: []Definition,
+ decls: []Declaration,
};
pub const Optional = struct {
@@ -7573,7 +7596,7 @@ pub const TypeInfo = union(TypeId) {
layout: ContainerLayout,
tag_type: type,
fields: []EnumField,
- defs: []Definition,
+ decls: []Declaration,
};
pub const UnionField = struct {
@@ -7586,7 +7609,7 @@ pub const TypeInfo = union(TypeId) {
layout: ContainerLayout,
tag_type: ?type,
fields: []UnionField,
- defs: []Definition,
+ decls: []Declaration,
};
pub const CallingConvention = enum {
@@ -7622,7 +7645,7 @@ pub const TypeInfo = union(TypeId) {
child: type,
};
- pub const Definition = struct {
+ pub const Declaration = struct {
name: []const u8,
is_pub: bool,
data: Data,
@@ -7630,9 +7653,9 @@ pub const TypeInfo = union(TypeId) {
pub const Data = union(enum) {
Type: type,
Var: type,
- Fn: FnDef,
+ Fn: FnDecl,
- pub const FnDef = struct {
+ pub const FnDecl = struct {
fn_type: type,
inline_type: Inline,
calling_convention: CallingConvention,
@@ -8466,6 +8489,8 @@ fn concat(allocator: *Allocator, a: []const u8, b: []const u8) ![]u8 {
Are you linking libc? In this case, {#syntax#}std.heap.c_allocator{#endsyntax#} is likely
the right choice, at least for your main allocator.
+ Are you building for WebAssembly? In this case, {#syntax#}std.heap.wasm_allocator{#endsyntax#} is likely
+ the right choice for your main allocator as it uses WebAssembly's memory instructions.
Is the maximum number of bytes that you will need bounded by a number known at
{#link|comptime#}? In this case, use {#syntax#}std.heap.FixedBufferAllocator{#endsyntax#} or
@@ -8996,8 +9021,12 @@ all your base are belong to us
{#header_close#}
{#header_close#}
{#header_open|WebAssembly#}
+ Zig supports building for WebAssembly out of the box. There is also a specialized {#syntax#}std.heap.wasm_allocator{#endsyntax#}
+ memory allocator for WebAssembly environments.
{#header_open|Freestanding#}
- {#code_begin|lib|wasm#}
+ For host environments like the web browser and nodejs, build as a library using the freestanding OS target.
+ Here's an example of running Zig code compiled to WebAssembly with nodejs.
+ {#code_begin|lib|math#}
{#target_wasm#}
extern fn print(i32) void;
@@ -9006,7 +9035,22 @@ export fn add(a: i32, b: i32) void {
}
{#code_end#}
{#header_close#}
+ test.js
+ const fs = require('fs');
+const source = fs.readFileSync("./math.wasm");
+const typedArray = new Uint8Array(source);
+
+WebAssembly.instantiate(typedArray, {
+ env: {
+ print: (result) => { console.log(`The result is ${result}`); }
+ }}).then(result => {
+ const add = result.instance.exports.add;
+ add(1, 2);
+});
+ $ node test.js
+The result is 3
{#header_open|WASI#}
+ Zig's support for WebAssembly System Interface (WASI) is under active development. Example of using the standard library and reading command line arguments:
{#code_begin|exe|wasi#}
{#target_wasi#}
const std = @import("std");
@@ -9020,6 +9064,10 @@ pub fn main() !void {
}
}
{#code_end#}
+ $ wasmer run wasi.wasm 123 hello
+0: wasi.wasm
+1: 123
+2: hello
{#header_close#}
{#header_close#}
{#header_open|Targets#}
@@ -9260,6 +9308,7 @@ Available libcs:
s390x-linux-musl
sparc-linux-gnu
sparcv9-linux-gnu
+ wasm32-freestanding-musl
x86_64-linux-gnu
x86_64-linux-gnux32
x86_64-linux-musl
@@ -9892,7 +9941,7 @@ KEYWORD_try <- 'try' end_of_word
KEYWORD_undefined <- 'undefined' end_of_word
KEYWORD_union <- 'union' end_of_word
KEYWORD_unreachable <- 'unreachable' end_of_word
-KEYWORD_use <- 'use' end_of_word
+KEYWORD_usingnamespace <- 'usingnamespace' end_of_word
KEYWORD_var <- 'var' end_of_word
KEYWORD_volatile <- 'volatile' end_of_word
KEYWORD_while <- 'while' end_of_word
@@ -9909,7 +9958,7 @@ keyword <- KEYWORD_align / KEYWORD_and / KEYWORD_allowzero / KEYWORD_anyerror
/ KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
/ KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
/ KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
- / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while
+ / KEYWORD_usingnamespace / KEYWORD_var / KEYWORD_volatile / KEYWORD_while
{#header_close#}
{#header_open|Zen#}
diff --git a/libc/include/wasm32-freestanding-musl/bits/alltypes.h b/libc/include/wasm32-freestanding-musl/bits/alltypes.h
new file mode 100644
index 0000000000..5c5a52c7e9
--- /dev/null
+++ b/libc/include/wasm32-freestanding-musl/bits/alltypes.h
@@ -0,0 +1,385 @@
+#define _Addr long
+#define _Int64 long long
+#define _Reg long
+
+#if defined(__NEED_va_list) && !defined(__DEFINED_va_list)
+typedef __builtin_va_list va_list;
+#define __DEFINED_va_list
+#endif
+
+#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list)
+typedef __builtin_va_list __isoc_va_list;
+#define __DEFINED___isoc_va_list
+#endif
+
+
+#ifndef __cplusplus
+#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t)
+typedef int wchar_t;
+#define __DEFINED_wchar_t
+#endif
+
+#endif
+
+#if defined(__NEED_float_t) && !defined(__DEFINED_float_t)
+typedef float float_t;
+#define __DEFINED_float_t
+#endif
+
+#if defined(__NEED_double_t) && !defined(__DEFINED_double_t)
+typedef double double_t;
+#define __DEFINED_double_t
+#endif
+
+
+#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t)
+typedef struct { long long __ll; long double __ld; } max_align_t;
+#define __DEFINED_max_align_t
+#endif
+
+
+#if defined(__NEED_time_t) && !defined(__DEFINED_time_t)
+typedef long time_t;
+#define __DEFINED_time_t
+#endif
+
+#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t)
+typedef long suseconds_t;
+#define __DEFINED_suseconds_t
+#endif
+
+
+#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t)
+typedef struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
+#define __DEFINED_pthread_attr_t
+#endif
+
+#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t)
+typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
+#define __DEFINED_pthread_mutex_t
+#endif
+
+#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t)
+typedef struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
+#define __DEFINED_mtx_t
+#endif
+
+#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
+#define __DEFINED_pthread_cond_t
+#endif
+
+#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t)
+typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
+#define __DEFINED_cnd_t
+#endif
+
+#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t)
+typedef struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
+#define __DEFINED_pthread_rwlock_t
+#endif
+
+#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t)
+typedef struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
+#define __DEFINED_pthread_barrier_t
+#endif
+
+#if defined(__NEED_size_t) && !defined(__DEFINED_size_t)
+typedef unsigned _Addr size_t;
+#define __DEFINED_size_t
+#endif
+
+#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t)
+typedef unsigned _Addr uintptr_t;
+#define __DEFINED_uintptr_t
+#endif
+
+#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t)
+typedef _Addr ptrdiff_t;
+#define __DEFINED_ptrdiff_t
+#endif
+
+#if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t)
+typedef _Addr ssize_t;
+#define __DEFINED_ssize_t
+#endif
+
+#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t)
+typedef _Addr intptr_t;
+#define __DEFINED_intptr_t
+#endif
+
+#if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t)
+typedef _Addr regoff_t;
+#define __DEFINED_regoff_t
+#endif
+
+#if defined(__NEED_register_t) && !defined(__DEFINED_register_t)
+typedef _Reg register_t;
+#define __DEFINED_register_t
+#endif
+
+
+#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t)
+typedef signed char int8_t;
+#define __DEFINED_int8_t
+#endif
+
+#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t)
+typedef signed short int16_t;
+#define __DEFINED_int16_t
+#endif
+
+#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t)
+typedef signed int int32_t;
+#define __DEFINED_int32_t
+#endif
+
+#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t)
+typedef signed _Int64 int64_t;
+#define __DEFINED_int64_t
+#endif
+
+#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t)
+typedef signed _Int64 intmax_t;
+#define __DEFINED_intmax_t
+#endif
+
+#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t)
+typedef unsigned char uint8_t;
+#define __DEFINED_uint8_t
+#endif
+
+#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t)
+typedef unsigned short uint16_t;
+#define __DEFINED_uint16_t
+#endif
+
+#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t)
+typedef unsigned int uint32_t;
+#define __DEFINED_uint32_t
+#endif
+
+#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t)
+typedef unsigned _Int64 uint64_t;
+#define __DEFINED_uint64_t
+#endif
+
+#if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t)
+typedef unsigned _Int64 u_int64_t;
+#define __DEFINED_u_int64_t
+#endif
+
+#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t)
+typedef unsigned _Int64 uintmax_t;
+#define __DEFINED_uintmax_t
+#endif
+
+
+#if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t)
+typedef unsigned mode_t;
+#define __DEFINED_mode_t
+#endif
+
+#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t)
+typedef unsigned _Reg nlink_t;
+#define __DEFINED_nlink_t
+#endif
+
+#if defined(__NEED_off_t) && !defined(__DEFINED_off_t)
+typedef _Int64 off_t;
+#define __DEFINED_off_t
+#endif
+
+#if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t)
+typedef unsigned _Int64 ino_t;
+#define __DEFINED_ino_t
+#endif
+
+#if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t)
+typedef unsigned _Int64 dev_t;
+#define __DEFINED_dev_t
+#endif
+
+#if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t)
+typedef long blksize_t;
+#define __DEFINED_blksize_t
+#endif
+
+#if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t)
+typedef _Int64 blkcnt_t;
+#define __DEFINED_blkcnt_t
+#endif
+
+#if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t)
+typedef unsigned _Int64 fsblkcnt_t;
+#define __DEFINED_fsblkcnt_t
+#endif
+
+#if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t)
+typedef unsigned _Int64 fsfilcnt_t;
+#define __DEFINED_fsfilcnt_t
+#endif
+
+
+#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t)
+typedef unsigned wint_t;
+#define __DEFINED_wint_t
+#endif
+
+#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t)
+typedef unsigned long wctype_t;
+#define __DEFINED_wctype_t
+#endif
+
+
+#if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t)
+typedef void * timer_t;
+#define __DEFINED_timer_t
+#endif
+
+#if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t)
+typedef int clockid_t;
+#define __DEFINED_clockid_t
+#endif
+
+#if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t)
+typedef long clock_t;
+#define __DEFINED_clock_t
+#endif
+
+#if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval)
+struct timeval { time_t tv_sec; suseconds_t tv_usec; };
+#define __DEFINED_struct_timeval
+#endif
+
+#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec)
+struct timespec { time_t tv_sec; long tv_nsec; };
+#define __DEFINED_struct_timespec
+#endif
+
+
+#if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t)
+typedef int pid_t;
+#define __DEFINED_pid_t
+#endif
+
+#if defined(__NEED_id_t) && !defined(__DEFINED_id_t)
+typedef unsigned id_t;
+#define __DEFINED_id_t
+#endif
+
+#if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t)
+typedef unsigned uid_t;
+#define __DEFINED_uid_t
+#endif
+
+#if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t)
+typedef unsigned gid_t;
+#define __DEFINED_gid_t
+#endif
+
+#if defined(__NEED_key_t) && !defined(__DEFINED_key_t)
+typedef int key_t;
+#define __DEFINED_key_t
+#endif
+
+#if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t)
+typedef unsigned useconds_t;
+#define __DEFINED_useconds_t
+#endif
+
+
+#ifdef __cplusplus
+#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
+typedef unsigned long pthread_t;
+#define __DEFINED_pthread_t
+#endif
+
+#else
+#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t)
+typedef struct __pthread * pthread_t;
+#define __DEFINED_pthread_t
+#endif
+
+#endif
+#if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t)
+typedef int pthread_once_t;
+#define __DEFINED_pthread_once_t
+#endif
+
+#if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t)
+typedef unsigned pthread_key_t;
+#define __DEFINED_pthread_key_t
+#endif
+
+#if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t)
+typedef int pthread_spinlock_t;
+#define __DEFINED_pthread_spinlock_t
+#endif
+
+#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t)
+typedef struct { unsigned __attr; } pthread_mutexattr_t;
+#define __DEFINED_pthread_mutexattr_t
+#endif
+
+#if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t)
+typedef struct { unsigned __attr; } pthread_condattr_t;
+#define __DEFINED_pthread_condattr_t
+#endif
+
+#if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t)
+typedef struct { unsigned __attr; } pthread_barrierattr_t;
+#define __DEFINED_pthread_barrierattr_t
+#endif
+
+#if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t)
+typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t;
+#define __DEFINED_pthread_rwlockattr_t
+#endif
+
+
+#if defined(__NEED_FILE) && !defined(__DEFINED_FILE)
+typedef struct _IO_FILE FILE;
+#define __DEFINED_FILE
+#endif
+
+
+#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t)
+typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t;
+#define __DEFINED_mbstate_t
+#endif
+
+
+#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t)
+typedef struct __locale_struct * locale_t;
+#define __DEFINED_locale_t
+#endif
+
+
+#if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t)
+typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t;
+#define __DEFINED_sigset_t
+#endif
+
+
+#if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec)
+struct iovec { void *iov_base; size_t iov_len; };
+#define __DEFINED_struct_iovec
+#endif
+
+
+#if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t)
+typedef unsigned socklen_t;
+#define __DEFINED_socklen_t
+#endif
+
+#if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t)
+typedef unsigned short sa_family_t;
+#define __DEFINED_sa_family_t
+#endif
+
+
+#undef _Addr
+#undef _Int64
+#undef _Reg
diff --git a/libc/include/wasm32-freestanding-musl/errno.h b/libc/include/wasm32-freestanding-musl/errno.h
new file mode 100644
index 0000000000..e26c76e754
--- /dev/null
+++ b/libc/include/wasm32-freestanding-musl/errno.h
@@ -0,0 +1,24 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WASM_THREAD_MODEL_SINGLE
+extern int errno;
+#else
+#ifdef __cplusplus
+extern thread_local int errno;
+#else
+extern _Thread_local int errno;
+#endif
+#endif
+
+#define errno errno
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src-self-hosted/c.zig b/src-self-hosted/c.zig
index 778d851240..1de2b6a24c 100644
--- a/src-self-hosted/c.zig
+++ b/src-self-hosted/c.zig
@@ -1,4 +1,4 @@
-pub use @cImport({
+pub usingnamespace @cImport({
@cDefine("__STDC_CONSTANT_MACROS", "");
@cDefine("__STDC_LIMIT_MACROS", "");
@cInclude("inttypes.h");
diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig
index c8faf1e56e..20a815cb75 100644
--- a/src-self-hosted/clang.zig
+++ b/src-self-hosted/clang.zig
@@ -1,5 +1,6 @@
pub const struct_ZigClangAPValue = @OpaqueType();
pub const struct_ZigClangAPSInt = @OpaqueType();
+pub const struct_ZigClangAPFloat = @OpaqueType();
pub const struct_ZigClangASTContext = @OpaqueType();
pub const struct_ZigClangASTUnit = @OpaqueType();
pub const struct_ZigClangArraySubscriptExpr = @OpaqueType();
@@ -12,7 +13,7 @@ pub const struct_ZigClangCStyleCastExpr = @OpaqueType();
pub const struct_ZigClangCallExpr = @OpaqueType();
pub const struct_ZigClangCaseStmt = @OpaqueType();
pub const struct_ZigClangCompoundAssignOperator = @OpaqueType();
-pub const ZigClangCompoundStmt = @OpaqueType();
+pub const struct_ZigClangCompoundStmt = @OpaqueType();
pub const struct_ZigClangConditionalOperator = @OpaqueType();
pub const struct_ZigClangConstantArrayType = @OpaqueType();
pub const struct_ZigClangContinueStmt = @OpaqueType();
@@ -33,7 +34,7 @@ pub const struct_ZigClangFieldDecl = @OpaqueType();
pub const struct_ZigClangFileID = @OpaqueType();
pub const struct_ZigClangForStmt = @OpaqueType();
pub const struct_ZigClangFullSourceLoc = @OpaqueType();
-pub const ZigClangFunctionDecl = @OpaqueType();
+pub const struct_ZigClangFunctionDecl = @OpaqueType();
pub const struct_ZigClangFunctionProtoType = @OpaqueType();
pub const struct_ZigClangIfStmt = @OpaqueType();
pub const struct_ZigClangImplicitCastExpr = @OpaqueType();
@@ -68,7 +69,8 @@ pub const struct_ZigClangUnaryOperator = @OpaqueType();
pub const struct_ZigClangValueDecl = @OpaqueType();
pub const struct_ZigClangVarDecl = @OpaqueType();
pub const struct_ZigClangWhileStmt = @OpaqueType();
-pub const ZigClangFunctionType = @OpaqueType();
+pub const struct_ZigClangFunctionType = @OpaqueType();
+pub const struct_ZigClangPredefinedExpr = @OpaqueType();
pub const ZigClangBO = extern enum {
PtrMemD,
@@ -450,188 +452,6 @@ pub const ZigClangAPValueKind = extern enum {
AddrLabelDiff,
};
-pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
-pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
-pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
-pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
-pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
-pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
-pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
-pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
-pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
-pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;
-pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
-pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
-pub extern fn ZigClangEnumDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
-pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(arg0: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
-pub extern fn ZigClangRecordDecl_getDefinition(arg0: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl;
-pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl;
-pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation;
-pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation;
-pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation;
-pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation;
-pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
-pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
-pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
-pub extern fn ZigClangEnumDecl_getIntegerType(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
-pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
-pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
-pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
-pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
-pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType;
-pub extern fn ZigClangQualType_getTypeClass(self: struct_ZigClangQualType) ZigClangTypeClass;
-pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
-pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void;
-pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
-pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool;
-pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool;
-pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool;
-pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
-pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
-pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
-pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
-pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
-pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
-pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
-pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
-pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
-pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
-pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
-pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
-pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
-pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
-pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
-pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
-pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
-pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
-pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
-pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
-pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
-pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
-pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
-pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
-pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
-
-pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType;
-pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation;
-pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
-pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
-pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
-pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
-
-pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
-
-pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
-pub extern fn ZigClangFunctionType_getCallConv(self: *const ZigClangFunctionType) ZigClangCallingConv;
-pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionType) ZigClangQualType;
-
-pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool;
-pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint;
-pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType;
-
-pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
-pub const ZigClangQualType = struct_ZigClangQualType;
-pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
-pub const ZigClangAPValue = struct_ZigClangAPValue;
-pub const ZigClangAPSInt = struct_ZigClangAPSInt;
-pub const ZigClangASTContext = struct_ZigClangASTContext;
-pub const ZigClangASTUnit = struct_ZigClangASTUnit;
-pub const ZigClangArraySubscriptExpr = struct_ZigClangArraySubscriptExpr;
-pub const ZigClangArrayType = struct_ZigClangArrayType;
-pub const ZigClangAttributedType = struct_ZigClangAttributedType;
-pub const ZigClangBinaryOperator = struct_ZigClangBinaryOperator;
-pub const ZigClangBreakStmt = struct_ZigClangBreakStmt;
-pub const ZigClangBuiltinType = struct_ZigClangBuiltinType;
-pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;
-pub const ZigClangCallExpr = struct_ZigClangCallExpr;
-pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;
-pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;
-pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;
-pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
-pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
-pub const ZigClangDecayedType = struct_ZigClangDecayedType;
-pub const ZigClangDecl = struct_ZigClangDecl;
-pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr;
-pub const ZigClangDeclStmt = struct_ZigClangDeclStmt;
-pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt;
-pub const ZigClangDiagnosticOptions = struct_ZigClangDiagnosticOptions;
-pub const ZigClangDiagnosticsEngine = struct_ZigClangDiagnosticsEngine;
-pub const ZigClangDoStmt = struct_ZigClangDoStmt;
-pub const ZigClangElaboratedType = struct_ZigClangElaboratedType;
-pub const ZigClangEnumConstantDecl = struct_ZigClangEnumConstantDecl;
-pub const ZigClangEnumDecl = struct_ZigClangEnumDecl;
-pub const ZigClangEnumType = struct_ZigClangEnumType;
-pub const ZigClangExpr = struct_ZigClangExpr;
-pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;
-pub const ZigClangFileID = struct_ZigClangFileID;
-pub const ZigClangForStmt = struct_ZigClangForStmt;
-pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;
-pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;
-pub const ZigClangIfStmt = struct_ZigClangIfStmt;
-pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
-pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType;
-pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral;
-pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord;
-pub const ZigClangMemberExpr = struct_ZigClangMemberExpr;
-pub const ZigClangNamedDecl = struct_ZigClangNamedDecl;
-pub const ZigClangNone = struct_ZigClangNone;
-pub const ZigClangPCHContainerOperations = struct_ZigClangPCHContainerOperations;
-pub const ZigClangParenExpr = struct_ZigClangParenExpr;
-pub const ZigClangParenType = struct_ZigClangParenType;
-pub const ZigClangParmVarDecl = struct_ZigClangParmVarDecl;
-pub const ZigClangPointerType = struct_ZigClangPointerType;
-pub const ZigClangPreprocessedEntity = struct_ZigClangPreprocessedEntity;
-pub const ZigClangRecordDecl = struct_ZigClangRecordDecl;
-pub const ZigClangRecordType = struct_ZigClangRecordType;
-pub const ZigClangReturnStmt = struct_ZigClangReturnStmt;
-pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope;
-pub const ZigClangSourceManager = struct_ZigClangSourceManager;
-pub const ZigClangSourceRange = struct_ZigClangSourceRange;
-pub const ZigClangStmt = struct_ZigClangStmt;
-pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
-pub const ZigClangStringRef = struct_ZigClangStringRef;
-pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
-pub const ZigClangTagDecl = struct_ZigClangTagDecl;
-pub const ZigClangType = struct_ZigClangType;
-pub const ZigClangTypedefNameDecl = struct_ZigClangTypedefNameDecl;
-pub const ZigClangTypedefType = struct_ZigClangTypedefType;
-pub const ZigClangUnaryExprOrTypeTraitExpr = struct_ZigClangUnaryExprOrTypeTraitExpr;
-pub const ZigClangUnaryOperator = struct_ZigClangUnaryOperator;
-pub const ZigClangValueDecl = struct_ZigClangValueDecl;
-pub const ZigClangVarDecl = struct_ZigClangVarDecl;
-pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
-
-pub const struct_ZigClangSourceLocation = extern struct {
- ID: c_uint,
-};
-
-pub const Stage2ErrorMsg = extern struct {
- filename_ptr: ?[*]const u8,
- filename_len: usize,
- msg_ptr: [*]const u8,
- msg_len: usize,
- // valid until the ASTUnit is freed
- source: ?[*]const u8,
- // 0 based
- line: c_uint,
- // 0 based
- column: c_uint,
- // byte offset into source
- offset: c_uint,
-};
-pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void;
-
-pub extern fn ZigClangLoadFromCommandLine(
- args_begin: [*]?[*]const u8,
- args_end: [*]?[*]const u8,
- errors_ptr: *[*]Stage2ErrorMsg,
- errors_len: *usize,
- resources_path: [*c]const u8,
-) ?*ZigClangASTUnit;
-
-pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
-pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;
-
pub const ZigClangDeclKind = extern enum {
AccessSpec,
Block,
@@ -709,10 +529,6 @@ pub const ZigClangDeclKind = extern enum {
TranslationUnit,
};
-pub const struct_ZigClangQualType = extern struct {
- ptr: ?*c_void,
-};
-
pub const ZigClangBuiltinTypeKind = extern enum {
OCLImage1dRO,
OCLImage1dArrayRO,
@@ -862,39 +678,219 @@ pub const ZigClangStorageClass = extern enum {
Register,
};
+pub const ZigClangAPFloat_roundingMode = extern enum {
+ NearestTiesToEven,
+ TowardPositive,
+ TowardNegative,
+ TowardZero,
+ NearestTiesToAway,
+};
+
+pub const ZigClangStringLiteral_StringKind = extern enum {
+ Ascii,
+ Wide,
+ UTF8,
+ UTF16,
+ UTF32,
+};
+
+pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
+pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
+pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
+pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
+pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
+pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
+pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
+pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
+pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
+pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;
+pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
+pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
+pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl;
+pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl;
+pub extern fn ZigClangRecordDecl_getDefinition(self: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangRecordDecl;
+pub extern fn ZigClangEnumDecl_getDefinition(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangEnumDecl;
+pub extern fn ZigClangRecordDecl_getLocation(self: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangEnumDecl_getLocation(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangTypedefNameDecl_getLocation(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation;
+pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
+pub extern fn ZigClangEnumDecl_getIntegerType(self: ?*const struct_ZigClangEnumDecl) struct_ZigClangQualType;
+pub extern fn ZigClangDecl_getName_bytes_begin(decl: ?*const struct_ZigClangDecl) [*c]const u8;
+pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
+pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
+pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(self: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
+pub extern fn ZigClangQualType_getCanonicalType(self: struct_ZigClangQualType) struct_ZigClangQualType;
+pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
+pub extern fn ZigClangQualType_addConst(self: [*c]struct_ZigClangQualType) void;
+pub extern fn ZigClangQualType_eq(self: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isConstQualified(self: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isVolatileQualified(self: struct_ZigClangQualType) bool;
+pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType) bool;
+pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
+pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
+pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
+pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
+pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
+pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
+pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
+pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
+pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
+pub extern fn ZigClangAPValue_getKind(self: ?*const struct_ZigClangAPValue) ZigClangAPValueKind;
+pub extern fn ZigClangAPValue_getInt(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPSInt;
+pub extern fn ZigClangAPValue_getArrayInitializedElts(self: ?*const struct_ZigClangAPValue) c_uint;
+pub extern fn ZigClangAPValue_getArrayInitializedElt(self: ?*const struct_ZigClangAPValue, i: c_uint) ?*const struct_ZigClangAPValue;
+pub extern fn ZigClangAPValue_getArrayFiller(self: ?*const struct_ZigClangAPValue) ?*const struct_ZigClangAPValue;
+pub extern fn ZigClangAPValue_getArraySize(self: ?*const struct_ZigClangAPValue) c_uint;
+pub extern fn ZigClangAPValue_getLValueBase(self: ?*const struct_ZigClangAPValue) struct_ZigClangAPValueLValueBase;
+pub extern fn ZigClangAPSInt_isSigned(self: ?*const struct_ZigClangAPSInt) bool;
+pub extern fn ZigClangAPSInt_isNegative(self: ?*const struct_ZigClangAPSInt) bool;
+pub extern fn ZigClangAPSInt_negate(self: ?*const struct_ZigClangAPSInt) ?*const struct_ZigClangAPSInt;
+pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
+pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
+pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
+pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
+pub extern fn ZigClangASTUnit_delete(self: ?*struct_ZigClangASTUnit) void;
+
+pub extern fn ZigClangFunctionDecl_getType(self: *const ZigClangFunctionDecl) struct_ZigClangQualType;
+pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl) struct_ZigClangSourceLocation;
+pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
+pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
+pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
+pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
+
+pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
+
+pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
+pub extern fn ZigClangFunctionType_getCallConv(self: *const ZigClangFunctionType) ZigClangCallingConv;
+pub extern fn ZigClangFunctionType_getReturnType(self: *const ZigClangFunctionType) ZigClangQualType;
+
+pub extern fn ZigClangFunctionProtoType_isVariadic(self: *const struct_ZigClangFunctionProtoType) bool;
+pub extern fn ZigClangFunctionProtoType_getNumParams(self: *const struct_ZigClangFunctionProtoType) c_uint;
+pub extern fn ZigClangFunctionProtoType_getParamType(self: *const struct_ZigClangFunctionProtoType, i: c_uint) ZigClangQualType;
+
+pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
+pub const ZigClangQualType = struct_ZigClangQualType;
+pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
+pub const ZigClangAPValue = struct_ZigClangAPValue;
+pub const ZigClangAPSInt = struct_ZigClangAPSInt;
+pub const ZigClangAPFloat = struct_ZigClangAPFloat;
+pub const ZigClangASTContext = struct_ZigClangASTContext;
+pub const ZigClangASTUnit = struct_ZigClangASTUnit;
+pub const ZigClangArraySubscriptExpr = struct_ZigClangArraySubscriptExpr;
+pub const ZigClangArrayType = struct_ZigClangArrayType;
+pub const ZigClangAttributedType = struct_ZigClangAttributedType;
+pub const ZigClangBinaryOperator = struct_ZigClangBinaryOperator;
+pub const ZigClangBreakStmt = struct_ZigClangBreakStmt;
+pub const ZigClangBuiltinType = struct_ZigClangBuiltinType;
+pub const ZigClangCStyleCastExpr = struct_ZigClangCStyleCastExpr;
+pub const ZigClangCallExpr = struct_ZigClangCallExpr;
+pub const ZigClangCaseStmt = struct_ZigClangCaseStmt;
+pub const ZigClangCompoundAssignOperator = struct_ZigClangCompoundAssignOperator;
+pub const ZigClangCompoundStmt = struct_ZigClangCompoundStmt;
+pub const ZigClangConditionalOperator = struct_ZigClangConditionalOperator;
+pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
+pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
+pub const ZigClangDecayedType = struct_ZigClangDecayedType;
+pub const ZigClangDecl = struct_ZigClangDecl;
+pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr;
+pub const ZigClangDeclStmt = struct_ZigClangDeclStmt;
+pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt;
+pub const ZigClangDiagnosticOptions = struct_ZigClangDiagnosticOptions;
+pub const ZigClangDiagnosticsEngine = struct_ZigClangDiagnosticsEngine;
+pub const ZigClangDoStmt = struct_ZigClangDoStmt;
+pub const ZigClangElaboratedType = struct_ZigClangElaboratedType;
+pub const ZigClangEnumConstantDecl = struct_ZigClangEnumConstantDecl;
+pub const ZigClangEnumDecl = struct_ZigClangEnumDecl;
+pub const ZigClangEnumType = struct_ZigClangEnumType;
+pub const ZigClangExpr = struct_ZigClangExpr;
+pub const ZigClangFieldDecl = struct_ZigClangFieldDecl;
+pub const ZigClangFileID = struct_ZigClangFileID;
+pub const ZigClangForStmt = struct_ZigClangForStmt;
+pub const ZigClangFullSourceLoc = struct_ZigClangFullSourceLoc;
+pub const ZigClangFunctionDecl = struct_ZigClangFunctionDecl;
+pub const ZigClangFunctionProtoType = struct_ZigClangFunctionProtoType;
+pub const ZigClangIfStmt = struct_ZigClangIfStmt;
+pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
+pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType;
+pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral;
+pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord;
+pub const ZigClangMemberExpr = struct_ZigClangMemberExpr;
+pub const ZigClangNamedDecl = struct_ZigClangNamedDecl;
+pub const ZigClangNone = struct_ZigClangNone;
+pub const ZigClangPCHContainerOperations = struct_ZigClangPCHContainerOperations;
+pub const ZigClangParenExpr = struct_ZigClangParenExpr;
+pub const ZigClangParenType = struct_ZigClangParenType;
+pub const ZigClangParmVarDecl = struct_ZigClangParmVarDecl;
+pub const ZigClangPointerType = struct_ZigClangPointerType;
+pub const ZigClangPreprocessedEntity = struct_ZigClangPreprocessedEntity;
+pub const ZigClangRecordDecl = struct_ZigClangRecordDecl;
+pub const ZigClangRecordType = struct_ZigClangRecordType;
+pub const ZigClangReturnStmt = struct_ZigClangReturnStmt;
+pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope;
+pub const ZigClangSourceManager = struct_ZigClangSourceManager;
+pub const ZigClangSourceRange = struct_ZigClangSourceRange;
+pub const ZigClangStmt = struct_ZigClangStmt;
+pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
+pub const ZigClangStringRef = struct_ZigClangStringRef;
+pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
+pub const ZigClangTagDecl = struct_ZigClangTagDecl;
+pub const ZigClangType = struct_ZigClangType;
+pub const ZigClangTypedefNameDecl = struct_ZigClangTypedefNameDecl;
+pub const ZigClangTypedefType = struct_ZigClangTypedefType;
+pub const ZigClangUnaryExprOrTypeTraitExpr = struct_ZigClangUnaryExprOrTypeTraitExpr;
+pub const ZigClangUnaryOperator = struct_ZigClangUnaryOperator;
+pub const ZigClangValueDecl = struct_ZigClangValueDecl;
+pub const ZigClangVarDecl = struct_ZigClangVarDecl;
+pub const ZigClangWhileStmt = struct_ZigClangWhileStmt;
+pub const ZigClangFunctionType = struct_ZigClangFunctionType;
+pub const ZigClangPredefinedExpr = struct_ZigClangPredefinedExpr;
+
+pub const struct_ZigClangSourceLocation = extern struct {
+ ID: c_uint,
+};
+
+pub const Stage2ErrorMsg = extern struct {
+ filename_ptr: ?[*]const u8,
+ filename_len: usize,
+ msg_ptr: [*]const u8,
+ msg_len: usize,
+ // valid until the ASTUnit is freed
+ source: ?[*]const u8,
+ // 0 based
+ line: c_uint,
+ // 0 based
+ column: c_uint,
+ // byte offset into source
+ offset: c_uint,
+};
+
+pub const struct_ZigClangQualType = extern struct {
+ ptr: ?*c_void,
+};
+
+pub const struct_ZigClangAPValueLValueBase = extern struct {
+ Ptr: ?*c_void,
+ CallIndex: c_uint,
+ Version: c_uint,
+};
+
+pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void;
+
+pub extern fn ZigClangLoadFromCommandLine(
+ args_begin: [*]?[*]const u8,
+ args_end: [*]?[*]const u8,
+ errors_ptr: *[*]Stage2ErrorMsg,
+ errors_len: *usize,
+ resources_path: [*c]const u8,
+) ?*ZigClangASTUnit;
+
+pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
+pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;
+
pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;
pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
-
-pub const ZigClangDeclStmt_const_decl_iterator = [*c]const *struct_ZigClangDecl;
-
-pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
-pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
-
-pub extern fn ZigClangVarDecl_getType(self: ?*const struct_ZigClangVarDecl) struct_ZigClangQualType;
-pub extern fn ZigClangVarDecl_getInit(*const ZigClangVarDecl) ?*const ZigClangExpr;
-pub extern fn ZigClangVarDecl_getTLSKind(self: ?*const struct_ZigClangVarDecl) ZigClangVarDecl_TLSKind;
-pub const ZigClangVarDecl_TLSKind = extern enum {
- None,
- Static,
- Dynamic,
-};
-
-pub extern fn ZigClangImplicitCastExpr_getBeginLoc(*const ZigClangImplicitCastExpr) ZigClangSourceLocation;
-pub extern fn ZigClangImplicitCastExpr_getCastKind(*const ZigClangImplicitCastExpr) ZigClangCK;
-pub extern fn ZigClangImplicitCastExpr_getSubExpr(*const ZigClangImplicitCastExpr) *const ZigClangExpr;
-
-pub extern fn ZigClangArrayType_getElementType(*const ZigClangArrayType) ZigClangQualType;
-
-pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const ZigClangValueDecl;
-
-pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
-
-pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;
-
-pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;
-
-pub extern fn ZigClangCStyleCastExpr_getBeginLoc(*const ZigClangCStyleCastExpr) ZigClangSourceLocation;
-pub extern fn ZigClangCStyleCastExpr_getSubExpr(*const ZigClangCStyleCastExpr) *const ZigClangExpr;
-pub extern fn ZigClangCStyleCastExpr_getType(*const ZigClangCStyleCastExpr) ZigClangQualType;
diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig
new file mode 100644
index 0000000000..0dde6da71c
--- /dev/null
+++ b/src-self-hosted/dep_tokenizer.zig
@@ -0,0 +1,1055 @@
+const std = @import("std");
+const testing = std.testing;
+
+pub const Tokenizer = struct {
+ arena: std.heap.ArenaAllocator,
+ index: usize,
+ bytes: []const u8,
+ error_text: []const u8,
+ state: State,
+
+ pub fn init(allocator: *std.mem.Allocator, bytes: []const u8) Tokenizer {
+ return Tokenizer{
+ .arena = std.heap.ArenaAllocator.init(allocator),
+ .index = 0,
+ .bytes = bytes,
+ .error_text = "",
+ .state = State{ .lhs = {} },
+ };
+ }
+
+ pub fn deinit(self: *Tokenizer) void {
+ self.arena.deinit();
+ }
+
+ pub fn next(self: *Tokenizer) Error!?Token {
+ while (self.index < self.bytes.len) {
+ const char = self.bytes[self.index];
+ while (true) {
+ switch (self.state) {
+ .lhs => switch (char) {
+ '\t', '\n', '\r', ' ' => {
+ // silently ignore whitespace
+ break; // advance
+ },
+ else => {
+ self.state = State{ .target = try std.Buffer.initSize(&self.arena.allocator, 0) };
+ },
+ },
+ .target => |*target| switch (char) {
+ '\t', '\n', '\r', ' ' => {
+ return self.errorIllegalChar(self.index, char, "invalid target");
+ },
+ '$' => {
+ self.state = State{ .target_dollar_sign = target.* };
+ break; // advance
+ },
+ '\\' => {
+ self.state = State{ .target_reverse_solidus = target.* };
+ break; // advance
+ },
+ ':' => {
+ self.state = State{ .target_colon = target.* };
+ break; // advance
+ },
+ else => {
+ try target.appendByte(char);
+ break; // advance
+ },
+ },
+ .target_reverse_solidus => |*target| switch (char) {
+ '\t', '\n', '\r' => {
+ return self.errorIllegalChar(self.index, char, "bad target escape");
+ },
+ ' ', '#', '\\' => {
+ try target.appendByte(char);
+ self.state = State{ .target = target.* };
+ break; // advance
+ },
+ '$' => {
+ try target.append(self.bytes[self.index - 1 .. self.index]);
+ self.state = State{ .target_dollar_sign = target.* };
+ break; // advance
+ },
+ else => {
+ try target.append(self.bytes[self.index - 1 .. self.index + 1]);
+ self.state = State{ .target = target.* };
+ break; // advance
+ },
+ },
+ .target_dollar_sign => |*target| switch (char) {
+ '$' => {
+ try target.appendByte(char);
+ self.state = State{ .target = target.* };
+ break; // advance
+ },
+ else => {
+ return self.errorIllegalChar(self.index, char, "expecting '$'");
+ },
+ },
+ .target_colon => |*target| switch (char) {
+ '\n', '\r' => {
+ const bytes = target.toSlice();
+ if (bytes.len != 0) {
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .target, .bytes = bytes };
+ }
+ // silently ignore null target
+ self.state = State{ .lhs = {} };
+ continue;
+ },
+ '\\' => {
+ self.state = State{ .target_colon_reverse_solidus = target.* };
+ break; // advance
+ },
+ else => {
+ const bytes = target.toSlice();
+ if (bytes.len != 0) {
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .target, .bytes = bytes };
+ }
+ // silently ignore null target
+ self.state = State{ .lhs = {} };
+ continue;
+ },
+ },
+ .target_colon_reverse_solidus => |*target| switch (char) {
+ '\n', '\r' => {
+ const bytes = target.toSlice();
+ if (bytes.len != 0) {
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .target, .bytes = bytes };
+ }
+ // silently ignore null target
+ self.state = State{ .lhs = {} };
+ continue;
+ },
+ else => {
+ try target.append(self.bytes[self.index - 2 .. self.index + 1]);
+ self.state = State{ .target = target.* };
+ break;
+ },
+ },
+ .rhs => switch (char) {
+ '\t', ' ' => {
+ // silently ignore horizontal whitespace
+ break; // advance
+ },
+ '\n', '\r' => {
+ self.state = State{ .lhs = {} };
+ continue;
+ },
+ '\\' => {
+ self.state = State{ .rhs_continuation = {} };
+ break; // advance
+ },
+ '"' => {
+ self.state = State{ .prereq_quote = try std.Buffer.initSize(&self.arena.allocator, 0) };
+ break; // advance
+ },
+ else => {
+ self.state = State{ .prereq = try std.Buffer.initSize(&self.arena.allocator, 0) };
+ },
+ },
+ .rhs_continuation => switch (char) {
+ '\n' => {
+ self.state = State{ .rhs = {} };
+ break; // advance
+ },
+ '\r' => {
+ self.state = State{ .rhs_continuation_linefeed = {} };
+ break; // advance
+ },
+ else => {
+ return self.errorIllegalChar(self.index, char, "continuation expecting end-of-line");
+ },
+ },
+ .rhs_continuation_linefeed => switch (char) {
+ '\n' => {
+ self.state = State{ .rhs = {} };
+ break; // advance
+ },
+ else => {
+ return self.errorIllegalChar(self.index, char, "continuation expecting end-of-line");
+ },
+ },
+ .prereq_quote => |*prereq| switch (char) {
+ '"' => {
+ const bytes = prereq.toSlice();
+ self.index += 1;
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ else => {
+ try prereq.appendByte(char);
+ break; // advance
+ },
+ },
+ .prereq => |*prereq| switch (char) {
+ '\t', ' ' => {
+ const bytes = prereq.toSlice();
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ '\n', '\r' => {
+ const bytes = prereq.toSlice();
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ '\\' => {
+ self.state = State{ .prereq_continuation = prereq.* };
+ break; // advance
+ },
+ else => {
+ try prereq.appendByte(char);
+ break; // advance
+ },
+ },
+ .prereq_continuation => |*prereq| switch (char) {
+ '\n' => {
+ const bytes = prereq.toSlice();
+ self.index += 1;
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ '\r' => {
+ self.state = State{ .prereq_continuation_linefeed = prereq.* };
+ break; // advance
+ },
+ else => {
+ // not continuation
+ try prereq.append(self.bytes[self.index - 1 .. self.index + 1]);
+ self.state = State{ .prereq = prereq.* };
+ break; // advance
+ },
+ },
+ .prereq_continuation_linefeed => |prereq| switch (char) {
+ '\n' => {
+ const bytes = prereq.toSlice();
+ self.index += 1;
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ else => {
+ return self.errorIllegalChar(self.index, char, "continuation expecting end-of-line");
+ },
+ },
+ }
+ }
+ self.index += 1;
+ }
+
+ // eof, handle maybe incomplete token
+ if (self.index == 0) return null;
+ const idx = self.index - 1;
+ switch (self.state) {
+ .lhs,
+ .rhs,
+ .rhs_continuation,
+ .rhs_continuation_linefeed,
+ => {},
+ .target => |target| {
+ return self.errorPosition(idx, target.toSlice(), "incomplete target");
+ },
+ .target_reverse_solidus,
+ .target_dollar_sign,
+ => {
+ const index = self.index - 1;
+ return self.errorIllegalChar(idx, self.bytes[idx], "incomplete escape");
+ },
+ .target_colon => |target| {
+ const bytes = target.toSlice();
+ if (bytes.len != 0) {
+ self.index += 1;
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .target, .bytes = bytes };
+ }
+ // silently ignore null target
+ self.state = State{ .lhs = {} };
+ },
+ .target_colon_reverse_solidus => |target| {
+ const bytes = target.toSlice();
+ if (bytes.len != 0) {
+ self.index += 1;
+ self.state = State{ .rhs = {} };
+ return Token{ .id = .target, .bytes = bytes };
+ }
+ // silently ignore null target
+ self.state = State{ .lhs = {} };
+ },
+ .prereq_quote => |prereq| {
+ return self.errorPosition(idx, prereq.toSlice(), "incomplete quoted prerequisite");
+ },
+ .prereq => |prereq| {
+ const bytes = prereq.toSlice();
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ .prereq_continuation => |prereq| {
+ const bytes = prereq.toSlice();
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ .prereq_continuation_linefeed => |prereq| {
+ const bytes = prereq.toSlice();
+ self.state = State{ .lhs = {} };
+ return Token{ .id = .prereq, .bytes = bytes };
+ },
+ }
+ return null;
+ }
+
+ fn errorf(self: *Tokenizer, comptime fmt: []const u8, args: ...) Error {
+ self.error_text = (try std.Buffer.allocPrint(&self.arena.allocator, fmt, args)).toSlice();
+ return Error.InvalidInput;
+ }
+
+ fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: ...) Error {
+ var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
+ std.fmt.format(&buffer, anyerror, std.Buffer.append, fmt, args) catch {};
+ try buffer.append(" '");
+ var out = makeOutput(std.Buffer.append, &buffer);
+ try printCharValues(&out, bytes);
+ try buffer.append("'");
+ std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", position - (bytes.len - 1)) catch {};
+ self.error_text = buffer.toSlice();
+ return Error.InvalidInput;
+ }
+
+ fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: ...) Error {
+ var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
+ try buffer.append("illegal char ");
+ var out = makeOutput(std.Buffer.append, &buffer);
+ try printUnderstandableChar(&out, char);
+ std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", position) catch {};
+ if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
+ self.error_text = buffer.toSlice();
+ return Error.InvalidInput;
+ }
+
+ const Error = error{
+ OutOfMemory,
+ InvalidInput,
+ };
+
+ const State = union(enum) {
+ lhs: void,
+ target: std.Buffer,
+ target_reverse_solidus: std.Buffer,
+ target_dollar_sign: std.Buffer,
+ target_colon: std.Buffer,
+ target_colon_reverse_solidus: std.Buffer,
+ rhs: void,
+ rhs_continuation: void,
+ rhs_continuation_linefeed: void,
+ prereq_quote: std.Buffer,
+ prereq: std.Buffer,
+ prereq_continuation: std.Buffer,
+ prereq_continuation_linefeed: std.Buffer,
+ };
+
+ const Token = struct {
+ id: ID,
+ bytes: []const u8,
+
+ const ID = enum {
+ target,
+ prereq,
+ };
+ };
+};
+
+test "empty file" {
+ try depTokenizer("", "");
+}
+
+test "empty whitespace" {
+ try depTokenizer("\n", "");
+ try depTokenizer("\r", "");
+ try depTokenizer("\r\n", "");
+ try depTokenizer(" ", "");
+}
+
+test "empty colon" {
+ try depTokenizer(":", "");
+ try depTokenizer("\n:", "");
+ try depTokenizer("\r:", "");
+ try depTokenizer("\r\n:", "");
+ try depTokenizer(" :", "");
+}
+
+test "empty target" {
+ try depTokenizer("foo.o:", "target = {foo.o}");
+ try depTokenizer(
+ \\foo.o:
+ \\bar.o:
+ \\abcd.o:
+ ,
+ \\target = {foo.o}
+ \\target = {bar.o}
+ \\target = {abcd.o}
+ );
+}
+
+test "whitespace empty target" {
+ try depTokenizer("\nfoo.o:", "target = {foo.o}");
+ try depTokenizer("\rfoo.o:", "target = {foo.o}");
+ try depTokenizer("\r\nfoo.o:", "target = {foo.o}");
+ try depTokenizer(" foo.o:", "target = {foo.o}");
+}
+
+test "escape empty target" {
+ try depTokenizer("\\ foo.o:", "target = { foo.o}");
+ try depTokenizer("\\#foo.o:", "target = {#foo.o}");
+ try depTokenizer("\\\\foo.o:", "target = {\\foo.o}");
+ try depTokenizer("$$foo.o:", "target = {$foo.o}");
+}
+
+test "empty target linefeeds" {
+ try depTokenizer("\n", "");
+ try depTokenizer("\r\n", "");
+
+ const expect = "target = {foo.o}";
+ try depTokenizer(
+ \\foo.o:
+ , expect);
+ try depTokenizer(
+ \\foo.o:
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o:
+ , expect);
+ try depTokenizer(
+ \\foo.o:
+ \\
+ , expect);
+}
+
+test "empty target linefeeds + continuations" {
+ const expect = "target = {foo.o}";
+ try depTokenizer(
+ \\foo.o:\
+ , expect);
+ try depTokenizer(
+ \\foo.o:\
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o:\
+ , expect);
+ try depTokenizer(
+ \\foo.o:\
+ \\
+ , expect);
+}
+
+test "empty target linefeeds + hspace + continuations" {
+ const expect = "target = {foo.o}";
+ try depTokenizer(
+ \\foo.o: \
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\
+ , expect);
+}
+
+test "prereq" {
+ const expect =
+ \\target = {foo.o}
+ \\prereq = {foo.c}
+ ;
+ try depTokenizer("foo.o: foo.c", expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\foo.c
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\ foo.c
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\ foo.c
+ , expect);
+}
+
+test "prereq continuation" {
+ const expect =
+ \\target = {foo.o}
+ \\prereq = {foo.h}
+ \\prereq = {bar.h}
+ ;
+ try depTokenizer(
+ \\foo.o: foo.h\
+ \\bar.h
+ , expect);
+ try depTokenizer(
+ \\foo.o: foo.h\
+ \\bar.h
+ , expect);
+}
+
+test "multiple prereqs" {
+ const expect =
+ \\target = {foo.o}
+ \\prereq = {foo.c}
+ \\prereq = {foo.h}
+ \\prereq = {bar.h}
+ ;
+ try depTokenizer("foo.o: foo.c foo.h bar.h", expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\foo.c foo.h bar.h
+ , expect);
+ try depTokenizer(
+ \\foo.o: foo.c foo.h bar.h\
+ , expect);
+ try depTokenizer(
+ \\foo.o: foo.c foo.h bar.h\
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\foo.c \
+ \\ foo.h\
+ \\bar.h
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\foo.c \
+ \\ foo.h\
+ \\bar.h\
+ \\
+ , expect);
+ try depTokenizer(
+ \\foo.o: \
+ \\foo.c \
+ \\ foo.h\
+ \\bar.h\
+ , expect);
+}
+
+test "multiple targets and prereqs" {
+ try depTokenizer(
+ \\foo.o: foo.c
+ \\bar.o: bar.c a.h b.h c.h
+ \\abc.o: abc.c \
+ \\ one.h two.h \
+ \\ three.h four.h
+ ,
+ \\target = {foo.o}
+ \\prereq = {foo.c}
+ \\target = {bar.o}
+ \\prereq = {bar.c}
+ \\prereq = {a.h}
+ \\prereq = {b.h}
+ \\prereq = {c.h}
+ \\target = {abc.o}
+ \\prereq = {abc.c}
+ \\prereq = {one.h}
+ \\prereq = {two.h}
+ \\prereq = {three.h}
+ \\prereq = {four.h}
+ );
+ try depTokenizer(
+ \\ascii.o: ascii.c
+ \\base64.o: base64.c stdio.h
+ \\elf.o: elf.c a.h b.h c.h
+ \\macho.o: \
+ \\ macho.c\
+ \\ a.h b.h c.h
+ ,
+ \\target = {ascii.o}
+ \\prereq = {ascii.c}
+ \\target = {base64.o}
+ \\prereq = {base64.c}
+ \\prereq = {stdio.h}
+ \\target = {elf.o}
+ \\prereq = {elf.c}
+ \\prereq = {a.h}
+ \\prereq = {b.h}
+ \\prereq = {c.h}
+ \\target = {macho.o}
+ \\prereq = {macho.c}
+ \\prereq = {a.h}
+ \\prereq = {b.h}
+ \\prereq = {c.h}
+ );
+ try depTokenizer(
+ \\a$$scii.o: ascii.c
+ \\\\base64.o: "\base64.c" "s t#dio.h"
+ \\e\\lf.o: "e\lf.c" "a.h$$" "$$b.h c.h$$"
+ \\macho.o: \
+ \\ "macho!.c" \
+ \\ a.h b.h c.h
+ ,
+ \\target = {a$scii.o}
+ \\prereq = {ascii.c}
+ \\target = {\base64.o}
+ \\prereq = {\base64.c}
+ \\prereq = {s t#dio.h}
+ \\target = {e\lf.o}
+ \\prereq = {e\lf.c}
+ \\prereq = {a.h$$}
+ \\prereq = {$$b.h c.h$$}
+ \\target = {macho.o}
+ \\prereq = {macho!.c}
+ \\prereq = {a.h}
+ \\prereq = {b.h}
+ \\prereq = {c.h}
+ );
+}
+
+test "windows quoted prereqs" {
+ try depTokenizer(
+ \\c:\foo.o: "C:\Program Files (x86)\Microsoft Visual Studio\foo.c"
+ \\c:\foo2.o: "C:\Program Files (x86)\Microsoft Visual Studio\foo2.c" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\foo1.h" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\foo2.h"
+ ,
+ \\target = {c:\foo.o}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo.c}
+ \\target = {c:\foo2.o}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo2.c}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo1.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\foo2.h}
+ );
+}
+
+test "windows mixed prereqs" {
+ try depTokenizer(
+ \\cimport.o: \
+ \\ C:\msys64\home\anon\project\zig\master\zig-cache\o\qhvhbUo7GU5iKyQ5mpA8TcQpncCYaQu0wwvr3ybiSTj_Dtqi1Nmcb70kfODJ2Qlg\cimport.h \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\stdio.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt.h" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime.h" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\sal.h" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\concurrencysal.h" \
+ \\ C:\msys64\opt\zig\lib\zig\include\vadefs.h \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vadefs.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstdio.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_stdio_config.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\string.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memory.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memcpy_s.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\errno.h" \
+ \\ "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime_string.h" \
+ \\ "C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstring.h"
+ ,
+ \\target = {cimport.o}
+ \\prereq = {C:\msys64\home\anon\project\zig\master\zig-cache\o\qhvhbUo7GU5iKyQ5mpA8TcQpncCYaQu0wwvr3ybiSTj_Dtqi1Nmcb70kfODJ2Qlg\cimport.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\stdio.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\sal.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\concurrencysal.h}
+ \\prereq = {C:\msys64\opt\zig\lib\zig\include\vadefs.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vadefs.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstdio.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_stdio_config.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\string.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memory.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_memcpy_s.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\errno.h}
+ \\prereq = {C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.21.27702\lib\x64\\..\..\include\vcruntime_string.h}
+ \\prereq = {C:\Program Files (x86)\Windows Kits\10\\Include\10.0.17763.0\ucrt\corecrt_wstring.h}
+ );
+}
+
+test "funky targets" {
+ try depTokenizer(
+ \\C:\Users\anon\foo.o:
+ \\C:\Users\anon\foo\ .o:
+ \\C:\Users\anon\foo\#.o:
+ \\C:\Users\anon\foo$$.o:
+ \\C:\Users\anon\\\ foo.o:
+ \\C:\Users\anon\\#foo.o:
+ \\C:\Users\anon\$$foo.o:
+ \\C:\Users\anon\\\ \ \ \ \ foo.o:
+ ,
+ \\target = {C:\Users\anon\foo.o}
+ \\target = {C:\Users\anon\foo .o}
+ \\target = {C:\Users\anon\foo#.o}
+ \\target = {C:\Users\anon\foo$.o}
+ \\target = {C:\Users\anon\ foo.o}
+ \\target = {C:\Users\anon\#foo.o}
+ \\target = {C:\Users\anon\$foo.o}
+ \\target = {C:\Users\anon\ foo.o}
+ );
+}
+
+test "error incomplete escape - reverse_solidus" {
+ try depTokenizer("\\",
+ \\ERROR: illegal char '\' at position 0: incomplete escape
+ );
+ try depTokenizer("\t\\",
+ \\ERROR: illegal char '\' at position 1: incomplete escape
+ );
+ try depTokenizer("\n\\",
+ \\ERROR: illegal char '\' at position 1: incomplete escape
+ );
+ try depTokenizer("\r\\",
+ \\ERROR: illegal char '\' at position 1: incomplete escape
+ );
+ try depTokenizer("\r\n\\",
+ \\ERROR: illegal char '\' at position 2: incomplete escape
+ );
+ try depTokenizer(" \\",
+ \\ERROR: illegal char '\' at position 1: incomplete escape
+ );
+}
+
+test "error incomplete escape - dollar_sign" {
+ try depTokenizer("$",
+ \\ERROR: illegal char '$' at position 0: incomplete escape
+ );
+ try depTokenizer("\t$",
+ \\ERROR: illegal char '$' at position 1: incomplete escape
+ );
+ try depTokenizer("\n$",
+ \\ERROR: illegal char '$' at position 1: incomplete escape
+ );
+ try depTokenizer("\r$",
+ \\ERROR: illegal char '$' at position 1: incomplete escape
+ );
+ try depTokenizer("\r\n$",
+ \\ERROR: illegal char '$' at position 2: incomplete escape
+ );
+ try depTokenizer(" $",
+ \\ERROR: illegal char '$' at position 1: incomplete escape
+ );
+}
+
+test "error incomplete target" {
+ try depTokenizer("foo.o",
+ \\ERROR: incomplete target 'foo.o' at position 0
+ );
+ try depTokenizer("\tfoo.o",
+ \\ERROR: incomplete target 'foo.o' at position 1
+ );
+ try depTokenizer("\nfoo.o",
+ \\ERROR: incomplete target 'foo.o' at position 1
+ );
+ try depTokenizer("\rfoo.o",
+ \\ERROR: incomplete target 'foo.o' at position 1
+ );
+ try depTokenizer("\r\nfoo.o",
+ \\ERROR: incomplete target 'foo.o' at position 2
+ );
+ try depTokenizer(" foo.o",
+ \\ERROR: incomplete target 'foo.o' at position 1
+ );
+
+ try depTokenizer("\\ foo.o",
+ \\ERROR: incomplete target ' foo.o' at position 1
+ );
+ try depTokenizer("\\#foo.o",
+ \\ERROR: incomplete target '#foo.o' at position 1
+ );
+ try depTokenizer("\\\\foo.o",
+ \\ERROR: incomplete target '\foo.o' at position 1
+ );
+ try depTokenizer("$$foo.o",
+ \\ERROR: incomplete target '$foo.o' at position 1
+ );
+}
+
+test "error illegal char at position - bad target escape" {
+ try depTokenizer("\\\t",
+ \\ERROR: illegal char \x09 at position 1: bad target escape
+ );
+ try depTokenizer("\\\n",
+ \\ERROR: illegal char \x0A at position 1: bad target escape
+ );
+ try depTokenizer("\\\r",
+ \\ERROR: illegal char \x0D at position 1: bad target escape
+ );
+ try depTokenizer("\\\r\n",
+ \\ERROR: illegal char \x0D at position 1: bad target escape
+ );
+}
+
+test "error illegal char at position - execting dollar_sign" {
+ try depTokenizer("$\t",
+ \\ERROR: illegal char \x09 at position 1: expecting '$'
+ );
+ try depTokenizer("$\n",
+ \\ERROR: illegal char \x0A at position 1: expecting '$'
+ );
+ try depTokenizer("$\r",
+ \\ERROR: illegal char \x0D at position 1: expecting '$'
+ );
+ try depTokenizer("$\r\n",
+ \\ERROR: illegal char \x0D at position 1: expecting '$'
+ );
+}
+
+test "error illegal char at position - invalid target" {
+ try depTokenizer("foo\t.o",
+ \\ERROR: illegal char \x09 at position 3: invalid target
+ );
+ try depTokenizer("foo\n.o",
+ \\ERROR: illegal char \x0A at position 3: invalid target
+ );
+ try depTokenizer("foo\r.o",
+ \\ERROR: illegal char \x0D at position 3: invalid target
+ );
+ try depTokenizer("foo\r\n.o",
+ \\ERROR: illegal char \x0D at position 3: invalid target
+ );
+}
+
+test "error target - continuation expecting end-of-line" {
+ try depTokenizer("foo.o: \\\t",
+ \\target = {foo.o}
+ \\ERROR: illegal char \x09 at position 8: continuation expecting end-of-line
+ );
+ try depTokenizer("foo.o: \\ ",
+ \\target = {foo.o}
+ \\ERROR: illegal char \x20 at position 8: continuation expecting end-of-line
+ );
+ try depTokenizer("foo.o: \\x",
+ \\target = {foo.o}
+ \\ERROR: illegal char 'x' at position 8: continuation expecting end-of-line
+ );
+ try depTokenizer("foo.o: \\\x0dx",
+ \\target = {foo.o}
+ \\ERROR: illegal char 'x' at position 9: continuation expecting end-of-line
+ );
+}
+
+test "error prereq - continuation expecting end-of-line" {
+ try depTokenizer("foo.o: foo.h\\\x0dx",
+ \\target = {foo.o}
+ \\ERROR: illegal char 'x' at position 14: continuation expecting end-of-line
+ );
+}
+
+// - tokenize input, emit textual representation, and compare to expect
+fn depTokenizer(input: []const u8, expect: []const u8) !void {
+ var direct_allocator = std.heap.DirectAllocator.init();
+ var arena_allocator = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
+ const arena = &arena_allocator.allocator;
+ defer arena_allocator.deinit();
+
+ var it = Tokenizer.init(&direct_allocator.allocator, input);
+ var buffer = try std.Buffer.initSize(arena, 0);
+ var i: usize = 0;
+ while (true) {
+ const r = it.next() catch |err| {
+ switch (err) {
+ Tokenizer.Error.InvalidInput => {
+ if (i != 0) try buffer.append("\n");
+ try buffer.append("ERROR: ");
+ try buffer.append(it.error_text);
+ },
+ else => return err,
+ }
+ break;
+ };
+ const token = r orelse break;
+ if (i != 0) try buffer.append("\n");
+ try buffer.append(@tagName(token.id));
+ try buffer.append(" = {");
+ for (token.bytes) |b| {
+ try buffer.appendByte(printable_char_tab[b]);
+ }
+ try buffer.append("}");
+ i += 1;
+ }
+ const got: []const u8 = buffer.toSlice();
+
+ if (std.mem.eql(u8, expect, got)) {
+ testing.expect(true);
+ return;
+ }
+
+ var out = makeOutput(std.fs.File.write, try std.io.getStdErr());
+
+ try out.write("\n");
+ try printSection(&out, "<<<< input", input);
+ try printSection(&out, "==== expect", expect);
+ try printSection(&out, ">>>> got", got);
+ try printRuler(&out);
+
+ testing.expect(false);
+}
+
+fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
+ try printLabel(out, label, bytes);
+ try hexDump(out, bytes);
+ try printRuler(out);
+ try out.write(bytes);
+ try out.write("\n");
+}
+
+fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
+ var buf: [80]u8 = undefined;
+ var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", label, bytes.len);
+ try out.write(text);
+ var i: usize = text.len;
+ const end = 79;
+ while (i < 79) : (i += 1) {
+ try out.write([]const u8{label[0]});
+ }
+ try out.write("\n");
+}
+
+fn printRuler(out: var) !void {
+ var i: usize = 0;
+ const end = 79;
+ while (i < 79) : (i += 1) {
+ try out.write("-");
+ }
+ try out.write("\n");
+}
+
+fn hexDump(out: var, bytes: []const u8) !void {
+ const n16 = bytes.len >> 4;
+ var line: usize = 0;
+ var offset: usize = 0;
+ while (line < n16) : (line += 1) {
+ try hexDump16(out, offset, bytes[offset .. offset + 16]);
+ offset += 16;
+ }
+
+ const n = bytes.len & 0x0f;
+ if (n > 0) {
+ try printDecValue(out, offset, 8);
+ try out.write(":");
+ try out.write(" ");
+ var end1 = std.math.min(offset + n, offset + 8);
+ for (bytes[offset..end1]) |b| {
+ try out.write(" ");
+ try printHexValue(out, b, 2);
+ }
+ var end2 = offset + n;
+ if (end2 > end1) {
+ try out.write(" ");
+ for (bytes[end1..end2]) |b| {
+ try out.write(" ");
+ try printHexValue(out, b, 2);
+ }
+ }
+ const short = 16 - n;
+ var i: usize = 0;
+ while (i < short) : (i += 1) {
+ try out.write(" ");
+ }
+ if (end2 > end1) {
+ try out.write(" |");
+ } else {
+ try out.write(" |");
+ }
+ try printCharValues(out, bytes[offset..end2]);
+ try out.write("|\n");
+ offset += n;
+ }
+
+ try printDecValue(out, offset, 8);
+ try out.write(":");
+ try out.write("\n");
+}
+
+fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {
+ try printDecValue(out, offset, 8);
+ try out.write(":");
+ try out.write(" ");
+ for (bytes[0..8]) |b| {
+ try out.write(" ");
+ try printHexValue(out, b, 2);
+ }
+ try out.write(" ");
+ for (bytes[8..16]) |b| {
+ try out.write(" ");
+ try printHexValue(out, b, 2);
+ }
+ try out.write(" |");
+ try printCharValues(out, bytes);
+ try out.write("|\n");
+}
+
+fn printDecValue(out: var, value: u64, width: u8) !void {
+ var buffer: [20]u8 = undefined;
+ const len = std.fmt.formatIntBuf(buffer[0..], value, 10, false, width);
+ try out.write(buffer[0..len]);
+}
+
+fn printHexValue(out: var, value: u64, width: u8) !void {
+ var buffer: [16]u8 = undefined;
+ const len = std.fmt.formatIntBuf(buffer[0..], value, 16, false, width);
+ try out.write(buffer[0..len]);
+}
+
+fn printCharValues(out: var, bytes: []const u8) !void {
+ for (bytes) |b| {
+ try out.write([]const u8{printable_char_tab[b]});
+ }
+}
+
+fn printUnderstandableChar(out: var, char: u8) !void {
+ if (!std.ascii.isPrint(char) or char == ' ') {
+ std.fmt.format(out.context, anyerror, out.output, "\\x{X2}", char) catch {};
+ } else {
+ try out.write("'");
+ try out.write([]const u8{printable_char_tab[char]});
+ try out.write("'");
+ }
+}
+
+// zig fmt: off
+const printable_char_tab: []const u8 =
+ "................................ !\"#$%&'()*+,-./0123456789:;<=>?" ++
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~." ++
+ "................................................................" ++
+ "................................................................";
+// zig fmt: on
+comptime {
+ std.debug.assert(printable_char_tab.len == 256);
+}
+
+// Make an output var that wraps a context and output function.
+// output: must be a function that takes a `self` idiom parameter
+// and a bytes parameter
+// context: must be that self
+fn makeOutput(output: var, context: var) Output(@typeOf(output)) {
+ return Output(@typeOf(output)){
+ .output = output,
+ .context = context,
+ };
+}
+
+fn Output(comptime T: type) type {
+ const args = switch (@typeInfo(T)) {
+ .Fn => |f| f.args,
+ else => @compileError("output parameter is not a function"),
+ };
+ if (args.len != 2) {
+ @compileError("output function must take 2 arguments");
+ }
+ const at0 = args[0].arg_type orelse @compileError("output arg[0] does not have a type");
+ const at1 = args[1].arg_type orelse @compileError("output arg[1] does not have a type");
+ const arg1p = switch (@typeInfo(at1)) {
+ .Pointer => |p| p,
+ else => @compileError("output arg[1] is not a slice"),
+ };
+ if (arg1p.child != u8) @compileError("output arg[1] is not a u8 slice");
+ return struct {
+ output: T,
+ context: at0,
+
+ fn write(self: *@This(), bytes: []const u8) !void {
+ try self.output(self.context, bytes);
+ }
+ };
+}
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig
index a47dbbbe92..838cbbc480 100644
--- a/src-self-hosted/link.zig
+++ b/src-self-hosted/link.zig
@@ -670,7 +670,7 @@ const DarwinPlatform = struct {
Compilation.DarwinVersionMin.None => blk: {
assert(comp.target.getOs() == .macosx);
result.kind = Kind.MacOS;
- break :blk "10.10";
+ break :blk "10.14";
},
};
diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig
index dd1c137c74..bc1a746154 100644
--- a/src-self-hosted/stage1.zig
+++ b/src-self-hosted/stage1.zig
@@ -15,11 +15,16 @@ const self_hosted_main = @import("main.zig");
const Args = arg.Args;
const Flag = arg.Flag;
const errmsg = @import("errmsg.zig");
+const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
var stderr_file: fs.File = undefined;
var stderr: *io.OutStream(fs.File.WriteError) = undefined;
var stdout: *io.OutStream(fs.File.WriteError) = undefined;
+comptime {
+ _ = @import("dep_tokenizer.zig");
+}
+
// ABI warning
export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
const info_zen = @import("main.zig").info_zen;
@@ -393,3 +398,60 @@ fn printErrMsgToFile(
try stream.writeByteNTimes('~', last_token.end - first_token.start);
try stream.write("\n");
}
+
+export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer {
+ const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer");
+ t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]);
+ return stage2_DepTokenizer{
+ .handle = t,
+ };
+}
+
+export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void {
+ self.handle.deinit();
+}
+
+export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult {
+ const otoken = self.handle.next() catch {
+ const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text");
+ return stage2_DepNextResult{
+ .type_id = .error_,
+ .textz = textz.toSlice().ptr,
+ };
+ };
+ const token = otoken orelse {
+ return stage2_DepNextResult{
+ .type_id = .null_,
+ .textz = undefined,
+ };
+ };
+ const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
+ return stage2_DepNextResult{
+ .type_id = switch (token.id) {
+ .target => stage2_DepNextResult.TypeId.target,
+ .prereq => stage2_DepNextResult.TypeId.prereq,
+ },
+ .textz = textz.toSlice().ptr,
+ };
+}
+
+export const stage2_DepTokenizer = extern struct {
+ handle: *DepTokenizer,
+};
+
+export const stage2_DepNextResult = extern struct {
+ type_id: TypeId,
+
+ // when type_id == error --> error text
+ // when type_id == null --> undefined
+ // when type_id == target --> target pathname
+ // when type_id == prereq --> prereq pathname
+ textz: [*]const u8,
+
+ export const TypeId = extern enum {
+ error_,
+ null_,
+ target,
+ prereq,
+ };
+};
diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig
index 7e1c6571e2..6d64a28f1f 100644
--- a/src-self-hosted/translate_c.zig
+++ b/src-self-hosted/translate_c.zig
@@ -6,7 +6,7 @@ const builtin = @import("builtin");
const assert = std.debug.assert;
const ast = std.zig.ast;
const Token = std.zig.Token;
-use @import("clang.zig");
+usingnamespace @import("clang.zig");
pub const Mode = enum {
import,
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2cd4a5f958..2a6bb1feb5 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1069,6 +1069,7 @@ struct TypeStructField {
size_t gen_index;
size_t offset; // byte offset from beginning of struct
AstNode *decl_node;
+ ConstExprValue *init_val; // null and then memoized
uint32_t bit_offset_in_host; // offset from the memory at gen_index
uint32_t host_int_bytes; // size of host integer
};
@@ -1633,6 +1634,12 @@ enum WantPIC {
WantPICEnabled,
};
+enum WantStackCheck {
+ WantStackCheckAuto,
+ WantStackCheckDisabled,
+ WantStackCheckEnabled,
+};
+
struct CFile {
ZigList args;
const char *source_path;
@@ -1790,6 +1797,8 @@ struct CodeGen {
TldFn *panic_tld_fn;
AstNode *root_export_decl;
+ WantPIC want_pic;
+ WantStackCheck want_stack_check;
CacheHash cache_hash;
ErrColor err_color;
uint32_t next_unresolved_index;
@@ -1807,8 +1816,6 @@ struct CodeGen {
bool have_dllmain_crt_startup;
bool have_pub_panic;
bool have_err_ret_tracing;
- bool have_pic;
- bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
bool c_want_stdint;
bool c_want_stdbool;
bool verbose_tokenize;
@@ -1824,6 +1831,7 @@ struct CodeGen {
bool enable_time_report;
bool system_linker_hack;
bool reported_bad_link_libc_error;
+ bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.
//////////////////////////// Participates in Input Parameter Cache Hash
/////// Note: there is a separate cache hash for builtin.zig, when adding fields,
@@ -1850,10 +1858,8 @@ struct CodeGen {
BuildMode build_mode;
OutType out_type;
const ZigTarget *zig_target;
- TargetSubsystem subsystem;
+ TargetSubsystem subsystem; // careful using this directly; see detect_subsystem
ValgrindSupport valgrind_support;
- WantPIC want_pic;
- bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.
bool strip_debug_symbols;
bool is_test_build;
bool is_single_threaded;
@@ -1863,7 +1869,9 @@ struct CodeGen {
bool is_dummy_so;
bool disable_gen_h;
bool bundle_compiler_rt;
- bool disable_stack_probing;
+ bool have_pic;
+ bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
+ bool have_stack_probing;
Buf *mmacosx_version_min;
Buf *mios_version_min;
@@ -2299,6 +2307,7 @@ enum IrInstructionId {
IrInstructionIdAssertZero,
IrInstructionIdAssertNonNull,
IrInstructionIdHasDecl,
+ IrInstructionIdUndeclaredIdent,
};
struct IrInstruction {
@@ -3512,6 +3521,12 @@ struct IrInstructionHasDecl {
IrInstruction *name;
};
+struct IrInstructionUndeclaredIdent {
+ IrInstruction base;
+
+ Buf *name;
+};
+
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index d6396832c4..0878cf04a7 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -965,9 +965,7 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
return entry;
}
-static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
- Buf *type_name)
-{
+ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
size_t backward_branch_count = 0;
size_t backward_branch_quota = default_backward_branch_quota;
return ir_eval_const_value(g, scope, node, type_entry,
@@ -981,6 +979,17 @@ ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
return g->builtin_types.entry_invalid;
assert(result->special != ConstValSpecialRuntime);
+ // Reject undefined as valid `type` type even though the specification
+ // allows it to be casted to anything.
+ // See also ir_resolve_type()
+ if (result->special == ConstValSpecialUndef) {
+ add_node_error(g, node,
+ buf_sprintf("expected type 'type', found '%s'",
+ buf_ptr(&g->builtin_types.entry_undef->name)));
+ return g->builtin_types.entry_invalid;
+ }
+
+ assert(result->data.x_type != nullptr);
return result->data.x_type;
}
@@ -2178,10 +2187,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
type_struct_field->src_index = i;
type_struct_field->gen_index = SIZE_MAX;
- if (field_node->data.struct_field.value != nullptr) {
- add_node_error(g, field_node->data.struct_field.value,
- buf_sprintf("enums, not structs, support field assignment"));
- }
if (field_type->id == ZigTypeIdOpaque) {
add_node_error(g, field_node->data.struct_field.type,
buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
@@ -2711,12 +2716,10 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
if (ccc) {
if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
g->have_c_main = true;
- g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(symbol_name, "WinMain") &&
g->zig_target->os == OsWindows)
{
g->have_winmain = true;
- g->subsystem = TargetSubsystemWindows;
} else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
g->zig_target->os == OsWindows)
{
@@ -3442,11 +3445,12 @@ TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag) {
}
-static bool is_container(ZigType *type_entry) {
+bool is_container(ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdStruct:
+ return !type_entry->data.structure.is_slice;
case ZigTypeIdEnum:
case ZigTypeIdUnion:
return true;
@@ -3487,9 +3491,9 @@ bool is_array_ref(ZigType *type_entry) {
return array->id == ZigTypeIdArray;
}
-bool is_container_ref(ZigType *type_entry) {
- return is_ref(type_entry) ?
- is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
+bool is_container_ref(ZigType *parent_ty) {
+ ZigType *ty = is_ref(parent_ty) ? parent_ty->data.pointer.child_type : parent_ty;
+ return is_slice(ty) || is_container(ty);
}
ZigType *container_ref_type(ZigType *type_entry) {
@@ -3754,49 +3758,59 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
analyze_fn_ir(g, fn_table_entry, return_type_node);
}
-static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
+static void add_symbols_from_container(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
if (src_use_node->data.use.resolution == TldResolutionUnresolved) {
preview_use_decl(g, src_use_node, decls_scope);
}
- ConstExprValue *use_target_value = src_use_node->data.use.using_namespace_value;
- if (type_is_invalid(use_target_value->type)) {
+ ConstExprValue *use_expr = src_use_node->data.use.using_namespace_value;
+ if (type_is_invalid(use_expr->type)) {
decls_scope->any_imports_failed = true;
return;
}
dst_use_node->data.use.resolution = TldResolutionOk;
- assert(use_target_value->special != ConstValSpecialRuntime);
+ assert(use_expr->special != ConstValSpecialRuntime);
- ZigType *target_import = use_target_value->data.x_type;
- assert(target_import);
+ // The source struct for the imported symbols
+ ZigType *src_ty = use_expr->data.x_type;
+ assert(src_ty);
- if (target_import->id != ZigTypeIdStruct) {
+ if (!is_container(src_ty)) {
add_node_error(g, dst_use_node,
- buf_sprintf("expected struct, found '%s'", buf_ptr(&target_import->name)));
+ buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&src_ty->name)));
decls_scope->any_imports_failed = true;
return;
}
- if (get_container_scope(target_import)->any_imports_failed) {
+ // The source scope for the imported symbols
+ ScopeDecls *src_scope = get_container_scope(src_ty);
+ // The top-level container where the symbols are defined, it's used in the
+ // loop below in order to exclude the ones coming from an import statement
+ ZigType *src_import = get_scope_import(&src_scope->base);
+ assert(src_import != nullptr);
+
+ if (src_scope->any_imports_failed) {
decls_scope->any_imports_failed = true;
}
- auto it = get_container_scope(target_import)->decl_table.entry_iterator();
+ auto it = src_scope->decl_table.entry_iterator();
for (;;) {
auto *entry = it.next();
if (!entry)
break;
+ Buf *target_tld_name = entry->key;
Tld *target_tld = entry->value;
- if (target_tld->import != target_import ||
- target_tld->visib_mod == VisibModPrivate)
- {
+
+ if (target_tld->visib_mod == VisibModPrivate) {
continue;
}
- Buf *target_tld_name = entry->key;
+ if (target_tld->import != src_import) {
+ continue;
+ }
auto existing_entry = decls_scope->decl_table.put_unique(target_tld_name, target_tld);
if (existing_entry) {
@@ -3811,10 +3825,10 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
}
}
- for (size_t i = 0; i < get_container_scope(target_import)->use_decls.length; i += 1) {
- AstNode *use_decl_node = get_container_scope(target_import)->use_decls.at(i);
+ for (size_t i = 0; i < src_scope->use_decls.length; i += 1) {
+ AstNode *use_decl_node = src_scope->use_decls.at(i);
if (use_decl_node->data.use.visib_mod != VisibModPrivate)
- add_symbols_from_import(g, use_decl_node, dst_use_node, decls_scope);
+ add_symbols_from_container(g, use_decl_node, dst_use_node, decls_scope);
}
}
@@ -3826,7 +3840,7 @@ void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
{
return;
}
- add_symbols_from_import(g, node, node, decls_scope);
+ add_symbols_from_container(g, node, node, decls_scope);
}
void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
@@ -3892,10 +3906,17 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
buf_init_from_buf(&namespace_name, &package->pkg_path);
if (source_kind == SourceKindNonRoot) {
assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
-
- if (buf_len(&namespace_name) != 0) buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);
- buf_append_mem(&namespace_name, buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
- buf_len(&noextname) - (buf_len(&resolved_root_src_dir) + 1));
+ if (buf_len(&namespace_name) != 0) {
+ buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);
+ }
+ // The namespace components are obtained from the relative path to the
+ // source directory
+ if (buf_len(&noextname) > buf_len(&resolved_root_src_dir)) {
+ // Skip the trailing separator
+ buf_append_mem(&namespace_name,
+ buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
+ buf_len(&noextname) - buf_len(&resolved_root_src_dir) - 1);
+ }
buf_replace(&namespace_name, ZIG_OS_SEP_CHAR, NAMESPACE_SEP_CHAR);
}
Buf *bare_name = buf_alloc();
@@ -3937,7 +3958,6 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
if (is_pub) {
if (buf_eql_str(proto_name, "main")) {
g->have_pub_main = true;
- g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(proto_name, "panic")) {
g->have_pub_panic = true;
}
@@ -6368,12 +6388,14 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
len_debug_size_in_bits,
len_debug_align_in_bits,
len_offset_in_bits,
- 0, usize_llvm_di_type),
+ ZigLLVM_DIFlags_Zero,
+ usize_llvm_di_type),
};
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
compile_unit_scope,
buf_ptr(&type->name),
- di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
+ di_file, line, debug_size_in_bits, debug_align_in_bits,
+ ZigLLVM_DIFlags_Zero,
nullptr, di_element_types, 1, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
@@ -6405,18 +6427,19 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
ptr_debug_size_in_bits,
ptr_debug_align_in_bits,
ptr_offset_in_bits,
- 0, get_llvm_di_type(g, ptr_type)),
+ ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_type)),
ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
"len", di_file, line,
len_debug_size_in_bits,
len_debug_align_in_bits,
len_offset_in_bits,
- 0, usize_llvm_di_type),
+ ZigLLVM_DIFlags_Zero, usize_llvm_di_type),
};
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
compile_unit_scope,
buf_ptr(&type->name),
- di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
+ di_file, line, debug_size_in_bits, debug_align_in_bits,
+ ZigLLVM_DIFlags_Zero,
nullptr, di_element_types, 2, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
@@ -6577,7 +6600,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
debug_size_in_bits,
debug_align_in_bits,
debug_offset_in_bits,
- 0, field_di_type);
+ ZigLLVM_DIFlags_Zero, field_di_type);
assert(di_element_types[debug_field_index]);
debug_field_index += 1;
}
@@ -6590,7 +6613,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
di_file, line,
debug_size_in_bits,
debug_align_in_bits,
- 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
+ ZigLLVM_DIFlags_Zero,
+ nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type);
struct_type->llvm_di_type = replacement_di_type;
@@ -6619,7 +6643,8 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) {
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
debug_size_in_bits,
debug_align_in_bits,
- 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
+ ZigLLVM_DIFlags_Zero,
+ nullptr, di_element_types, (int)debug_field_count, 0, nullptr, "");
return;
}
@@ -6703,7 +6728,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
store_size_in_bits,
abi_align_in_bits,
0,
- 0, field_di_type);
+ ZigLLVM_DIFlags_Zero, field_di_type);
}
@@ -6732,7 +6757,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
union_type->data.unionation.union_abi_size * 8,
most_aligned_union_member->abi_align * 8,
- 0, union_inner_di_types,
+ ZigLLVM_DIFlags_Zero, union_inner_di_types,
gen_field_count, 0, "");
ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type);
@@ -6766,7 +6791,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion",
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
most_aligned_union_member->size_in_bits, 8*most_aligned_union_member->abi_align,
- 0, union_inner_di_types, gen_field_count, 0, "");
+ ZigLLVM_DIFlags_Zero, union_inner_di_types, gen_field_count, 0, "");
uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type,
union_type->data.unionation.gen_union_index);
@@ -6779,7 +6804,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
most_aligned_union_member->size_in_bits,
8*most_aligned_union_member->abi_align,
union_offset_in_bits,
- 0, union_di_type);
+ ZigLLVM_DIFlags_Zero, union_di_type);
uint64_t tag_debug_size_in_bits = tag_type->size_in_bits;
uint64_t tag_debug_align_in_bits = 8*tag_type->abi_align;
@@ -6790,7 +6815,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
tag_debug_size_in_bits,
tag_debug_align_in_bits,
tag_offset_in_bits,
- 0, get_llvm_di_type(g, tag_type));
+ ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, tag_type));
ZigLLVMDIType *di_root_members[2];
di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type;
@@ -6804,7 +6829,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1),
debug_size_in_bits,
debug_align_in_bits,
- 0, nullptr, di_root_members, 2, 0, nullptr, "");
+ ZigLLVM_DIFlags_Zero, nullptr, di_root_members, 2, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type);
union_type->llvm_di_type = replacement_di_type;
@@ -6932,18 +6957,18 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) {
val_debug_size_in_bits,
val_debug_align_in_bits,
val_offset_in_bits,
- 0, child_llvm_di_type),
+ ZigLLVM_DIFlags_Zero, child_llvm_di_type),
ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
"maybe", di_file, line,
maybe_debug_size_in_bits,
maybe_debug_align_in_bits,
maybe_offset_in_bits,
- 0, bool_llvm_di_type),
+ ZigLLVM_DIFlags_Zero, bool_llvm_di_type),
};
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
compile_unit_scope,
buf_ptr(&type->name),
- di_file, line, debug_size_in_bits, debug_align_in_bits, 0,
+ di_file, line, debug_size_in_bits, debug_align_in_bits, ZigLLVM_DIFlags_Zero,
nullptr, di_element_types, 2, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
@@ -6996,13 +7021,13 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
tag_debug_size_in_bits,
tag_debug_align_in_bits,
tag_offset_in_bits,
- 0, get_llvm_di_type(g, err_set_type)),
+ ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, err_set_type)),
ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type),
"value", di_file, line,
value_debug_size_in_bits,
value_debug_align_in_bits,
value_offset_in_bits,
- 0, get_llvm_di_type(g, payload_type)),
+ ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, payload_type)),
};
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
@@ -7011,7 +7036,7 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
di_file, line,
debug_size_in_bits,
debug_align_in_bits,
- 0,
+ ZigLLVM_DIFlags_Zero,
nullptr, di_element_types, 2, 0, nullptr, "");
ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type);
diff --git a/src/analyze.hpp b/src/analyze.hpp
index a43b3063e0..57f1072355 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -250,5 +250,7 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_path, bool translate_c);
void src_assert(bool ok, AstNode *source_node);
+bool is_container(ZigType *type_entry);
+ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name);
#endif
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 95ae216f70..defe40cb19 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -352,7 +352,7 @@ static void string_literal_escape(Buf *source, Buf *dest) {
} else if (is_printable(c)) {
buf_append_char(dest, c);
} else {
- buf_appendf(dest, "\\x%x", (int)c);
+ buf_appendf(dest, "\\x%02x", (int)c);
}
}
}
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
index cd0cc5324d..714b9b4c18 100644
--- a/src/cache_hash.cpp
+++ b/src/cache_hash.cpp
@@ -5,6 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
+#include "userland.h"
#include "cache_hash.hpp"
#include "all_types.hpp"
#include "buffer.hpp"
@@ -473,71 +474,62 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
if (err == ErrorFileNotFound)
return err;
if (verbose) {
- fprintf(stderr, "unable to read .d file: %s\n", err_str(err));
+ fprintf(stderr, "%s: unable to read .d file: %s\n", err_str(err), buf_ptr(dep_file_path));
}
return ErrorReadingDepFile;
}
- SplitIterator it = memSplit(buf_to_slice(contents), str("\r\n"));
- // skip first line
- SplitIterator_next(&it);
- for (;;) {
- Optional> opt_line = SplitIterator_next(&it);
- if (!opt_line.is_some)
- break;
- if (opt_line.value.len == 0)
- continue;
- // skip over indentation
- while (opt_line.value.len != 0 && (opt_line.value.ptr[0] == ' ' || opt_line.value.ptr[0] == '\t')) {
- opt_line.value.ptr += 1;
- opt_line.value.len -= 1;
- }
- if (opt_line.value.len == 0)
- continue;
-
- if (opt_line.value.ptr[0] == '"') {
- if (opt_line.value.len < 2) {
+ auto it = stage2_DepTokenizer_init(buf_ptr(contents), buf_len(contents));
+ // skip first token: target
+ {
+ auto result = stage2_DepTokenizer_next(&it);
+ switch (result.type_id) {
+ case stage2_DepNextResult::error:
if (verbose) {
- fprintf(stderr, "unable to process invalid .d file %s: line too short\n", buf_ptr(dep_file_path));
+ fprintf(stderr, "%s: failed processing .d file: %s\n", result.textz, buf_ptr(dep_file_path));
}
- return ErrorInvalidDepFile;
- }
- opt_line.value.ptr += 1;
- opt_line.value.len -= 2;
- while (opt_line.value.len != 0 && opt_line.value.ptr[opt_line.value.len] != '"') {
- opt_line.value.len -= 1;
- }
- if (opt_line.value.len == 0) {
- if (verbose) {
- fprintf(stderr, "unable to process invalid .d file %s: missing double quote\n", buf_ptr(dep_file_path));
- }
- return ErrorInvalidDepFile;
- }
- Buf *filename_buf = buf_create_from_slice(opt_line.value);
- if ((err = cache_add_file(ch, filename_buf))) {
- if (verbose) {
- fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
- fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
- }
- return err;
- }
- } else {
- // sometimes there are multiple files on the same line; we actually need space tokenization.
- SplitIterator line_it = memSplit(opt_line.value, str(" \t"));
- Slice filename;
- while (SplitIterator_next(&line_it).unwrap(&filename)) {
- Buf *filename_buf = buf_create_from_slice(filename);
- if (buf_eql_str(filename_buf, "\\")) continue;
- if ((err = cache_add_file(ch, filename_buf))) {
- if (verbose) {
- fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
- fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
- }
- return err;
- }
- }
+ err = ErrorInvalidDepFile;
+ goto finish;
+ case stage2_DepNextResult::null:
+ err = ErrorNone;
+ goto finish;
+ case stage2_DepNextResult::target:
+ case stage2_DepNextResult::prereq:
+ err = ErrorNone;
+ break;
}
}
- return ErrorNone;
+ // Process 0+ preqreqs.
+ // clang is invoked in single-source mode so we never get more targets.
+ for (;;) {
+ auto result = stage2_DepTokenizer_next(&it);
+ switch (result.type_id) {
+ case stage2_DepNextResult::error:
+ if (verbose) {
+ fprintf(stderr, "%s: failed processing .d file: %s\n", result.textz, buf_ptr(dep_file_path));
+ }
+ err = ErrorInvalidDepFile;
+ goto finish;
+ case stage2_DepNextResult::null:
+ case stage2_DepNextResult::target:
+ err = ErrorNone;
+ goto finish;
+ case stage2_DepNextResult::prereq:
+ break;
+ }
+ auto textbuf = buf_alloc();
+ buf_init_from_str(textbuf, result.textz);
+ if ((err = cache_add_file(ch, textbuf))) {
+ if (verbose) {
+ fprintf(stderr, "unable to add %s to cache: %s\n", result.textz, err_str(err));
+ fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
+ }
+ goto finish;
+ }
+ }
+
+ finish:
+ stage2_DepTokenizer_deinit(&it);
+ return err;
}
static Error write_manifest_file(CacheHash *ch) {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 00a4338810..12b07ea6bc 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -48,7 +48,7 @@ static void init_darwin_native(CodeGen *g) {
} else if (ios_target) {
g->mios_version_min = buf_create_from_str(ios_target);
} else if (g->zig_target->os != OsIOS) {
- g->mmacosx_version_min = buf_create_from_str("10.10");
+ g->mmacosx_version_min = buf_create_from_str("10.14");
}
}
@@ -100,6 +100,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
codegen_add_time_event(g, "Initialize");
+ g->subsystem = TargetSubsystemAuto;
g->libc = libc;
g->zig_target = target;
g->cache_dir = cache_dir;
@@ -296,6 +297,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
static void generate_error_name_table(CodeGen *g);
static bool value_is_all_undef(ConstExprValue *const_val);
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
+static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment);
static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
@@ -399,15 +401,6 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
}
}
-static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) {
- // Windows already emits its own stack probes
- if (!g->disable_stack_probing && g->zig_target->os != OsWindows &&
- (g->zig_target->arch == ZigLLVM_x86 ||
- g->zig_target->arch == ZigLLVM_x86_64)) {
- addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack");
- }
-}
-
static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
switch (id) {
case GlobalLinkageIdInternal:
@@ -596,8 +589,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
}
-
- add_probe_stack_attr(g, fn_table_entry->llvm_value);
+ }
+ if (g->have_stack_probing && !fn_table_entry->def_scope->safety_off) {
+ addLLVMFnAttrStr(fn_table_entry->llvm_value, "probe-stack", "__zig_probe_stack");
}
} else {
maybe_import_dll(g, fn_table_entry->llvm_value, linkage);
@@ -680,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
bool is_optimized = g->build_mode != BuildModeDebug;
bool is_internal_linkage = (fn_table_entry->body_node != nullptr &&
fn_table_entry->export_list.length == 0);
- unsigned flags = 0;
+ unsigned flags = ZigLLVM_DIFlags_StaticMember;
ZigLLVMDIScope *fn_di_scope = get_di_scope(g, scope->parent);
assert(fn_di_scope != nullptr);
ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
@@ -1526,53 +1520,12 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
generate_error_name_table(g);
assert(g->err_name_table != nullptr);
- size_t unwrap_err_msg_text_len = strlen(unwrap_err_msg_text);
- size_t err_buf_len = strlen(unwrap_err_msg_text) + g->largest_err_name_len;
- LLVMValueRef *err_buf_vals = allocate(err_buf_len);
- size_t i = 0;
- for (; i < unwrap_err_msg_text_len; i += 1) {
- err_buf_vals[i] = LLVMConstInt(LLVMInt8Type(), unwrap_err_msg_text[i], false);
- }
- for (; i < err_buf_len; i += 1) {
- err_buf_vals[i] = LLVMGetUndef(LLVMInt8Type());
- }
- uint32_t u8_align_bytes = get_abi_alignment(g, g->builtin_types.entry_u8);
- LLVMValueRef init_value = LLVMConstArray(LLVMInt8Type(), err_buf_vals, err_buf_len);
- LLVMValueRef global_array = LLVMAddGlobal(g->module, LLVMTypeOf(init_value), "");
- LLVMSetInitializer(global_array, init_value);
- LLVMSetLinkage(global_array, LLVMInternalLinkage);
- LLVMSetGlobalConstant(global_array, false);
- LLVMSetUnnamedAddr(global_array, true);
- LLVMSetAlignment(global_array, u8_align_bytes);
-
- ZigType *usize = g->builtin_types.entry_usize;
- LLVMValueRef full_buf_ptr_indices[] = {
- LLVMConstNull(usize->llvm_type),
- LLVMConstNull(usize->llvm_type),
- };
- LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_array, full_buf_ptr_indices, 2);
-
-
- ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
- PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
- ZigType *str_type = get_slice_type(g, u8_ptr_type);
- LLVMValueRef global_slice_fields[] = {
- full_buf_ptr,
- LLVMConstNull(usize->llvm_type),
- };
- LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, str_type), global_slice_fields, 2);
- LLVMValueRef global_slice = LLVMAddGlobal(g->module, LLVMTypeOf(slice_init_value), "");
- LLVMSetInitializer(global_slice, slice_init_value);
- LLVMSetLinkage(global_slice, LLVMInternalLinkage);
- LLVMSetGlobalConstant(global_slice, false);
- LLVMSetUnnamedAddr(global_slice, true);
- LLVMSetAlignment(global_slice, get_abi_alignment(g, str_type));
-
- LLVMValueRef offset_ptr_indices[] = {
- LLVMConstNull(usize->llvm_type),
- LLVMConstInt(usize->llvm_type, unwrap_err_msg_text_len, false),
- };
- LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2);
+ // Generate the constant part of the error message
+ LLVMValueRef msg_prefix_init = LLVMConstString(unwrap_err_msg_text, strlen(unwrap_err_msg_text), 1);
+ LLVMValueRef msg_prefix = LLVMAddGlobal(g->module, LLVMTypeOf(msg_prefix_init), "");
+ LLVMSetInitializer(msg_prefix, msg_prefix_init);
+ LLVMSetLinkage(msg_prefix, LLVMInternalLinkage);
+ LLVMSetGlobalConstant(msg_prefix, true);
Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false);
LLVMTypeRef fn_type_ref;
@@ -1609,6 +1562,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
LLVMPositionBuilderAtEnd(g->builder, entry_block);
ZigLLVMClearCurrentDebugLocation(g->builder);
+ ZigType *usize_ty = g->builtin_types.entry_usize;
+ ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
+ PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false);
+ ZigType *str_type = get_slice_type(g, u8_ptr_type);
+
+ // Allocate a buffer to hold the fully-formatted error message
+ const size_t err_buf_len = strlen(unwrap_err_msg_text) + g->largest_err_name_len;
+ LLVMValueRef max_msg_len = LLVMConstInt(usize_ty->llvm_type, err_buf_len, 0);
+ LLVMValueRef msg_buffer = LLVMBuildArrayAlloca(g->builder, LLVMInt8Type(), max_msg_len, "msg_buffer");
+
+ // Allocate a []u8 slice for the message
+ LLVMValueRef msg_slice = build_alloca(g, str_type, "msg_slice", 0);
+
LLVMValueRef err_ret_trace_arg;
LLVMValueRef err_val;
if (g->have_err_ret_tracing) {
@@ -1619,8 +1585,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
err_val = LLVMGetParam(fn_val, 0);
}
+ // Fetch the error name from the global table
LLVMValueRef err_table_indices[] = {
- LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
+ LLVMConstNull(usize_ty->llvm_type),
err_val,
};
LLVMValueRef err_name_val = LLVMBuildInBoundsGEP(g->builder, g->err_name_table, err_table_indices, 2, "");
@@ -1631,15 +1598,38 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, "");
LLVMValueRef err_name_len = gen_load_untyped(g, len_field_ptr, 0, false, "");
- ZigLLVMBuildMemCpy(g->builder, offset_buf_ptr, u8_align_bytes, err_name_ptr, u8_align_bytes, err_name_len, false);
+ LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false);
+ // Points to the beginning of msg_buffer
+ LLVMValueRef msg_buffer_ptr_indices[] = {
+ LLVMConstNull(usize_ty->llvm_type),
+ };
+ LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_indices, 1, "");
+ // Points to the beginning of the constant prefix message
+ LLVMValueRef msg_prefix_ptr_indices[] = {
+ LLVMConstNull(usize_ty->llvm_type),
+ };
+ LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP(msg_prefix, msg_prefix_ptr_indices, 1);
- LLVMValueRef const_prefix_len = LLVMConstInt(LLVMTypeOf(err_name_len), strlen(unwrap_err_msg_text), false);
- LLVMValueRef full_buf_len = LLVMBuildNUWAdd(g->builder, const_prefix_len, err_name_len, "");
+ // Build the message using the prefix...
+ ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr, 1, msg_prefix_ptr, 1, msg_prefix_len, false);
+ // ..and append the error name
+ LLVMValueRef msg_buffer_ptr_after_indices[] = {
+ msg_prefix_len,
+ };
+ LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_after_indices, 1, "");
+ ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr_after, 1, err_name_ptr, 1, err_name_len, false);
- LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, "");
- gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type);
+ // Set the slice pointer
+ LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_ptr_index, "");
+ gen_store_untyped(g, msg_buffer_ptr, msg_slice_ptr_field_ptr, 0, false);
- gen_panic(g, global_slice, err_ret_trace_arg);
+ // Set the slice length
+ LLVMValueRef slice_len = LLVMBuildNUWAdd(g->builder, msg_prefix_len, err_name_len, "");
+ LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_len_index, "");
+ gen_store_untyped(g, slice_len, msg_slice_len_field_ptr, 0, false);
+
+ // Call panic()
+ gen_panic(g, msg_slice, err_ret_trace_arg);
LLVMPositionBuilderAtEnd(g->builder, prev_block);
LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
@@ -2013,7 +2003,7 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
render_const_val_global(g, &instruction->value, "");
ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true);
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), "");
- } else if (instruction->value.type->id == ZigTypeIdPointer) {
+ } else if (get_codegen_ptr_type(instruction->value.type) != nullptr) {
instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value,
get_llvm_type(g, instruction->value.type), "");
} else {
@@ -5617,6 +5607,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdBitCast:
case IrInstructionIdGlobalAsm:
case IrInstructionIdHasDecl:
+ case IrInstructionIdUndeclaredIdent:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -7252,7 +7243,7 @@ static void define_builtin_types(CodeGen *g) {
buf_init_from_str(&entry->name, "void");
entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
0,
- ZigLLVMEncoding_DW_ATE_unsigned());
+ ZigLLVMEncoding_DW_ATE_signed());
g->builtin_types.entry_void = entry;
g->primitive_type_table.put(&entry->name, entry);
}
@@ -7427,6 +7418,21 @@ static const char *build_mode_to_str(BuildMode build_mode) {
zig_unreachable();
}
+static const char *subsystem_to_str(TargetSubsystem subsystem) {
+ switch (subsystem) {
+ case TargetSubsystemConsole: return "Console";
+ case TargetSubsystemWindows: return "Windows";
+ case TargetSubsystemPosix: return "Posix";
+ case TargetSubsystemNative: return "Native";
+ case TargetSubsystemEfiApplication: return "EfiApplication";
+ case TargetSubsystemEfiBootServiceDriver: return "EfiBootServiceDriver";
+ case TargetSubsystemEfiRom: return "EfiRom";
+ case TargetSubsystemEfiRuntimeDriver: return "EfiRuntimeDriver";
+ case TargetSubsystemAuto: zig_unreachable();
+ }
+ zig_unreachable();
+}
+
static bool detect_dynamic_link(CodeGen *g) {
if (g->is_dynamic)
return true;
@@ -7458,6 +7464,37 @@ static bool detect_pic(CodeGen *g) {
zig_unreachable();
}
+static bool detect_stack_probing(CodeGen *g) {
+ if (!target_supports_stack_probing(g->zig_target))
+ return false;
+ switch (g->want_stack_check) {
+ case WantStackCheckDisabled:
+ return false;
+ case WantStackCheckEnabled:
+ return true;
+ case WantStackCheckAuto:
+ return g->build_mode == BuildModeSafeRelease || g->build_mode == BuildModeDebug;
+ }
+ zig_unreachable();
+}
+
+// Returns TargetSubsystemAuto to mean "no subsystem"
+TargetSubsystem detect_subsystem(CodeGen *g) {
+ if (g->subsystem != TargetSubsystemAuto)
+ return g->subsystem;
+ if (g->zig_target->os == OsWindows) {
+ if (g->have_dllmain_crt_startup || (g->out_type == OutTypeLib && g->is_dynamic))
+ return TargetSubsystemAuto;
+ if (g->have_c_main || g->have_pub_main || g->is_test_build)
+ return TargetSubsystemConsole;
+ if (g->have_winmain || g->have_winmain_crt_startup)
+ return TargetSubsystemWindows;
+ } else if (g->zig_target->os == OsUefi) {
+ return TargetSubsystemEfiApplication;
+ }
+ return TargetSubsystemAuto;
+}
+
static bool detect_single_threaded(CodeGen *g) {
if (g->want_single_threaded)
return true;
@@ -7476,6 +7513,7 @@ static bool detect_err_ret_tracing(CodeGen *g) {
Buf *codegen_generate_builtin_source(CodeGen *g) {
g->have_dynamic_link = detect_dynamic_link(g);
g->have_pic = detect_pic(g);
+ g->have_stack_probing = detect_stack_probing(g);
g->is_single_threaded = detect_single_threaded(g);
g->have_err_ret_tracing = detect_err_ret_tracing(g);
@@ -7724,7 +7762,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" pub const Struct = struct {\n"
" layout: ContainerLayout,\n"
" fields: []StructField,\n"
- " defs: []Definition,\n"
+ " decls: []Declaration,\n"
" };\n"
"\n"
" pub const Optional = struct {\n"
@@ -7752,7 +7790,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" layout: ContainerLayout,\n"
" tag_type: type,\n"
" fields: []EnumField,\n"
- " defs: []Definition,\n"
+ " decls: []Declaration,\n"
" };\n"
"\n"
" pub const UnionField = struct {\n"
@@ -7765,7 +7803,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" layout: ContainerLayout,\n"
" tag_type: ?type,\n"
" fields: []UnionField,\n"
- " defs: []Definition,\n"
+ " decls: []Declaration,\n"
" };\n"
"\n"
" pub const CallingConvention = enum {\n"
@@ -7801,7 +7839,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" child: type,\n"
" };\n"
"\n"
- " pub const Definition = struct {\n"
+ " pub const Declaration = struct {\n"
" name: []const u8,\n"
" is_pub: bool,\n"
" data: Data,\n"
@@ -7809,9 +7847,9 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" pub const Data = union(enum) {\n"
" Type: type,\n"
" Var: type,\n"
- " Fn: FnDef,\n"
+ " Fn: FnDecl,\n"
"\n"
- " pub const FnDef = struct {\n"
+ " pub const FnDecl = struct {\n"
" fn_type: type,\n"
" inline_type: Inline,\n"
" calling_convention: CallingConvention,\n"
@@ -7864,6 +7902,28 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
//assert(EndianBig == 0);
//assert(EndianLittle == 1);
}
+ {
+ buf_appendf(contents,
+ "pub const SubSystem = enum {\n"
+ " Console,\n"
+ " Windows,\n"
+ " Posix,\n"
+ " Native,\n"
+ " EfiApplication,\n"
+ " EfiBootServiceDriver,\n"
+ " EfiRom,\n"
+ " EfiRuntimeDriver,\n"
+ "};\n\n");
+
+ assert(TargetSubsystemConsole == 0);
+ assert(TargetSubsystemWindows == 1);
+ assert(TargetSubsystemPosix == 2);
+ assert(TargetSubsystemNative == 3);
+ assert(TargetSubsystemEfiApplication == 4);
+ assert(TargetSubsystemEfiBootServiceDriver == 5);
+ assert(TargetSubsystemEfiRom == 6);
+ assert(TargetSubsystemEfiRuntimeDriver == 7);
+ }
{
const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
@@ -7880,6 +7940,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
+ {
+ TargetSubsystem detected_subsystem = detect_subsystem(g);
+ if (detected_subsystem != TargetSubsystemAuto) {
+ buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
+ }
+ }
+
if (g->is_test_build) {
buf_appendf(contents,
"const TestFn = struct {\n"
@@ -7923,6 +7990,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_bool(&cache_hash, g->have_err_ret_tracing);
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
cache_bool(&cache_hash, g->valgrind_support);
+ cache_int(&cache_hash, detect_subsystem(g));
Buf digest = BUF_INIT;
buf_resize(&digest, 0);
@@ -7982,6 +8050,7 @@ static void init(CodeGen *g) {
g->have_dynamic_link = detect_dynamic_link(g);
g->have_pic = detect_pic(g);
+ g->have_stack_probing = detect_stack_probing(g);
g->is_single_threaded = detect_single_threaded(g);
g->have_err_ret_tracing = detect_err_ret_tracing(g);
@@ -7989,10 +8058,6 @@ static void init(CodeGen *g) {
g->is_single_threaded = true;
}
- if (g->is_test_build) {
- g->subsystem = TargetSubsystemConsole;
- }
-
assert(g->root_out_name);
g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
@@ -9077,8 +9142,11 @@ static void gen_h_file(CodeGen *g) {
if (!out_h)
zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno));
- Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
- buf_upcase(export_macro);
+ Buf *export_macro = nullptr;
+ if (g->is_dynamic) {
+ export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
+ buf_upcase(export_macro);
+ }
Buf *extern_c_macro = preprocessor_mangle(buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name)));
buf_upcase(extern_c_macro);
@@ -9103,10 +9171,11 @@ static void gen_h_file(CodeGen *g) {
FnExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
}
+
buf_appendf(&h_buf, "%s %s %s(",
- buf_ptr(export_macro),
- buf_ptr(&return_type_c),
- buf_ptr(symbol_name));
+ buf_ptr(g->is_dynamic ? export_macro : extern_c_macro),
+ buf_ptr(&return_type_c),
+ buf_ptr(symbol_name));
Buf param_type_c = BUF_INIT;
if (fn_type_id->param_count > 0) {
@@ -9156,13 +9225,16 @@ static void gen_h_file(CodeGen *g) {
fprintf(out_h, "#define %s\n", buf_ptr(extern_c_macro));
fprintf(out_h, "#endif\n");
fprintf(out_h, "\n");
- fprintf(out_h, "#if defined(_WIN32)\n");
- fprintf(out_h, "#define %s %s __declspec(dllimport)\n", buf_ptr(export_macro), buf_ptr(extern_c_macro));
- fprintf(out_h, "#else\n");
- fprintf(out_h, "#define %s %s __attribute__((visibility (\"default\")))\n",
+
+ if (g->is_dynamic) {
+ fprintf(out_h, "#if defined(_WIN32)\n");
+ fprintf(out_h, "#define %s %s __declspec(dllimport)\n", buf_ptr(export_macro), buf_ptr(extern_c_macro));
+ fprintf(out_h, "#else\n");
+ fprintf(out_h, "#define %s %s __attribute__((visibility (\"default\")))\n",
buf_ptr(export_macro), buf_ptr(extern_c_macro));
- fprintf(out_h, "#endif\n");
- fprintf(out_h, "\n");
+ fprintf(out_h, "#endif\n");
+ fprintf(out_h, "\n");
+ }
for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) {
ZigType *type_entry = gen_h->types_to_declare.at(type_i);
@@ -9339,7 +9411,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target->vendor);
cache_int(ch, g->zig_target->os);
cache_int(ch, g->zig_target->abi);
- cache_int(ch, g->subsystem);
+ cache_int(ch, detect_subsystem(g));
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
if (g->is_test_build) {
@@ -9351,10 +9423,10 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->each_lib_rpath);
cache_bool(ch, g->disable_gen_h);
cache_bool(ch, g->bundle_compiler_rt);
- cache_bool(ch, g->disable_stack_probing);
cache_bool(ch, want_valgrind_support(g));
cache_bool(ch, g->have_pic);
cache_bool(ch, g->have_dynamic_link);
+ cache_bool(ch, g->have_stack_probing);
cache_bool(ch, g->is_dummy_so);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 47c0097e4b..9a340d7205 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -56,4 +56,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
Buf *codegen_generate_builtin_source(CodeGen *g);
+TargetSubsystem detect_subsystem(CodeGen *g);
+
#endif
diff --git a/src/ir.cpp b/src/ir.cpp
index 42b1acc4df..fb9e7b51c7 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1015,6 +1015,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionHasDecl *) {
return IrInstructionIdHasDecl;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionUndeclaredIdent *) {
+ return IrInstructionIdUndeclaredIdent;
+}
+
template
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate(1);
@@ -3031,6 +3035,15 @@ static IrInstruction *ir_build_has_decl(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
+static IrInstruction *ir_build_undeclared_identifier(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ Buf *name)
+{
+ IrInstructionUndeclaredIdent *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->name = name;
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
IrInstructionCheckRuntimeScope *instruction = ir_build_instruction(irb, scope, source_node);
instruction->scope_is_comptime = scope_is_comptime;
@@ -3896,13 +3909,18 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
Buf *variable_name = node->data.symbol_expr.symbol;
- if (buf_eql_str(variable_name, "_") && lval == LValPtr) {
- IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, node);
- const_instruction->base.value.type = get_pointer_to_type(irb->codegen,
- irb->codegen->builtin_types.entry_void, false);
- const_instruction->base.value.special = ConstValSpecialStatic;
- const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialDiscard;
- return &const_instruction->base;
+ if (buf_eql_str(variable_name, "_")) {
+ if (lval == LValPtr) {
+ IrInstructionConst *const_instruction = ir_build_instruction(irb, scope, node);
+ const_instruction->base.value.type = get_pointer_to_type(irb->codegen,
+ irb->codegen->builtin_types.entry_void, false);
+ const_instruction->base.value.special = ConstValSpecialStatic;
+ const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialDiscard;
+ return &const_instruction->base;
+ } else {
+ add_node_error(irb->codegen, node, buf_sprintf("`_` may only be used to assign things to"));
+ return irb->codegen->invalid_instruction;
+ }
}
ZigType *primitive_type;
@@ -3943,11 +3961,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
return irb->codegen->invalid_instruction;
}
- // put a variable of same name with invalid type in global scope
- // so that future references to this same name will find a variable with an invalid type
- populate_invalid_variable_in_scope(irb->codegen, scope, node, variable_name);
- add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
- return irb->codegen->invalid_instruction;
+ return ir_build_undeclared_identifier(irb, scope, node, variable_name);
}
static IrInstruction *ir_gen_array_access(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
@@ -10252,12 +10266,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
return result;
}
-static bool is_container(ZigType *type) {
- return type->id == ZigTypeIdStruct ||
- type->id == ZigTypeIdEnum ||
- type->id == ZigTypeIdUnion;
-}
-
static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
assert(old_bb);
@@ -16165,7 +16173,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(container_type)) {
return ira->codegen->invalid_instruction;
- } else if (is_container_ref(container_type)) {
+ } else if (is_slice(container_type) || is_container_ref(container_type)) {
assert(container_ptr->value.type->id == ZigTypeIdPointer);
if (container_type->id == ZigTypeIdPointer) {
ZigType *bare_type = container_ref_type(container_type);
@@ -16235,7 +16243,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(child_type)) {
return ira->codegen->invalid_instruction;
- } else if (is_container(child_type) && !is_slice(child_type)) {
+ } else if (is_container(child_type)) {
if (child_type->id == ZigTypeIdEnum) {
if ((err = ensure_complete_type(ira->codegen, child_type)))
return ira->codegen->invalid_instruction;
@@ -17879,10 +17887,37 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
bool any_missing = false;
for (size_t i = 0; i < actual_field_count; i += 1) {
- if (!field_assign_nodes[i]) {
- ir_add_error_node(ira, instruction->source_node,
- buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
- any_missing = true;
+ if (field_assign_nodes[i]) continue;
+
+ // look for a default field value
+ TypeStructField *field = &container_type->data.structure.fields[i];
+ if (field->init_val == nullptr) {
+ // it's not memoized. time to go analyze it
+ assert(field->decl_node->type == NodeTypeStructField);
+ AstNode *init_node = field->decl_node->data.struct_field.value;
+ if (init_node == nullptr) {
+ ir_add_error_node(ira, instruction->source_node,
+ buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
+ any_missing = true;
+ continue;
+ }
+ // scope is not the scope of the struct init, it's the scope of the struct type decl
+ Scope *analyze_scope = &get_container_scope(container_type)->base;
+ // memoize it
+ field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,
+ field->type_entry, nullptr);
+ }
+ if (type_is_invalid(field->init_val->type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *runtime_inst = ir_const(ira, instruction, field->init_val->type);
+ copy_const_val(&runtime_inst->value, field->init_val, true);
+
+ new_fields[i].value = runtime_inst;
+ new_fields[i].type_struct_field = field;
+
+ if (const_val.special == ConstValSpecialStatic) {
+ copy_const_val(&const_val.data.x_struct.fields[i], field->init_val, true);
}
}
if (any_missing)
@@ -18372,37 +18407,37 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
return var->const_value->data.x_type;
}
-static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,
+static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,
ScopeDecls *decls_scope)
{
Error err;
- ZigType *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr);
- if ((err = type_resolve(ira->codegen, type_info_definition_type, ResolveStatusSizeKnown)))
+ ZigType *type_info_declaration_type = ir_type_info_get_type(ira, "Declaration", nullptr);
+ if ((err = type_resolve(ira->codegen, type_info_declaration_type, ResolveStatusSizeKnown)))
return err;
- ensure_field_index(type_info_definition_type, "name", 0);
- ensure_field_index(type_info_definition_type, "is_pub", 1);
- ensure_field_index(type_info_definition_type, "data", 2);
+ ensure_field_index(type_info_declaration_type, "name", 0);
+ ensure_field_index(type_info_declaration_type, "is_pub", 1);
+ ensure_field_index(type_info_declaration_type, "data", 2);
- ZigType *type_info_definition_data_type = ir_type_info_get_type(ira, "Data", type_info_definition_type);
- if ((err = ensure_complete_type(ira->codegen, type_info_definition_data_type)))
+ ZigType *type_info_declaration_data_type = ir_type_info_get_type(ira, "Data", type_info_declaration_type);
+ if ((err = ensure_complete_type(ira->codegen, type_info_declaration_data_type)))
return err;
- ZigType *type_info_fn_def_type = ir_type_info_get_type(ira, "FnDef", type_info_definition_data_type);
- if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_type)))
+ ZigType *type_info_fn_decl_type = ir_type_info_get_type(ira, "FnDecl", type_info_declaration_data_type);
+ if ((err = ensure_complete_type(ira->codegen, type_info_fn_decl_type)))
return err;
- ZigType *type_info_fn_def_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_def_type);
- if ((err = ensure_complete_type(ira->codegen, type_info_fn_def_inline_type)))
+ ZigType *type_info_fn_decl_inline_type = ir_type_info_get_type(ira, "Inline", type_info_fn_decl_type);
+ if ((err = ensure_complete_type(ira->codegen, type_info_fn_decl_inline_type)))
return err;
- // Loop through our definitions once to figure out how many definitions we will generate info for.
+ // Loop through our declarations once to figure out how many declarations we will generate info for.
auto decl_it = decls_scope->decl_table.entry_iterator();
decltype(decls_scope->decl_table)::Entry *curr_entry = nullptr;
- int definition_count = 0;
+ int declaration_count = 0;
while ((curr_entry = decl_it.next()) != nullptr) {
- // If the definition is unresolved, force it to be resolved again.
+ // If the declaration is unresolved, force it to be resolved again.
if (curr_entry->value->resolution == TldResolutionUnresolved) {
resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node);
if (curr_entry->value->resolution != TldResolutionOk) {
@@ -18418,21 +18453,21 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
continue;
}
- definition_count += 1;
+ declaration_count += 1;
}
}
- ConstExprValue *definition_array = create_const_vals(1);
- definition_array->special = ConstValSpecialStatic;
- definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
- definition_array->data.x_array.special = ConstArraySpecialNone;
- definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
- init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
+ ConstExprValue *declaration_array = create_const_vals(1);
+ declaration_array->special = ConstValSpecialStatic;
+ declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count);
+ declaration_array->data.x_array.special = ConstArraySpecialNone;
+ declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);
+ init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);
- // Loop through the definitions and generate info.
+ // Loop through the declarations and generate info.
decl_it = decls_scope->decl_table.entry_iterator();
curr_entry = nullptr;
- int definition_index = 0;
+ int declaration_index = 0;
while ((curr_entry = decl_it.next()) != nullptr) {
// Skip comptime blocks and test functions.
if (curr_entry->value->id == TldIdCompTime) {
@@ -18443,10 +18478,10 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
continue;
}
- ConstExprValue *definition_val = &definition_array->data.x_array.data.s_none.elements[definition_index];
+ ConstExprValue *declaration_val = &declaration_array->data.x_array.data.s_none.elements[declaration_index];
- definition_val->special = ConstValSpecialStatic;
- definition_val->type = type_info_definition_type;
+ declaration_val->special = ConstValSpecialStatic;
+ declaration_val->type = type_info_declaration_type;
ConstExprValue *inner_fields = create_const_vals(3);
ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key);
@@ -18455,9 +18490,9 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
inner_fields[1].type = ira->codegen->builtin_types.entry_bool;
inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
inner_fields[2].special = ConstValSpecialStatic;
- inner_fields[2].type = type_info_definition_data_type;
+ inner_fields[2].type = type_info_declaration_data_type;
inner_fields[2].parent.id = ConstParentIdStruct;
- inner_fields[2].parent.data.p_struct.struct_val = definition_val;
+ inner_fields[2].parent.data.p_struct.struct_val = declaration_val;
inner_fields[2].parent.data.p_struct.field_index = 1;
switch (curr_entry->value->id) {
@@ -18468,7 +18503,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
return ErrorSemanticAnalyzeFail;
if (var->const_value->type->id == ZigTypeIdMetaType) {
- // We have a variable of type 'type', so it's actually a type definition.
+ // We have a variable of type 'type', so it's actually a type declaration.
// 0: Data.Type: type
bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
inner_fields[2].data.x_union.payload = var->const_value;
@@ -18488,7 +18523,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
}
case TldIdFn:
{
- // 2: Data.Fn: Data.FnDef
+ // 2: Data.Fn: Data.FnDecl
bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2);
ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry;
@@ -18499,70 +18534,70 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
return ErrorSemanticAnalyzeFail;
}
- AstNodeFnProto *fn_node = (AstNodeFnProto *)(fn_entry->proto_node);
+ AstNodeFnProto *fn_node = &fn_entry->proto_node->data.fn_proto;
- ConstExprValue *fn_def_val = create_const_vals(1);
- fn_def_val->special = ConstValSpecialStatic;
- fn_def_val->type = type_info_fn_def_type;
- fn_def_val->parent.id = ConstParentIdUnion;
- fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
+ ConstExprValue *fn_decl_val = create_const_vals(1);
+ fn_decl_val->special = ConstValSpecialStatic;
+ fn_decl_val->type = type_info_fn_decl_type;
+ fn_decl_val->parent.id = ConstParentIdUnion;
+ fn_decl_val->parent.data.p_union.union_val = &inner_fields[2];
- ConstExprValue *fn_def_fields = create_const_vals(9);
- fn_def_val->data.x_struct.fields = fn_def_fields;
+ ConstExprValue *fn_decl_fields = create_const_vals(9);
+ fn_decl_val->data.x_struct.fields = fn_decl_fields;
// fn_type: type
- ensure_field_index(fn_def_val->type, "fn_type", 0);
- fn_def_fields[0].special = ConstValSpecialStatic;
- fn_def_fields[0].type = ira->codegen->builtin_types.entry_type;
- fn_def_fields[0].data.x_type = fn_entry->type_entry;
- // inline_type: Data.FnDef.Inline
- ensure_field_index(fn_def_val->type, "inline_type", 1);
- fn_def_fields[1].special = ConstValSpecialStatic;
- fn_def_fields[1].type = type_info_fn_def_inline_type;
- bigint_init_unsigned(&fn_def_fields[1].data.x_enum_tag, fn_entry->fn_inline);
+ ensure_field_index(fn_decl_val->type, "fn_type", 0);
+ fn_decl_fields[0].special = ConstValSpecialStatic;
+ fn_decl_fields[0].type = ira->codegen->builtin_types.entry_type;
+ fn_decl_fields[0].data.x_type = fn_entry->type_entry;
+ // inline_type: Data.FnDecl.Inline
+ ensure_field_index(fn_decl_val->type, "inline_type", 1);
+ fn_decl_fields[1].special = ConstValSpecialStatic;
+ fn_decl_fields[1].type = type_info_fn_decl_inline_type;
+ bigint_init_unsigned(&fn_decl_fields[1].data.x_enum_tag, fn_entry->fn_inline);
// calling_convention: TypeInfo.CallingConvention
- ensure_field_index(fn_def_val->type, "calling_convention", 2);
- fn_def_fields[2].special = ConstValSpecialStatic;
- fn_def_fields[2].type = ir_type_info_get_type(ira, "CallingConvention", nullptr);
- bigint_init_unsigned(&fn_def_fields[2].data.x_enum_tag, fn_node->cc);
+ ensure_field_index(fn_decl_val->type, "calling_convention", 2);
+ fn_decl_fields[2].special = ConstValSpecialStatic;
+ fn_decl_fields[2].type = ir_type_info_get_type(ira, "CallingConvention", nullptr);
+ bigint_init_unsigned(&fn_decl_fields[2].data.x_enum_tag, fn_node->cc);
// is_var_args: bool
- ensure_field_index(fn_def_val->type, "is_var_args", 3);
+ ensure_field_index(fn_decl_val->type, "is_var_args", 3);
bool is_varargs = fn_node->is_var_args;
- fn_def_fields[3].special = ConstValSpecialStatic;
- fn_def_fields[3].type = ira->codegen->builtin_types.entry_bool;
- fn_def_fields[3].data.x_bool = is_varargs;
+ fn_decl_fields[3].special = ConstValSpecialStatic;
+ fn_decl_fields[3].type = ira->codegen->builtin_types.entry_bool;
+ fn_decl_fields[3].data.x_bool = is_varargs;
// is_extern: bool
- ensure_field_index(fn_def_val->type, "is_extern", 4);
- fn_def_fields[4].special = ConstValSpecialStatic;
- fn_def_fields[4].type = ira->codegen->builtin_types.entry_bool;
- fn_def_fields[4].data.x_bool = fn_node->is_extern;
+ ensure_field_index(fn_decl_val->type, "is_extern", 4);
+ fn_decl_fields[4].special = ConstValSpecialStatic;
+ fn_decl_fields[4].type = ira->codegen->builtin_types.entry_bool;
+ fn_decl_fields[4].data.x_bool = fn_node->is_extern;
// is_export: bool
- ensure_field_index(fn_def_val->type, "is_export", 5);
- fn_def_fields[5].special = ConstValSpecialStatic;
- fn_def_fields[5].type = ira->codegen->builtin_types.entry_bool;
- fn_def_fields[5].data.x_bool = fn_node->is_export;
+ ensure_field_index(fn_decl_val->type, "is_export", 5);
+ fn_decl_fields[5].special = ConstValSpecialStatic;
+ fn_decl_fields[5].type = ira->codegen->builtin_types.entry_bool;
+ fn_decl_fields[5].data.x_bool = fn_node->is_export;
// lib_name: ?[]const u8
- ensure_field_index(fn_def_val->type, "lib_name", 6);
- fn_def_fields[6].special = ConstValSpecialStatic;
+ ensure_field_index(fn_decl_val->type, "lib_name", 6);
+ fn_decl_fields[6].special = ConstValSpecialStatic;
ZigType *u8_ptr = get_pointer_to_type_extra(
ira->codegen, ira->codegen->builtin_types.entry_u8,
true, false, PtrLenUnknown,
0, 0, 0, false);
- fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
+ fn_decl_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
- fn_def_fields[6].data.x_optional = create_const_vals(1);
+ fn_decl_fields[6].data.x_optional = create_const_vals(1);
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
- init_const_slice(ira->codegen, fn_def_fields[6].data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true);
+ init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true);
} else {
- fn_def_fields[6].data.x_optional = nullptr;
+ fn_decl_fields[6].data.x_optional = nullptr;
}
// return_type: type
- ensure_field_index(fn_def_val->type, "return_type", 7);
- fn_def_fields[7].special = ConstValSpecialStatic;
- fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
- fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
+ ensure_field_index(fn_decl_val->type, "return_type", 7);
+ fn_decl_fields[7].special = ConstValSpecialStatic;
+ fn_decl_fields[7].type = ira->codegen->builtin_types.entry_type;
+ fn_decl_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
// arg_names: [][] const u8
- ensure_field_index(fn_def_val->type, "arg_names", 8);
+ ensure_field_index(fn_decl_val->type, "arg_names", 8);
size_t fn_arg_count = fn_entry->variable_list.length;
ConstExprValue *fn_arg_name_array = create_const_vals(1);
fn_arg_name_array->special = ConstValSpecialStatic;
@@ -18571,7 +18606,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
- init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
+ init_const_slice(ira->codegen, &fn_decl_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
@@ -18583,7 +18618,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
}
- inner_fields[2].data.x_union.payload = fn_def_val;
+ inner_fields[2].data.x_union.payload = fn_decl_val;
break;
}
case TldIdContainer:
@@ -18607,11 +18642,11 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr,
zig_unreachable();
}
- definition_val->data.x_struct.fields = inner_fields;
- definition_index++;
+ declaration_val->data.x_struct.fields = inner_fields;
+ declaration_index++;
}
- assert(definition_index == definition_count);
+ assert(declaration_index == declaration_count);
return ErrorNone;
}
@@ -18919,9 +18954,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
enum_field_val->parent.data.p_array.array_val = enum_field_array;
enum_field_val->parent.data.p_array.elem_index = enum_field_index;
}
- // defs: []TypeInfo.Definition
- ensure_field_index(result->type, "defs", 3);
- if ((err = ir_make_type_info_defs(ira, source_instr, &fields[3],
+ // decls: []TypeInfo.Declaration
+ ensure_field_index(result->type, "decls", 3);
+ if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3],
type_entry->data.enumeration.decls_scope)))
{
return err;
@@ -19086,9 +19121,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
union_field_val->parent.data.p_array.array_val = union_field_array;
union_field_val->parent.data.p_array.elem_index = union_field_index;
}
- // defs: []TypeInfo.Definition
- ensure_field_index(result->type, "defs", 3);
- if ((err = ir_make_type_info_defs(ira, source_instr, &fields[3],
+ // decls: []TypeInfo.Declaration
+ ensure_field_index(result->type, "decls", 3);
+ if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3],
type_entry->data.unionation.decls_scope)))
{
return err;
@@ -19167,9 +19202,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
struct_field_val->parent.data.p_array.array_val = struct_field_array;
struct_field_val->parent.data.p_array.elem_index = struct_field_index;
}
- // defs: []TypeInfo.Definition
- ensure_field_index(result->type, "defs", 2);
- if ((err = ir_make_type_info_defs(ira, source_instr, &fields[2],
+ // decls: []TypeInfo.Declaration
+ ensure_field_index(result->type, "decls", 2);
+ if ((err = ir_make_type_info_decls(ira, source_instr, &fields[2],
type_entry->data.structure.decls_scope)))
{
return err;
@@ -23237,6 +23272,16 @@ static IrInstruction *ir_analyze_instruction_has_decl(IrAnalyze *ira, IrInstruct
return ir_const_bool(ira, &instruction->base, true);
}
+static IrInstruction *ir_analyze_instruction_undeclared_ident(IrAnalyze *ira, IrInstructionUndeclaredIdent *instruction) {
+ // put a variable of same name with invalid type in global scope
+ // so that future references to this same name will find a variable with an invalid type
+ populate_invalid_variable_in_scope(ira->codegen, instruction->base.scope, instruction->base.source_node,
+ instruction->name);
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("use of undeclared identifier '%s'", buf_ptr(instruction->name)));
+ return ira->codegen->invalid_instruction;
+}
+
static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -23533,6 +23578,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
return ir_analyze_instruction_check_runtime_scope(ira, (IrInstructionCheckRuntimeScope *)instruction);
case IrInstructionIdHasDecl:
return ir_analyze_instruction_has_decl(ira, (IrInstructionHasDecl *)instruction);
+ case IrInstructionIdUndeclaredIdent:
+ return ir_analyze_instruction_undeclared_ident(ira, (IrInstructionUndeclaredIdent *)instruction);
}
zig_unreachable();
}
@@ -23667,6 +23714,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdAssertNonNull:
case IrInstructionIdResizeSlice:
case IrInstructionIdGlobalAsm:
+ case IrInstructionIdUndeclaredIdent:
return true;
case IrInstructionIdPhi:
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index dd671231c0..bf9ced89c5 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -1461,6 +1461,10 @@ static void ir_print_has_decl(IrPrint *irp, IrInstructionHasDecl *instruction) {
fprintf(irp->f, ")");
}
+static void ir_print_undeclared_ident(IrPrint *irp, IrInstructionUndeclaredIdent *instruction) {
+ fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name));
+}
+
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
ir_print_prefix(irp, instruction);
switch (instruction->id) {
@@ -1931,6 +1935,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdHasDecl:
ir_print_has_decl(irp, (IrInstructionHasDecl *)instruction);
break;
+ case IrInstructionIdUndeclaredIdent:
+ ir_print_undeclared_ident(irp, (IrInstructionUndeclaredIdent *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/link.cpp b/src/link.cpp
index b47da87c68..3a437e4eda 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -25,7 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
child_gen->disable_gen_h = true;
- child_gen->disable_stack_probing = true;
+ child_gen->want_stack_check = WantStackCheckDisabled;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
child_gen->verbose_ast = parent_gen->verbose_ast;
child_gen->verbose_link = parent_gen->verbose_link;
@@ -528,9 +528,6 @@ static const char *build_musl(CodeGen *parent) {
Buf noextbasename = BUF_INIT;
Buf dirbasename = BUF_INIT;
Buf before_arch_dir = BUF_INIT;
- Buf override_c = BUF_INIT;
- Buf override_s = BUF_INIT;
- Buf override_S = BUF_INIT;
auto source_it = source_table.entry_iterator();
for (;;) {
@@ -543,31 +540,37 @@ static const char *build_musl(CodeGen *parent) {
os_path_split(src_file, &dirname, &basename);
os_path_extname(&basename, &noextbasename, nullptr);
os_path_split(&dirname, &before_arch_dir, &dirbasename);
+
+ bool is_arch_specific = false;
+ // Architecture-specific implementations are under a / folder.
if (is_musl_arch_name(buf_ptr(&dirbasename))) {
- // We find these by explicitly looking for overrides.
- continue;
+ // Not the architecture we're compiling for.
+ if (strcmp(buf_ptr(&dirbasename), target_musl_arch_name) != 0)
+ continue;
+ is_arch_specific = true;
}
- // Look for an arch specific override.
- buf_resize(&override_c, 0);
- buf_resize(&override_s, 0);
- buf_resize(&override_S, 0);
- buf_appendf(&override_c, "%s" OS_SEP "%s" OS_SEP "%s.c",
- buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
- buf_appendf(&override_s, "%s" OS_SEP "%s" OS_SEP "%s.s",
- buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
- buf_appendf(&override_S, "%s" OS_SEP "%s" OS_SEP "%s.S",
- buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
+ if (!is_arch_specific) {
+ Buf override_path = BUF_INIT;
- if (source_table.maybe_get(&override_c) != nullptr) {
- src_file = &override_c;
- src_kind = (src_kind == MuslSrcAsm) ? MuslSrcNormal : src_kind;
- } else if (source_table.maybe_get(&override_s) != nullptr) {
- src_file = &override_s;
- src_kind = MuslSrcAsm;
- } else if (source_table.maybe_get(&override_S) != nullptr) {
- src_file = &override_S;
- src_kind = MuslSrcAsm;
+ // Look for an arch specific override.
+ buf_resize(&override_path, 0);
+ buf_appendf(&override_path, "%s" OS_SEP "%s" OS_SEP "%s.s",
+ buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
+ if (source_table.maybe_get(&override_path) != nullptr)
+ continue;
+
+ buf_resize(&override_path, 0);
+ buf_appendf(&override_path, "%s" OS_SEP "%s" OS_SEP "%s.S",
+ buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
+ if (source_table.maybe_get(&override_path) != nullptr)
+ continue;
+
+ buf_resize(&override_path, 0);
+ buf_appendf(&override_path, "%s" OS_SEP "%s" OS_SEP "%s.c",
+ buf_ptr(&dirname), target_musl_arch_name, buf_ptr(&noextbasename));
+ if (source_table.maybe_get(&override_path) != nullptr)
+ continue;
}
Buf *full_path = buf_sprintf("%s" OS_SEP "libc" OS_SEP "%s",
@@ -1225,7 +1228,7 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
- if (g->subsystem == TargetSubsystemWindows) {
+ if (detect_subsystem(g) == TargetSubsystemWindows) {
lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
}
@@ -1307,7 +1310,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
- switch (g->subsystem) {
+ switch (detect_subsystem(g)) {
case TargetSubsystemAuto:
if (g->zig_target->os == OsUefi) {
add_uefi_link_args(lj);
@@ -1471,7 +1474,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
platform->kind = IPhoneOS;
} else if (g->zig_target->os == OsMacOSX) {
platform->kind = MacOS;
- g->mmacosx_version_min = buf_create_from_str("10.10");
+ g->mmacosx_version_min = buf_create_from_str("10.14");
} else {
zig_panic("unable to infer -mmacosx-version-min or -mios-version-min");
}
diff --git a/src/main.cpp b/src/main.cpp
index 934c998435..29c17212cf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -55,7 +55,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --disable-gen-h do not generate a C header file (.h)\n"
" --disable-valgrind omit valgrind client requests in debug builds\n"
" --enable-valgrind include valgrind client requests release builds\n"
- " --disable-stack-probing workaround for macosx\n"
+ " -fstack-check enable stack probing in unsafe builds\n"
+ " -fno-stack-check disable stack probing in safe builds\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" -fPIC enable Position Independent Code\n"
" -fno-PIC disable Position Independent Code\n"
@@ -443,12 +444,12 @@ int main(int argc, char **argv) {
bool want_single_threaded = false;
bool disable_gen_h = false;
bool bundle_compiler_rt = false;
- bool disable_stack_probing = false;
Buf *override_std_dir = nullptr;
Buf *override_lib_dir = nullptr;
Buf *main_pkg_path = nullptr;
ValgrindSupport valgrind_support = ValgrindSupportAuto;
WantPIC want_pic = WantPICAuto;
+ WantStackCheck want_stack_check = WantStackCheckAuto;
ZigList llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@@ -648,6 +649,10 @@ int main(int argc, char **argv) {
want_pic = WantPICEnabled;
} else if (strcmp(arg, "-fno-PIC") == 0) {
want_pic = WantPICDisabled;
+ } else if (strcmp(arg, "-fstack-check") == 0) {
+ want_stack_check = WantStackCheckEnabled;
+ } else if (strcmp(arg, "-fno-stack-check") == 0) {
+ want_stack_check = WantStackCheckDisabled;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
} else if (strcmp(arg, "--single-threaded") == 0) {
@@ -656,8 +661,6 @@ int main(int argc, char **argv) {
disable_gen_h = true;
} else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
bundle_compiler_rt = true;
- } else if (strcmp(arg, "--disable-stack-probing") == 0) {
- disable_stack_probing = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
@@ -951,8 +954,10 @@ int main(int argc, char **argv) {
case CmdBuiltin: {
CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
+ g->subsystem = subsystem;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
+ g->want_stack_check = want_stack_check;
g->want_single_threaded = want_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
@@ -981,6 +986,9 @@ int main(int argc, char **argv) {
{
fprintf(stderr, "Expected source file argument.\n");
return print_error_usage(arg0);
+ } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) {
+ fprintf(stderr, "Cannot run non-executable file.\n");
+ return print_error_usage(arg0);
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
@@ -1048,6 +1056,7 @@ int main(int argc, char **argv) {
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
+ g->want_stack_check = want_stack_check;
g->subsystem = subsystem;
g->enable_time_report = timing_info;
@@ -1074,7 +1083,6 @@ int main(int argc, char **argv) {
g->output_dir = output_dir;
g->disable_gen_h = disable_gen_h;
g->bundle_compiler_rt = bundle_compiler_rt;
- g->disable_stack_probing = disable_stack_probing;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
@@ -1185,6 +1193,12 @@ int main(int argc, char **argv) {
Buf *test_exe_path = buf_alloc();
*test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
+ if (emit_file_type != EmitFileTypeBinary) {
+ fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
+ buf_ptr(test_exe_path));
+ return 0;
+ }
+
for (size_t i = 0; i < test_exec_args.length; i += 1) {
if (test_exec_args.items[i] == nullptr) {
test_exec_args.items[i] = buf_ptr(test_exe_path);
diff --git a/src/parser.cpp b/src/parser.cpp
index 583accfd72..3d7bbf7801 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -668,7 +668,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
return res;
}
- Token *use = eat_token_if(pc, TokenIdKeywordUse);
+ Token *use = eat_token_if(pc, TokenIdKeywordUsingNamespace);
if (use != nullptr) {
AstNode *expr = ast_expect(pc, ast_parse_expr);
expect_token(pc, TokenIdSemicolon);
diff --git a/src/target.cpp b/src/target.cpp
index 630096204b..7862f6d449 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -1356,6 +1356,10 @@ bool target_supports_fpic(const ZigTarget *target) {
return target->os != OsWindows;
}
+bool target_supports_stack_probing(const ZigTarget *target) {
+ return target->os != OsWindows && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64);
+}
+
bool target_requires_pic(const ZigTarget *target, bool linking_libc) {
// This function returns whether non-pic code is completely invalid on the given target.
return target->os == OsWindows || target_os_requires_libc(target->os) ||
diff --git a/src/target.hpp b/src/target.hpp
index fd5c7471c3..7fa99bcda8 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -62,7 +62,6 @@ enum SubArchList {
};
enum TargetSubsystem {
- TargetSubsystemAuto, // Zig should infer the subsystem
TargetSubsystemConsole,
TargetSubsystemWindows,
TargetSubsystemPosix,
@@ -71,6 +70,11 @@ enum TargetSubsystem {
TargetSubsystemEfiBootServiceDriver,
TargetSubsystemEfiRom,
TargetSubsystemEfiRuntimeDriver,
+
+ // This means Zig should infer the subsystem.
+ // It's last so that the indexes of other items can line up
+ // with the enum in builtin.zig.
+ TargetSubsystemAuto
};
struct ZigTarget {
@@ -172,6 +176,7 @@ bool target_is_glibc(const ZigTarget *target);
bool target_is_musl(const ZigTarget *target);
bool target_is_wasm(const ZigTarget *target);
bool target_is_single_threaded(const ZigTarget *target);
+bool target_supports_stack_probing(const ZigTarget *target);
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 958c4f7ef7..7bae45f477 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -153,7 +153,8 @@ static const struct ZigKeyword zig_keywords[] = {
{"undefined", TokenIdKeywordUndefined},
{"union", TokenIdKeywordUnion},
{"unreachable", TokenIdKeywordUnreachable},
- {"use", TokenIdKeywordUse},
+ {"use", TokenIdKeywordUsingNamespace},
+ {"usingnamespace", TokenIdKeywordUsingNamespace},
{"var", TokenIdKeywordVar},
{"volatile", TokenIdKeywordVolatile},
{"while", TokenIdKeywordWhile},
@@ -1546,7 +1547,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordUndefined: return "undefined";
case TokenIdKeywordUnion: return "union";
case TokenIdKeywordUnreachable: return "unreachable";
- case TokenIdKeywordUse: return "use";
+ case TokenIdKeywordUsingNamespace: return "usingnamespace";
case TokenIdKeywordVar: return "var";
case TokenIdKeywordVolatile: return "volatile";
case TokenIdKeywordWhile: return "while";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index f898ca4e59..b17d056109 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -96,7 +96,7 @@ enum TokenId {
TokenIdKeywordUndefined,
TokenIdKeywordUnion,
TokenIdKeywordUnreachable,
- TokenIdKeywordUse,
+ TokenIdKeywordUsingNamespace,
TokenIdKeywordVar,
TokenIdKeywordVolatile,
TokenIdKeywordWhile,
diff --git a/src/userland.cpp b/src/userland.cpp
index 20740711e5..d0330669dd 100644
--- a/src/userland.cpp
+++ b/src/userland.cpp
@@ -42,3 +42,18 @@ int stage2_fmt(int argc, char **argv) {
const char *msg = "stage0 called stage2_fmt";
stage2_panic(msg, strlen(msg));
}
+
+stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
+ const char *msg = "stage0 called stage2_DepTokenizer_init";
+ stage2_panic(msg, strlen(msg));
+}
+
+void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
+ const char *msg = "stage0 called stage2_DepTokenizer_deinit";
+ stage2_panic(msg, strlen(msg));
+}
+
+stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
+ const char *msg = "stage0 called stage2_DepTokenizer_next";
+ stage2_panic(msg, strlen(msg));
+}
diff --git a/src/userland.h b/src/userland.h
index d61081c0a0..eac28053e6 100644
--- a/src/userland.h
+++ b/src/userland.h
@@ -9,6 +9,7 @@
#define ZIG_USERLAND_H
#include
+#include
#include
#ifdef __cplusplus
@@ -118,4 +119,36 @@ ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t le
// ABI warning
ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
+// ABI warning
+struct stage2_DepTokenizer {
+ void *handle;
+};
+
+// ABI warning
+struct stage2_DepNextResult {
+ enum TypeId {
+ error,
+ null,
+ target,
+ prereq,
+ };
+
+ TypeId type_id;
+
+ // when ent == error --> error text
+ // when ent == null --> undefined
+ // when ent == target --> target pathname
+ // when ent == prereq --> prereq pathname
+ const char *textz;
+};
+
+// ABI warning
+ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
+
+// ABI warning
+ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
+
+// ABI warning
+ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
+
#endif
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index c825ed3896..fe1b279cf0 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -318,12 +318,12 @@ ZigLLVMDIType *ZigLLVMCreateDebugMemberType(ZigLLVMDIBuilder *dibuilder, ZigLLVM
const char *name, ZigLLVMDIFile *file, unsigned line, uint64_t size_in_bits,
uint64_t align_in_bits, uint64_t offset_in_bits, unsigned flags, ZigLLVMDIType *type)
{
- assert(flags == 0);
DIType *di_type = reinterpret_cast(dibuilder)->createMemberType(
reinterpret_cast(scope),
name,
reinterpret_cast(file),
- line, size_in_bits, align_in_bits, offset_in_bits, DINode::FlagZero,
+ line, size_in_bits, align_in_bits, offset_in_bits,
+ static_cast(flags),
reinterpret_cast(type));
return reinterpret_cast(di_type);
}
@@ -338,12 +338,12 @@ ZigLLVMDIType *ZigLLVMCreateDebugUnionType(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
DIType *ditype = reinterpret_cast(types_array[i]);
fields.push_back(ditype);
}
- assert(flags == 0);
DIType *di_type = reinterpret_cast(dibuilder)->createUnionType(
reinterpret_cast(scope),
name,
reinterpret_cast(file),
- line_number, size_in_bits, align_in_bits, DINode::FlagZero,
+ line_number, size_in_bits, align_in_bits,
+ static_cast(flags),
reinterpret_cast(dibuilder)->getOrCreateArray(fields),
run_time_lang, unique_id);
return reinterpret_cast(di_type);
@@ -360,12 +360,12 @@ ZigLLVMDIType *ZigLLVMCreateDebugStructType(ZigLLVMDIBuilder *dibuilder, ZigLLVM
DIType *ditype = reinterpret_cast(types_array[i]);
fields.push_back(ditype);
}
- assert(flags == 0);
DIType *di_type = reinterpret_cast(dibuilder)->createStructType(
reinterpret_cast(scope),
name,
reinterpret_cast(file),
- line_number, size_in_bits, align_in_bits, DINode::FlagZero,
+ line_number, size_in_bits, align_in_bits,
+ static_cast(flags),
reinterpret_cast(derived_from),
reinterpret_cast(dibuilder)->getOrCreateArray(fields),
run_time_lang,
@@ -426,11 +426,10 @@ ZigLLVMDIType *ZigLLVMCreateSubroutineType(ZigLLVMDIBuilder *dibuilder_wrapped,
DIType *ditype = reinterpret_cast(types_array[i]);
types.push_back(ditype);
}
- assert(flags == 0);
DIBuilder *dibuilder = reinterpret_cast(dibuilder_wrapped);
DISubroutineType *subroutine_type = dibuilder->createSubroutineType(
dibuilder->getOrCreateTypeArray(types),
- DINode::FlagZero);
+ static_cast(flags));
DIType *ditype = subroutine_type;
return reinterpret_cast(ditype);
}
@@ -516,7 +515,6 @@ ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(ZigLLVMDIBuilder *dbuilder,
ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
ZigLLVMDIType *type, bool always_preserve, unsigned flags)
{
- assert(flags == 0);
DILocalVariable *result = reinterpret_cast(dbuilder)->createAutoVariable(
reinterpret_cast(scope),
name,
@@ -524,7 +522,7 @@ ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(ZigLLVMDIBuilder *dbuilder,
line_no,
reinterpret_cast(type),
always_preserve,
- DINode::FlagZero);
+ static_cast(flags));
return reinterpret_cast(result);
}
@@ -547,7 +545,6 @@ ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilde
ZigLLVMDIScope *scope, const char *name, ZigLLVMDIFile *file, unsigned line_no,
ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no)
{
- assert(flags == 0);
assert(arg_no != 0);
DILocalVariable *result = reinterpret_cast(dbuilder)->createParameterVariable(
reinterpret_cast(scope),
@@ -557,7 +554,7 @@ ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilde
line_no,
reinterpret_cast(type),
always_preserve,
- DINode::FlagZero);
+ static_cast(flags));
return reinterpret_cast(result);
}
@@ -612,7 +609,6 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
unsigned flags, bool is_optimized, ZigLLVMDISubprogram *decl_subprogram)
{
DISubroutineType *di_sub_type = static_cast(reinterpret_cast(fn_di_type));
- assert(flags == 0);
DISubprogram *result = reinterpret_cast(dibuilder)->createFunction(
reinterpret_cast(scope),
name, linkage_name,
@@ -620,7 +616,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
lineno,
di_sub_type,
scope_line,
- DINode::FlagStaticMember,
+ static_cast(flags),
DISubprogram::toSPFlags(is_local_to_unit, is_definition, is_optimized),
nullptr,
reinterpret_cast(decl_subprogram),
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index c60cfd058d..d667e0423d 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -406,6 +406,39 @@ enum ZigLLVM_ObjectFormatType {
ZigLLVM_Wasm,
};
+#define ZigLLVM_DIFlags_Zero 0U
+#define ZigLLVM_DIFlags_Private 1U
+#define ZigLLVM_DIFlags_Protected 2U
+#define ZigLLVM_DIFlags_Public 3U
+#define ZigLLVM_DIFlags_FwdDecl (1U << 2)
+#define ZigLLVM_DIFlags_AppleBlock (1U << 3)
+#define ZigLLVM_DIFlags_BlockByrefStruct (1U << 4)
+#define ZigLLVM_DIFlags_Virtual (1U << 5)
+#define ZigLLVM_DIFlags_Artificial (1U << 6)
+#define ZigLLVM_DIFlags_Explicit (1U << 7)
+#define ZigLLVM_DIFlags_Prototyped (1U << 8)
+#define ZigLLVM_DIFlags_ObjcClassComplete (1U << 9)
+#define ZigLLVM_DIFlags_ObjectPointer (1U << 10)
+#define ZigLLVM_DIFlags_Vector (1U << 11)
+#define ZigLLVM_DIFlags_StaticMember (1U << 12)
+#define ZigLLVM_DIFlags_LValueReference (1U << 13)
+#define ZigLLVM_DIFlags_RValueReference (1U << 14)
+#define ZigLLVM_DIFlags_Reserved (1U << 15)
+#define ZigLLVM_DIFlags_SingleInheritance (1U << 16)
+#define ZigLLVM_DIFlags_MultipleInheritance (2 << 16)
+#define ZigLLVM_DIFlags_VirtualInheritance (3 << 16)
+#define ZigLLVM_DIFlags_IntroducedVirtual (1U << 18)
+#define ZigLLVM_DIFlags_BitField (1U << 19)
+#define ZigLLVM_DIFlags_NoReturn (1U << 20)
+#define ZigLLVM_DIFlags_TypePassByValue (1U << 22)
+#define ZigLLVM_DIFlags_TypePassByReference (1U << 23)
+#define ZigLLVM_DIFlags_EnumClass (1U << 24)
+#define ZigLLVM_DIFlags_Thunk (1U << 25)
+#define ZigLLVM_DIFlags_NonTrivial (1U << 26)
+#define ZigLLVM_DIFlags_BigEndian (1U << 27)
+#define ZigLLVM_DIFlags_LittleEndian (1U << 28)
+#define ZigLLVM_DIFlags_AllCallsDescribed (1U << 29)
+
ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
diff --git a/std/build.zig b/std/build.zig
index d427521251..363890bd4b 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -877,6 +877,13 @@ pub const Target = union(enum) {
};
}
+ pub fn getArch(self: Target) builtin.Arch {
+ switch (self) {
+ Target.Native => return builtin.arch,
+ Target.Cross => |t| return t.arch,
+ }
+ }
+
pub fn isDarwin(self: Target) bool {
return switch (self.getOs()) {
.ios, .macosx, .watchos, .tvos => true,
@@ -891,6 +898,13 @@ pub const Target = union(enum) {
};
}
+ pub fn isWasm(self: Target) bool {
+ return switch (self.getArch()) {
+ .wasm32, .wasm64 => true,
+ else => false,
+ };
+ }
+
pub fn isFreeBSD(self: Target) bool {
return switch (self.getOs()) {
.freebsd => true,
@@ -1080,7 +1094,11 @@ pub const LibExeObjStep = struct {
self.out_filename = self.builder.fmt("{}.lib", self.name);
},
else => {
- self.out_filename = self.builder.fmt("lib{}.a", self.name);
+ if (self.target.isWasm()) {
+ self.out_filename = self.builder.fmt("{}.wasm", self.name);
+ } else {
+ self.out_filename = self.builder.fmt("lib{}.a", self.name);
+ }
},
}
self.out_lib_filename = self.out_filename;
diff --git a/std/c.zig b/std/c.zig
index 4a223cc9e2..029b92e549 100644
--- a/std/c.zig
+++ b/std/c.zig
@@ -2,9 +2,9 @@ const builtin = @import("builtin");
const std = @import("std");
const page_size = std.mem.page_size;
-pub use @import("os/bits.zig");
+pub usingnamespace @import("os/bits.zig");
-pub use switch (builtin.os) {
+pub usingnamespace switch (builtin.os) {
.linux => @import("c/linux.zig"),
.windows => @import("c/windows.zig"),
.macosx, .ios, .tvos, .watchos => @import("c/darwin.zig"),
diff --git a/std/c/darwin.zig b/std/c/darwin.zig
index e45a158f68..14a5baff5c 100644
--- a/std/c/darwin.zig
+++ b/std/c/darwin.zig
@@ -3,7 +3,7 @@ const assert = std.debug.assert;
const builtin = @import("builtin");
const macho = std.macho;
-use @import("../os/bits.zig");
+usingnamespace @import("../os/bits.zig");
extern "c" fn __error() *c_int;
pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
@@ -54,3 +54,5 @@ pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t
pub fn sigaddset(set: *sigset_t, signo: u5) void {
set.* |= u32(1) << (signo - 1);
}
+
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig
index 70f3aeb9ca..bcc60e65ed 100644
--- a/std/c/freebsd.zig
+++ b/std/c/freebsd.zig
@@ -1,4 +1,8 @@
+const std = @import("../std.zig");
+usingnamespace std.c;
+
extern "c" fn __error() *c_int;
pub const _errno = __error;
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/linux.zig b/std/c/linux.zig
index 9e028728c7..9689f61082 100644
--- a/std/c/linux.zig
+++ b/std/c/linux.zig
@@ -1,5 +1,5 @@
const std = @import("../std.zig");
-use std.c;
+usingnamespace std.c;
extern "c" fn __errno_location() *c_int;
pub const _errno = __errno_location;
@@ -7,7 +7,7 @@ pub const _errno = __errno_location;
pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int;
pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;
-pub extern "c" fn epoll_ctl(epfd: fd_t, op: c_uint, fd: fd_t, event: *epoll_event) c_int;
+pub extern "c" fn epoll_ctl(epfd: fd_t, op: c_uint, fd: fd_t, event: ?*epoll_event) c_int;
pub extern "c" fn epoll_create1(flags: c_uint) c_int;
pub extern "c" fn epoll_wait(epfd: fd_t, events: [*]epoll_event, maxevents: c_uint, timeout: c_int) c_int;
pub extern "c" fn epoll_pwait(
@@ -25,3 +25,5 @@ pub extern "c" fn getauxval(__type: c_ulong) c_ulong;
pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int;
pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
+
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/c/netbsd.zig b/std/c/netbsd.zig
index c677e1500b..417c78db69 100644
--- a/std/c/netbsd.zig
+++ b/std/c/netbsd.zig
@@ -1,4 +1,8 @@
+const std = @import("../std.zig");
+usingnamespace std.c;
+
extern "c" fn __errno() *c_int;
pub const _errno = __errno;
pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
+pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
diff --git a/std/dynamic_library.zig b/std/dynamic_library.zig
index 3ae3b4c66a..3413788019 100644
--- a/std/dynamic_library.zig
+++ b/std/dynamic_library.zig
@@ -104,17 +104,18 @@ pub const LinuxDynLib = struct {
memory: []align(mem.page_size) u8,
/// Trusts the file
- pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
+ pub fn open(path: []const u8) !DynLib {
const fd = try os.open(path, 0, os.O_RDONLY | os.O_CLOEXEC);
errdefer os.close(fd);
+ // TODO remove this @intCast
const size = @intCast(usize, (try os.fstat(fd)).size);
const bytes = try os.mmap(
null,
- size,
+ mem.alignForward(size, mem.page_size),
os.PROT_READ | os.PROT_EXEC,
- os.MAP_PRIVATE | os.MAP_LOCKED,
+ os.MAP_PRIVATE,
fd,
0,
);
@@ -244,14 +245,12 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
}
pub const WindowsDynLib = struct {
- allocator: *mem.Allocator,
dll: windows.HMODULE,
- pub fn open(allocator: *mem.Allocator, path: []const u8) !WindowsDynLib {
+ pub fn open(path: []const u8) !WindowsDynLib {
const wpath = try windows.sliceToPrefixedFileW(path);
return WindowsDynLib{
- .allocator = allocator,
.dll = try windows.LoadLibraryW(&wpath),
};
}
@@ -273,7 +272,7 @@ test "dynamic_library" {
else => return,
};
- const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
+ const dynlib = DynLib.open(libname) catch |err| {
testing.expect(err == error.FileNotFound);
return;
};
diff --git a/std/event/loop.zig b/std/event/loop.zig
index 61732d78f5..6cddb50ef5 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -421,7 +421,7 @@ pub const Loop = struct {
}
pub fn linuxRemoveFd(self: *Loop, fd: i32) void {
- os.epoll_ctl(self.os_data.epollfd, os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
+ os.epoll_ctl(self.os_data.epollfd, os.linux.EPOLL_CTL_DEL, fd, null) catch {};
self.finishOneEvent();
}
diff --git a/std/fmt.zig b/std/fmt.zig
index 74c36f7086..be3e26b585 100644
--- a/std/fmt.zig
+++ b/std/fmt.zig
@@ -145,23 +145,7 @@ pub fn formatType(
return format(context, Errors, output, "promise@{x}", @ptrToInt(value));
},
builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
- const has_cust_fmt = comptime cf: {
- const info = @typeInfo(T);
- const defs = switch (info) {
- builtin.TypeId.Struct => |s| s.defs,
- builtin.TypeId.Union => |u| u.defs,
- builtin.TypeId.Enum => |e| e.defs,
- else => unreachable,
- };
-
- for (defs) |def| {
- if (mem.eql(u8, def.name, "format")) {
- break :cf true;
- }
- }
- break :cf false;
- };
- if (has_cust_fmt) return value.format(fmt, context, Errors, output);
+ if (comptime std.meta.trait.hasFn("format")(T)) return value.format(fmt, context, Errors, output);
try output(context, @typeName(T));
switch (comptime @typeId(T)) {
@@ -236,8 +220,10 @@ pub fn formatType(
if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
return formatText(value, fmt, context, Errors, output);
}
- const casted_value = ([]const u8)(value);
- return output(context, casted_value);
+ if (ptr_info.child == u8) {
+ return formatText(value, fmt, context, Errors, output);
+ }
+ return format(context, Errors, output, "{}@{x}", @typeName(ptr_info.child), @ptrToInt(value.ptr));
},
builtin.TypeInfo.Pointer.Size.C => {
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
@@ -1025,6 +1011,10 @@ test "fmt.format" {
const value: []const u8 = "abc";
try testFmt("slice: abc\n", "slice: {}\n", value);
}
+ {
+ const value = @intToPtr([*]const []const u8, 0xdeadbeef)[0..0];
+ try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", value);
+ }
{
const value = @intToPtr(*i32, 0xdeadbeef);
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
diff --git a/std/hash_map.zig b/std/hash_map.zig
index 8cbff7be9d..e64bdd09b4 100644
--- a/std/hash_map.zig
+++ b/std/hash_map.zig
@@ -139,9 +139,9 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
// ensure that the hash map will be at most 60% full if
// expected_count items are put into it
var optimized_capacity = expected_count * 5 / 3;
- // round capacity to the next power of two
- const pow = math.log2_int_ceil(usize, optimized_capacity);
- return math.pow(usize, 2, pow);
+ // an overflow here would mean the amount of memory required would not
+ // be representable in the address space
+ return math.ceilPowerOfTwo(usize, optimized_capacity) catch unreachable;
}
/// Increases capacity so that the hash map will be at most
@@ -155,6 +155,8 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
/// capacity is greater than the current capacity.
/// New capacity must be a power of two.
fn ensureCapacityExact(self: *Self, new_capacity: usize) !void {
+ // capacity must always be a power of two to allow for modulo
+ // optimization in the constrainIndex fn
const is_power_of_two = new_capacity & (new_capacity - 1) == 0;
assert(is_power_of_two);
@@ -209,7 +211,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
{
var roll_over: usize = 0;
while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
- const index = (start_index + roll_over) % hm.entries.len;
+ const index = hm.constrainIndex(start_index + roll_over);
var entry = &hm.entries[index];
if (!entry.used) return null;
@@ -218,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
const removed_kv = entry.kv;
while (roll_over < hm.entries.len) : (roll_over += 1) {
- const next_index = (start_index + roll_over + 1) % hm.entries.len;
+ const next_index = hm.constrainIndex(start_index + roll_over + 1);
const next_entry = &hm.entries[next_index];
if (!next_entry.used or next_entry.distance_from_start_index == 0) {
entry.used = false;
@@ -301,7 +303,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
roll_over += 1;
distance_from_start_index += 1;
}) {
- const index = (start_index + roll_over) % self.entries.len;
+ const index = self.constrainIndex(start_index + roll_over);
const entry = &self.entries[index];
if (entry.used and !eql(entry.kv.key, key)) {
@@ -358,7 +360,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
{
var roll_over: usize = 0;
while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
- const index = (start_index + roll_over) % hm.entries.len;
+ const index = hm.constrainIndex(start_index + roll_over);
const entry = &hm.entries[index];
if (!entry.used) return null;
@@ -369,7 +371,13 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
}
fn keyToIndex(hm: Self, key: K) usize {
- return usize(hash(key)) % hm.entries.len;
+ return hm.constrainIndex(usize(hash(key)));
+ }
+
+ fn constrainIndex(hm: Self, i: usize) usize {
+ // this is an optimization for modulo of power of two integers;
+ // it requires hm.entries.len to always be a power of two
+ return i & (hm.entries.len - 1);
}
};
}
diff --git a/std/io.zig b/std/io.zig
index 258961fdfc..de33d95626 100644
--- a/std/io.zig
+++ b/std/io.zig
@@ -1131,7 +1131,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
}
pub fn alignToByte(self: *Self) void {
- if (!is_packed) return;
+ if (packing == .Byte) return;
self.in_stream.alignToByte();
}
diff --git a/std/io/test.zig b/std/io/test.zig
index fc3b0f8902..bd0a0a902a 100644
--- a/std/io/test.zig
+++ b/std/io/test.zig
@@ -417,6 +417,7 @@ fn testIntSerializerDeserializerInfNaN(
const nan_check_f16 = try deserializer.deserialize(f16);
const inf_check_f16 = try deserializer.deserialize(f16);
const nan_check_f32 = try deserializer.deserialize(f32);
+ deserializer.alignToByte();
const inf_check_f32 = try deserializer.deserialize(f32);
const nan_check_f64 = try deserializer.deserialize(f64);
const inf_check_f64 = try deserializer.deserialize(f64);
diff --git a/std/math.zig b/std/math.zig
index 04f0d0a49a..765df6280c 100644
--- a/std/math.zig
+++ b/std/math.zig
@@ -696,6 +696,76 @@ test "math.floorPowerOfTwo" {
comptime testFloorPowerOfTwo();
}
+fn testFloorPowerOfTwo() void {
+ testing.expect(floorPowerOfTwo(u32, 63) == 32);
+ testing.expect(floorPowerOfTwo(u32, 64) == 64);
+ testing.expect(floorPowerOfTwo(u32, 65) == 64);
+ testing.expect(floorPowerOfTwo(u4, 7) == 4);
+ testing.expect(floorPowerOfTwo(u4, 8) == 8);
+ testing.expect(floorPowerOfTwo(u4, 9) == 8);
+}
+
+/// Returns the next power of two (if the value is not already a power of two).
+/// Only unsigned integers can be used. Zero is not an allowed input.
+/// Result is a type with 1 more bit than the input type.
+pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T.bit_count + 1) {
+ comptime assert(@typeId(T) == builtin.TypeId.Int);
+ comptime assert(!T.is_signed);
+ assert(value != 0);
+ comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1);
+ comptime const shiftType = std.math.Log2Int(promotedType);
+ return promotedType(1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1));
+}
+
+/// Returns the next power of two (if the value is not already a power of two).
+/// Only unsigned integers can be used. Zero is not an allowed input.
+/// If the value doesn't fit, returns an error.
+pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {
+ comptime assert(@typeId(T) == builtin.TypeId.Int);
+ comptime assert(!T.is_signed);
+ comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1);
+ comptime const overflowBit = promotedType(1) << T.bit_count;
+ var x = ceilPowerOfTwoPromote(T, value);
+ if (overflowBit & x != 0) {
+ return error.Overflow;
+ }
+ return @intCast(T, x);
+}
+
+test "math.ceilPowerOfTwoPromote" {
+ testCeilPowerOfTwoPromote();
+ comptime testCeilPowerOfTwoPromote();
+}
+
+fn testCeilPowerOfTwoPromote() void {
+ testing.expectEqual(u33(1), ceilPowerOfTwoPromote(u32, 1));
+ testing.expectEqual(u33(2), ceilPowerOfTwoPromote(u32, 2));
+ testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 63));
+ testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 64));
+ testing.expectEqual(u33(128), ceilPowerOfTwoPromote(u32, 65));
+ testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 7));
+ testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 8));
+ testing.expectEqual(u6(16), ceilPowerOfTwoPromote(u5, 9));
+ testing.expectEqual(u5(16), ceilPowerOfTwoPromote(u4, 9));
+}
+
+test "math.ceilPowerOfTwo" {
+ try testCeilPowerOfTwo();
+ comptime try testCeilPowerOfTwo();
+}
+
+fn testCeilPowerOfTwo() !void {
+ testing.expectEqual(u32(1), try ceilPowerOfTwo(u32, 1));
+ testing.expectEqual(u32(2), try ceilPowerOfTwo(u32, 2));
+ testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 63));
+ testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 64));
+ testing.expectEqual(u32(128), try ceilPowerOfTwo(u32, 65));
+ testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 7));
+ testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 8));
+ testing.expectEqual(u5(16), try ceilPowerOfTwo(u5, 9));
+ testing.expectError(error.Overflow, ceilPowerOfTwo(u4, 9));
+}
+
pub fn log2_int(comptime T: type, x: T) Log2Int(T) {
assert(x != 0);
return @intCast(Log2Int(T), T.bit_count - 1 - @clz(T, x));
@@ -722,15 +792,6 @@ test "std.math.log2_int_ceil" {
testing.expect(log2_int_ceil(u32, 10) == 4);
}
-fn testFloorPowerOfTwo() void {
- testing.expect(floorPowerOfTwo(u32, 63) == 32);
- testing.expect(floorPowerOfTwo(u32, 64) == 64);
- testing.expect(floorPowerOfTwo(u32, 65) == 64);
- testing.expect(floorPowerOfTwo(u4, 7) == 4);
- testing.expect(floorPowerOfTwo(u4, 8) == 8);
- testing.expect(floorPowerOfTwo(u4, 9) == 8);
-}
-
pub fn lossyCast(comptime T: type, value: var) T {
switch (@typeInfo(@typeOf(value))) {
builtin.TypeId.Int => return @intToFloat(T, value),
diff --git a/std/math/big.zig b/std/math/big.zig
index 44b5ce675f..8105beb506 100644
--- a/std/math/big.zig
+++ b/std/math/big.zig
@@ -1,5 +1,5 @@
-pub use @import("big/int.zig");
-pub use @import("big/rational.zig");
+pub usingnamespace @import("big/int.zig");
+pub usingnamespace @import("big/rational.zig");
test "math.big" {
_ = @import("big/int.zig");
diff --git a/std/meta.zig b/std/meta.zig
index a8c7e4b415..297b55894e 100644
--- a/std/meta.zig
+++ b/std/meta.zig
@@ -160,16 +160,16 @@ test "std.meta.containerLayout" {
testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
}
-pub fn definitions(comptime T: type) []TypeInfo.Definition {
+pub fn declarations(comptime T: type) []TypeInfo.Declaration {
return switch (@typeInfo(T)) {
- TypeId.Struct => |info| info.defs,
- TypeId.Enum => |info| info.defs,
- TypeId.Union => |info| info.defs,
+ TypeId.Struct => |info| info.decls,
+ TypeId.Enum => |info| info.decls,
+ TypeId.Union => |info| info.decls,
else => @compileError("Expected struct, enum or union type, found '" ++ @typeName(T) ++ "'"),
};
}
-test "std.meta.definitions" {
+test "std.meta.declarations" {
const E1 = enum {
A,
@@ -184,28 +184,28 @@ test "std.meta.definitions" {
fn a() void {}
};
- const defs = comptime [][]TypeInfo.Definition{
- definitions(E1),
- definitions(S1),
- definitions(U1),
+ const decls = comptime [][]TypeInfo.Declaration{
+ declarations(E1),
+ declarations(S1),
+ declarations(U1),
};
- inline for (defs) |def| {
- testing.expect(def.len == 1);
- testing.expect(comptime mem.eql(u8, def[0].name, "a"));
+ inline for (decls) |decl| {
+ testing.expect(decl.len == 1);
+ testing.expect(comptime mem.eql(u8, decl[0].name, "a"));
}
}
-pub fn definitionInfo(comptime T: type, comptime def_name: []const u8) TypeInfo.Definition {
- inline for (comptime definitions(T)) |def| {
- if (comptime mem.eql(u8, def.name, def_name))
- return def;
+pub fn declarationInfo(comptime T: type, comptime decl_name: []const u8) TypeInfo.Declaration {
+ inline for (comptime declarations(T)) |decl| {
+ if (comptime mem.eql(u8, decl.name, decl_name))
+ return decl;
}
- @compileError("'" ++ @typeName(T) ++ "' has no definition '" ++ def_name ++ "'");
+ @compileError("'" ++ @typeName(T) ++ "' has no declaration '" ++ decl_name ++ "'");
}
-test "std.meta.definitionInfo" {
+test "std.meta.declarationInfo" {
const E1 = enum {
A,
@@ -220,10 +220,10 @@ test "std.meta.definitionInfo" {
fn a() void {}
};
- const infos = comptime []TypeInfo.Definition{
- definitionInfo(E1, "a"),
- definitionInfo(S1, "a"),
- definitionInfo(U1, "a"),
+ const infos = comptime []TypeInfo.Declaration{
+ declarationInfo(E1, "a"),
+ declarationInfo(S1, "a"),
+ declarationInfo(U1, "a"),
};
inline for (infos) |info| {
diff --git a/std/meta/trait.zig b/std/meta/trait.zig
index f77619ec39..db3e52fc3f 100644
--- a/std/meta/trait.zig
+++ b/std/meta/trait.zig
@@ -55,53 +55,15 @@ test "std.meta.trait.multiTrait" {
testing.expect(!isVector(u8));
}
-///
-pub fn hasDef(comptime name: []const u8) TraitFn {
- const Closure = struct {
- pub fn trait(comptime T: type) bool {
- const info = @typeInfo(T);
- const defs = switch (info) {
- builtin.TypeId.Struct => |s| s.defs,
- builtin.TypeId.Union => |u| u.defs,
- builtin.TypeId.Enum => |e| e.defs,
- else => return false,
- };
-
- inline for (defs) |def| {
- if (mem.eql(u8, def.name, name)) return def.is_pub;
- }
-
- return false;
- }
- };
- return Closure.trait;
-}
-
-test "std.meta.trait.hasDef" {
- const TestStruct = struct {
- pub const value = u8(16);
- };
-
- const TestStructFail = struct {
- const value = u8(16);
- };
-
- testing.expect(hasDef("value")(TestStruct));
- testing.expect(!hasDef("value")(TestStructFail));
- testing.expect(!hasDef("value")(*TestStruct));
- testing.expect(!hasDef("value")(**TestStructFail));
- testing.expect(!hasDef("x")(TestStruct));
- testing.expect(!hasDef("value")(u8));
-}
-
///
pub fn hasFn(comptime name: []const u8) TraitFn {
const Closure = struct {
pub fn trait(comptime T: type) bool {
- if (!comptime hasDef(name)(T)) return false;
- const DefType = @typeOf(@field(T, name));
- const def_type_id = @typeId(DefType);
- return def_type_id == builtin.TypeId.Fn;
+ if (!comptime isContainer(T)) return false;
+ if (!comptime @hasDecl(T, name)) return false;
+ const DeclType = @typeOf(@field(T, name));
+ const decl_type_id = @typeId(DeclType);
+ return decl_type_id == builtin.TypeId.Fn;
}
};
return Closure.trait;
diff --git a/std/os.zig b/std/os.zig
index be2be92f7d..46f73bc7ce 100644
--- a/std/os.zig
+++ b/std/os.zig
@@ -19,6 +19,8 @@ const builtin = @import("builtin");
const assert = std.debug.assert;
const math = std.math;
const mem = std.mem;
+const elf = std.elf;
+const dl = @import("dynamic_library.zig");
const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES;
comptime {
@@ -46,7 +48,7 @@ pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {
else => struct {},
};
-pub use @import("os/bits.zig");
+pub usingnamespace @import("os/bits.zig");
/// See also `getenv`. Populated by startup code before main().
pub var environ: [][*]u8 = undefined;
@@ -1509,7 +1511,7 @@ pub const EpollCtlError = error{
Unexpected,
};
-pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: *epoll_event) EpollCtlError!void {
+pub fn epoll_ctl(epfd: i32, op: u32, fd: i32, event: ?*epoll_event) EpollCtlError!void {
const rc = system.epoll_ctl(epfd, op, fd, event);
switch (errno(rc)) {
0 => return,
@@ -1883,20 +1885,29 @@ pub fn inotify_rm_watch(inotify_fd: i32, wd: i32) void {
}
pub const MProtectError = error{
+ /// The memory cannot be given the specified access. This can happen, for example, if you
+ /// mmap(2) a file to which you have read-only access, then ask mprotect() to mark it
+ /// PROT_WRITE.
AccessDenied,
+
+ /// Changing the protection of a memory region would result in the total number of map‐
+ /// pings with distinct attributes (e.g., read versus read/write protection) exceeding the
+ /// allowed maximum. (For example, making the protection of a range PROT_READ in the mid‐
+ /// dle of a region currently protected as PROT_READ|PROT_WRITE would result in three map‐
+ /// pings: two read/write mappings at each end and a read-only mapping in the middle.)
OutOfMemory,
Unexpected,
};
/// `memory.len` must be page-aligned.
-pub fn mprotect(memory: [*]align(mem.page_size) u8, protection: u32) MProtectError!void {
+pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void {
assert(mem.isAligned(memory.len, mem.page_size));
switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {
0 => return,
EINVAL => unreachable,
EACCES => return error.AccessDenied,
ENOMEM => return error.OutOfMemory,
- else => return unexpectedErrno(err),
+ else => |err| return unexpectedErrno(err),
}
}
@@ -1935,7 +1946,6 @@ pub const MMapError = error{
/// Map files or devices into memory.
/// Use of a mapped region can result in these signals:
-/// `length` must be page-aligned.
/// * SIGSEGV - Attempted write into a region mapped as read-only.
/// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file
pub fn mmap(
@@ -1946,7 +1956,6 @@ pub fn mmap(
fd: fd_t,
offset: isize,
) MMapError![]align(mem.page_size) u8 {
- assert(mem.isAligned(length, mem.page_size));
const err = if (builtin.link_libc) blk: {
const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
if (rc != MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
@@ -2359,6 +2368,70 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
}
}
+pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_info, size: usize, data: ?*T) i32, data: ?*T) isize {
+ // This is implemented only for systems using ELF executables
+ if (windows.is_the_target or builtin.os == .uefi or wasi.is_the_target or darwin.is_the_target)
+ @compileError("dl_iterate_phdr is not available for this target");
+
+ if (builtin.link_libc) {
+ return system.dl_iterate_phdr(
+ @ptrCast(std.c.dl_iterate_phdr_callback, callback),
+ @ptrCast(?*c_void, data),
+ );
+ }
+
+ const elf_base = std.process.getBaseAddress();
+ const ehdr = @intToPtr(*elf.Ehdr, elf_base);
+ // Make sure the base address points to an ELF image
+ assert(mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF"));
+ const n_phdr = ehdr.e_phnum;
+ const phdrs = (@intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff))[0..n_phdr];
+
+ var it = dl.linkmap_iterator(phdrs) catch unreachable;
+
+ // The executable has no dynamic link segment, create a single entry for
+ // the whole ELF image
+ if (it.end()) {
+ var info = dl_phdr_info{
+ .dlpi_addr = elf_base,
+ .dlpi_name = c"/proc/self/exe",
+ .dlpi_phdr = phdrs.ptr,
+ .dlpi_phnum = ehdr.e_phnum,
+ };
+
+ return callback(&info, @sizeOf(dl_phdr_info), data);
+ }
+
+ // Last return value from the callback function
+ var last_r: isize = 0;
+ while (it.next()) |entry| {
+ var dlpi_phdr: [*]elf.Phdr = undefined;
+ var dlpi_phnum: u16 = undefined;
+
+ if (entry.l_addr != 0) {
+ const elf_header = @intToPtr(*elf.Ehdr, entry.l_addr);
+ dlpi_phdr = @intToPtr([*]elf.Phdr, entry.l_addr + elf_header.e_phoff);
+ dlpi_phnum = elf_header.e_phnum;
+ } else {
+ // This is the running ELF image
+ dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff);
+ dlpi_phnum = ehdr.e_phnum;
+ }
+
+ var info = dl_phdr_info{
+ .dlpi_addr = entry.l_addr,
+ .dlpi_name = entry.l_name,
+ .dlpi_phdr = dlpi_phdr,
+ .dlpi_phnum = dlpi_phnum,
+ };
+
+ last_r = callback(&info, @sizeOf(dl_phdr_info), data);
+ if (last_r != 0) break;
+ }
+
+ return last_r;
+}
+
pub const ClockGetTimeError = error{
UnsupportedClock,
Unexpected,
@@ -2433,6 +2506,29 @@ pub fn unexpectedErrno(err: usize) UnexpectedError {
return error.Unexpected;
}
+pub const SigaltstackError = error{
+ /// The supplied stack size was less than MINSIGSTKSZ.
+ SizeTooSmall,
+
+ /// Attempted to change the signal stack while it was active.
+ PermissionDenied,
+ Unexpected,
+};
+
+pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
+ if (windows.is_the_target or uefi.is_the_target or wasi.is_the_target)
+ @compileError("std.os.sigaltstack not available for this target");
+
+ switch (errno(system.sigaltstack(ss, old_ss))) {
+ 0 => return,
+ EFAULT => unreachable,
+ EINVAL => unreachable,
+ ENOMEM => return error.SizeTooSmall,
+ EPERM => return error.PermissionDenied,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
test "" {
_ = @import("os/darwin.zig");
_ = @import("os/freebsd.zig");
diff --git a/std/os/bits.zig b/std/os/bits.zig
index 7b87cc6e4d..f16da2487b 100644
--- a/std/os/bits.zig
+++ b/std/os/bits.zig
@@ -3,7 +3,7 @@
const builtin = @import("builtin");
-pub use switch (builtin.os) {
+pub usingnamespace switch (builtin.os) {
.macosx, .ios, .tvos, .watchos => @import("bits/darwin.zig"),
.freebsd => @import("bits/freebsd.zig"),
.linux => @import("bits/linux.zig"),
diff --git a/std/os/bits/darwin.zig b/std/os/bits/darwin.zig
index a685735da0..39dae6e7a1 100644
--- a/std/os/bits/darwin.zig
+++ b/std/os/bits/darwin.zig
@@ -1078,3 +1078,15 @@ pub const EQFULL = 106;
/// Must be equal largest errno
pub const ELAST = 106;
+
+pub const SIGSTKSZ = 131072;
+pub const MINSIGSTKSZ = 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/bits/freebsd.zig b/std/os/bits/freebsd.zig
index 1925b75f3f..c73887d648 100644
--- a/std/os/bits/freebsd.zig
+++ b/std/os/bits/freebsd.zig
@@ -20,6 +20,13 @@ pub const pthread_attr_t = extern struct {
__align: c_long,
};
+pub const dl_phdr_info = extern struct {
+ dlpi_addr: usize,
+ dlpi_name: ?[*]const u8,
+ dlpi_phdr: [*]std.elf.Phdr,
+ dlpi_phnum: u16,
+};
+
pub const msghdr = extern struct {
/// optional address
msg_name: ?*sockaddr,
@@ -835,3 +842,19 @@ pub const ENOTRECOVERABLE = 95; // State not recoverable
pub const EOWNERDEAD = 96; // Previous owner died
pub const ELAST = 96; // Must be equal largest errno
+
+pub const MINSIGSTKSZ = switch (builtin.arch) {
+ .i386, .x86_64 => 2048,
+ .arm, .aarch64 => 4096,
+ else => @compileError("MINSIGSTKSZ not defined for this architecture"),
+};
+pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/bits/linux.zig b/std/os/bits/linux.zig
index 6532e72362..ff541077d9 100644
--- a/std/os/bits/linux.zig
+++ b/std/os/bits/linux.zig
@@ -1,10 +1,10 @@
const builtin = @import("builtin");
const std = @import("../../std.zig");
const maxInt = std.math.maxInt;
-use @import("../bits.zig");
+usingnamespace @import("../bits.zig");
-pub use @import("linux/errno.zig");
-pub use switch (builtin.arch) {
+pub usingnamespace @import("linux/errno.zig");
+pub usingnamespace switch (builtin.arch) {
.x86_64 => @import("linux/x86_64.zig"),
.aarch64 => @import("linux/arm64.zig"),
else => struct {},
@@ -762,16 +762,16 @@ pub const epoll_data = extern union {
// On x86_64 the structure is packed so that it matches the definition of its
// 32bit counterpart
-pub const epoll_event = if (builtin.arch != .x86_64)
- extern struct {
+pub const epoll_event = switch (builtin.arch) {
+ .x86_64 => packed struct {
events: u32,
data: epoll_data,
- }
-else
- packed struct {
+ },
+ else => extern struct {
events: u32,
data: epoll_data,
- };
+ },
+};
pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
pub const _LINUX_CAPABILITY_U32S_1 = 1;
@@ -929,3 +929,24 @@ pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
//#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set)
//#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set)
//#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2)
+
+pub const MINSIGSTKSZ = switch (builtin.arch) {
+ .i386, .x86_64, .arm => 2048,
+ .aarch64 => 5120,
+ else => @compileError("MINSIGSTKSZ not defined for this architecture"),
+};
+pub const SIGSTKSZ = switch (builtin.arch) {
+ .i386, .x86_64, .arm => 8192,
+ .aarch64 => 16384,
+ else => @compileError("SIGSTKSZ not defined for this architecture"),
+};
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 2;
+pub const SS_AUTODISARM = 1 << 31;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_flags: i32,
+ ss_size: isize,
+};
diff --git a/std/os/bits/linux/arm64.zig b/std/os/bits/linux/arm64.zig
index 8966df30d2..527b78bbcd 100644
--- a/std/os/bits/linux/arm64.zig
+++ b/std/os/bits/linux/arm64.zig
@@ -299,16 +299,16 @@ pub const O_NONBLOCK = 0o4000;
pub const O_DSYNC = 0o10000;
pub const O_SYNC = 0o4010000;
pub const O_RSYNC = 0o4010000;
-pub const O_DIRECTORY = 0o200000;
-pub const O_NOFOLLOW = 0o400000;
+pub const O_DIRECTORY = 0o40000;
+pub const O_NOFOLLOW = 0o100000;
pub const O_CLOEXEC = 0o2000000;
pub const O_ASYNC = 0o20000;
-pub const O_DIRECT = 0o40000;
-pub const O_LARGEFILE = 0;
+pub const O_DIRECT = 0o200000;
+pub const O_LARGEFILE = 0o400000;
pub const O_NOATIME = 0o1000000;
pub const O_PATH = 0o10000000;
-pub const O_TMPFILE = 0o20200000;
+pub const O_TMPFILE = 0o20040000;
pub const O_NDELAY = O_NONBLOCK;
pub const F_DUPFD = 0;
diff --git a/std/os/bits/netbsd.zig b/std/os/bits/netbsd.zig
index fc4c2904e0..d83ea82b06 100644
--- a/std/os/bits/netbsd.zig
+++ b/std/os/bits/netbsd.zig
@@ -20,6 +20,13 @@ pub const pthread_attr_t = extern struct {
pta_private: *c_void,
};
+pub const dl_phdr_info = extern struct {
+ dlpi_addr: usize,
+ dlpi_name: ?[*]const u8,
+ dlpi_phdr: [*]std.elf.Phdr,
+ dlpi_phnum: u16,
+};
+
pub const msghdr = extern struct {
/// optional address
msg_name: ?*sockaddr,
@@ -723,3 +730,15 @@ pub const ENOLINK = 95; // Link has been severed
pub const EPROTO = 96; // Protocol error
pub const ELAST = 96; // Must equal largest errno
+
+pub const MINSIGSTKSZ = 8192;
+pub const SIGSTKSZ = MINSIGSTKSZ + 32768;
+
+pub const SS_ONSTACK = 1;
+pub const SS_DISABLE = 4;
+
+pub const stack_t = extern struct {
+ ss_sp: [*]u8,
+ ss_size: isize,
+ ss_flags: i32,
+};
diff --git a/std/os/bits/windows.zig b/std/os/bits/windows.zig
index a242113ba0..fc148d812f 100644
--- a/std/os/bits/windows.zig
+++ b/std/os/bits/windows.zig
@@ -1,6 +1,6 @@
// The reference for these types and values is Microsoft Windows's ucrt (Universal C RunTime).
-use @import("../windows/bits.zig");
+usingnamespace @import("../windows/bits.zig");
pub const fd_t = HANDLE;
pub const pid_t = HANDLE;
@@ -158,10 +158,3 @@ pub const EWOULDBLOCK = 140;
pub const EDQUOT = 10069;
pub const F_OK = 0;
-
-// These are workarounds for "use of undeclared identifier" compile errors
-// TODO make the compiler even more lazy. don't emit "use of undeclared identifier" errors
-// for if branches that aren't taken.
-pub const SIGKILL = @compileError("Windows libc does not have this");
-
-
diff --git a/std/os/darwin.zig b/std/os/darwin.zig
index d6e0a1b77c..67ce9a06cf 100644
--- a/std/os/darwin.zig
+++ b/std/os/darwin.zig
@@ -4,4 +4,4 @@ pub const is_the_target = switch (builtin.os) {
.macosx, .tvos, .watchos, .ios => true,
else => false,
};
-pub use std.c;
+pub usingnamespace std.c;
diff --git a/std/os/freebsd.zig b/std/os/freebsd.zig
index c0f3382bd0..d418ccd415 100644
--- a/std/os/freebsd.zig
+++ b/std/os/freebsd.zig
@@ -1,4 +1,4 @@
const std = @import("../std.zig");
const builtin = @import("builtin");
pub const is_the_target = builtin.os == .freebsd;
-pub use std.c;
+pub usingnamespace std.c;
diff --git a/std/os/linux.zig b/std/os/linux.zig
index 282aa19bf1..61a13ff164 100644
--- a/std/os/linux.zig
+++ b/std/os/linux.zig
@@ -14,12 +14,12 @@ const vdso = @import("linux/vdso.zig");
const dl = @import("../dynamic_library.zig");
pub const is_the_target = builtin.os == .linux;
-pub use switch (builtin.arch) {
+pub usingnamespace switch (builtin.arch) {
.x86_64 => @import("linux/x86_64.zig"),
.aarch64 => @import("linux/arm64.zig"),
else => struct {},
};
-pub use @import("bits.zig");
+pub usingnamespace @import("bits.zig");
pub const tls = @import("linux/tls.zig");
/// Set by startup code, used by `getauxval`.
@@ -131,7 +131,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz
if (@hasDecl(@This(), "SYS_readlink")) {
return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
} else {
- return syscall4(SYS_readlinkat, AT_FDCWD, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+ return syscall4(SYS_readlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
}
}
@@ -145,7 +145,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
if (@hasDecl(@This(), "SYS_mkdir")) {
return syscall2(SYS_mkdir, @ptrToInt(path), mode);
} else {
- return syscall3(SYS_mkdirat, AT_FDCWD, @ptrToInt(path), mode);
+ return syscall3(SYS_mkdirat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), mode);
}
}
@@ -206,7 +206,7 @@ pub fn rmdir(path: [*]const u8) usize {
if (@hasDecl(@This(), "SYS_rmdir")) {
return syscall1(SYS_rmdir, @ptrToInt(path));
} else {
- return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), AT_REMOVEDIR);
+ return syscall3(SYS_unlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), AT_REMOVEDIR);
}
}
@@ -215,7 +215,7 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
if (@hasDecl(@This(), "SYS_symlink")) {
return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
} else {
- return syscall3(SYS_symlinkat, @ptrToInt(existing), AT_FDCWD, @ptrToInt(new));
+ return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new));
}
}
@@ -231,12 +231,16 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
// TODO https://github.com/ziglang/zig/issues/265
pub fn access(path: [*]const u8, mode: u32) usize {
- return syscall2(SYS_access, @ptrToInt(path), mode);
+ if (@hasDecl(@This(), "SYS_access")) {
+ return syscall2(SYS_access, @ptrToInt(path), mode);
+ } else {
+ return syscall4(SYS_faccessat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), mode, 0);
+ }
}
// TODO https://github.com/ziglang/zig/issues/265
-pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
- return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
+pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32, flags: u32) usize {
+ return syscall4(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode, flags);
}
pub fn pipe(fd: *[2]i32) usize {
@@ -264,9 +268,9 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {
if (@hasDecl(@This(), "SYS_rename")) {
return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
} else if (@hasDecl(@This(), "SYS_renameat")) {
- return syscall4(SYS_renameat, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new));
+ return syscall4(SYS_renameat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(old), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new));
} else {
- return syscall5(SYS_renameat2, AT_FDCWD, @ptrToInt(old), AT_FDCWD, @ptrToInt(new), 0);
+ return syscall5(SYS_renameat2, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(old), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new), 0);
}
}
@@ -305,7 +309,17 @@ pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const
// TODO https://github.com/ziglang/zig/issues/265
pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
- return syscall3(SYS_open, @ptrToInt(path), flags, perm);
+ if (@hasDecl(@This(), "SYS_open")) {
+ return syscall3(SYS_open, @ptrToInt(path), flags, perm);
+ } else {
+ return syscall4(
+ SYS_openat,
+ @bitCast(usize, isize(AT_FDCWD)),
+ @ptrToInt(path),
+ flags,
+ perm,
+ );
+ }
}
// TODO https://github.com/ziglang/zig/issues/265
@@ -373,7 +387,7 @@ pub fn unlink(path: [*]const u8) usize {
if (@hasDecl(@This(), "SYS_unlink")) {
return syscall1(SYS_unlink, @ptrToInt(path));
} else {
- return syscall3(SYS_unlinkat, AT_FDCWD, @ptrToInt(path), 0);
+ return syscall3(SYS_unlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), 0);
}
}
@@ -759,18 +773,12 @@ pub fn epoll_create1(flags: usize) usize {
return syscall1(SYS_epoll_create1, flags);
}
-pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
+pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: ?*epoll_event) usize {
return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
}
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
- return syscall4(
- SYS_epoll_wait,
- @bitCast(usize, isize(epoll_fd)),
- @ptrToInt(events),
- maxevents,
- @bitCast(usize, isize(timeout)),
- );
+ return epoll_pwait(epoll_fd, events, maxevents, timeout, null);
}
pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
@@ -818,6 +826,10 @@ pub fn capset(hdrp: *cap_user_header_t, datap: *const cap_user_data_t) usize {
return syscall2(SYS_capset, @ptrToInt(hdrp), @ptrToInt(datap));
}
+pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) usize {
+ return syscall2(SYS_sigaltstack, @ptrToInt(ss), @ptrToInt(old_ss));
+}
+
// XXX: This should be weak
extern const __ehdr_start: elf.Ehdr = undefined;
diff --git a/std/os/linux/test.zig b/std/os/linux/test.zig
index c78b071c74..637308638a 100644
--- a/std/os/linux/test.zig
+++ b/std/os/linux/test.zig
@@ -44,42 +44,3 @@ test "timer" {
// TODO implicit cast from *[N]T to [*]T
err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
}
-
-export fn iter_fn(info: *linux.dl_phdr_info, size: usize, data: ?*usize) i32 {
- var counter = data.?;
- // Count how many libraries are loaded
- counter.* += usize(1);
-
- // The image should contain at least a PT_LOAD segment
- if (info.dlpi_phnum < 1) return -1;
-
- // Quick & dirty validation of the phdr pointers, make sure we're not
- // pointing to some random gibberish
- var i: usize = 0;
- var found_load = false;
- while (i < info.dlpi_phnum) : (i += 1) {
- const phdr = info.dlpi_phdr[i];
-
- if (phdr.p_type != elf.PT_LOAD) continue;
-
- // Find the ELF header
- const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
- // Validate the magic
- if (!mem.eql(u8, elf_header.e_ident[0..], "\x7fELF")) return -1;
- // Consistency check
- if (elf_header.e_phnum != info.dlpi_phnum) return -1;
-
- found_load = true;
- break;
- }
-
- if (!found_load) return -1;
-
- return 42;
-}
-
-test "dl_iterate_phdr" {
- var counter: usize = 0;
- expect(linux.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
- expect(counter != 0);
-}
diff --git a/std/os/linux/x86_64.zig b/std/os/linux/x86_64.zig
index fa866cff4c..82eed0256b 100644
--- a/std/os/linux/x86_64.zig
+++ b/std/os/linux/x86_64.zig
@@ -1,4 +1,4 @@
-use @import("../bits.zig");
+usingnamespace @import("../bits.zig");
pub fn syscall0(number: usize) usize {
return asm volatile ("syscall"
diff --git a/std/os/netbsd.zig b/std/os/netbsd.zig
index 25e72c10a8..cd63e40f5c 100644
--- a/std/os/netbsd.zig
+++ b/std/os/netbsd.zig
@@ -1,4 +1,4 @@
const builtin = @import("builtin");
const std = @import("../std.zig");
pub const is_the_target = builtin.os == .netbsd;
-pub use std.c;
+pub usingnamespace std.c;
diff --git a/std/os/test.zig b/std/os/test.zig
index d4d662e97f..a821c5dd9f 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -5,6 +5,7 @@ const expect = std.testing.expect;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
+const elf = std.elf;
const File = std.fs.File;
const Thread = std.Thread;
@@ -149,3 +150,63 @@ test "realpath" {
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf));
}
+
+test "sigaltstack" {
+ if (builtin.os == .windows or builtin.os == .wasi) return error.SkipZigTest;
+
+ var st: os.stack_t = undefined;
+ try os.sigaltstack(null, &st);
+ // Setting a stack size less than MINSIGSTKSZ returns ENOMEM
+ st.ss_flags = 0;
+ st.ss_size = 1;
+ testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
+}
+
+// If the type is not available use void to avoid erroring out when `iter_fn` is
+// analyzed
+const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
+
+export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
+ if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
+ return 0;
+
+ var counter = data.?;
+ // Count how many libraries are loaded
+ counter.* += usize(1);
+
+ // The image should contain at least a PT_LOAD segment
+ if (info.dlpi_phnum < 1) return -1;
+
+ // Quick & dirty validation of the phdr pointers, make sure we're not
+ // pointing to some random gibberish
+ var i: usize = 0;
+ var found_load = false;
+ while (i < info.dlpi_phnum) : (i += 1) {
+ const phdr = info.dlpi_phdr[i];
+
+ if (phdr.p_type != elf.PT_LOAD) continue;
+
+ // Find the ELF header
+ const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
+ // Validate the magic
+ if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1;
+ // Consistency check
+ if (elf_header.e_phnum != info.dlpi_phnum) return -1;
+
+ found_load = true;
+ break;
+ }
+
+ if (!found_load) return -1;
+
+ return 42;
+}
+
+test "dl_iterate_phdr" {
+ if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
+ return error.SkipZigTest;
+
+ var counter: usize = 0;
+ expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
+ expect(counter != 0);
+}
diff --git a/std/os/uefi.zig b/std/os/uefi.zig
index 8ed60d9c9b..7102938d70 100644
--- a/std/os/uefi.zig
+++ b/std/os/uefi.zig
@@ -1,2 +1,6 @@
// TODO this is where the extern declarations go. For example, see
// inc/efilib.h in gnu-efi-code
+
+const builtin = @import("builtin");
+
+pub const is_the_target = builtin.os == .uefi;
diff --git a/std/os/wasi.zig b/std/os/wasi.zig
index adfe9e821d..57b708395c 100644
--- a/std/os/wasi.zig
+++ b/std/os/wasi.zig
@@ -5,7 +5,7 @@ const std = @import("std");
const assert = std.debug.assert;
pub const is_the_target = builtin.os == .wasi;
-pub use @import("bits.zig");
+pub usingnamespace @import("bits.zig");
comptime {
assert(@alignOf(i8) == 1);
diff --git a/std/os/windows.zig b/std/os/windows.zig
index 526ac1cfd6..1b25f59a55 100644
--- a/std/os/windows.zig
+++ b/std/os/windows.zig
@@ -18,7 +18,7 @@ pub const ntdll = @import("windows/ntdll.zig");
pub const ole32 = @import("windows/ole32.zig");
pub const shell32 = @import("windows/shell32.zig");
-pub use @import("windows/bits.zig");
+pub usingnamespace @import("windows/bits.zig");
pub const CreateFileError = error{
SharingViolation,
@@ -756,11 +756,23 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
return result;
}
+inline fn MAKELANGID(p: c_ushort, s: c_ushort) LANGID {
+ return (s << 10) | p;
+}
+
/// Call this when you made a windows DLL call or something that does SetLastError
/// and you get an unexpected error.
pub fn unexpectedError(err: DWORD) std.os.UnexpectedError {
if (std.os.unexpected_error_tracing) {
- std.debug.warn("unexpected GetLastError(): {}\n", err);
+ // 614 is the length of the longest windows error desciption
+ var buf_u16: [614]u16 = undefined;
+ var buf_u8: [614]u8 = undefined;
+ var len = kernel32.FormatMessageW(
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ null, err, MAKELANGID(LANG.NEUTRAL, SUBLANG.DEFAULT),
+ buf_u16[0..].ptr, buf_u16.len / @sizeOf(TCHAR), null);
+ _ = std.unicode.utf16leToUtf8(&buf_u8, buf_u16[0..len]) catch unreachable;
+ std.debug.warn("error.Unexpected: GetLastError({}): {}\n", err, buf_u8[0..len]);
std.debug.dumpCurrentStackTrace(null);
}
return error.Unexpected;
diff --git a/std/os/windows/advapi32.zig b/std/os/windows/advapi32.zig
index df3220e24c..165a2c10a3 100644
--- a/std/os/windows/advapi32.zig
+++ b/std/os/windows/advapi32.zig
@@ -1,4 +1,4 @@
-use @import("bits.zig");
+usingnamespace @import("bits.zig");
pub extern "advapi32" stdcallcc fn RegOpenKeyExW(
hKey: HKEY,
diff --git a/std/os/windows/bits.zig b/std/os/windows/bits.zig
index 0bf2991903..c99f3ae463 100644
--- a/std/os/windows/bits.zig
+++ b/std/os/windows/bits.zig
@@ -6,6 +6,8 @@ const assert = std.debug.assert;
const maxInt = std.math.maxInt;
pub const ERROR = @import("error.zig");
+pub const LANG = @import("lang.zig");
+pub const SUBLANG = @import("sublang.zig");
/// The standard input device. Initially, this is the console input buffer, CONIN$.
pub const STD_INPUT_HANDLE = maxInt(DWORD) - 10 + 1;
@@ -55,6 +57,10 @@ pub const ULONG = u32;
pub const LONG = i32;
pub const ULONGLONG = u64;
pub const LONGLONG = i64;
+pub const HLOCAL = HANDLE;
+pub const LANGID = c_ushort;
+
+pub const va_list = *@OpaqueType();
pub const TRUE = 1;
pub const FALSE = 0;
@@ -525,3 +531,11 @@ pub const COINIT = extern enum {
/// > this expansion applies to the total length.
/// from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
pub const PATH_MAX_WIDE = 32767;
+
+pub const FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
+pub const FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
+pub const FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
+pub const FORMAT_MESSAGE_FROM_STRING = 0x00000400;
+pub const FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+pub const FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+pub const FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF;
diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig
index 2bd1824620..27516342ac 100644
--- a/std/os/windows/kernel32.zig
+++ b/std/os/windows/kernel32.zig
@@ -1,4 +1,4 @@
-use @import("bits.zig");
+usingnamespace @import("bits.zig");
pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
@@ -50,6 +50,8 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
+pub extern "kernel32" stdcallcc fn FormatMessageW(dwFlags: DWORD, lpSource: ?LPVOID, dwMessageId: DWORD, dwLanguageId: DWORD, lpBuffer: LPWSTR, nSize: DWORD, Arguments: ?*va_list) DWORD;
+
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
diff --git a/std/os/windows/lang.zig b/std/os/windows/lang.zig
new file mode 100644
index 0000000000..b173a62a73
--- /dev/null
+++ b/std/os/windows/lang.zig
@@ -0,0 +1,140 @@
+pub const NEUTRAL = 0x00;
+pub const INVARIANT = 0x7f;
+pub const AFRIKAANS = 0x36;
+pub const ALBANIAN = 0x1c;
+pub const ALSATIAN = 0x84;
+pub const AMHARIC = 0x5e;
+pub const ARABIC = 0x01;
+pub const ARMENIAN = 0x2b;
+pub const ASSAMESE = 0x4d;
+pub const AZERI = 0x2c;
+pub const AZERBAIJANI = 0x2c;
+pub const BANGLA = 0x45;
+pub const BASHKIR = 0x6d;
+pub const BASQUE = 0x2d;
+pub const BELARUSIAN = 0x23;
+pub const BENGALI = 0x45;
+pub const BRETON = 0x7e;
+pub const BOSNIAN = 0x1a;
+pub const BOSNIAN_NEUTRAL = 0x781a;
+pub const BULGARIAN = 0x02;
+pub const CATALAN = 0x03;
+pub const CENTRAL_KURDISH = 0x92;
+pub const CHEROKEE = 0x5c;
+pub const CHINESE = 0x04;
+pub const CHINESE_SIMPLIFIED = 0x04;
+pub const CHINESE_TRADITIONAL = 0x7c04;
+pub const CORSICAN = 0x83;
+pub const CROATIAN = 0x1a;
+pub const CZECH = 0x05;
+pub const DANISH = 0x06;
+pub const DARI = 0x8c;
+pub const DIVEHI = 0x65;
+pub const DUTCH = 0x13;
+pub const ENGLISH = 0x09;
+pub const ESTONIAN = 0x25;
+pub const FAEROESE = 0x38;
+pub const FARSI = 0x29;
+pub const FILIPINO = 0x64;
+pub const FINNISH = 0x0b;
+pub const FRENCH = 0x0c;
+pub const FRISIAN = 0x62;
+pub const FULAH = 0x67;
+pub const GALICIAN = 0x56;
+pub const GEORGIAN = 0x37;
+pub const GERMAN = 0x07;
+pub const GREEK = 0x08;
+pub const GREENLANDIC = 0x6f;
+pub const GUJARATI = 0x47;
+pub const HAUSA = 0x68;
+pub const HAWAIIAN = 0x75;
+pub const HEBREW = 0x0d;
+pub const HINDI = 0x39;
+pub const HUNGARIAN = 0x0e;
+pub const ICELANDIC = 0x0f;
+pub const IGBO = 0x70;
+pub const INDONESIAN = 0x21;
+pub const INUKTITUT = 0x5d;
+pub const IRISH = 0x3c;
+pub const ITALIAN = 0x10;
+pub const JAPANESE = 0x11;
+pub const KANNADA = 0x4b;
+pub const KASHMIRI = 0x60;
+pub const KAZAK = 0x3f;
+pub const KHMER = 0x53;
+pub const KICHE = 0x86;
+pub const KINYARWANDA = 0x87;
+pub const KONKANI = 0x57;
+pub const KOREAN = 0x12;
+pub const KYRGYZ = 0x40;
+pub const LAO = 0x54;
+pub const LATVIAN = 0x26;
+pub const LITHUANIAN = 0x27;
+pub const LOWER_SORBIAN = 0x2e;
+pub const LUXEMBOURGISH = 0x6e;
+pub const MACEDONIAN = 0x2f;
+pub const MALAY = 0x3e;
+pub const MALAYALAM = 0x4c;
+pub const MALTESE = 0x3a;
+pub const MANIPURI = 0x58;
+pub const MAORI = 0x81;
+pub const MAPUDUNGUN = 0x7a;
+pub const MARATHI = 0x4e;
+pub const MOHAWK = 0x7c;
+pub const MONGOLIAN = 0x50;
+pub const NEPALI = 0x61;
+pub const NORWEGIAN = 0x14;
+pub const OCCITAN = 0x82;
+pub const ODIA = 0x48;
+pub const ORIYA = 0x48;
+pub const PASHTO = 0x63;
+pub const PERSIAN = 0x29;
+pub const POLISH = 0x15;
+pub const PORTUGUESE = 0x16;
+pub const PULAR = 0x67;
+pub const PUNJABI = 0x46;
+pub const QUECHUA = 0x6b;
+pub const ROMANIAN = 0x18;
+pub const ROMANSH = 0x17;
+pub const RUSSIAN = 0x19;
+pub const SAKHA = 0x85;
+pub const SAMI = 0x3b;
+pub const SANSKRIT = 0x4f;
+pub const SCOTTISH_GAELIC = 0x91;
+pub const SERBIAN = 0x1a;
+pub const SERBIAN_NEUTRAL = 0x7c1a;
+pub const SINDHI = 0x59;
+pub const SINHALESE = 0x5b;
+pub const SLOVAK = 0x1b;
+pub const SLOVENIAN = 0x24;
+pub const SOTHO = 0x6c;
+pub const SPANISH = 0x0a;
+pub const SWAHILI = 0x41;
+pub const SWEDISH = 0x1d;
+pub const SYRIAC = 0x5a;
+pub const TAJIK = 0x28;
+pub const TAMAZIGHT = 0x5f;
+pub const TAMIL = 0x49;
+pub const TATAR = 0x44;
+pub const TELUGU = 0x4a;
+pub const THAI = 0x1e;
+pub const TIBETAN = 0x51;
+pub const TIGRIGNA = 0x73;
+pub const TIGRINYA = 0x73;
+pub const TSWANA = 0x32;
+pub const TURKISH = 0x1f;
+pub const TURKMEN = 0x42;
+pub const UIGHUR = 0x80;
+pub const UKRAINIAN = 0x22;
+pub const UPPER_SORBIAN = 0x2e;
+pub const URDU = 0x20;
+pub const UZBEK = 0x43;
+pub const VALENCIAN = 0x03;
+pub const VIETNAMESE = 0x2a;
+pub const WELSH = 0x52;
+pub const WOLOF = 0x88;
+pub const XHOSA = 0x34;
+pub const YAKUT = 0x85;
+pub const YI = 0x78;
+pub const YORUBA = 0x6a;
+pub const ZULU = 0x35;
diff --git a/std/os/windows/ntdll.zig b/std/os/windows/ntdll.zig
index 60c03ffc07..e5469cdcf9 100644
--- a/std/os/windows/ntdll.zig
+++ b/std/os/windows/ntdll.zig
@@ -1,3 +1,3 @@
-use @import("bits.zig");
+usingnamespace @import("bits.zig");
pub extern "NtDll" stdcallcc fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) WORD;
diff --git a/std/os/windows/ole32.zig b/std/os/windows/ole32.zig
index 80f5bebc36..39c12d074c 100644
--- a/std/os/windows/ole32.zig
+++ b/std/os/windows/ole32.zig
@@ -1,4 +1,4 @@
-use @import("bits.zig");
+usingnamespace @import("bits.zig");
pub extern "ole32" stdcallcc fn CoTaskMemFree(pv: LPVOID) void;
pub extern "ole32" stdcallcc fn CoUninitialize() void;
diff --git a/std/os/windows/shell32.zig b/std/os/windows/shell32.zig
index 9f24acc5c4..c178997aad 100644
--- a/std/os/windows/shell32.zig
+++ b/std/os/windows/shell32.zig
@@ -1,3 +1,3 @@
-use @import("bits.zig");
+usingnamespace @import("bits.zig");
pub extern "shell32" stdcallcc fn SHGetKnownFolderPath(rfid: *const KNOWNFOLDERID, dwFlags: DWORD, hToken: ?HANDLE, ppszPath: *[*]WCHAR) HRESULT;
diff --git a/std/os/windows/sublang.zig b/std/os/windows/sublang.zig
new file mode 100644
index 0000000000..e9929c6d79
--- /dev/null
+++ b/std/os/windows/sublang.zig
@@ -0,0 +1,244 @@
+pub const NEUTRAL = 0x00;
+pub const DEFAULT = 0x01;
+pub const SYS_DEFAULT = 0x02;
+pub const CUSTOM_DEFAULT = 0x03;
+pub const CUSTOM_UNSPECIFIED = 0x04;
+pub const UI_CUSTOM_DEFAULT = 0x05;
+pub const AFRIKAANS_SOUTH_AFRICA = 0x01;
+pub const ALBANIAN_ALBANIA = 0x01;
+pub const ALSATIAN_FRANCE = 0x01;
+pub const AMHARIC_ETHIOPIA = 0x01;
+pub const ARABIC_SAUDI_ARABIA = 0x01;
+pub const ARABIC_IRAQ = 0x02;
+pub const ARABIC_EGYPT = 0x03;
+pub const ARABIC_LIBYA = 0x04;
+pub const ARABIC_ALGERIA = 0x05;
+pub const ARABIC_MOROCCO = 0x06;
+pub const ARABIC_TUNISIA = 0x07;
+pub const ARABIC_OMAN = 0x08;
+pub const ARABIC_YEMEN = 0x09;
+pub const ARABIC_SYRIA = 0x0a;
+pub const ARABIC_JORDAN = 0x0b;
+pub const ARABIC_LEBANON = 0x0c;
+pub const ARABIC_KUWAIT = 0x0d;
+pub const ARABIC_UAE = 0x0e;
+pub const ARABIC_BAHRAIN = 0x0f;
+pub const ARABIC_QATAR = 0x10;
+pub const ARMENIAN_ARMENIA = 0x01;
+pub const ASSAMESE_INDIA = 0x01;
+pub const AZERI_LATIN = 0x01;
+pub const AZERI_CYRILLIC = 0x02;
+pub const AZERBAIJANI_AZERBAIJAN_LATIN = 0x01;
+pub const AZERBAIJANI_AZERBAIJAN_CYRILLIC = 0x02;
+pub const BANGLA_INDIA = 0x01;
+pub const BANGLA_BANGLADESH = 0x02;
+pub const BASHKIR_RUSSIA = 0x01;
+pub const BASQUE_BASQUE = 0x01;
+pub const BELARUSIAN_BELARUS = 0x01;
+pub const BENGALI_INDIA = 0x01;
+pub const BENGALI_BANGLADESH = 0x02;
+pub const BOSNIAN_BOSNIA_HERZEGOVINA_LATIN = 0x05;
+pub const BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC = 0x08;
+pub const BRETON_FRANCE = 0x01;
+pub const BULGARIAN_BULGARIA = 0x01;
+pub const CATALAN_CATALAN = 0x01;
+pub const CENTRAL_KURDISH_IRAQ = 0x01;
+pub const CHEROKEE_CHEROKEE = 0x01;
+pub const CHINESE_TRADITIONAL = 0x01;
+pub const CHINESE_SIMPLIFIED = 0x02;
+pub const CHINESE_HONGKONG = 0x03;
+pub const CHINESE_SINGAPORE = 0x04;
+pub const CHINESE_MACAU = 0x05;
+pub const CORSICAN_FRANCE = 0x01;
+pub const CZECH_CZECH_REPUBLIC = 0x01;
+pub const CROATIAN_CROATIA = 0x01;
+pub const CROATIAN_BOSNIA_HERZEGOVINA_LATIN = 0x04;
+pub const DANISH_DENMARK = 0x01;
+pub const DARI_AFGHANISTAN = 0x01;
+pub const DIVEHI_MALDIVES = 0x01;
+pub const DUTCH = 0x01;
+pub const DUTCH_BELGIAN = 0x02;
+pub const ENGLISH_US = 0x01;
+pub const ENGLISH_UK = 0x02;
+pub const ENGLISH_AUS = 0x03;
+pub const ENGLISH_CAN = 0x04;
+pub const ENGLISH_NZ = 0x05;
+pub const ENGLISH_EIRE = 0x06;
+pub const ENGLISH_SOUTH_AFRICA = 0x07;
+pub const ENGLISH_JAMAICA = 0x08;
+pub const ENGLISH_CARIBBEAN = 0x09;
+pub const ENGLISH_BELIZE = 0x0a;
+pub const ENGLISH_TRINIDAD = 0x0b;
+pub const ENGLISH_ZIMBABWE = 0x0c;
+pub const ENGLISH_PHILIPPINES = 0x0d;
+pub const ENGLISH_INDIA = 0x10;
+pub const ENGLISH_MALAYSIA = 0x11;
+pub const ENGLISH_SINGAPORE = 0x12;
+pub const ESTONIAN_ESTONIA = 0x01;
+pub const FAEROESE_FAROE_ISLANDS = 0x01;
+pub const FILIPINO_PHILIPPINES = 0x01;
+pub const FINNISH_FINLAND = 0x01;
+pub const FRENCH = 0x01;
+pub const FRENCH_BELGIAN = 0x02;
+pub const FRENCH_CANADIAN = 0x03;
+pub const FRENCH_SWISS = 0x04;
+pub const FRENCH_LUXEMBOURG = 0x05;
+pub const FRENCH_MONACO = 0x06;
+pub const FRISIAN_NETHERLANDS = 0x01;
+pub const FULAH_SENEGAL = 0x02;
+pub const GALICIAN_GALICIAN = 0x01;
+pub const GEORGIAN_GEORGIA = 0x01;
+pub const GERMAN = 0x01;
+pub const GERMAN_SWISS = 0x02;
+pub const GERMAN_AUSTRIAN = 0x03;
+pub const GERMAN_LUXEMBOURG = 0x04;
+pub const GERMAN_LIECHTENSTEIN = 0x05;
+pub const GREEK_GREECE = 0x01;
+pub const GREENLANDIC_GREENLAND = 0x01;
+pub const GUJARATI_INDIA = 0x01;
+pub const HAUSA_NIGERIA_LATIN = 0x01;
+pub const HAWAIIAN_US = 0x01;
+pub const HEBREW_ISRAEL = 0x01;
+pub const HINDI_INDIA = 0x01;
+pub const HUNGARIAN_HUNGARY = 0x01;
+pub const ICELANDIC_ICELAND = 0x01;
+pub const IGBO_NIGERIA = 0x01;
+pub const INDONESIAN_INDONESIA = 0x01;
+pub const INUKTITUT_CANADA = 0x01;
+pub const INUKTITUT_CANADA_LATIN = 0x02;
+pub const IRISH_IRELAND = 0x02;
+pub const ITALIAN = 0x01;
+pub const ITALIAN_SWISS = 0x02;
+pub const JAPANESE_JAPAN = 0x01;
+pub const KANNADA_INDIA = 0x01;
+pub const KASHMIRI_SASIA = 0x02;
+pub const KASHMIRI_INDIA = 0x02;
+pub const KAZAK_KAZAKHSTAN = 0x01;
+pub const KHMER_CAMBODIA = 0x01;
+pub const KICHE_GUATEMALA = 0x01;
+pub const KINYARWANDA_RWANDA = 0x01;
+pub const KONKANI_INDIA = 0x01;
+pub const KOREAN = 0x01;
+pub const KYRGYZ_KYRGYZSTAN = 0x01;
+pub const LAO_LAO = 0x01;
+pub const LATVIAN_LATVIA = 0x01;
+pub const LITHUANIAN = 0x01;
+pub const LOWER_SORBIAN_GERMANY = 0x02;
+pub const LUXEMBOURGISH_LUXEMBOURG = 0x01;
+pub const MACEDONIAN_MACEDONIA = 0x01;
+pub const MALAY_MALAYSIA = 0x01;
+pub const MALAY_BRUNEI_DARUSSALAM = 0x02;
+pub const MALAYALAM_INDIA = 0x01;
+pub const MALTESE_MALTA = 0x01;
+pub const MAORI_NEW_ZEALAND = 0x01;
+pub const MAPUDUNGUN_CHILE = 0x01;
+pub const MARATHI_INDIA = 0x01;
+pub const MOHAWK_MOHAWK = 0x01;
+pub const MONGOLIAN_CYRILLIC_MONGOLIA = 0x01;
+pub const MONGOLIAN_PRC = 0x02;
+pub const NEPALI_INDIA = 0x02;
+pub const NEPALI_NEPAL = 0x01;
+pub const NORWEGIAN_BOKMAL = 0x01;
+pub const NORWEGIAN_NYNORSK = 0x02;
+pub const OCCITAN_FRANCE = 0x01;
+pub const ODIA_INDIA = 0x01;
+pub const ORIYA_INDIA = 0x01;
+pub const PASHTO_AFGHANISTAN = 0x01;
+pub const PERSIAN_IRAN = 0x01;
+pub const POLISH_POLAND = 0x01;
+pub const PORTUGUESE = 0x02;
+pub const PORTUGUESE_BRAZILIAN = 0x01;
+pub const PULAR_SENEGAL = 0x02;
+pub const PUNJABI_INDIA = 0x01;
+pub const PUNJABI_PAKISTAN = 0x02;
+pub const QUECHUA_BOLIVIA = 0x01;
+pub const QUECHUA_ECUADOR = 0x02;
+pub const QUECHUA_PERU = 0x03;
+pub const ROMANIAN_ROMANIA = 0x01;
+pub const ROMANSH_SWITZERLAND = 0x01;
+pub const RUSSIAN_RUSSIA = 0x01;
+pub const SAKHA_RUSSIA = 0x01;
+pub const SAMI_NORTHERN_NORWAY = 0x01;
+pub const SAMI_NORTHERN_SWEDEN = 0x02;
+pub const SAMI_NORTHERN_FINLAND = 0x03;
+pub const SAMI_LULE_NORWAY = 0x04;
+pub const SAMI_LULE_SWEDEN = 0x05;
+pub const SAMI_SOUTHERN_NORWAY = 0x06;
+pub const SAMI_SOUTHERN_SWEDEN = 0x07;
+pub const SAMI_SKOLT_FINLAND = 0x08;
+pub const SAMI_INARI_FINLAND = 0x09;
+pub const SANSKRIT_INDIA = 0x01;
+pub const SCOTTISH_GAELIC = 0x01;
+pub const SERBIAN_BOSNIA_HERZEGOVINA_LATIN = 0x06;
+pub const SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC = 0x07;
+pub const SERBIAN_MONTENEGRO_LATIN = 0x0b;
+pub const SERBIAN_MONTENEGRO_CYRILLIC = 0x0c;
+pub const SERBIAN_SERBIA_LATIN = 0x09;
+pub const SERBIAN_SERBIA_CYRILLIC = 0x0a;
+pub const SERBIAN_CROATIA = 0x01;
+pub const SERBIAN_LATIN = 0x02;
+pub const SERBIAN_CYRILLIC = 0x03;
+pub const SINDHI_INDIA = 0x01;
+pub const SINDHI_PAKISTAN = 0x02;
+pub const SINDHI_AFGHANISTAN = 0x02;
+pub const SINHALESE_SRI_LANKA = 0x01;
+pub const SOTHO_NORTHERN_SOUTH_AFRICA = 0x01;
+pub const SLOVAK_SLOVAKIA = 0x01;
+pub const SLOVENIAN_SLOVENIA = 0x01;
+pub const SPANISH = 0x01;
+pub const SPANISH_MEXICAN = 0x02;
+pub const SPANISH_MODERN = 0x03;
+pub const SPANISH_GUATEMALA = 0x04;
+pub const SPANISH_COSTA_RICA = 0x05;
+pub const SPANISH_PANAMA = 0x06;
+pub const SPANISH_DOMINICAN_REPUBLIC = 0x07;
+pub const SPANISH_VENEZUELA = 0x08;
+pub const SPANISH_COLOMBIA = 0x09;
+pub const SPANISH_PERU = 0x0a;
+pub const SPANISH_ARGENTINA = 0x0b;
+pub const SPANISH_ECUADOR = 0x0c;
+pub const SPANISH_CHILE = 0x0d;
+pub const SPANISH_URUGUAY = 0x0e;
+pub const SPANISH_PARAGUAY = 0x0f;
+pub const SPANISH_BOLIVIA = 0x10;
+pub const SPANISH_EL_SALVADOR = 0x11;
+pub const SPANISH_HONDURAS = 0x12;
+pub const SPANISH_NICARAGUA = 0x13;
+pub const SPANISH_PUERTO_RICO = 0x14;
+pub const SPANISH_US = 0x15;
+pub const SWAHILI_KENYA = 0x01;
+pub const SWEDISH = 0x01;
+pub const SWEDISH_FINLAND = 0x02;
+pub const SYRIAC_SYRIA = 0x01;
+pub const TAJIK_TAJIKISTAN = 0x01;
+pub const TAMAZIGHT_ALGERIA_LATIN = 0x02;
+pub const TAMAZIGHT_MOROCCO_TIFINAGH = 0x04;
+pub const TAMIL_INDIA = 0x01;
+pub const TAMIL_SRI_LANKA = 0x02;
+pub const TATAR_RUSSIA = 0x01;
+pub const TELUGU_INDIA = 0x01;
+pub const THAI_THAILAND = 0x01;
+pub const TIBETAN_PRC = 0x01;
+pub const TIGRIGNA_ERITREA = 0x02;
+pub const TIGRINYA_ERITREA = 0x02;
+pub const TIGRINYA_ETHIOPIA = 0x01;
+pub const TSWANA_BOTSWANA = 0x02;
+pub const TSWANA_SOUTH_AFRICA = 0x01;
+pub const TURKISH_TURKEY = 0x01;
+pub const TURKMEN_TURKMENISTAN = 0x01;
+pub const UIGHUR_PRC = 0x01;
+pub const UKRAINIAN_UKRAINE = 0x01;
+pub const UPPER_SORBIAN_GERMANY = 0x01;
+pub const URDU_PAKISTAN = 0x01;
+pub const URDU_INDIA = 0x02;
+pub const UZBEK_LATIN = 0x01;
+pub const UZBEK_CYRILLIC = 0x02;
+pub const VALENCIAN_VALENCIA = 0x02;
+pub const VIETNAMESE_VIETNAM = 0x01;
+pub const WELSH_UNITED_KINGDOM = 0x01;
+pub const WOLOF_SENEGAL = 0x01;
+pub const XHOSA_SOUTH_AFRICA = 0x01;
+pub const YAKUT_RUSSIA = 0x01;
+pub const YI_PRC = 0x01;
+pub const YORUBA_NIGERIA = 0x01;
+pub const ZULU_SOUTH_AFRICA = 0x01;
diff --git a/std/os/zen.zig b/std/os/zen.zig
index 8d2f963486..727f55fa6d 100644
--- a/std/os/zen.zig
+++ b/std/os/zen.zig
@@ -80,7 +80,7 @@ pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;
// FIXME: let's borrow Linux's error numbers for now.
-use @import("bits/linux/errno.zig");
+usingnamespace @import("bits/linux/errno.zig");
// Get the errno from a syscall return value, or 0 for no error.
pub fn getErrno(r: usize) usize {
const signed_r = @bitCast(isize, r);
diff --git a/std/special/c.zig b/std/special/c.zig
index 08789c920f..456070f609 100644
--- a/std/special/c.zig
+++ b/std/special/c.zig
@@ -20,6 +20,12 @@ comptime {
if (is_freestanding and is_wasm and builtin.link_libc) {
@export("_start", wasm_start, .Strong);
}
+ if (builtin.link_libc) {
+ @export("strcmp", strcmp, .Strong);
+ @export("strncmp", strncmp, .Strong);
+ @export("strerror", strerror, .Strong);
+ @export("strlen", strlen, .Strong);
+ }
}
extern fn main(argc: c_int, argv: [*][*]u8) c_int;
@@ -27,6 +33,38 @@ extern fn wasm_start() void {
_ = main(0, undefined);
}
+extern fn strcmp(s1: [*]const u8, s2: [*]const u8) c_int {
+ return std.cstr.cmp(s1, s2);
+}
+
+extern fn strlen(s: [*]const u8) usize {
+ return std.mem.len(u8, s);
+}
+
+extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {
+ if (_n == 0) return 0;
+ var l = _l;
+ var r = _r;
+ var n = _n - 1;
+ while (l[0] != 0 and r[0] != 0 and n != 0 and l[0] == r[0]) {
+ l += 1;
+ r += 1;
+ n -= 1;
+ }
+ return c_int(l[0]) - c_int(r[0]);
+}
+
+extern fn strerror(errnum: c_int) [*]const u8 {
+ return c"TODO strerror implementation";
+}
+
+test "strncmp" {
+ std.testing.expect(strncmp(c"a", c"b", 1) == -1);
+ std.testing.expect(strncmp(c"a", c"c", 1) == -2);
+ std.testing.expect(strncmp(c"b", c"a", 1) == 1);
+ std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253);
+}
+
// Avoid dragging in the runtime safety mechanisms into this .o file,
// unless we're trying to test this file.
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
@@ -98,8 +136,32 @@ test "test_memcmp" {
const arr3 = []u8{ 1, 2, 1 };
std.testing.expect(memcmp(base_arr[0..].ptr, arr1[0..].ptr, base_arr.len) == 0);
- std.testing.expect(memcmp(base_arr[0..].ptr, arr2[0..].ptr, base_arr.len) == 1);
- std.testing.expect(memcmp(base_arr[0..].ptr, arr3[0..].ptr, base_arr.len) == -1);
+ std.testing.expect(memcmp(base_arr[0..].ptr, arr2[0..].ptr, base_arr.len) > 0);
+ std.testing.expect(memcmp(base_arr[0..].ptr, arr3[0..].ptr, base_arr.len) < 0);
+}
+
+export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) isize {
+ @setRuntimeSafety(false);
+
+ var index: usize = 0;
+ while (index != n) : (index += 1) {
+ if (vl[index] != vr[index]) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+test "test_bcmp" {
+ const base_arr = []u8{ 1, 1, 1 };
+ const arr1 = []u8{ 1, 1, 1 };
+ const arr2 = []u8{ 1, 0, 1 };
+ const arr3 = []u8{ 1, 2, 1 };
+
+ std.testing.expect(bcmp(base_arr[0..].ptr, arr1[0..].ptr, base_arr.len) == 0);
+ std.testing.expect(bcmp(base_arr[0..].ptr, arr2[0..].ptr, base_arr.len) != 0);
+ std.testing.expect(bcmp(base_arr[0..].ptr, arr3[0..].ptr, base_arr.len) != 0);
}
comptime {
diff --git a/std/thread.zig b/std/thread.zig
index 49b2decb09..abf2f1cae1 100644
--- a/std/thread.zig
+++ b/std/thread.zig
@@ -223,15 +223,17 @@ pub const Thread = struct {
}
};
- const MAP_GROWSDOWN = if (os.linux.is_the_target) os.linux.MAP_GROWSDOWN else 0;
-
+ var guard_end_offset: usize = undefined;
var stack_end_offset: usize = undefined;
var thread_start_offset: usize = undefined;
var context_start_offset: usize = undefined;
var tls_start_offset: usize = undefined;
const mmap_len = blk: {
- // First in memory will be the stack, which grows downwards.
- var l: usize = mem.alignForward(default_stack_size, mem.page_size);
+ var l: usize = mem.page_size;
+ // Allocate a guard page right after the end of the stack region
+ guard_end_offset = l;
+ // The stack itself, which grows downwards.
+ l = mem.alignForward(l + default_stack_size, mem.page_size);
stack_end_offset = l;
// Above the stack, so that it can be in the same mmap call, put the Thread object.
l = mem.alignForward(l, @alignOf(Thread));
@@ -253,20 +255,32 @@ pub const Thread = struct {
}
break :blk l;
};
+ // Map the whole stack with no rw permissions to avoid committing the
+ // whole region right away
const mmap_slice = os.mmap(
null,
mem.alignForward(mmap_len, mem.page_size),
- os.PROT_READ | os.PROT_WRITE,
- os.MAP_PRIVATE | os.MAP_ANONYMOUS | MAP_GROWSDOWN,
+ os.PROT_NONE,
+ os.MAP_PRIVATE | os.MAP_ANONYMOUS,
-1,
0,
) catch |err| switch (err) {
- error.MemoryMappingNotSupported => unreachable, // no file descriptor
- error.AccessDenied => unreachable, // no file descriptor
- error.PermissionDenied => unreachable, // no file descriptor
+ error.MemoryMappingNotSupported => unreachable,
+ error.AccessDenied => unreachable,
+ error.PermissionDenied => unreachable,
else => |e| return e,
};
errdefer os.munmap(mmap_slice);
+
+ // Map everything but the guard page as rw
+ os.mprotect(
+ mmap_slice,
+ os.PROT_READ | os.PROT_WRITE,
+ ) catch |err| switch (err) {
+ error.AccessDenied => unreachable,
+ else => |e| return e,
+ };
+
const mmap_addr = @ptrToInt(mmap_slice.ptr);
const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 12a28bf657..7a8287db0c 100644
--- a/std/zig/parse.zig
+++ b/std/zig/parse.zig
@@ -203,7 +203,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*
/// TopLevelDecl
/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
/// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
-/// / KEYWORD_use Expr SEMICOLON
+/// / KEYWORD_usingnamespace Expr SEMICOLON
fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
var lib_name: ?*Node = null;
const extern_export_inline_token = blk: {
@@ -1026,7 +1026,7 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
else_node.* = Node.Else{
.base = Node{ .id = .Else },
.else_token = else_token,
- .payload = null,
+ .payload = payload,
.body = body,
};
@@ -2809,7 +2809,7 @@ fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
}
fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
- const token = eatToken(it, .Keyword_use) orelse return null;
+ const token = eatToken(it, .Keyword_usingnamespace) orelse return null;
const node = try arena.create(Node.Use);
node.* = Node.Use{
.base = Node{ .id = .Use },
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 9165c9bbe8..281f09d57b 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1,3 +1,42 @@
+// TODO remove `use` keyword eventually
+test "zig fmt: change use to usingnamespace" {
+ try testTransform(
+ \\use @import("std");
+ ,
+ \\usingnamespace @import("std");
+ \\
+ );
+}
+
+test "zig fmt: while else err prong with no block" {
+ try testCanonical(
+ \\test "" {
+ \\ const result = while (returnError()) |value| {
+ \\ break value;
+ \\ } else |err| i32(2);
+ \\ expect(result == 2);
+ \\}
+ \\
+ );
+}
+
+test "zig fmt: tagged union with enum values" {
+ try testCanonical(
+ \\const MultipleChoice2 = union(enum(u32)) {
+ \\ Unspecified1: i32,
+ \\ A: f32 = 20,
+ \\ Unspecified2: void,
+ \\ B: bool = 40,
+ \\ Unspecified3: i32,
+ \\ C: i8 = 60,
+ \\ Unspecified4: void,
+ \\ D: void = 1000,
+ \\ Unspecified5: i32,
+ \\};
+ \\
+ );
+}
+
test "zig fmt: allowzero pointer" {
try testCanonical(
\\const T = [*]allowzero const u8;
@@ -2090,8 +2129,8 @@ test "zig fmt: Block after if" {
test "zig fmt: use" {
try testCanonical(
- \\use @import("std");
- \\pub use @import("std");
+ \\usingnamespace @import("std");
+ \\pub usingnamespace @import("std");
\\
);
}
@@ -2170,6 +2209,31 @@ test "zig fmt: inline asm parameter alignment" {
);
}
+test "zig fmt: multiline string in array" {
+ try testCanonical(
+ \\const Foo = [][]const u8{
+ \\ \\aaa
+ \\,
+ \\ \\bbb
+ \\};
+ \\
+ \\fn bar() void {
+ \\ const Foo = [][]const u8{
+ \\ \\aaa
+ \\ ,
+ \\ \\bbb
+ \\ };
+ \\ const Bar = [][]const u8{ // comment here
+ \\ \\aaa
+ \\ \\
+ \\ , // and another comment can go here
+ \\ \\bbb
+ \\ };
+ \\}
+ \\
+ );
+}
+
const std = @import("std");
const mem = std.mem;
const warn = std.debug.warn;
diff --git a/std/zig/render.zig b/std/zig/render.zig
index dc879ee49f..ef5c8f2346 100644
--- a/std/zig/render.zig
+++ b/std/zig/render.zig
@@ -168,7 +168,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
if (use_decl.visib_token) |visib_token| {
try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
}
- try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use
+ // TODO after depracating use, go back to this:
+ //try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // usingnamespace
+ try stream.write("usingnamespace ");
try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);
try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;
},
@@ -212,7 +214,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Space); // type
- try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
+ try renderToken(tree, stream, tree.nextToken(field.type_expr.?.lastToken()), indent, start_col, Space.Space); // =
return renderExpression(allocator, stream, tree, indent, start_col, field.value_expr.?, Space.Comma); // value,
}
},
@@ -724,9 +726,15 @@ fn renderExpression(
expr_widths[i] = width;
}
- const new_indent = indent + indent_delta;
- try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
- try stream.writeByteNTimes(' ', new_indent);
+ var new_indent = indent + indent_delta;
+
+ if (tree.tokens.at(tree.nextToken(lbrace)).id != Token.Id.MultilineStringLiteralLine) {
+ try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
+ try stream.writeByteNTimes(' ', new_indent);
+ } else {
+ new_indent -= indent_delta;
+ try renderToken(tree, stream, lbrace, new_indent, start_col, Space.None);
+ }
it.set(0);
i = 0;
@@ -748,15 +756,24 @@ fn renderExpression(
}
col = 1;
- try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
+ if (tree.tokens.at(tree.nextToken(comma)).id != Token.Id.MultilineStringLiteralLine) {
+ try renderToken(tree, stream, comma, new_indent, start_col, Space.Newline); // ,
+ } else {
+ try renderToken(tree, stream, comma, new_indent, start_col, Space.None); // ,
+ }
try renderExtraNewline(tree, stream, start_col, next_expr.*);
- try stream.writeByteNTimes(' ', new_indent);
+ if (next_expr.*.id != ast.Node.Id.MultilineStringLiteral) {
+ try stream.writeByteNTimes(' ', new_indent);
+ }
} else {
try renderExpression(allocator, stream, tree, new_indent, start_col, expr.*, Space.Comma); // ,
}
}
- try stream.writeByteNTimes(' ', indent);
+ const last_node = it.prev().?;
+ if (last_node.*.id != ast.Node.Id.MultilineStringLiteral) {
+ try stream.writeByteNTimes(' ', indent);
+ }
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
} else {
try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
@@ -1037,6 +1054,8 @@ fn renderExpression(
},
ast.Node.Id.MultilineStringLiteral => {
+ // TODO: Don't indent in this function, but let the caller indent.
+ // If this has been implemented, a lot of hacky solutions in i.e. ArrayInit and FunctionCall can be removed
const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
var skip_first_indent = true;
diff --git a/std/zig/tokenizer.zig b/std/zig/tokenizer.zig
index 2ace430a15..9a59d8ab08 100644
--- a/std/zig/tokenizer.zig
+++ b/std/zig/tokenizer.zig
@@ -59,7 +59,8 @@ pub const Token = struct {
Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined },
Keyword{ .bytes = "union", .id = Id.Keyword_union },
Keyword{ .bytes = "unreachable", .id = Id.Keyword_unreachable },
- Keyword{ .bytes = "use", .id = Id.Keyword_use },
+ Keyword{ .bytes = "use", .id = Id.Keyword_usingnamespace },
+ Keyword{ .bytes = "usingnamespace", .id = Id.Keyword_usingnamespace },
Keyword{ .bytes = "var", .id = Id.Keyword_var },
Keyword{ .bytes = "volatile", .id = Id.Keyword_volatile },
Keyword{ .bytes = "while", .id = Id.Keyword_while },
@@ -190,7 +191,7 @@ pub const Token = struct {
Keyword_undefined,
Keyword_union,
Keyword_unreachable,
- Keyword_use,
+ Keyword_usingnamespace,
Keyword_var,
Keyword_volatile,
Keyword_while,
diff --git a/test/build_examples.zig b/test/build_examples.zig
index c75c38b138..d38336939d 100644
--- a/test/build_examples.zig
+++ b/test/build_examples.zig
@@ -17,9 +17,7 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
cases.addBuildFile("test/standalone/use_alias/build.zig");
cases.addBuildFile("test/standalone/brace_expansion/build.zig");
cases.addBuildFile("test/standalone/empty_env/build.zig");
- if (false) {
- // TODO this test is disabled because it is failing on the CI server's linux. when this is fixed
- // enable it for at least linux
+ if (builtin.os == builtin.Os.linux) {
// TODO hook up the DynLib API for windows using LoadLibraryA
// TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it
cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index d151b31343..7ee5896568 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -2,6 +2,38 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "compile error in struct init expression",
+ \\const Foo = struct {
+ \\ a: i32 = crap,
+ \\ b: i32,
+ \\};
+ \\export fn entry() void {
+ \\ var x = Foo{
+ \\ .b = 5,
+ \\ };
+ \\}
+ ,
+ "tmp.zig:2:14: error: use of undeclared identifier 'crap'",
+ );
+
+ cases.add(
+ "undefined as field type is rejected",
+ \\const Foo = struct {
+ \\ a: undefined,
+ \\};
+ \\const Bar = union {
+ \\ a: undefined,
+ \\};
+ \\pub fn main() void {
+ \\ const foo: Foo = undefined;
+ \\ const bar: Bar = undefined;
+ \\}
+ ,
+ "tmp.zig:2:8: error: expected type 'type', found '(undefined)'",
+ "tmp.zig:5:8: error: expected type 'type', found '(undefined)'",
+ );
+
cases.add(
"@hasDecl with non-container",
\\export fn entry() void {
@@ -146,7 +178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"usingnamespace with wrong type",
\\use void;
,
- "tmp.zig:1:1: error: expected struct, found 'void'",
+ "tmp.zig:1:1: error: expected struct, enum, or union; found 'void'",
);
cases.add(
@@ -1202,7 +1234,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
,
"tmp.zig:2:5: error: `_` is not a declarable symbol",
- "tmp.zig:3:12: error: use of undeclared identifier '_'",
);
cases.add(
@@ -1215,7 +1246,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ }
\\}
,
- "tmp.zig:4:20: error: use of undeclared identifier '_'",
+ "tmp.zig:4:20: error: `_` may only be used to assign things to",
);
cases.add(
@@ -1231,7 +1262,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return 1;
\\}
,
- "tmp.zig:4:20: error: use of undeclared identifier '_'",
+ "tmp.zig:4:20: error: `_` may only be used to assign things to",
);
cases.add(
@@ -1249,7 +1280,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\ return error.optionalReturnError;
\\}
,
- "tmp.zig:6:17: error: use of undeclared identifier '_'",
+ "tmp.zig:6:17: error: `_` may only be used to assign things to",
);
cases.add(
@@ -5468,18 +5499,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"tmp.zig:10:31: error: expected type 'u2', found 'u3'",
);
- cases.add(
- "struct fields with value assignments",
- \\const MultipleChoice = struct {
- \\ A: i32 = 20,
- \\};
- \\export fn entry() void {
- \\ var x: MultipleChoice = undefined;
- \\}
- ,
- "tmp.zig:2:14: error: enums, not structs, support field assignment",
- );
-
cases.add(
"union fields with value assignments",
\\const MultipleChoice = union {
diff --git a/test/gen_h.zig b/test/gen_h.zig
index 11fb55344f..5979afd66a 100644
--- a/test/gen_h.zig
+++ b/test/gen_h.zig
@@ -11,7 +11,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ C = 2
\\};
\\
- \\TEST_EXPORT void entry(enum Foo foo);
+ \\TEST_EXTERN_C void entry(enum Foo foo);
\\
);
@@ -35,7 +35,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ uint64_t F;
\\};
\\
- \\TEST_EXPORT void entry(struct Foo foo);
+ \\TEST_EXTERN_C void entry(struct Foo foo);
\\
);
@@ -70,7 +70,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ struct Big D;
\\};
\\
- \\TEST_EXPORT void entry(union Foo foo);
+ \\TEST_EXTERN_C void entry(union Foo foo);
\\
);
@@ -81,7 +81,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
,
\\struct Foo;
\\
- \\TEST_EXPORT void entry(struct Foo * foo);
+ \\TEST_EXTERN_C void entry(struct Foo * foo);
);
cases.add("array field-type",
@@ -96,7 +96,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\ uint32_t * B[4];
\\};
\\
- \\TEST_EXPORT void entry(struct Foo foo, uint8_t bar[]);
+ \\TEST_EXTERN_C void entry(struct Foo foo, uint8_t bar[]);
\\
);
@@ -110,7 +110,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\}
,
\\struct S;
- \\TEST_EXPORT uint8_t a(struct S * s);
+ \\TEST_EXTERN_C uint8_t a(struct S * s);
\\
);
@@ -125,7 +125,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\}
,
\\union U;
- \\TEST_EXPORT uint8_t a(union U * s);
+ \\TEST_EXTERN_C uint8_t a(union U * s);
\\
);
@@ -140,7 +140,7 @@ pub fn addCases(cases: *tests.GenHContext) void {
\\}
,
\\enum E;
- \\TEST_EXPORT uint8_t a(enum E * s);
+ \\TEST_EXTERN_C uint8_t a(enum E * s);
\\
);
}
diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig
index e9ff84c035..f477bb64ed 100644
--- a/test/stage1/behavior.zig
+++ b/test/stage1/behavior.zig
@@ -26,6 +26,7 @@ comptime {
_ = @import("behavior/bugs/2006.zig");
_ = @import("behavior/bugs/2114.zig");
_ = @import("behavior/bugs/2346.zig");
+ _ = @import("behavior/bugs/2578.zig");
_ = @import("behavior/bugs/394.zig");
_ = @import("behavior/bugs/421.zig");
_ = @import("behavior/bugs/529.zig");
diff --git a/test/stage1/behavior/alignof.zig b/test/stage1/behavior/alignof.zig
index d4d9661ead..f923fd9355 100644
--- a/test/stage1/behavior/alignof.zig
+++ b/test/stage1/behavior/alignof.zig
@@ -15,4 +15,3 @@ test "@alignOf(T) before referencing T" {
comptime expect(@alignOf(Foo) == 4);
}
}
-
diff --git a/test/stage1/behavior/bugs/1076.zig b/test/stage1/behavior/bugs/1076.zig
index 9dc1d111ea..550ee9703a 100644
--- a/test/stage1/behavior/bugs/1076.zig
+++ b/test/stage1/behavior/bugs/1076.zig
@@ -13,4 +13,3 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
}
-
diff --git a/test/stage1/behavior/bugs/1486.zig b/test/stage1/behavior/bugs/1486.zig
index d1bb8d7053..1b8e5ca4a1 100644
--- a/test/stage1/behavior/bugs/1486.zig
+++ b/test/stage1/behavior/bugs/1486.zig
@@ -8,4 +8,3 @@ test "constant pointer to global variable causes runtime load" {
expect(&global == ptr);
expect(ptr.* == 1234);
}
-
diff --git a/test/stage1/behavior/bugs/2578.zig b/test/stage1/behavior/bugs/2578.zig
new file mode 100644
index 0000000000..cf7d941562
--- /dev/null
+++ b/test/stage1/behavior/bugs/2578.zig
@@ -0,0 +1,12 @@
+const Foo = struct {
+ y: u8,
+};
+
+var foo: Foo = undefined;
+const t = &foo;
+
+fn bar(pointer: ?*c_void) void {}
+
+test "fixed" {
+ bar(t);
+}
diff --git a/test/stage1/behavior/bugs/421.zig b/test/stage1/behavior/bugs/421.zig
index e5f67f61b7..a618876e00 100644
--- a/test/stage1/behavior/bugs/421.zig
+++ b/test/stage1/behavior/bugs/421.zig
@@ -13,4 +13,3 @@ fn extractOne64(a: u128) u64 {
const x = @bitCast([2]u64, a);
return x[1];
}
-
diff --git a/test/stage1/behavior/bugs/529.zig b/test/stage1/behavior/bugs/529.zig
index 08d6768f7c..6aeb73c331 100644
--- a/test/stage1/behavior/bugs/529.zig
+++ b/test/stage1/behavior/bugs/529.zig
@@ -12,4 +12,3 @@ test "issue 529 fixed" {
@import("529_other_file.zig").issue529(null);
issue529(null);
}
-
diff --git a/test/stage1/behavior/bugs/726.zig b/test/stage1/behavior/bugs/726.zig
index dd2a135b56..632d3b1511 100644
--- a/test/stage1/behavior/bugs/726.zig
+++ b/test/stage1/behavior/bugs/726.zig
@@ -13,4 +13,3 @@ test "@ptrCast from var in empty struct to nullable" {
var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
expect(x.?.* == 4);
}
-
diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig
index 6d5ede418e..6d581c1128 100644
--- a/test/stage1/behavior/eval.zig
+++ b/test/stage1/behavior/eval.zig
@@ -93,11 +93,13 @@ pub const Vec3 = struct {
data: [3]f32,
};
pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
- return Vec3{ .data = []f32{
- x,
- y,
- z,
- } };
+ return Vec3{
+ .data = []f32{
+ x,
+ y,
+ z,
+ },
+ };
}
test "constant expressions" {
@@ -776,3 +778,9 @@ fn oneItem(x: i32) [1]i32 {
fn scalar(x: u32) u32 {
return x;
}
+
+test "no undeclared identifier error in unanalyzed branches" {
+ if (false) {
+ lol_this_doesnt_exist = nonsense;
+ }
+}
diff --git a/test/stage1/behavior/fn.zig b/test/stage1/behavior/fn.zig
index 3f78c80290..86f382674c 100644
--- a/test/stage1/behavior/fn.zig
+++ b/test/stage1/behavior/fn.zig
@@ -205,4 +205,3 @@ test "extern struct with stdcallcc fn pointer" {
s.ptr = S.foo;
expect(s.ptr() == 1234);
}
-
diff --git a/test/stage1/behavior/import.zig b/test/stage1/behavior/import.zig
index 11d696f81e..aa6e9d82ba 100644
--- a/test/stage1/behavior/import.zig
+++ b/test/stage1/behavior/import.zig
@@ -12,7 +12,7 @@ test "importing the same thing gives the same import" {
test "import in non-toplevel scope" {
const S = struct {
- use @import("import/a_namespace.zig");
+ usingnamespace @import("import/a_namespace.zig");
};
expectEqual(i32(1234), S.foo());
}
diff --git a/test/stage1/behavior/popcount.zig b/test/stage1/behavior/popcount.zig
index 327bee62a1..044864cede 100644
--- a/test/stage1/behavior/popcount.zig
+++ b/test/stage1/behavior/popcount.zig
@@ -41,4 +41,3 @@ fn testPopCount() void {
expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
}
}
-
diff --git a/test/stage1/behavior/reflection.zig b/test/stage1/behavior/reflection.zig
index 55efc85b97..739e0b318a 100644
--- a/test/stage1/behavior/reflection.zig
+++ b/test/stage1/behavior/reflection.zig
@@ -93,4 +93,3 @@ const Bar = union(enum) {
Three: bool,
Four: f64,
};
-
diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig
index c38359be24..3c1db4989c 100644
--- a/test/stage1/behavior/struct.zig
+++ b/test/stage1/behavior/struct.zig
@@ -549,3 +549,32 @@ test "packed struct with fp fields" {
expectEqual(f32(11.0), s.data[1]);
expectEqual(f32(20.0), s.data[2]);
}
+
+test "use within struct scope" {
+ const S = struct {
+ usingnamespace struct {
+ pub fn inner() i32 {
+ return 42;
+ }
+ };
+ };
+ expectEqual(i32(42), S.inner());
+}
+
+test "default struct initialization fields" {
+ const S = struct {
+ a: i32 = 1234,
+ b: i32,
+ };
+ const x = S{
+ .b = 5,
+ };
+ if (x.a + x.b != 1239) {
+ @compileError("it should be comptime known");
+ }
+ var five: i32 = 5;
+ const y = S{
+ .b = five,
+ };
+ expectEqual(1239, x.a + x.b);
+}
diff --git a/test/stage1/behavior/this.zig b/test/stage1/behavior/this.zig
index a0bee3a3ee..927c0808ea 100644
--- a/test/stage1/behavior/this.zig
+++ b/test/stage1/behavior/this.zig
@@ -32,4 +32,3 @@ test "this refer to container" {
expect(pt.x == 13);
expect(pt.y == 35);
}
-
diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig
index 2d088fa261..f05b02e7ab 100644
--- a/test/stage1/behavior/type_info.zig
+++ b/test/stage1/behavior/type_info.zig
@@ -177,7 +177,7 @@ fn testEnum() void {
expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
expect(os_info.Enum.fields[3].value == 3);
expect(os_info.Enum.tag_type == u2);
- expect(os_info.Enum.defs.len == 0);
+ expect(os_info.Enum.decls.len == 0);
}
test "type info: union info" {
@@ -194,7 +194,7 @@ fn testUnion() void {
expect(typeinfo_info.Union.fields[4].enum_field != null);
expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
- expect(typeinfo_info.Union.defs.len == 21);
+ expect(typeinfo_info.Union.decls.len == 21);
const TestNoTagUnion = union {
Foo: void,
@@ -232,12 +232,12 @@ fn testStruct() void {
expect(struct_info.Struct.fields.len == 3);
expect(struct_info.Struct.fields[1].offset == null);
expect(struct_info.Struct.fields[2].field_type == *TestStruct);
- expect(struct_info.Struct.defs.len == 2);
- expect(struct_info.Struct.defs[0].is_pub);
- expect(!struct_info.Struct.defs[0].data.Fn.is_extern);
- expect(struct_info.Struct.defs[0].data.Fn.lib_name == null);
- expect(struct_info.Struct.defs[0].data.Fn.return_type == void);
- expect(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
+ 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);
+ expect(struct_info.Struct.decls[0].data.Fn.lib_name == null);
+ expect(struct_info.Struct.decls[0].data.Fn.return_type == void);
+ expect(struct_info.Struct.decls[0].data.Fn.fn_type == fn (*const TestStruct) void);
}
const TestStruct = packed struct {
diff --git a/test/stage1/behavior/undefined.zig b/test/stage1/behavior/undefined.zig
index 4c233576cd..4f2cbed3bc 100644
--- a/test/stage1/behavior/undefined.zig
+++ b/test/stage1/behavior/undefined.zig
@@ -66,4 +66,3 @@ test "type name of undefined" {
const x = undefined;
expect(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
}
-
diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig
index b8bb9a51b8..58a5203e8a 100644
--- a/test/stage1/behavior/union.zig
+++ b/test/stage1/behavior/union.zig
@@ -374,7 +374,7 @@ const Attribute = union(enum) {
fn setAttribute(attr: Attribute) void {}
fn Setter(attr: Attribute) type {
- return struct{
+ return struct {
fn set() void {
setAttribute(attr);
}
diff --git a/test/stage1/behavior/widening.zig b/test/stage1/behavior/widening.zig
index f7c238ee8d..d79270b811 100644
--- a/test/stage1/behavior/widening.zig
+++ b/test/stage1/behavior/widening.zig
@@ -25,4 +25,3 @@ test "float widening" {
var d: f128 = c;
expect(d == a);
}
-
diff --git a/test/standalone/load_dynamic_library/main.zig b/test/standalone/load_dynamic_library/main.zig
index 4c45ad6fde..a222f5b315 100644
--- a/test/standalone/load_dynamic_library/main.zig
+++ b/test/standalone/load_dynamic_library/main.zig
@@ -1,12 +1,12 @@
const std = @import("std");
pub fn main() !void {
- const args = try std.os.argsAlloc(std.debug.global_allocator);
- defer std.os.argsFree(std.debug.global_allocator, args);
+ const args = try std.process.argsAlloc(std.debug.global_allocator);
+ defer std.process.argsFree(std.debug.global_allocator, args);
const dynlib_name = args[1];
- var lib = try std.DynLib.open(std.debug.global_allocator, dynlib_name);
+ var lib = try std.DynLib.open(dynlib_name);
defer lib.close();
const addr = lib.lookup("add") orelse return error.SymbolNotFound;
diff --git a/test/standalone/use_alias/c.zig b/test/standalone/use_alias/c.zig
index 1bc325b117..2835a51615 100644
--- a/test/standalone/use_alias/c.zig
+++ b/test/standalone/use_alias/c.zig
@@ -1 +1 @@
-pub use @cImport(@cInclude("foo.h"));
+pub usingnamespace @cImport(@cInclude("foo.h"));
diff --git a/test/tests.zig b/test/tests.zig
index 030864aee0..7f750091b0 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -341,7 +341,7 @@ pub const CompareOutputContext = struct {
\\
\\========= Expected this output: =========
\\{}
- \\================================================
+ \\========= But found: ====================
\\{}
\\
, self.expected_output, stdout.toSliceConst());
@@ -1036,7 +1036,7 @@ pub const TranslateCContext = struct {
\\
\\========= Expected this output: ================
\\{}
- \\================================================
+ \\========= But found: ===========================
\\{}
\\
, expected_line, stdout);
@@ -1211,7 +1211,7 @@ pub const GenHContext = struct {
\\
\\========= Expected this output: ================
\\{}
- \\================================================
+ \\========= But found: ===========================
\\{}
\\
, expected_line, actual_h);