authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-16 10:51:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-16 10:51:58-04:00
loga2abdb185f9e47b663edce1bdfa3fa525502f321
tree9027e6f6886937afa463563dae176e5757cf006e
parenta6bf37f8ca5a2eabc7cacb22696d2a2c622a993d
parent780e5674467ebac4534cd3d3f2199ccaf1d0922c
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm7


102 files changed, 4814 insertions(+), 2216 deletions(-)

CMakeLists.txt+13-1
...@@ -393,7 +393,7 @@ if(MSVC)...@@ -393,7 +393,7 @@ if(MSVC)
393 )393 )
394else()394else()
395 set_target_properties(embedded_softfloat PROPERTIES395 set_target_properties(embedded_softfloat PROPERTIES
396 COMPILE_FLAGS "-std=c99"396 COMPILE_FLAGS "-std=c99 -O3"
397 )397 )
398endif()398endif()
399target_include_directories(embedded_softfloat PUBLIC399target_include_directories(embedded_softfloat PUBLIC
...@@ -412,7 +412,9 @@ set(ZIG_SOURCES...@@ -412,7 +412,9 @@ set(ZIG_SOURCES
412 "${CMAKE_SOURCE_DIR}/src/bigint.cpp"412 "${CMAKE_SOURCE_DIR}/src/bigint.cpp"
413 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"413 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
414 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"414 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
415 "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
415 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"416 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
417 "${CMAKE_SOURCE_DIR}/src/compiler.cpp"
416 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"418 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
417 "${CMAKE_SOURCE_DIR}/src/error.cpp"419 "${CMAKE_SOURCE_DIR}/src/error.cpp"
418 "${CMAKE_SOURCE_DIR}/src/ir.cpp"420 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
...@@ -427,6 +429,9 @@ set(ZIG_SOURCES...@@ -427,6 +429,9 @@ set(ZIG_SOURCES
427 "${CMAKE_SOURCE_DIR}/src/util.cpp"429 "${CMAKE_SOURCE_DIR}/src/util.cpp"
428 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"430 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
429)431)
432set(BLAKE_SOURCES
433 "${CMAKE_SOURCE_DIR}/src/blake2b.c"
434)
430set(ZIG_CPP_SOURCES435set(ZIG_CPP_SOURCES
431 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"436 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
432 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"437 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
...@@ -793,6 +798,7 @@ else()...@@ -793,6 +798,7 @@ else()
793 set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")798 set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
794endif()799endif()
795800
801set(BLAKE_CFLAGS "-std=c99")
796802
797set(EXE_LDFLAGS " ")803set(EXE_LDFLAGS " ")
798if(MINGW)804if(MINGW)
...@@ -814,6 +820,11 @@ set_target_properties(zig_cpp PROPERTIES...@@ -814,6 +820,11 @@ set_target_properties(zig_cpp PROPERTIES
814 COMPILE_FLAGS ${EXE_CFLAGS}820 COMPILE_FLAGS ${EXE_CFLAGS}
815)821)
816822
823add_library(embedded_blake STATIC ${BLAKE_SOURCES})
824set_target_properties(embedded_blake PROPERTIES
825 COMPILE_FLAGS "${BLAKE_CFLAGS} -O3"
826)
827
817add_executable(zig ${ZIG_SOURCES})828add_executable(zig ${ZIG_SOURCES})
818set_target_properties(zig PROPERTIES829set_target_properties(zig PROPERTIES
819 COMPILE_FLAGS ${EXE_CFLAGS}830 COMPILE_FLAGS ${EXE_CFLAGS}
...@@ -822,6 +833,7 @@ set_target_properties(zig PROPERTIES...@@ -822,6 +833,7 @@ set_target_properties(zig PROPERTIES
822833
823target_link_libraries(zig LINK_PUBLIC834target_link_libraries(zig LINK_PUBLIC
824 zig_cpp835 zig_cpp
836 embedded_blake
825 ${SOFTFLOAT_LIBRARIES}837 ${SOFTFLOAT_LIBRARIES}
826 ${CLANG_LIBRARIES}838 ${CLANG_LIBRARIES}
827 ${LLD_LIBRARIES}839 ${LLD_LIBRARIES}
build.zig+27-9
...@@ -16,11 +16,12 @@ pub fn build(b: *Builder) !void {...@@ -16,11 +16,12 @@ pub fn build(b: *Builder) !void {
16 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");16 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
18 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);18 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
19 const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable;
19 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{20 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
20 docgen_exe.getOutputPath(),21 docgen_exe.getOutputPath(),
21 rel_zig_exe,22 rel_zig_exe,
22 "doc" ++ os.path.sep_str ++ "langref.html.in",23 "doc" ++ os.path.sep_str ++ "langref.html.in",
23 os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable,24 langref_out_path,
24 });25 });
25 docgen_cmd.step.dependOn(&docgen_exe.step);26 docgen_cmd.step.dependOn(&docgen_exe.step);
2627
...@@ -61,6 +62,9 @@ pub fn build(b: *Builder) !void {...@@ -61,6 +62,9 @@ pub fn build(b: *Builder) !void {
61 b.default_step.dependOn(&exe.step);62 b.default_step.dependOn(&exe.step);
6263
63 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;64 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
65 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
66 const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
67 const skip_release_safe = b.option(bool, "skip-release-safe", "Main test suite skips release-safe builds") orelse skip_release;
64 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;68 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
65 if (!skip_self_hosted) {69 if (!skip_self_hosted) {
66 test_step.dependOn(&exe.step);70 test_step.dependOn(&exe.step);
...@@ -76,15 +80,29 @@ pub fn build(b: *Builder) !void {...@@ -76,15 +80,29 @@ pub fn build(b: *Builder) !void {
7680
77 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");81 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
78 test_stage2_step.dependOn(&test_stage2.step);82 test_stage2_step.dependOn(&test_stage2.step);
79 test_step.dependOn(test_stage2_step);
8083
81 const all_modes = []builtin.Mode{84 // TODO see https://github.com/ziglang/zig/issues/1364
82 builtin.Mode.Debug,85 if (false) {
83 builtin.Mode.ReleaseSafe,86 test_step.dependOn(test_stage2_step);
84 builtin.Mode.ReleaseFast,87 }
85 builtin.Mode.ReleaseSmall,88
86 };89 var chosen_modes: [4]builtin.Mode = undefined;
87 const modes = if (skip_release) []builtin.Mode{builtin.Mode.Debug} else all_modes;90 var chosen_mode_index: usize = 0;
91 chosen_modes[chosen_mode_index] = builtin.Mode.Debug;
92 chosen_mode_index += 1;
93 if (!skip_release_safe) {
94 chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSafe;
95 chosen_mode_index += 1;
96 }
97 if (!skip_release_fast) {
98 chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseFast;
99 chosen_mode_index += 1;
100 }
101 if (!skip_release_small) {
102 chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSmall;
103 chosen_mode_index += 1;
104 }
105 const modes = chosen_modes[0..chosen_mode_index];
88106
89 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));
90108
ci/appveyor/build_script.bat+1-1
...@@ -23,4 +23,4 @@ cd %ZIGBUILDDIR%...@@ -23,4 +23,4 @@ cd %ZIGBUILDDIR%
23cmake.exe .. -Thost=x64 -G"Visual Studio 14 2015 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGBUILDDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b23cmake.exe .. -Thost=x64 -G"Visual Studio 14 2015 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGBUILDDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
24msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b24msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b
2525
26bin\zig.exe build --build-file ..\build.zig test || exit /b26bin\zig.exe build --build-file ..\build.zig test -Dskip-release || exit /b
ci/travis_linux_script+2-2
...@@ -8,9 +8,9 @@ export CXX=clang++-7.0...@@ -8,9 +8,9 @@ export CXX=clang++-7.0
8echo $PATH8echo $PATH
9mkdir build9mkdir build
10cd build10cd build
11cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd)11cmake .. -DCMAKE_BUILD_TYPE=Release
12make -j2 install12make -j2 install
13./zig build --build-file ../build.zig test13./zig build --build-file ../build.zig test -Dskip-release-small
1414
15if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then15if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then
16 mkdir $TRAVIS_BUILD_DIR/artifacts16 mkdir $TRAVIS_BUILD_DIR/artifacts
ci/travis_osx_script+2-2
...@@ -5,8 +5,8 @@ set -e...@@ -5,8 +5,8 @@ set -e
55
6mkdir build6mkdir build
7cd build7cd build
8cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm@7/ -DCMAKE_INSTALL_PREFIX=$(pwd)8cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm@7/ -DCMAKE_BUILD_TYPE=Release
9make VERBOSE=19make VERBOSE=1
10make install10make install
1111
12./zig build --build-file ../build.zig test12./zig build --build-file ../build.zig test -Dskip-release-small
doc/docgen.zig+254-3
...@@ -11,6 +11,7 @@ const max_doc_file_size = 10 * 1024 * 1024;...@@ -11,6 +11,7 @@ const max_doc_file_size = 10 * 1024 * 1024;
11const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();11const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
12const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();12const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
13const tmp_dir_name = "docgen_tmp";13const tmp_dir_name = "docgen_tmp";
14const test_out_path = tmp_dir_name ++ os.path.sep_str ++ "test" ++ exe_ext;
1415
15pub fn main() !void {16pub fn main() !void {
16 var direct_allocator = std.heap.DirectAllocator.init();17 var direct_allocator = std.heap.DirectAllocator.init();
...@@ -299,6 +300,7 @@ const Node = union(enum) {...@@ -299,6 +300,7 @@ const Node = union(enum) {
299 SeeAlso: []const SeeAlsoItem,300 SeeAlso: []const SeeAlsoItem,
300 Code: Code,301 Code: Code,
301 Link: Link,302 Link: Link,
303 Syntax: Token,
302};304};
303305
304const Toc = struct {306const Toc = struct {
...@@ -529,6 +531,17 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -529,6 +531,17 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
529 },531 },
530 });532 });
531 tokenizer.code_node_count += 1;533 tokenizer.code_node_count += 1;
534 } else if (mem.eql(u8, tag_name, "syntax")) {
535 _ = try eatToken(tokenizer, Token.Id.BracketClose);
536 const content_tok = try eatToken(tokenizer, Token.Id.Content);
537 _ = try eatToken(tokenizer, Token.Id.BracketOpen);
538 const end_syntax_tag = try eatToken(tokenizer, Token.Id.TagContent);
539 const end_tag_name = tokenizer.buffer[end_syntax_tag.start..end_syntax_tag.end];
540 if (!mem.eql(u8, end_tag_name, "endsyntax")) {
541 return parseError(tokenizer, end_syntax_tag, "invalid token inside syntax: {}", end_tag_name);
542 }
543 _ = try eatToken(tokenizer, Token.Id.BracketClose);
544 try nodes.append(Node{ .Syntax = content_tok });
532 } else {545 } else {
533 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);546 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
534 }547 }
...@@ -570,6 +583,11 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {...@@ -570,6 +583,11 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
570583
571 var buf_adapter = io.BufferOutStream.init(&buf);584 var buf_adapter = io.BufferOutStream.init(&buf);
572 var out = &buf_adapter.stream;585 var out = &buf_adapter.stream;
586 try writeEscaped(out, input);
587 return buf.toOwnedSlice();
588}
589
590fn writeEscaped(out: var, input: []const u8) !void {
573 for (input) |c| {591 for (input) |c| {
574 try switch (c) {592 try switch (c) {
575 '&' => out.write("&amp;"),593 '&' => out.write("&amp;"),
...@@ -579,7 +597,6 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {...@@ -579,7 +597,6 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
579 else => out.writeByte(c),597 else => out.writeByte(c),
580 };598 };
581 }599 }
582 return buf.toOwnedSlice();
583}600}
584601
585//#define VT_RED "\x1b[31;1m"602//#define VT_RED "\x1b[31;1m"
...@@ -686,6 +703,230 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {...@@ -686,6 +703,230 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
686 return buf.toOwnedSlice();703 return buf.toOwnedSlice();
687}704}
688705
706const builtin_types = [][]const u8{
707 "f16", "f32", "f64", "f128", "c_longdouble", "c_short",
708 "c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_longlong",
709 "c_ulonglong", "c_char", "c_void", "void", "bool", "isize",
710 "usize", "noreturn", "type", "error", "comptime_int", "comptime_float",
711};
712
713fn isType(name: []const u8) bool {
714 for (builtin_types) |t| {
715 if (mem.eql(u8, t, name))
716 return true;
717 }
718 return false;
719}
720
721fn tokenizeAndPrint(allocator: *mem.Allocator, docgen_tokenizer: *Tokenizer, out: var, source_token: Token) !void {
722 const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
723 const src = mem.trim(u8, raw_src, " \n");
724 try out.write("<code class=\"zig\">");
725 var tokenizer = std.zig.Tokenizer.init(src);
726 var index: usize = 0;
727 var next_tok_is_fn = false;
728 while (true) {
729 const prev_tok_was_fn = next_tok_is_fn;
730 next_tok_is_fn = false;
731
732 const token = tokenizer.next();
733 try writeEscaped(out, src[index..token.start]);
734 switch (token.id) {
735 std.zig.Token.Id.Eof => break,
736
737 std.zig.Token.Id.Keyword_align,
738 std.zig.Token.Id.Keyword_and,
739 std.zig.Token.Id.Keyword_asm,
740 std.zig.Token.Id.Keyword_async,
741 std.zig.Token.Id.Keyword_await,
742 std.zig.Token.Id.Keyword_break,
743 std.zig.Token.Id.Keyword_cancel,
744 std.zig.Token.Id.Keyword_catch,
745 std.zig.Token.Id.Keyword_comptime,
746 std.zig.Token.Id.Keyword_const,
747 std.zig.Token.Id.Keyword_continue,
748 std.zig.Token.Id.Keyword_defer,
749 std.zig.Token.Id.Keyword_else,
750 std.zig.Token.Id.Keyword_enum,
751 std.zig.Token.Id.Keyword_errdefer,
752 std.zig.Token.Id.Keyword_error,
753 std.zig.Token.Id.Keyword_export,
754 std.zig.Token.Id.Keyword_extern,
755 std.zig.Token.Id.Keyword_for,
756 std.zig.Token.Id.Keyword_if,
757 std.zig.Token.Id.Keyword_inline,
758 std.zig.Token.Id.Keyword_nakedcc,
759 std.zig.Token.Id.Keyword_noalias,
760 std.zig.Token.Id.Keyword_or,
761 std.zig.Token.Id.Keyword_orelse,
762 std.zig.Token.Id.Keyword_packed,
763 std.zig.Token.Id.Keyword_promise,
764 std.zig.Token.Id.Keyword_pub,
765 std.zig.Token.Id.Keyword_resume,
766 std.zig.Token.Id.Keyword_return,
767 std.zig.Token.Id.Keyword_section,
768 std.zig.Token.Id.Keyword_stdcallcc,
769 std.zig.Token.Id.Keyword_struct,
770 std.zig.Token.Id.Keyword_suspend,
771 std.zig.Token.Id.Keyword_switch,
772 std.zig.Token.Id.Keyword_test,
773 std.zig.Token.Id.Keyword_try,
774 std.zig.Token.Id.Keyword_union,
775 std.zig.Token.Id.Keyword_unreachable,
776 std.zig.Token.Id.Keyword_use,
777 std.zig.Token.Id.Keyword_var,
778 std.zig.Token.Id.Keyword_volatile,
779 std.zig.Token.Id.Keyword_while,
780 => {
781 try out.write("<span class=\"tok-kw\">");
782 try writeEscaped(out, src[token.start..token.end]);
783 try out.write("</span>");
784 },
785
786 std.zig.Token.Id.Keyword_fn => {
787 try out.write("<span class=\"tok-kw\">");
788 try writeEscaped(out, src[token.start..token.end]);
789 try out.write("</span>");
790 next_tok_is_fn = true;
791 },
792
793 std.zig.Token.Id.Keyword_undefined,
794 std.zig.Token.Id.Keyword_null,
795 std.zig.Token.Id.Keyword_true,
796 std.zig.Token.Id.Keyword_false,
797 std.zig.Token.Id.Keyword_this,
798 => {
799 try out.write("<span class=\"tok-null\">");
800 try writeEscaped(out, src[token.start..token.end]);
801 try out.write("</span>");
802 },
803
804 std.zig.Token.Id.StringLiteral,
805 std.zig.Token.Id.MultilineStringLiteralLine,
806 std.zig.Token.Id.CharLiteral,
807 => {
808 try out.write("<span class=\"tok-str\">");
809 try writeEscaped(out, src[token.start..token.end]);
810 try out.write("</span>");
811 },
812
813 std.zig.Token.Id.Builtin => {
814 try out.write("<span class=\"tok-builtin\">");
815 try writeEscaped(out, src[token.start..token.end]);
816 try out.write("</span>");
817 },
818
819 std.zig.Token.Id.LineComment,
820 std.zig.Token.Id.DocComment,
821 => {
822 try out.write("<span class=\"tok-comment\">");
823 try writeEscaped(out, src[token.start..token.end]);
824 try out.write("</span>");
825 },
826
827 std.zig.Token.Id.Identifier => {
828 if (prev_tok_was_fn) {
829 try out.write("<span class=\"tok-fn\">");
830 try writeEscaped(out, src[token.start..token.end]);
831 try out.write("</span>");
832 } else {
833 const is_int = blk: {
834 if (src[token.start] != 'i' and src[token.start] != 'u')
835 break :blk false;
836 var i = token.start + 1;
837 if (i == token.end)
838 break :blk false;
839 while (i != token.end) : (i += 1) {
840 if (src[i] < '0' or src[i] > '9')
841 break :blk false;
842 }
843 break :blk true;
844 };
845 if (is_int or isType(src[token.start..token.end])) {
846 try out.write("<span class=\"tok-type\">");
847 try writeEscaped(out, src[token.start..token.end]);
848 try out.write("</span>");
849 } else {
850 try writeEscaped(out, src[token.start..token.end]);
851 }
852 }
853 },
854
855 std.zig.Token.Id.IntegerLiteral,
856 std.zig.Token.Id.FloatLiteral,
857 => {
858 try out.write("<span class=\"tok-number\">");
859 try writeEscaped(out, src[token.start..token.end]);
860 try out.write("</span>");
861 },
862
863 std.zig.Token.Id.Bang,
864 std.zig.Token.Id.Pipe,
865 std.zig.Token.Id.PipePipe,
866 std.zig.Token.Id.PipeEqual,
867 std.zig.Token.Id.Equal,
868 std.zig.Token.Id.EqualEqual,
869 std.zig.Token.Id.EqualAngleBracketRight,
870 std.zig.Token.Id.BangEqual,
871 std.zig.Token.Id.LParen,
872 std.zig.Token.Id.RParen,
873 std.zig.Token.Id.Semicolon,
874 std.zig.Token.Id.Percent,
875 std.zig.Token.Id.PercentEqual,
876 std.zig.Token.Id.LBrace,
877 std.zig.Token.Id.RBrace,
878 std.zig.Token.Id.LBracket,
879 std.zig.Token.Id.RBracket,
880 std.zig.Token.Id.Period,
881 std.zig.Token.Id.Ellipsis2,
882 std.zig.Token.Id.Ellipsis3,
883 std.zig.Token.Id.Caret,
884 std.zig.Token.Id.CaretEqual,
885 std.zig.Token.Id.Plus,
886 std.zig.Token.Id.PlusPlus,
887 std.zig.Token.Id.PlusEqual,
888 std.zig.Token.Id.PlusPercent,
889 std.zig.Token.Id.PlusPercentEqual,
890 std.zig.Token.Id.Minus,
891 std.zig.Token.Id.MinusEqual,
892 std.zig.Token.Id.MinusPercent,
893 std.zig.Token.Id.MinusPercentEqual,
894 std.zig.Token.Id.Asterisk,
895 std.zig.Token.Id.AsteriskEqual,
896 std.zig.Token.Id.AsteriskAsterisk,
897 std.zig.Token.Id.AsteriskPercent,
898 std.zig.Token.Id.AsteriskPercentEqual,
899 std.zig.Token.Id.Arrow,
900 std.zig.Token.Id.Colon,
901 std.zig.Token.Id.Slash,
902 std.zig.Token.Id.SlashEqual,
903 std.zig.Token.Id.Comma,
904 std.zig.Token.Id.Ampersand,
905 std.zig.Token.Id.AmpersandEqual,
906 std.zig.Token.Id.QuestionMark,
907 std.zig.Token.Id.AngleBracketLeft,
908 std.zig.Token.Id.AngleBracketLeftEqual,
909 std.zig.Token.Id.AngleBracketAngleBracketLeft,
910 std.zig.Token.Id.AngleBracketAngleBracketLeftEqual,
911 std.zig.Token.Id.AngleBracketRight,
912 std.zig.Token.Id.AngleBracketRightEqual,
913 std.zig.Token.Id.AngleBracketAngleBracketRight,
914 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
915 std.zig.Token.Id.Tilde,
916 std.zig.Token.Id.BracketStarBracket,
917 => try writeEscaped(out, src[token.start..token.end]),
918
919 std.zig.Token.Id.Invalid => return parseError(
920 docgen_tokenizer,
921 source_token,
922 "syntax error",
923 ),
924 }
925 index = token.end;
926 }
927 try out.write("</code>");
928}
929
689fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {930fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
690 var code_progress_index: usize = 0;931 var code_progress_index: usize = 0;
691932
...@@ -725,17 +966,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -725,17 +966,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
725 }966 }
726 try out.write("</ul>\n");967 try out.write("</ul>\n");
727 },968 },
969 Node.Syntax => |content_tok| {
970 try tokenizeAndPrint(allocator, tokenizer, out, content_tok);
971 },
728 Node.Code => |code| {972 Node.Code => |code| {
729 code_progress_index += 1;973 code_progress_index += 1;
730 warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count);974 warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count);
731975
732 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];976 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
733 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");977 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
734 const escaped_source = try escapeHtml(allocator, trimmed_raw_source);
735 if (!code.is_inline) {978 if (!code.is_inline) {
736 try out.print("<p class=\"file\">{}.zig</p>", code.name);979 try out.print("<p class=\"file\">{}.zig</p>", code.name);
737 }980 }
738 try out.print("<pre><code class=\"zig\">{}</code></pre>", escaped_source);981 try out.write("<pre>");
982 try tokenizeAndPrint(allocator, tokenizer, out, code.source_token);
983 try out.write("</pre>");
739 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);984 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
740 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);985 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
741 try io.writeFile(tmp_source_file_name, trimmed_raw_source);986 try io.writeFile(tmp_source_file_name, trimmed_raw_source);
...@@ -821,6 +1066,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -821,6 +1066,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
821 zig_exe,1066 zig_exe,
822 "test",1067 "test",
823 tmp_source_file_name,1068 tmp_source_file_name,
1069 "--output",
1070 test_out_path,
824 });1071 });
825 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);1072 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
826 switch (code.mode) {1073 switch (code.mode) {
...@@ -863,6 +1110,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -863,6 +1110,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
863 "--color",1110 "--color",
864 "on",1111 "on",
865 tmp_source_file_name,1112 tmp_source_file_name,
1113 "--output",
1114 test_out_path,
866 });1115 });
867 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);1116 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
868 switch (code.mode) {1117 switch (code.mode) {
...@@ -918,6 +1167,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -918,6 +1167,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
918 zig_exe,1167 zig_exe,
919 "test",1168 "test",
920 tmp_source_file_name,1169 tmp_source_file_name,
1170 "--output",
1171 test_out_path,
921 });1172 });
922 switch (code.mode) {1173 switch (code.mode) {
923 builtin.Mode.Debug => {},1174 builtin.Mode.Debug => {},
doc/langref.html.in+742-809
...@@ -5,9 +5,6 @@...@@ -5,9 +5,6 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
6 <title>Documentation - The Zig Programming Language</title>6 <title>Documentation - The Zig Programming Language</title>
7 <style type="text/css">7 <style type="text/css">
8.hljs{display:block;overflow-x:auto;padding:0.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:bold}.hljs-number,.hljs-literal,.hljs-variable,.hljs-template-variable,.hljs-tag .hljs-attr{color:#008080}.hljs-string,.hljs-doctag{color:#d14}.hljs-title,.hljs-section,.hljs-selector-id{color:#900;font-weight:bold}.hljs-subst{font-weight:normal}.hljs-type,.hljs-class .hljs-title{color:#458;font-weight:bold}.hljs-tag,.hljs-name,.hljs-attribute{color:#000080;font-weight:normal}.hljs-regexp,.hljs-link{color:#009926}.hljs-symbol,.hljs-bullet{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}
9 </style>
10 <style type="text/css">
11 table, th, td {8 table, th, td {
12 border-collapse: collapse;9 border-collapse: collapse;
13 border: 1px solid grey;10 border: 1px solid grey;
...@@ -39,11 +36,46 @@...@@ -39,11 +36,46 @@
39 pre > code {36 pre > code {
40 display: block;37 display: block;
41 overflow: auto;38 overflow: auto;
39
40 overflow-x: auto;
41 padding: 0.5em;
42 color: #333;
43 background: #f8f8f8;
42 }44 }
43 .table-wrapper {45 .table-wrapper {
44 width: 100%;46 width: 100%;
45 overflow-y: auto;47 overflow-y: auto;
46 }48 }
49
50 .tok-kw {
51 color: #333;
52 font-weight: bold;
53 }
54 .tok-str {
55 color: #d14;
56 }
57 .tok-builtin {
58 color: #0086b3;
59 }
60 .tok-comment {
61 color: #998;
62 font-style: italic;
63 }
64 .tok-fn {
65 color: #900;
66 font-weight: bold;
67 }
68 .tok-null {
69 color: #008080;
70 }
71 .tok-number {
72 color: #008080;
73 }
74 .tok-type {
75 color: #458;
76 font-weight: bold;
77 }
78
47 /* Desktop */79 /* Desktop */
48 @media screen and (min-width: 56.25em) {80 @media screen and (min-width: 56.25em) {
49 #nav {81 #nav {
...@@ -129,8 +161,8 @@ pub fn main() void {...@@ -129,8 +161,8 @@ pub fn main() void {
129}161}
130 {#code_end#}162 {#code_end#}
131 <p>163 <p>
132 Note that we also left off the <code class="zig">!</code> from the return type.164 Note that we also left off the {#syntax#}!{#endsyntax#} from the return type.
133 In Zig, if your main function cannot fail, you must use the <code class="zig">void</code> return type.165 In Zig, if your main function cannot fail, you must use the {#syntax#}void{#endsyntax#} return type.
134 </p>166 </p>
135 {#see_also|Values|@import|Errors|Root Source File#}167 {#see_also|Values|@import|Errors|Root Source File#}
136 {#header_close#}168 {#header_close#}
...@@ -149,14 +181,14 @@ test "comments" {...@@ -149,14 +181,14 @@ test "comments" {
149}181}
150 {#code_end#}182 {#code_end#}
151 <p>183 <p>
152 There are no multiline comments in Zig (e.g. like <code>/* */</code>184 There are no multiline comments in Zig (e.g. like <code class="c">/* */</code>
153 comments in C). This helps allow Zig to have the property that each line185 comments in C). This helps allow Zig to have the property that each line
154 of code can be tokenized out of context.186 of code can be tokenized out of context.
155 </p>187 </p>
156 {#header_open|Doc comments#}188 {#header_open|Doc comments#}
157 <p>189 <p>
158 A doc comment is one that begins with exactly three slashes (i.e.190 A doc comment is one that begins with exactly three slashes (i.e.
159 <code class="zig">///</code> but not <code class="zig">////</code>);191 {#syntax#}///{#endsyntax#} but not {#syntax#}////{#endsyntax#});
160 multiple doc comments in a row are merged together to form a multiline192 multiple doc comments in a row are merged together to form a multiline
161 doc comment. The doc comment documents whatever immediately follows it.193 doc comment. The doc comment documents whatever immediately follows it.
162 </p>194 </p>
...@@ -248,169 +280,169 @@ pub fn main() void {...@@ -248,169 +280,169 @@ pub fn main() void {
248 </th>280 </th>
249 </tr>281 </tr>
250 <tr>282 <tr>
251 <td><code>i8</code></td>283 <td>{#syntax#}i8{#endsyntax#}</td>
252 <td><code>int8_t</code></td>284 <td><code class="c">int8_t</code></td>
253 <td>signed 8-bit integer</td>285 <td>signed 8-bit integer</td>
254 </tr>286 </tr>
255 <tr>287 <tr>
256 <td><code>u8</code></td>288 <td>{#syntax#}u8{#endsyntax#}</td>
257 <td><code>uint8_t</code></td>289 <td><code class="c">uint8_t</code></td>
258 <td>unsigned 8-bit integer</td>290 <td>unsigned 8-bit integer</td>
259 </tr>291 </tr>
260 <tr>292 <tr>
261 <td><code>i16</code></td>293 <td>{#syntax#}i16{#endsyntax#}</td>
262 <td><code>int16_t</code></td>294 <td><code class="c">int16_t</code></td>
263 <td>signed 16-bit integer</td>295 <td>signed 16-bit integer</td>
264 </tr>296 </tr>
265 <tr>297 <tr>
266 <td><code>u16</code></td>298 <td>{#syntax#}u16{#endsyntax#}</td>
267 <td><code>uint16_t</code></td>299 <td><code class="c">uint16_t</code></td>
268 <td>unsigned 16-bit integer</td>300 <td>unsigned 16-bit integer</td>
269 </tr>301 </tr>
270 <tr>302 <tr>
271 <td><code>i32</code></td>303 <td>{#syntax#}i32{#endsyntax#}</td>
272 <td><code>int32_t</code></td>304 <td><code class="c">int32_t</code></td>
273 <td>signed 32-bit integer</td>305 <td>signed 32-bit integer</td>
274 </tr>306 </tr>
275 <tr>307 <tr>
276 <td><code>u32</code></td>308 <td>{#syntax#}u32{#endsyntax#}</td>
277 <td><code>uint32_t</code></td>309 <td><code class="c">uint32_t</code></td>
278 <td>unsigned 32-bit integer</td>310 <td>unsigned 32-bit integer</td>
279 </tr>311 </tr>
280 <tr>312 <tr>
281 <td><code>i64</code></td>313 <td>{#syntax#}i64{#endsyntax#}</td>
282 <td><code>int64_t</code></td>314 <td><code class="c">int64_t</code></td>
283 <td>signed 64-bit integer</td>315 <td>signed 64-bit integer</td>
284 </tr>316 </tr>
285 <tr>317 <tr>
286 <td><code>u64</code></td>318 <td>{#syntax#}u64{#endsyntax#}</td>
287 <td><code>uint64_t</code></td>319 <td><code class="c">uint64_t</code></td>
288 <td>unsigned 64-bit integer</td>320 <td>unsigned 64-bit integer</td>
289 </tr>321 </tr>
290 <tr>322 <tr>
291 <td><code>i128</code></td>323 <td>{#syntax#}i128{#endsyntax#}</td>
292 <td><code>__int128</code></td>324 <td><code class="c">__int128</code></td>
293 <td>signed 128-bit integer</td>325 <td>signed 128-bit integer</td>
294 </tr>326 </tr>
295 <tr>327 <tr>
296 <td><code>u128</code></td>328 <td>{#syntax#}u128{#endsyntax#}</td>
297 <td><code>unsigned __int128</code></td>329 <td><code class="c">unsigned __int128</code></td>
298 <td>unsigned 128-bit integer</td>330 <td>unsigned 128-bit integer</td>
299 </tr>331 </tr>
300 <tr>332 <tr>
301 <td><code>isize</code></td>333 <td>{#syntax#}isize{#endsyntax#}</td>
302 <td><code>intptr_t</code></td>334 <td><code class="c">intptr_t</code></td>
303 <td>signed pointer sized integer</td>335 <td>signed pointer sized integer</td>
304 </tr>336 </tr>
305 <tr>337 <tr>
306 <td><code>usize</code></td>338 <td>{#syntax#}usize{#endsyntax#}</td>
307 <td><code>uintptr_t</code></td>339 <td><code class="c">uintptr_t</code></td>
308 <td>unsigned pointer sized integer</td>340 <td>unsigned pointer sized integer</td>
309 </tr>341 </tr>
310342
311 <tr>343 <tr>
312 <td><code>c_short</code></td>344 <td>{#syntax#}c_short{#endsyntax#}</td>
313 <td><code>short</code></td>345 <td><code class="c">short</code></td>
314 <td>for ABI compatibility with C</td>346 <td>for ABI compatibility with C</td>
315 </tr>347 </tr>
316 <tr>348 <tr>
317 <td><code>c_ushort</code></td>349 <td>{#syntax#}c_ushort{#endsyntax#}</td>
318 <td><code>unsigned short</code></td>350 <td><code class="c">unsigned short</code></td>
319 <td>for ABI compatibility with C</td>351 <td>for ABI compatibility with C</td>
320 </tr>352 </tr>
321 <tr>353 <tr>
322 <td><code>c_int</code></td>354 <td>{#syntax#}c_int{#endsyntax#}</td>
323 <td><code>int</code></td>355 <td><code class="c">int</code></td>
324 <td>for ABI compatibility with C</td>356 <td>for ABI compatibility with C</td>
325 </tr>357 </tr>
326 <tr>358 <tr>
327 <td><code>c_uint</code></td>359 <td>{#syntax#}c_uint{#endsyntax#}</td>
328 <td><code>unsigned int</code></td>360 <td><code class="c">unsigned int</code></td>
329 <td>for ABI compatibility with C</td>361 <td>for ABI compatibility with C</td>
330 </tr>362 </tr>
331 <tr>363 <tr>
332 <td><code>c_long</code></td>364 <td>{#syntax#}c_long{#endsyntax#}</td>
333 <td><code>long</code></td>365 <td><code class="c">long</code></td>
334 <td>for ABI compatibility with C</td>366 <td>for ABI compatibility with C</td>
335 </tr>367 </tr>
336 <tr>368 <tr>
337 <td><code>c_ulong</code></td>369 <td>{#syntax#}c_ulong{#endsyntax#}</td>
338 <td><code>unsigned long</code></td>370 <td><code class="c">unsigned long</code></td>
339 <td>for ABI compatibility with C</td>371 <td>for ABI compatibility with C</td>
340 </tr>372 </tr>
341 <tr>373 <tr>
342 <td><code>c_longlong</code></td>374 <td>{#syntax#}c_longlong{#endsyntax#}</td>
343 <td><code>long long</code></td>375 <td><code class="c">long long</code></td>
344 <td>for ABI compatibility with C</td>376 <td>for ABI compatibility with C</td>
345 </tr>377 </tr>
346 <tr>378 <tr>
347 <td><code>c_ulonglong</code></td>379 <td>{#syntax#}c_ulonglong{#endsyntax#}</td>
348 <td><code>unsigned long long</code></td>380 <td><code class="c">unsigned long long</code></td>
349 <td>for ABI compatibility with C</td>381 <td>for ABI compatibility with C</td>
350 </tr>382 </tr>
351 <tr>383 <tr>
352 <td><code>c_longdouble</code></td>384 <td>{#syntax#}c_longdouble{#endsyntax#}</td>
353 <td><code>long double</code></td>385 <td><code class="c">long double</code></td>
354 <td>for ABI compatibility with C</td>386 <td>for ABI compatibility with C</td>
355 </tr>387 </tr>
356 <tr>388 <tr>
357 <td><code>c_void</code></td>389 <td>{#syntax#}c_void{#endsyntax#}</td>
358 <td><code>void</code></td>390 <td><code class="c">void</code></td>
359 <td>for ABI compatibility with C</td>391 <td>for ABI compatibility with C</td>
360 </tr>392 </tr>
361393
362 <tr>394 <tr>
363 <td><code>f16</code></td>395 <td>{#syntax#}f16{#endsyntax#}</td>
364 <td><code>float</code></td>396 <td><code class="c">float</code></td>
365 <td>16-bit floating point (10-bit mantissa) IEEE-754-2008 binary16</td>397 <td>16-bit floating point (10-bit mantissa) IEEE-754-2008 binary16</td>
366 </tr>398 </tr>
367 <tr>399 <tr>
368 <td><code>f32</code></td>400 <td>{#syntax#}f32{#endsyntax#}</td>
369 <td><code>float</code></td>401 <td><code class="c">float</code></td>
370 <td>32-bit floating point (23-bit mantissa) IEEE-754-2008 binary32</td>402 <td>32-bit floating point (23-bit mantissa) IEEE-754-2008 binary32</td>
371 </tr>403 </tr>
372 <tr>404 <tr>
373 <td><code>f64</code></td>405 <td>{#syntax#}f64{#endsyntax#}</td>
374 <td><code>double</code></td>406 <td><code class="c">double</code></td>
375 <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td>407 <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td>
376 </tr>408 </tr>
377 <tr>409 <tr>
378 <td><code>f128</code></td>410 <td>{#syntax#}f128{#endsyntax#}</td>
379 <td>(none)</td>411 <td>(none)</td>
380 <td>128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128</td>412 <td>128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128</td>
381 </tr>413 </tr>
382 <tr>414 <tr>
383 <td><code>bool</code></td>415 <td>{#syntax#}bool{#endsyntax#}</td>
384 <td><code>bool</code></td>416 <td><code class="c">bool</code></td>
385 <td><code>true</code> or <code>false</code></td>417 <td>{#syntax#}true{#endsyntax#} or {#syntax#}false{#endsyntax#}</td>
386 </tr>418 </tr>
387 <tr>419 <tr>
388 <td><code>void</code></td>420 <td>{#syntax#}void{#endsyntax#}</td>
389 <td>(none)</td>421 <td>(none)</td>
390 <td>0 bit type</td>422 <td>0 bit type</td>
391 </tr>423 </tr>
392 <tr>424 <tr>
393 <td><code>noreturn</code></td>425 <td>{#syntax#}noreturn{#endsyntax#}</td>
394 <td>(none)</td>426 <td>(none)</td>
395 <td>the type of <code>break</code>, <code>continue</code>, <code>return</code>, <code>unreachable</code>, and <code>while (true) {}</code></td>427 <td>the type of {#syntax#}break{#endsyntax#}, {#syntax#}continue{#endsyntax#}, {#syntax#}return{#endsyntax#}, {#syntax#}unreachable{#endsyntax#}, and {#syntax#}while (true) {}{#endsyntax#}</td>
396 </tr>428 </tr>
397 <tr>429 <tr>
398 <td><code>type</code></td>430 <td>{#syntax#}type{#endsyntax#}</td>
399 <td>(none)</td>431 <td>(none)</td>
400 <td>the type of types</td>432 <td>the type of types</td>
401 </tr>433 </tr>
402 <tr>434 <tr>
403 <td><code>error</code></td>435 <td>{#syntax#}error{#endsyntax#}</td>
404 <td>(none)</td>436 <td>(none)</td>
405 <td>an error code</td>437 <td>an error code</td>
406 </tr>438 </tr>
407 <tr>439 <tr>
408 <td><code>comptime_int</code></td>440 <td>{#syntax#}comptime_int{#endsyntax#}</td>
409 <td>(none)</td>441 <td>(none)</td>
410 <td>Only allowed for {#link|comptime#}-known values. The type of integer literals.</td>442 <td>Only allowed for {#link|comptime#}-known values. The type of integer literals.</td>
411 </tr>443 </tr>
412 <tr>444 <tr>
413 <td><code>comptime_float</code></td>445 <td>{#syntax#}comptime_float{#endsyntax#}</td>
414 <td>(none)</td>446 <td>(none)</td>
415 <td>Only allowed for {#link|comptime#}-known values. The type of float literals.</td>447 <td>Only allowed for {#link|comptime#}-known values. The type of float literals.</td>
416 </tr>448 </tr>
...@@ -419,7 +451,7 @@ pub fn main() void {...@@ -419,7 +451,7 @@ pub fn main() void {
419 <p>451 <p>
420 In addition to the integer types above, arbitrary bit-width integers can be referenced by using452 In addition to the integer types above, arbitrary bit-width integers can be referenced by using
421 an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier453 an identifier of <code>i</code> or </code>u</code> followed by digits. For example, the identifier
422 <code>i7</code> refers to a signed 7-bit integer.454 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer.
423 </p>455 </p>
424 {#see_also|Integers|Floats|void|Errors#}456 {#see_also|Integers|Floats|void|Errors#}
425 {#header_close#}457 {#header_close#}
...@@ -435,24 +467,20 @@ pub fn main() void {...@@ -435,24 +467,20 @@ pub fn main() void {
435 </th>467 </th>
436 </tr>468 </tr>
437 <tr>469 <tr>
438 <td><code>true</code> and <code>false</code></td>470 <td>{#syntax#}true{#endsyntax#} and {#syntax#}false{#endsyntax#}</td>
439 <td><code>bool</code> values</td>471 <td>{#syntax#}bool{#endsyntax#} values</td>
440 </tr>472 </tr>
441 <tr>473 <tr>
442 <td><code>null</code></td>474 <td>{#syntax#}null{#endsyntax#}</td>
443 <td>used to set an optional type to <code>null</code></td>475 <td>used to set an optional type to {#syntax#}null{#endsyntax#}</td>
444 </tr>476 </tr>
445 <tr>477 <tr>
446 <td><code>undefined</code></td>478 <td>{#syntax#}undefined{#endsyntax#}</td>
447 <td>used to leave a value unspecified</td>479 <td>used to leave a value unspecified</td>
448 </tr>480 </tr>
449 <tr>
450 <td><code>this</code></td>
451 <td>refers to the thing in immediate scope</td>
452 </tr>
453 </table>481 </table>
454 </div>482 </div>
455 {#see_also|Optionals|this#}483 {#see_also|Optionals#}
456 {#header_close#}484 {#header_close#}
457 {#header_open|String Literals#}485 {#header_open|String Literals#}
458 {#code_begin|test#}486 {#code_begin|test#}
...@@ -487,52 +515,52 @@ test "string literals" {...@@ -487,52 +515,52 @@ test "string literals" {
487 </th>515 </th>
488 </tr>516 </tr>
489 <tr>517 <tr>
490 <td><code>\n</code></td>518 <td><code>\n</code></td>
491 <td>Newline</td>519 <td>Newline</td>
492 </tr>520 </tr>
493 <tr>521 <tr>
494 <td><code>\r</code></td>522 <td><code>\r</code></td>
495 <td>Carriage Return</td>523 <td>Carriage Return</td>
496 </tr>524 </tr>
497 <tr>525 <tr>
498 <td><code>\t</code></td>526 <td><code>\t</code></td>
499 <td>Tab</td>527 <td>Tab</td>
500 </tr>528 </tr>
501 <tr>529 <tr>
502 <td><code>\\</code></td>530 <td><code>\\</code></td>
503 <td>Backslash</td>531 <td>Backslash</td>
504 </tr>532 </tr>
505 <tr>533 <tr>
506 <td><code>\'</code></td>534 <td><code>\'</code></td>
507 <td>Single Quote</td>535 <td>Single Quote</td>
508 </tr>536 </tr>
509 <tr>537 <tr>
510 <td><code>\"</code></td>538 <td><code>\"</code></td>
511 <td>Double Quote</td>539 <td>Double Quote</td>
512 </tr>540 </tr>
513 <tr>541 <tr>
514 <td><code>\xNN</code></td>542 <td><code>\xNN</code></td>
515 <td>hexadecimal 8-bit character code (2 digits)</td>543 <td>hexadecimal 8-bit character code (2 digits)</td>
516 </tr>544 </tr>
517 <tr>545 <tr>
518 <td><code>\uNNNN</code></td>546 <td><code>\uNNNN</code></td>
519 <td>hexadecimal 16-bit Unicode character code UTF-8 encoded (4 digits)</td>547 <td>hexadecimal 16-bit Unicode character code UTF-8 encoded (4 digits)</td>
520 </tr>548 </tr>
521 <tr>549 <tr>
522 <td><code>\UNNNNNN</code></td>550 <td><code>\UNNNNNN</code></td>
523 <td>hexadecimal 24-bit Unicode character code UTF-8 encoded (6 digits)</td>551 <td>hexadecimal 24-bit Unicode character code UTF-8 encoded (6 digits)</td>
524 </tr>552 </tr>
525 </table>553 </table>
526 </div>554 </div>
527 <p>Note that the maximum valid Unicode point is <code>0x10ffff</code>.</p>555 <p>Note that the maximum valid Unicode point is {#syntax#}0x10ffff{#endsyntax#}.</p>
528 {#header_close#}556 {#header_close#}
529 {#header_open|Multiline String Literals#}557 {#header_open|Multiline String Literals#}
530 <p>558 <p>
531 Multiline string literals have no escapes and can span across multiple lines.559 Multiline string literals have no escapes and can span across multiple lines.
532 To start a multiline string literal, use the <code>\\</code> token. Just like a comment,560 To start a multiline string literal, use the {#syntax#}\\{#endsyntax#} token. Just like a comment,
533 the string literal goes until the end of the line. The end of the line is561 the string literal goes until the end of the line. The end of the line is
534 not included in the string literal.562 not included in the string literal.
535 However, if the next line begins with <code>\\</code> then a newline is appended and563 However, if the next line begins with {#syntax#}\\{#endsyntax#} then a newline is appended and
536 the string literal continues.564 the string literal continues.
537 </p>565 </p>
538 {#code_begin|syntax#}566 {#code_begin|syntax#}
...@@ -546,7 +574,7 @@ const hello_world_in_c =...@@ -546,7 +574,7 @@ const hello_world_in_c =
546;574;
547 {#code_end#}575 {#code_end#}
548 <p>576 <p>
549 For a multiline C string literal, prepend <code>c</code> to each <code>\\</code>:577 For a multiline C string literal, prepend <code>c</code> to each {#syntax#}\\{#endsyntax#}:
550 </p>578 </p>
551 {#code_begin|syntax#}579 {#code_begin|syntax#}
552const c_string_literal =580const c_string_literal =
...@@ -559,14 +587,14 @@ const c_string_literal =...@@ -559,14 +587,14 @@ const c_string_literal =
559;587;
560 {#code_end#}588 {#code_end#}
561 <p>589 <p>
562 In this example the variable <code>c_string_literal</code> has type <code>[*]const char</code> and590 In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const char{#endsyntax#} and
563 has a terminating null byte.591 has a terminating null byte.
564 </p>592 </p>
565 {#see_also|@embedFile#}593 {#see_also|@embedFile#}
566 {#header_close#}594 {#header_close#}
567 {#header_close#}595 {#header_close#}
568 {#header_open|Assignment#}596 {#header_open|Assignment#}
569 <p>Use the <code>const</code> keyword to assign a value to an identifier:</p>597 <p>Use the {#syntax#}const{#endsyntax#} keyword to assign a value to an identifier:</p>
570 {#code_begin|test_err|cannot assign to constant#}598 {#code_begin|test_err|cannot assign to constant#}
571const x = 1234;599const x = 1234;
572600
...@@ -582,8 +610,8 @@ test "assignment" {...@@ -582,8 +610,8 @@ test "assignment" {
582 foo();610 foo();
583}611}
584 {#code_end#}612 {#code_end#}
585 <p><code>const</code> applies to all of the bytes that the identifier immediately addresses. {#link|Pointers#} have their own const-ness.</p>613 <p>{#syntax#}const{#endsyntax#} applies to all of the bytes that the identifier immediately addresses. {#link|Pointers#} have their own const-ness.</p>
586 <p>If you need a variable that you can modify, use the <code>var</code> keyword:</p>614 <p>If you need a variable that you can modify, use the {#syntax#}var{#endsyntax#} keyword:</p>
587 {#code_begin|test#}615 {#code_begin|test#}
588const assert = @import("std").debug.assert;616const assert = @import("std").debug.assert;
589617
...@@ -604,7 +632,7 @@ test "initialization" {...@@ -604,7 +632,7 @@ test "initialization" {
604}632}
605 {#code_end#}633 {#code_end#}
606 {#header_open|undefined#}634 {#header_open|undefined#}
607 <p>Use <code>undefined</code> to leave variables uninitialized:</p>635 <p>Use {#syntax#}undefined{#endsyntax#} to leave variables uninitialized:</p>
608 {#code_begin|test#}636 {#code_begin|test#}
609const assert = @import("std").debug.assert;637const assert = @import("std").debug.assert;
610638
...@@ -615,14 +643,14 @@ test "init with undefined" {...@@ -615,14 +643,14 @@ test "init with undefined" {
615}643}
616 {#code_end#}644 {#code_end#}
617 <p>645 <p>
618 <code>undefined</code> can be {#link|implicitly cast|Implicit Casts#} to any type.646 {#syntax#}undefined{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to any type.
619 Once this happens, it is no longer possible to detect that the value is <code>undefined</code>.647 Once this happens, it is no longer possible to detect that the value is {#syntax#}undefined{#endsyntax#}.
620 <code>undefined</code> means the value could be anything, even something that is nonsense648 {#syntax#}undefined{#endsyntax#} means the value could be anything, even something that is nonsense
621 according to the type. Translated into English, <code>undefined</code> means "Not a meaningful649 according to the type. Translated into English, {#syntax#}undefined{#endsyntax#} means "Not a meaningful
622 value. Using this value would be a bug. The value will be unused, or overwritten before being used."650 value. Using this value would be a bug. The value will be unused, or overwritten before being used."
623 </p>651 </p>
624 <p>652 <p>
625 In {#link|Debug#} mode, Zig writes <code>0xaa</code> bytes to undefined memory. This is to catch653 In {#link|Debug#} mode, Zig writes {#syntax#}0xaa{#endsyntax#} bytes to undefined memory. This is to catch
626 bugs early, and to help detect use of undefined memory in a debugger.654 bugs early, and to help detect use of undefined memory in a debugger.
627 </p>655 </p>
628 {#header_close#}656 {#header_close#}
...@@ -653,14 +681,14 @@ fn divide(a: i32, b: i32) i32 {...@@ -653,14 +681,14 @@ fn divide(a: i32, b: i32) i32 {
653}681}
654 {#code_end#}682 {#code_end#}
655 <p>683 <p>
656 In this function, values <code>a</code> and <code>b</code> are known only at runtime,684 In this function, values {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are known only at runtime,
657 and thus this division operation is vulnerable to both integer overflow and685 and thus this division operation is vulnerable to both integer overflow and
658 division by zero.686 division by zero.
659 </p>687 </p>
660 <p>688 <p>
661 Operators such as <code>+</code> and <code>-</code> cause undefined behavior on689 Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
662 integer overflow. Also available are operations such as <code>+%</code> and690 integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
663 <code>-%</code> which are defined to have wrapping arithmetic on all targets.691 {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
664 </p>692 </p>
665 {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#}693 {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#}
666 {#header_close#}694 {#header_close#}
...@@ -668,15 +696,15 @@ fn divide(a: i32, b: i32) i32 {...@@ -668,15 +696,15 @@ fn divide(a: i32, b: i32) i32 {
668 {#header_open|Floats#}696 {#header_open|Floats#}
669 <p>Zig has the following floating point types:</p>697 <p>Zig has the following floating point types:</p>
670 <ul>698 <ul>
671 <li><code>f16</code> - IEEE-754-2008 binary16</li>699 <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li>
672 <li><code>f32</code> - IEEE-754-2008 binary32</li>700 <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li>
673 <li><code>f64</code> - IEEE-754-2008 binary64</li>701 <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li>
674 <li><code>f128</code> - IEEE-754-2008 binary128</li>702 <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li>
675 <li><code>c_longdouble</code> - matches <code>long double</code> for the target C ABI</li>703 <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li>
676 </ul>704 </ul>
677 {#header_open|Float Literals#}705 {#header_open|Float Literals#}
678 <p>706 <p>
679 Float literals have type <code>comptime_float</code> which is guaranteed to hold at least all possible values707 Float literals have type {#syntax#}comptime_float{#endsyntax#} which is guaranteed to hold at least all possible values
680 that the largest other floating point type can hold. Float literals {#link|implicitly cast|Implicit Casts#} to any other type.708 that the largest other floating point type can hold. Float literals {#link|implicitly cast|Implicit Casts#} to any other type.
681 </p>709 </p>
682 {#code_begin|syntax#}710 {#code_begin|syntax#}
...@@ -690,8 +718,8 @@ const yet_another_hex_float = 0x103.70P-5;...@@ -690,8 +718,8 @@ const yet_another_hex_float = 0x103.70P-5;
690 {#code_end#}718 {#code_end#}
691 {#header_close#}719 {#header_close#}
692 {#header_open|Floating Point Operations#}720 {#header_open|Floating Point Operations#}
693 <p>By default floating point operations use <code>Strict</code> mode,721 <p>By default floating point operations use {#syntax#}Strict{#endsyntax#} mode,
694 but you can switch to <code>Optimized</code> mode on a per-block basis:</p>722 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>
695 {#code_begin|obj|foo#}723 {#code_begin|obj|foo#}
696 {#code_release_fast#}724 {#code_release_fast#}
697const builtin = @import("builtin");725const builtin = @import("builtin");
...@@ -702,7 +730,7 @@ export fn foo_strict(x: f64) f64 {...@@ -702,7 +730,7 @@ export fn foo_strict(x: f64) f64 {
702}730}
703731
704export fn foo_optimized(x: f64) f64 {732export fn foo_optimized(x: f64) f64 {
705 @setFloatMode(this, builtin.FloatMode.Optimized);733 @setFloatMode(builtin.FloatMode.Optimized);
706 return x + big - big;734 return x + big - big;
707}735}
708 {#code_end#}736 {#code_end#}
...@@ -744,8 +772,8 @@ pub fn main() void {...@@ -744,8 +772,8 @@ pub fn main() void {
744 </th>772 </th>
745 </tr>773 </tr>
746 <tr>774 <tr>
747 <td><pre><code class="zig">a + b775 <td><pre>{#syntax#}a + b
748a += b</code></pre></td>776a += b{#endsyntax#}</pre></td>
749 <td>777 <td>
750 <ul>778 <ul>
751 <li>{#link|Integers#}</li>779 <li>{#link|Integers#}</li>
...@@ -760,12 +788,12 @@ a += b</code></pre></td>...@@ -760,12 +788,12 @@ a += b</code></pre></td>
760 </ul>788 </ul>
761 </td>789 </td>
762 <td>790 <td>
763 <pre><code class="zig">2 + 5 == 7</code></pre>791 <pre>{#syntax#}2 + 5 == 7{#endsyntax#}</pre>
764 </td>792 </td>
765 </tr>793 </tr>
766 <tr>794 <tr>
767 <td><pre><code class="zig">a +% b795 <td><pre>{#syntax#}a +% b
768a +%= b</code></pre></td>796a +%= b{#endsyntax#}</pre></td>
769 <td>797 <td>
770 <ul>798 <ul>
771 <li>{#link|Integers#}</li>799 <li>{#link|Integers#}</li>
...@@ -779,12 +807,12 @@ a +%= b</code></pre></td>...@@ -779,12 +807,12 @@ a +%= b</code></pre></td>
779 </ul>807 </ul>
780 </td>808 </td>
781 <td>809 <td>
782 <pre><code class="zig">u32(@maxValue(u32)) +% 1 == 0</code></pre>810 <pre>{#syntax#}u32(@maxValue(u32)) +% 1 == 0{#endsyntax#}</pre>
783 </td>811 </td>
784 </tr>812 </tr>
785 <tr>813 <tr>
786 <td><pre><code class="zig">a - b814 <td><pre>{#syntax#}a - b
787a -= b</code></pre></td>815a -= b{#endsyntax#}</pre></td>
788 <td>816 <td>
789 <ul>817 <ul>
790 <li>{#link|Integers#}</li>818 <li>{#link|Integers#}</li>
...@@ -799,12 +827,12 @@ a -= b</code></pre></td>...@@ -799,12 +827,12 @@ a -= b</code></pre></td>
799 </ul>827 </ul>
800 </td>828 </td>
801 <td>829 <td>
802 <pre><code class="zig">2 - 5 == -3</code></pre>830 <pre>{#syntax#}2 - 5 == -3{#endsyntax#}</pre>
803 </td>831 </td>
804 </tr>832 </tr>
805 <tr>833 <tr>
806 <td><pre><code class="zig">a -% b834 <td><pre>{#syntax#}a -% b
807a -%= b</code></pre></td>835a -%= b{#endsyntax#}</pre></td>
808 <td>836 <td>
809 <ul>837 <ul>
810 <li>{#link|Integers#}</li>838 <li>{#link|Integers#}</li>
...@@ -818,11 +846,11 @@ a -%= b</code></pre></td>...@@ -818,11 +846,11 @@ a -%= b</code></pre></td>
818 </ul>846 </ul>
819 </td>847 </td>
820 <td>848 <td>
821 <pre><code class="zig">u32(0) -% 1 == @maxValue(u32)</code></pre>849 <pre>{#syntax#}u32(0) -% 1 == @maxValue(u32){#endsyntax#}</pre>
822 </td>850 </td>
823 </tr>851 </tr>
824 <tr>852 <tr>
825 <td><pre><code class="zig">-a<code></pre></td>853 <td><pre>{#syntax#}-a{#endsyntax#}</pre></td>
826 <td>854 <td>
827 <ul>855 <ul>
828 <li>{#link|Integers#}</li>856 <li>{#link|Integers#}</li>
...@@ -836,11 +864,11 @@ a -%= b</code></pre></td>...@@ -836,11 +864,11 @@ a -%= b</code></pre></td>
836 </ul>864 </ul>
837 </td>865 </td>
838 <td>866 <td>
839 <pre><code class="zig">-1 == 0 - 1</code></pre>867 <pre>{#syntax#}-1 == 0 - 1{#endsyntax#}</pre>
840 </td>868 </td>
841 </tr>869 </tr>
842 <tr>870 <tr>
843 <td><pre><code class="zig">-%a<code></pre></td>871 <td><pre>{#syntax#}-%a{#endsyntax#}</pre></td>
844 <td>872 <td>
845 <ul>873 <ul>
846 <li>{#link|Integers#}</li>874 <li>{#link|Integers#}</li>
...@@ -853,12 +881,12 @@ a -%= b</code></pre></td>...@@ -853,12 +881,12 @@ a -%= b</code></pre></td>
853 </ul>881 </ul>
854 </td>882 </td>
855 <td>883 <td>
856 <pre><code class="zig">-%i32(@minValue(i32)) == @minValue(i32)</code></pre>884 <pre>{#syntax#}-%i32(@minValue(i32)) == @minValue(i32){#endsyntax#}</pre>
857 </td>885 </td>
858 </tr>886 </tr>
859 <tr>887 <tr>
860 <td><pre><code class="zig">a * b888 <td><pre>{#syntax#}a * b
861a *= b</code></pre></td>889a *= b{#endsyntax#}</pre></td>
862 <td>890 <td>
863 <ul>891 <ul>
864 <li>{#link|Integers#}</li>892 <li>{#link|Integers#}</li>
...@@ -873,12 +901,12 @@ a *= b</code></pre></td>...@@ -873,12 +901,12 @@ a *= b</code></pre></td>
873 </ul>901 </ul>
874 </td>902 </td>
875 <td>903 <td>
876 <pre><code class="zig">2 * 5 == 10</code></pre>904 <pre>{#syntax#}2 * 5 == 10{#endsyntax#}</pre>
877 </td>905 </td>
878 </tr>906 </tr>
879 <tr>907 <tr>
880 <td><pre><code class="zig">a *% b908 <td><pre>{#syntax#}a *% b
881a *%= b</code></pre></td>909a *%= b{#endsyntax#}</pre></td>
882 <td>910 <td>
883 <ul>911 <ul>
884 <li>{#link|Integers#}</li>912 <li>{#link|Integers#}</li>
...@@ -892,12 +920,12 @@ a *%= b</code></pre></td>...@@ -892,12 +920,12 @@ a *%= b</code></pre></td>
892 </ul>920 </ul>
893 </td>921 </td>
894 <td>922 <td>
895 <pre><code class="zig">u8(200) *% 2 == 144</code></pre>923 <pre>{#syntax#}u8(200) *% 2 == 144{#endsyntax#}</pre>
896 </td>924 </td>
897 </tr>925 </tr>
898 <tr>926 <tr>
899 <td><pre><code class="zig">a / b927 <td><pre>{#syntax#}a / b
900a /= b</code></pre></td>928a /= b{#endsyntax#}</pre></td>
901 <td>929 <td>
902 <ul>930 <ul>
903 <li>{#link|Integers#}</li>931 <li>{#link|Integers#}</li>
...@@ -912,18 +940,18 @@ a /= b</code></pre></td>...@@ -912,18 +940,18 @@ a /= b</code></pre></td>
912 <li>For non-compile-time-known signed integers, must use940 <li>For non-compile-time-known signed integers, must use
913 {#link|@divTrunc#},941 {#link|@divTrunc#},
914 {#link|@divFloor#}, or942 {#link|@divFloor#}, or
915 {#link|@divExact#} instead of <code>/</code>.943 {#link|@divExact#} instead of {#syntax#}/{#endsyntax#}.
916 </li>944 </li>
917 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>945 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
918 </ul>946 </ul>
919 </td>947 </td>
920 <td>948 <td>
921 <pre><code class="zig">10 / 5 == 2</code></pre>949 <pre>{#syntax#}10 / 5 == 2{#endsyntax#}</pre>
922 </td>950 </td>
923 </tr>951 </tr>
924 <tr>952 <tr>
925 <td><pre><code class="zig">a % b953 <td><pre>{#syntax#}a % b
926a %= b</code></pre></td>954a %= b{#endsyntax#}</pre></td>
927 <td>955 <td>
928 <ul>956 <ul>
929 <li>{#link|Integers#}</li>957 <li>{#link|Integers#}</li>
...@@ -936,18 +964,18 @@ a %= b</code></pre></td>...@@ -936,18 +964,18 @@ a %= b</code></pre></td>
936 <li>Can cause {#link|Division by Zero#} for floats in {#link|FloatMode.Optimized Mode|Floating Point Operations#}.</li>964 <li>Can cause {#link|Division by Zero#} for floats in {#link|FloatMode.Optimized Mode|Floating Point Operations#}.</li>
937 <li>For non-compile-time-known signed integers, must use965 <li>For non-compile-time-known signed integers, must use
938 {#link|@rem#} or966 {#link|@rem#} or
939 {#link|@mod#} instead of <code>%</code>.967 {#link|@mod#} instead of {#syntax#}%{#endsyntax#}.
940 </li>968 </li>
941 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>969 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
942 </ul>970 </ul>
943 </td>971 </td>
944 <td>972 <td>
945 <pre><code class="zig">10 % 3 == 1</code></pre>973 <pre>{#syntax#}10 % 3 == 1{#endsyntax#}</pre>
946 </td>974 </td>
947 </tr>975 </tr>
948 <tr>976 <tr>
949 <td><pre><code class="zig">a &lt;&lt; b977 <td><pre>{#syntax#}a << b
950a &lt;&lt;= b</code></pre></td>978a <<= b{#endsyntax#}</pre></td>
951 <td>979 <td>
952 <ul>980 <ul>
953 <li>{#link|Integers#}</li>981 <li>{#link|Integers#}</li>
...@@ -955,18 +983,18 @@ a &lt;&lt;= b</code></pre></td>...@@ -955,18 +983,18 @@ a &lt;&lt;= b</code></pre></td>
955 </td>983 </td>
956 <td>Bit Shift Left.984 <td>Bit Shift Left.
957 <ul>985 <ul>
958 <li><code>b</code> must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as <code>a</code>.</li>986 <li>{#syntax#}b{#endsyntax#} must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as {#syntax#}a{#endsyntax#}.</li>
959 <li>See also {#link|@shlExact#}.</li>987 <li>See also {#link|@shlExact#}.</li>
960 <li>See also {#link|@shlWithOverflow#}.</li>988 <li>See also {#link|@shlWithOverflow#}.</li>
961 </ul>989 </ul>
962 </td>990 </td>
963 <td>991 <td>
964 <pre><code class="zig">1 &lt;&lt; 8 == 256</code></pre>992 <pre>{#syntax#}1 << 8 == 256{#endsyntax#}</pre>
965 </td>993 </td>
966 </tr>994 </tr>
967 <tr>995 <tr>
968 <td><pre><code class="zig">a &gt;&gt; b996 <td><pre>{#syntax#}a >> b
969a &gt;&gt;= b</code></pre></td>997a >>= b{#endsyntax#}</pre></td>
970 <td>998 <td>
971 <ul>999 <ul>
972 <li>{#link|Integers#}</li>1000 <li>{#link|Integers#}</li>
...@@ -974,17 +1002,17 @@ a &gt;&gt;= b</code></pre></td>...@@ -974,17 +1002,17 @@ a &gt;&gt;= b</code></pre></td>
974 </td>1002 </td>
975 <td>Bit Shift Right.1003 <td>Bit Shift Right.
976 <ul>1004 <ul>
977 <li><code>b</code> must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as <code>a</code>.</li>1005 <li>{#syntax#}b{#endsyntax#} must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as {#syntax#}a{#endsyntax#}.</li>
978 <li>See also {#link|@shrExact#}.</li>1006 <li>See also {#link|@shrExact#}.</li>
979 </ul>1007 </ul>
980 </td>1008 </td>
981 <td>1009 <td>
982 <pre><code class="zig">10 &gt;&gt; 1 == 5</code></pre>1010 <pre>{#syntax#}10 >> 1 == 5{#endsyntax#}</pre>
983 </td>1011 </td>
984 </tr>1012 </tr>
985 <tr>1013 <tr>
986 <td><pre><code class="zig">a &amp; b1014 <td><pre>{#syntax#}a & b
987a &amp;= b</code></pre></td>1015a &= b{#endsyntax#}</pre></td>
988 <td>1016 <td>
989 <ul>1017 <ul>
990 <li>{#link|Integers#}</li>1018 <li>{#link|Integers#}</li>
...@@ -996,12 +1024,12 @@ a &amp;= b</code></pre></td>...@@ -996,12 +1024,12 @@ a &amp;= b</code></pre></td>
996 </ul>1024 </ul>
997 </td>1025 </td>
998 <td>1026 <td>
999 <pre><code class="zig">0b011 &amp; 0b101 == 0b001</code></pre>1027 <pre>{#syntax#}0b011 &amp; 0b101 == 0b001{#endsyntax#}</pre>
1000 </td>1028 </td>
1001 </tr>1029 </tr>
1002 <tr>1030 <tr>
1003 <td><pre><code class="zig">a | b1031 <td><pre>{#syntax#}a | b
1004a |= b</code></pre></td>1032a |= b{#endsyntax#}</pre></td>
1005 <td>1033 <td>
1006 <ul>1034 <ul>
1007 <li>{#link|Integers#}</li>1035 <li>{#link|Integers#}</li>
...@@ -1013,12 +1041,12 @@ a |= b</code></pre></td>...@@ -1013,12 +1041,12 @@ a |= b</code></pre></td>
1013 </ul>1041 </ul>
1014 </td>1042 </td>
1015 <td>1043 <td>
1016 <pre><code class="zig">0b010 | 0b100 == 0b110</code></pre>1044 <pre>{#syntax#}0b010 | 0b100 == 0b110{#endsyntax#}</pre>
1017 </td>1045 </td>
1018 </tr>1046 </tr>
1019 <tr>1047 <tr>
1020 <td><pre><code class="zig">a ^ b1048 <td><pre>{#syntax#}a ^ b
1021a ^= b</code></pre></td>1049a ^= b{#endsyntax#}</pre></td>
1022 <td>1050 <td>
1023 <ul>1051 <ul>
1024 <li>{#link|Integers#}</li>1052 <li>{#link|Integers#}</li>
...@@ -1030,11 +1058,11 @@ a ^= b</code></pre></td>...@@ -1030,11 +1058,11 @@ a ^= b</code></pre></td>
1030 </ul>1058 </ul>
1031 </td>1059 </td>
1032 <td>1060 <td>
1033 <pre><code class="zig">0b011 ^ 0b101 == 0b110</code></pre>1061 <pre>{#syntax#}0b011 ^ 0b101 == 0b110{#endsyntax#}</pre>
1034 </td>1062 </td>
1035 </tr>1063 </tr>
1036 <tr>1064 <tr>
1037 <td><pre><code class="zig">~a<code></pre></td>1065 <td><pre>{#syntax#}~a{#endsyntax#}</pre></td>
1038 <td>1066 <td>
1039 <ul>1067 <ul>
1040 <li>{#link|Integers#}</li>1068 <li>{#link|Integers#}</li>
...@@ -1044,29 +1072,29 @@ a ^= b</code></pre></td>...@@ -1044,29 +1072,29 @@ a ^= b</code></pre></td>
1044 Bitwise NOT.1072 Bitwise NOT.
1045 </td>1073 </td>
1046 <td>1074 <td>
1047 <pre><code class="zig">~u8(0b0101111) == 0b1010000</code></pre>1075 <pre>{#syntax#}~u8(0b0101111) == 0b1010000{#endsyntax#}</pre>
1048 </td>1076 </td>
1049 </tr>1077 </tr>
1050 <tr>1078 <tr>
1051 <td><pre><code class="zig">a orelse b</code></pre></td>1079 <td><pre>{#syntax#}a orelse b{#endsyntax#}</pre></td>
1052 <td>1080 <td>
1053 <ul>1081 <ul>
1054 <li>{#link|Optionals#}</li>1082 <li>{#link|Optionals#}</li>
1055 </ul>1083 </ul>
1056 </td>1084 </td>
1057 <td>If <code>a</code> is <code>null</code>,1085 <td>If {#syntax#}a{#endsyntax#} is {#syntax#}null{#endsyntax#},
1058 returns <code>b</code> ("default value"),1086 returns {#syntax#}b{#endsyntax#} ("default value"),
1059 otherwise returns the unwrapped value of <code>a</code>.1087 otherwise returns the unwrapped value of {#syntax#}a{#endsyntax#}.
1060 Note that <code>b</code> may be a value of type {#link|noreturn#}.1088 Note that {#syntax#}b{#endsyntax#} may be a value of type {#link|noreturn#}.
1061 </td>1089 </td>
1062 <td>1090 <td>
1063 <pre><code class="zig">const value: ?u32 = null;1091 <pre>{#syntax#}const value: ?u32 = null;
1064const unwrapped = value orelse 1234;1092const unwrapped = value orelse 1234;
1065unwrapped == 1234</code></pre>1093unwrapped == 1234{#endsyntax#}</pre>
1066 </td>1094 </td>
1067 </tr>1095 </tr>
1068 <tr>1096 <tr>
1069 <td><pre><code class="zig">a.?</code></pre></td>1097 <td><pre>{#syntax#}a.?{#endsyntax#}</pre></td>
1070 <td>1098 <td>
1071 <ul>1099 <ul>
1072 <li>{#link|Optionals#}</li>1100 <li>{#link|Optionals#}</li>
...@@ -1074,65 +1102,65 @@ unwrapped == 1234</code></pre>...@@ -1074,65 +1102,65 @@ unwrapped == 1234</code></pre>
1074 </td>1102 </td>
1075 <td>1103 <td>
1076 Equivalent to:1104 Equivalent to:
1077 <pre><code class="zig">a orelse unreachable</code></pre>1105 <pre>{#syntax#}a orelse unreachable{#endsyntax#}</pre>
1078 </td>1106 </td>
1079 <td>1107 <td>
1080 <pre><code class="zig">const value: ?u32 = 5678;1108 <pre>{#syntax#}const value: ?u32 = 5678;
1081value.? == 5678</code></pre>1109value.? == 5678{#endsyntax#}</pre>
1082 </td>1110 </td>
1083 </tr>1111 </tr>
1084 <tr>1112 <tr>
1085 <td><pre><code class="zig">a catch b1113 <td><pre>{#syntax#}a catch b
1086a catch |err| b</code></pre></td>1114a catch |err| b{#endsyntax#}</pre></td>
1087 <td>1115 <td>
1088 <ul>1116 <ul>
1089 <li>{#link|Error Unions|Errors#}</li>1117 <li>{#link|Error Unions|Errors#}</li>
1090 </ul>1118 </ul>
1091 </td>1119 </td>
1092 <td>If <code>a</code> is an <code>error</code>,1120 <td>If {#syntax#}a{#endsyntax#} is an {#syntax#}error{#endsyntax#},
1093 returns <code>b</code> ("default value"),1121 returns {#syntax#}b{#endsyntax#} ("default value"),
1094 otherwise returns the unwrapped value of <code>a</code>.1122 otherwise returns the unwrapped value of {#syntax#}a{#endsyntax#}.
1095 Note that <code>b</code> may be a value of type {#link|noreturn#}.1123 Note that {#syntax#}b{#endsyntax#} may be a value of type {#link|noreturn#}.
1096 <code>err</code> is the <code>error</code> and is in scope of the expression <code>b</code>.1124 {#syntax#}err{#endsyntax#} is the {#syntax#}error{#endsyntax#} and is in scope of the expression {#syntax#}b{#endsyntax#}.
1097 </td>1125 </td>
1098 <td>1126 <td>
1099 <pre><code class="zig">const value: error!u32 = error.Broken;1127 <pre>{#syntax#}const value: error!u32 = error.Broken;
1100const unwrapped = value catch 1234;1128const unwrapped = value catch 1234;
1101unwrapped == 1234</code></pre>1129unwrapped == 1234{#endsyntax#}</pre>
1102 </td>1130 </td>
1103 </tr>1131 </tr>
1104 <tr>1132 <tr>
1105 <td><pre><code class="zig">a and b<code></pre></td>1133 <td><pre>{#syntax#}a and b{#endsyntax#}</pre></td>
1106 <td>1134 <td>
1107 <ul>1135 <ul>
1108 <li>{#link|bool|Primitive Types#}</li>1136 <li>{#link|bool|Primitive Types#}</li>
1109 </ul>1137 </ul>
1110 </td>1138 </td>
1111 <td>1139 <td>
1112 If <code>a</code> is <code>false</code>, returns <code>false</code>1140 If {#syntax#}a{#endsyntax#} is {#syntax#}false{#endsyntax#}, returns {#syntax#}false{#endsyntax#}
1113 without evaluating <code>b</code>. Otherwise, returns <code>b</code>.1141 without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}.
1114 </td>1142 </td>
1115 <td>1143 <td>
1116 <pre><code class="zig">false and true == false</code></pre>1144 <pre>{#syntax#}false and true == false{#endsyntax#}</pre>
1117 </td>1145 </td>
1118 </tr>1146 </tr>
1119 <tr>1147 <tr>
1120 <td><pre><code class="zig">a or b<code></pre></td>1148 <td><pre>{#syntax#}a or b{#endsyntax#}</pre></td>
1121 <td>1149 <td>
1122 <ul>1150 <ul>
1123 <li>{#link|bool|Primitive Types#}</li>1151 <li>{#link|bool|Primitive Types#}</li>
1124 </ul>1152 </ul>
1125 </td>1153 </td>
1126 <td>1154 <td>
1127 If <code>a</code> is <code>true</code>, returns <code>true</code>1155 If {#syntax#}a{#endsyntax#} is {#syntax#}true{#endsyntax#}, returns {#syntax#}true{#endsyntax#}
1128 without evaluating <code>b</code>. Otherwise, returns <code>b</code>.1156 without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}.
1129 </td>1157 </td>
1130 <td>1158 <td>
1131 <pre><code class="zig">false or true == true</code></pre>1159 <pre>{#syntax#}false or true == true{#endsyntax#}</pre>
1132 </td>1160 </td>
1133 </tr>1161 </tr>
1134 <tr>1162 <tr>
1135 <td><pre><code class="zig">!a<code></pre></td>1163 <td><pre>{#syntax#}!a{#endsyntax#}</pre></td>
1136 <td>1164 <td>
1137 <ul>1165 <ul>
1138 <li>{#link|bool|Primitive Types#}</li>1166 <li>{#link|bool|Primitive Types#}</li>
...@@ -1142,11 +1170,11 @@ unwrapped == 1234</code></pre>...@@ -1142,11 +1170,11 @@ unwrapped == 1234</code></pre>
1142 Boolean NOT.1170 Boolean NOT.
1143 </td>1171 </td>
1144 <td>1172 <td>
1145 <pre><code class="zig">!false == true</code></pre>1173 <pre>{#syntax#}!false == true{#endsyntax#}</pre>
1146 </td>1174 </td>
1147 </tr>1175 </tr>
1148 <tr>1176 <tr>
1149 <td><pre><code class="zig">a == b<code></pre></td>1177 <td><pre>{#syntax#}a == b{#endsyntax#}</pre></td>
1150 <td>1178 <td>
1151 <ul>1179 <ul>
1152 <li>{#link|Integers#}</li>1180 <li>{#link|Integers#}</li>
...@@ -1156,30 +1184,30 @@ unwrapped == 1234</code></pre>...@@ -1156,30 +1184,30 @@ unwrapped == 1234</code></pre>
1156 </ul>1184 </ul>
1157 </td>1185 </td>
1158 <td>1186 <td>
1159 Returns <code>true</code> if a and b are equal, otherwise returns <code>false</code>.1187 Returns {#syntax#}true{#endsyntax#} if a and b are equal, otherwise returns {#syntax#}false{#endsyntax#}.
1160 Invokes {#link|Peer Type Resolution#} for the operands.1188 Invokes {#link|Peer Type Resolution#} for the operands.
1161 </td>1189 </td>
1162 <td>1190 <td>
1163 <pre><code class="zig">(1 == 1) == true</code></pre>1191 <pre>{#syntax#}(1 == 1) == true{#endsyntax#}</pre>
1164 </td>1192 </td>
1165 </tr>1193 </tr>
1166 <tr>1194 <tr>
1167 <td><pre><code class="zig">a == null<code></pre></td>1195 <td><pre>{#syntax#}a == null{#endsyntax#}</pre></td>
1168 <td>1196 <td>
1169 <ul>1197 <ul>
1170 <li>{#link|Optionals#}</li>1198 <li>{#link|Optionals#}</li>
1171 </ul>1199 </ul>
1172 </td>1200 </td>
1173 <td>1201 <td>
1174 Returns <code>true</code> if a is <code>null</code>, otherwise returns <code>false</code>.1202 Returns {#syntax#}true{#endsyntax#} if a is {#syntax#}null{#endsyntax#}, otherwise returns {#syntax#}false{#endsyntax#}.
1175 </td>1203 </td>
1176 <td>1204 <td>
1177 <pre><code class="zig">const value: ?u32 = null;1205 <pre>{#syntax#}const value: ?u32 = null;
1178value == null</code></pre>1206value == null{#endsyntax#}</pre>
1179 </td>1207 </td>
1180 </tr>1208 </tr>
1181 <tr>1209 <tr>
1182 <td><pre><code class="zig">a != b<code></pre></td>1210 <td><pre>{#syntax#}a != b{#endsyntax#}</pre></td>
1183 <td>1211 <td>
1184 <ul>1212 <ul>
1185 <li>{#link|Integers#}</li>1213 <li>{#link|Integers#}</li>
...@@ -1189,15 +1217,15 @@ value == null</code></pre>...@@ -1189,15 +1217,15 @@ value == null</code></pre>
1189 </ul>1217 </ul>
1190 </td>1218 </td>
1191 <td>1219 <td>
1192 Returns <code>false</code> if a and b are equal, otherwise returns <code>true</code>.1220 Returns {#syntax#}false{#endsyntax#} if a and b are equal, otherwise returns {#syntax#}true{#endsyntax#}.
1193 Invokes {#link|Peer Type Resolution#} for the operands.1221 Invokes {#link|Peer Type Resolution#} for the operands.
1194 </td>1222 </td>
1195 <td>1223 <td>
1196 <pre><code class="zig">(1 != 1) == false</code></pre>1224 <pre>{#syntax#}(1 != 1) == false{#endsyntax#}</pre>
1197 </td>1225 </td>
1198 </tr>1226 </tr>
1199 <tr>1227 <tr>
1200 <td><pre><code class="zig">a &gt; b<code></pre></td>1228 <td><pre>{#syntax#}a > b{#endsyntax#}</pre></td>
1201 <td>1229 <td>
1202 <ul>1230 <ul>
1203 <li>{#link|Integers#}</li>1231 <li>{#link|Integers#}</li>
...@@ -1205,15 +1233,15 @@ value == null</code></pre>...@@ -1205,15 +1233,15 @@ value == null</code></pre>
1205 </ul>1233 </ul>
1206 </td>1234 </td>
1207 <td>1235 <td>
1208 Returns <code>true</code> if a is greater than b, otherwise returns <code>false</code>.1236 Returns {#syntax#}true{#endsyntax#} if a is greater than b, otherwise returns {#syntax#}false{#endsyntax#}.
1209 Invokes {#link|Peer Type Resolution#} for the operands.1237 Invokes {#link|Peer Type Resolution#} for the operands.
1210 </td>1238 </td>
1211 <td>1239 <td>
1212 <pre><code class="zig">(2 &gt; 1) == true</code></pre>1240 <pre>{#syntax#}(2 > 1) == true{#endsyntax#}</pre>
1213 </td>1241 </td>
1214 </tr>1242 </tr>
1215 <tr>1243 <tr>
1216 <td><pre><code class="zig">a &gt;= b<code></pre></td>1244 <td><pre>{#syntax#}a >= b{#endsyntax#}</pre></td>
1217 <td>1245 <td>
1218 <ul>1246 <ul>
1219 <li>{#link|Integers#}</li>1247 <li>{#link|Integers#}</li>
...@@ -1221,15 +1249,15 @@ value == null</code></pre>...@@ -1221,15 +1249,15 @@ value == null</code></pre>
1221 </ul>1249 </ul>
1222 </td>1250 </td>
1223 <td>1251 <td>
1224 Returns <code>true</code> if a is greater than or equal to b, otherwise returns <code>false</code>.1252 Returns {#syntax#}true{#endsyntax#} if a is greater than or equal to b, otherwise returns {#syntax#}false{#endsyntax#}.
1225 Invokes {#link|Peer Type Resolution#} for the operands.1253 Invokes {#link|Peer Type Resolution#} for the operands.
1226 </td>1254 </td>
1227 <td>1255 <td>
1228 <pre><code class="zig">(2 &gt;= 1) == true</code></pre>1256 <pre>{#syntax#}(2 >= 1) == true{#endsyntax#}</pre>
1229 </td>1257 </td>
1230 </tr>1258 </tr>
1231 <tr>1259 <tr>
1232 <td><pre><code class="zig">a &lt; b<code></pre></td>1260 <td><pre>{#syntax#}a < b{#endsyntax#}</pre></td>
1233 <td>1261 <td>
1234 <ul>1262 <ul>
1235 <li>{#link|Integers#}</li>1263 <li>{#link|Integers#}</li>
...@@ -1237,15 +1265,15 @@ value == null</code></pre>...@@ -1237,15 +1265,15 @@ value == null</code></pre>
1237 </ul>1265 </ul>
1238 </td>1266 </td>
1239 <td>1267 <td>
1240 Returns <code>true</code> if a is less than b, otherwise returns <code>false</code>.1268 Returns {#syntax#}true{#endsyntax#} if a is less than b, otherwise returns {#syntax#}false{#endsyntax#}.
1241 Invokes {#link|Peer Type Resolution#} for the operands.1269 Invokes {#link|Peer Type Resolution#} for the operands.
1242 </td>1270 </td>
1243 <td>1271 <td>
1244 <pre><code class="zig">(1 &lt; 2) == true</code></pre>1272 <pre>{#syntax#}(1 < 2) == true{#endsyntax#}></pre>
1245 </td>1273 </td>
1246 </tr>1274 </tr>
1247 <tr>1275 <tr>
1248 <td><pre><code class="zig">a &lt;= b<code></pre></td>1276 <td><pre>{#syntax#}a <= b{#endsyntax#}</pre></td>
1249 <td>1277 <td>
1250 <ul>1278 <ul>
1251 <li>{#link|Integers#}</li>1279 <li>{#link|Integers#}</li>
...@@ -1253,15 +1281,15 @@ value == null</code></pre>...@@ -1253,15 +1281,15 @@ value == null</code></pre>
1253 </ul>1281 </ul>
1254 </td>1282 </td>
1255 <td>1283 <td>
1256 Returns <code>true</code> if a is less than or equal to b, otherwise returns <code>false</code>.1284 Returns {#syntax#}true{#endsyntax#} if a is less than or equal to b, otherwise returns {#syntax#}false{#endsyntax#}.
1257 Invokes {#link|Peer Type Resolution#} for the operands.1285 Invokes {#link|Peer Type Resolution#} for the operands.
1258 </td>1286 </td>
1259 <td>1287 <td>
1260 <pre><code class="zig">(1 &lt;= 2) == true</code></pre>1288 <pre>{#syntax#}(1 <= 2) == true{#endsyntax#}</pre>
1261 </td>1289 </td>
1262 </tr>1290 </tr>
1263 <tr>1291 <tr>
1264 <td><pre><code class="zig">a ++ b<code></pre></td>1292 <td><pre>{#syntax#}a ++ b{#endsyntax#}</pre></td>
1265 <td>1293 <td>
1266 <ul>1294 <ul>
1267 <li>{#link|Arrays#}</li>1295 <li>{#link|Arrays#}</li>
...@@ -1270,19 +1298,19 @@ value == null</code></pre>...@@ -1270,19 +1298,19 @@ value == null</code></pre>
1270 <td>1298 <td>
1271 Array concatenation.1299 Array concatenation.
1272 <ul>1300 <ul>
1273 <li>Only available when <code>a</code> and <code>b</code> are {#link|compile-time known|comptime#}.1301 <li>Only available when {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are {#link|compile-time known|comptime#}.
1274 </ul>1302 </ul>
1275 </td>1303 </td>
1276 <td>1304 <td>
1277 <pre><code class="zig">const mem = @import("std").mem;1305 <pre>{#syntax#}const mem = @import("std").mem;
1278const array1 = []u32{1,2};1306const array1 = []u32{1,2};
1279const array2 = []u32{3,4};1307const array2 = []u32{3,4};
1280const together = array1 ++ array2;1308const together = array1 ++ array2;
1281mem.eql(u32, together, []u32{1,2,3,4})</code></pre>1309mem.eql(u32, together, []u32{1,2,3,4}){#endsyntax#}</pre>
1282 </td>1310 </td>
1283 </tr>1311 </tr>
1284 <tr>1312 <tr>
1285 <td><pre><code class="zig">a ** b<code></pre></td>1313 <td><pre>{#syntax#}a ** b{#endsyntax#}</pre></td>
1286 <td>1314 <td>
1287 <ul>1315 <ul>
1288 <li>{#link|Arrays#}</li>1316 <li>{#link|Arrays#}</li>
...@@ -1291,17 +1319,17 @@ mem.eql(u32, together, []u32{1,2,3,4})</code></pre>...@@ -1291,17 +1319,17 @@ mem.eql(u32, together, []u32{1,2,3,4})</code></pre>
1291 <td>1319 <td>
1292 Array multiplication.1320 Array multiplication.
1293 <ul>1321 <ul>
1294 <li>Only available when <code>a</code> and <code>b</code> are {#link|compile-time known|comptime#}.1322 <li>Only available when {#syntax#}a{#endsyntax#} and {#syntax#}b{#endsyntax#} are {#link|compile-time known|comptime#}.
1295 </ul>1323 </ul>
1296 </td>1324 </td>
1297 <td>1325 <td>
1298 <pre><code class="zig">const mem = @import("std").mem;1326 <pre>{#syntax#}const mem = @import("std").mem;
1299const pattern = "ab" ** 3;1327const pattern = "ab" ** 3;
1300mem.eql(u8, pattern, "ababab")</code></pre>1328mem.eql(u8, pattern, "ababab"){#endsyntax#}</pre>
1301 </td>1329 </td>
1302 </tr>1330 </tr>
1303 <tr>1331 <tr>
1304 <td><pre><code class="zig">a.*<code></pre></td>1332 <td><pre>{#syntax#}a.*{#endsyntax#}</pre></td>
1305 <td>1333 <td>
1306 <ul>1334 <ul>
1307 <li>{#link|Pointers#}</li>1335 <li>{#link|Pointers#}</li>
...@@ -1311,13 +1339,13 @@ mem.eql(u8, pattern, "ababab")</code></pre>...@@ -1311,13 +1339,13 @@ mem.eql(u8, pattern, "ababab")</code></pre>
1311 Pointer dereference.1339 Pointer dereference.
1312 </td>1340 </td>
1313 <td>1341 <td>
1314 <pre><code class="zig">const x: u32 = 1234;1342 <pre>{#syntax#}const x: u32 = 1234;
1315const ptr = &amp;x;1343const ptr = &x;
1316x.* == 1234</code></pre>1344x.* == 1234{#endsyntax#}</pre>
1317 </td>1345 </td>
1318 </tr>1346 </tr>
1319 <tr>1347 <tr>
1320 <td><pre><code class="zig">&amp;a<code></pre></td>1348 <td><pre>{#syntax#}&amp;a{#endsyntax#}</pre></td>
1321 <td>1349 <td>
1322 All types1350 All types
1323 </td>1351 </td>
...@@ -1325,13 +1353,13 @@ x.* == 1234</code></pre>...@@ -1325,13 +1353,13 @@ x.* == 1234</code></pre>
1325 Address of.1353 Address of.
1326 </td>1354 </td>
1327 <td>1355 <td>
1328 <pre><code class="zig">const x: u32 = 1234;1356 <pre>{#syntax#}const x: u32 = 1234;
1329const ptr = &amp;x;1357const ptr = &x;
1330x.* == 1234</code></pre>1358x.* == 1234{#endsyntax#}</pre>
1331 </td>1359 </td>
1332 </tr>1360 </tr>
1333 <tr>1361 <tr>
1334 <td><pre><code class="zig">a || b<code></pre></td>1362 <td><pre>{#syntax#}a || b{#endsyntax#}</pre></td>
1335 <td>1363 <td>
1336 <ul>1364 <ul>
1337 <li>{#link|Error Set Type#}</li>1365 <li>{#link|Error Set Type#}</li>
...@@ -1341,30 +1369,30 @@ x.* == 1234</code></pre>...@@ -1341,30 +1369,30 @@ x.* == 1234</code></pre>
1341 {#link|Merging Error Sets#}1369 {#link|Merging Error Sets#}
1342 </td>1370 </td>
1343 <td>1371 <td>
1344 <pre><code class="zig">const A = error{One};1372 <pre>{#syntax#}const A = error{One};
1345const B = error{Two};1373const B = error{Two};
1346(A || B) == error{One, Two}</code></pre>1374(A || B) == error{One, Two}{#endsyntax#}</pre>
1347 </td>1375 </td>
1348 </tr>1376 </tr>
1349 </table>1377 </table>
1350 </div>1378 </div>
1351 {#header_close#}1379 {#header_close#}
1352 {#header_open|Precedence#}1380 {#header_open|Precedence#}
1353 <pre><code>x() x[] x.y1381 <pre>{#syntax#}x() x[] x.y
1354a!b1382a!b
1355!x -x -%x ~x &amp;x ?x1383!x -x -%x ~x &x ?x
1356x{} x.* x.?1384x{} x.* x.?
1357! * / % ** *% ||1385! * / % ** *% ||
1358+ - ++ +% -%1386+ - ++ +% -%
1359&lt;&lt; &gt;&gt;1387<< >>
1360&amp;1388&
1361^1389^
1362|1390|
1363== != &lt; &gt; &lt;= &gt;=1391== != < > <= >=
1364and1392and
1365or1393or
1366orelse catch1394orelse catch
1367= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>1395= *= /= %= += -= <<= >>= &= ^= |={#endsyntax#}</pre>
1368 {#header_close#}1396 {#header_close#}
1369 {#header_close#}1397 {#header_close#}
1370 {#header_open|Arrays#}1398 {#header_open|Arrays#}
...@@ -1613,7 +1641,7 @@ test "pointer child type" {...@@ -1613,7 +1641,7 @@ test "pointer child type" {
1613 </p>1641 </p>
1614 <p>1642 <p>
1615 Alignment depends on the CPU architecture, but is always a power of two, and1643 Alignment depends on the CPU architecture, but is always a power of two, and
1616 less than <code>1 &lt;&lt; 29</code>.1644 less than {#syntax#}1 << 29{#endsyntax#}.
1617 </p>1645 </p>
1618 <p>1646 <p>
1619 In Zig, a pointer type has an alignment value. If the value is equal to the1647 In Zig, a pointer type has an alignment value. If the value is equal to the
...@@ -1633,8 +1661,8 @@ test "variable alignment" {...@@ -1633,8 +1661,8 @@ test "variable alignment" {
1633 }1661 }
1634}1662}
1635 {#code_end#}1663 {#code_end#}
1636 <p>In the same way that a <code>*i32</code> can be {#link|implicitly cast|Implicit Casts#} to a1664 <p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to a
1637 <code>*const i32</code>, a pointer with a larger alignment can be implicitly1665 {#syntax#}*const i32{#endsyntax#}, a pointer with a larger alignment can be implicitly
1638 cast to a pointer with a smaller alignment, but not vice versa.1666 cast to a pointer with a smaller alignment, but not vice versa.
1639 </p>1667 </p>
1640 <p>1668 <p>
...@@ -1689,14 +1717,14 @@ fn foo(bytes: []u8) u32 {...@@ -1689,14 +1717,14 @@ fn foo(bytes: []u8) u32 {
1689 {#header_open|Type Based Alias Analysis#}1717 {#header_open|Type Based Alias Analysis#}
1690 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to1718 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
1691 perform some optimizations. This means that pointers of different types must1719 perform some optimizations. This means that pointers of different types must
1692 not alias the same memory, with the exception of <code>u8</code>. Pointers to1720 not alias the same memory, with the exception of {#syntax#}u8{#endsyntax#}. Pointers to
1693 <code>u8</code> can alias any memory.1721 {#syntax#}u8{#endsyntax#} can alias any memory.
1694 </p>1722 </p>
1695 <p>As an example, this code produces undefined behavior:</p>1723 <p>As an example, this code produces undefined behavior:</p>
1696 <pre><code class="zig">@ptrCast(*u32, f32(12.34)).*</code></pre>1724 <pre>{#syntax#}@ptrCast(*u32, f32(12.34)).*{#endsyntax#}</pre>
1697 <p>Instead, use {#link|@bitCast#}:1725 <p>Instead, use {#link|@bitCast#}:
1698 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>1726 <pre>{#syntax#}@bitCast(u32, f32(12.34)){#endsyntax#}</pre>
1699 <p>As an added benefit, the <code>@bitCast</code> version works at compile-time.</p>1727 <p>As an added benefit, the {#syntax#}@bitCast{#endsyntax#} version works at compile-time.</p>
1700 {#see_also|Slices|Memory#}1728 {#see_also|Slices|Memory#}
1701 {#header_close#}1729 {#header_close#}
1702 {#header_close#}1730 {#header_close#}
...@@ -1924,9 +1952,9 @@ test "linked list" {...@@ -1924,9 +1952,9 @@ test "linked list" {
1924 <ul>1952 <ul>
1925 <li>If the struct is in the initialization expression of a variable, it gets named after1953 <li>If the struct is in the initialization expression of a variable, it gets named after
1926 that variable.</li>1954 that variable.</li>
1927 <li>If the struct is in the <code>return</code> expression, it gets named after1955 <li>If the struct is in the {#syntax#}return{#endsyntax#} expression, it gets named after
1928 the function it is returning from, with the parameter values serialized.</li>1956 the function it is returning from, with the parameter values serialized.</li>
1929 <li>Otherwise, the struct gets a same such as <code>(anonymous struct at file.zig:7:38)</code>.</li>1957 <li>Otherwise, the struct gets a same such as {#syntax#}(anonymous struct at file.zig:7:38){#endsyntax#}.</li>
1930 </ul>1958 </ul>
1931 {#code_begin|exe|struct_name#}1959 {#code_begin|exe|struct_name#}
1932const std = @import("std");1960const std = @import("std");
...@@ -2058,7 +2086,7 @@ const Foo = enum { A, B, C };...@@ -2058,7 +2086,7 @@ const Foo = enum { A, B, C };
2058export fn entry(foo: Foo) void { }2086export fn entry(foo: Foo) void { }
2059 {#code_end#}2087 {#code_end#}
2060 <p>2088 <p>
2061 For a C-ABI-compatible enum, use <code class="zig">extern enum</code>:2089 For a C-ABI-compatible enum, use {#syntax#}extern enum{#endsyntax#}:
2062 </p>2090 </p>
2063 {#code_begin|obj#}2091 {#code_begin|obj#}
2064const Foo = extern enum { A, B, C };2092const Foo = extern enum { A, B, C };
...@@ -2067,7 +2095,7 @@ export fn entry(foo: Foo) void { }...@@ -2067,7 +2095,7 @@ export fn entry(foo: Foo) void { }
2067 {#header_close#}2095 {#header_close#}
2068 {#header_open|packed enum#}2096 {#header_open|packed enum#}
2069 <p>By default, the size of enums is not guaranteed.</p>2097 <p>By default, the size of enums is not guaranteed.</p>
2070 <p><code>packed enum</code> causes the size of the enum to be the same as the size of the integer tag type2098 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the integer tag type
2071 of the enum:</p>2099 of the enum:</p>
2072 {#code_begin|test#}2100 {#code_begin|test#}
2073const std = @import("std");2101const std = @import("std");
...@@ -2218,7 +2246,7 @@ test "access variable after block scope" {...@@ -2218,7 +2246,7 @@ test "access variable after block scope" {
2218 x += 1;2246 x += 1;
2219}2247}
2220 {#code_end#}2248 {#code_end#}
2221 <p>Blocks are expressions. When labeled, <code>break</code> can be used2249 <p>Blocks are expressions. When labeled, {#syntax#}break{#endsyntax#} can be used
2222 to return a value from the block:2250 to return a value from the block:
2223 </p>2251 </p>
2224 {#code_begin|test#}2252 {#code_begin|test#}
...@@ -2236,7 +2264,7 @@ test "labeled break from labeled block expression" {...@@ -2236,7 +2264,7 @@ test "labeled break from labeled block expression" {
2236 assert(y == 124);2264 assert(y == 124);
2237}2265}
2238 {#code_end#}2266 {#code_end#}
2239 <p>Here, <code>blk</code> can be any name.</p>2267 <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p>
2240 {#see_also|Labeled while|Labeled for#}2268 {#see_also|Labeled while|Labeled for#}
2241 {#header_close#}2269 {#header_close#}
2242 {#header_open|switch#}2270 {#header_open|switch#}
...@@ -2352,7 +2380,7 @@ test "while basic" {...@@ -2352,7 +2380,7 @@ test "while basic" {
2352}2380}
2353 {#code_end#}2381 {#code_end#}
2354 <p>2382 <p>
2355 Use <code>break</code> to exit a while loop early.2383 Use {#syntax#}break{#endsyntax#} to exit a while loop early.
2356 </p>2384 </p>
2357 {#code_begin|test|while#}2385 {#code_begin|test|while#}
2358const assert = @import("std").debug.assert;2386const assert = @import("std").debug.assert;
...@@ -2368,7 +2396,7 @@ test "while break" {...@@ -2368,7 +2396,7 @@ test "while break" {
2368}2396}
2369 {#code_end#}2397 {#code_end#}
2370 <p>2398 <p>
2371 Use <code>continue</code> to jump back to the beginning of the loop.2399 Use {#syntax#}continue{#endsyntax#} to jump back to the beginning of the loop.
2372 </p>2400 </p>
2373 {#code_begin|test|while#}2401 {#code_begin|test|while#}
2374const assert = @import("std").debug.assert;2402const assert = @import("std").debug.assert;
...@@ -2386,7 +2414,7 @@ test "while continue" {...@@ -2386,7 +2414,7 @@ test "while continue" {
2386 {#code_end#}2414 {#code_end#}
2387 <p>2415 <p>
2388 While loops support a continue expression which is executed when the loop2416 While loops support a continue expression which is executed when the loop
2389 is continued. The <code>continue</code> keyword respects this expression.2417 is continued. The {#syntax#}continue{#endsyntax#} keyword respects this expression.
2390 </p>2418 </p>
2391 {#code_begin|test|while#}2419 {#code_begin|test|while#}
2392const assert = @import("std").debug.assert;2420const assert = @import("std").debug.assert;
...@@ -2408,13 +2436,13 @@ test "while loop continue expression, more complicated" {...@@ -2408,13 +2436,13 @@ test "while loop continue expression, more complicated" {
2408 {#code_end#}2436 {#code_end#}
2409 <p>2437 <p>
2410 While loops are expressions. The result of the expression is the2438 While loops are expressions. The result of the expression is the
2411 result of the <code>else</code> clause of a while loop, which is executed when2439 result of the {#syntax#}else{#endsyntax#} clause of a while loop, which is executed when
2412 the condition of the while loop is tested as false.2440 the condition of the while loop is tested as false.
2413 </p>2441 </p>
2414 <p>2442 <p>
2415 <code>break</code>, like <code>return</code>, accepts a value2443 {#syntax#}break{#endsyntax#}, like {#syntax#}return{#endsyntax#}, accepts a value
2416 parameter. This is the result of the <code>while</code> expression.2444 parameter. This is the result of the {#syntax#}while{#endsyntax#} expression.
2417 When you <code>break</code> from a while loop, the <code>else</code> branch is not2445 When you {#syntax#}break{#endsyntax#} from a while loop, the {#syntax#}else{#endsyntax#} branch is not
2418 evaluated.2446 evaluated.
2419 </p>2447 </p>
2420 {#code_begin|test|while#}2448 {#code_begin|test|while#}
...@@ -2435,8 +2463,8 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {...@@ -2435,8 +2463,8 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
2435}2463}
2436 {#code_end#}2464 {#code_end#}
2437 {#header_open|Labeled while#}2465 {#header_open|Labeled while#}
2438 <p>When a <code>while</code> loop is labeled, it can be referenced from a <code>break</code>2466 <p>When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
2439 or <code>continue</code> from within a nested loop:</p>2467 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
2440 {#code_begin|test#}2468 {#code_begin|test#}
2441test "nested break" {2469test "nested break" {
2442 outer: while (true) {2470 outer: while (true) {
...@@ -2463,11 +2491,11 @@ test "nested continue" {...@@ -2463,11 +2491,11 @@ test "nested continue" {
2463 exits.2491 exits.
2464 </p>2492 </p>
2465 <p>2493 <p>
2466 When the <code>|x|</code> syntax is present on a <code>while</code> expression,2494 When the {#syntax#}|x|{#endsyntax#} syntax is present on a {#syntax#}while{#endsyntax#} expression,
2467 the while condition must have an {#link|Optional Type#}.2495 the while condition must have an {#link|Optional Type#}.
2468 </p>2496 </p>
2469 <p>2497 <p>
2470 The <code>else</code> branch is allowed on optional iteration. In this case, it will2498 The {#syntax#}else{#endsyntax#} branch is allowed on optional iteration. In this case, it will
2471 be executed on the first null value encountered.2499 be executed on the first null value encountered.
2472 </p>2500 </p>
2473 {#code_begin|test|while#}2501 {#code_begin|test|while#}
...@@ -2509,7 +2537,7 @@ fn eventuallyNullSequence() ?u32 {...@@ -2509,7 +2537,7 @@ fn eventuallyNullSequence() ?u32 {
2509 the loop is finished.2537 the loop is finished.
2510 </p>2538 </p>
2511 <p>2539 <p>
2512 When the <code>else |x|</code> syntax is present on a <code>while</code> expression,2540 When the {#syntax#}else |x|{#endsyntax#} syntax is present on a {#syntax#}while{#endsyntax#} expression,
2513 the while condition must have an {#link|Error Union Type#}.2541 the while condition must have an {#link|Error Union Type#}.
2514 </p>2542 </p>
2515 {#code_begin|test|while#}2543 {#code_begin|test|while#}
...@@ -2565,7 +2593,7 @@ fn typeNameLength(comptime T: type) usize {...@@ -2565,7 +2593,7 @@ fn typeNameLength(comptime T: type) usize {
2565}2593}
2566 {#code_end#}2594 {#code_end#}
2567 <p>2595 <p>
2568 It is recommended to use <code>inline</code> loops only for one of these reasons:2596 It is recommended to use {#syntax#}inline{#endsyntax#} loops only for one of these reasons:
2569 </p>2597 </p>
2570 <ul>2598 <ul>
2571 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>2599 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>
...@@ -2643,8 +2671,8 @@ test "for else" {...@@ -2643,8 +2671,8 @@ test "for else" {
2643}2671}
2644 {#code_end#}2672 {#code_end#}
2645 {#header_open|Labeled for#}2673 {#header_open|Labeled for#}
2646 <p>When a <code>for</code> loop is labeled, it can be referenced from a <code>break</code>2674 <p>When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
2647 or <code>continue</code> from within a nested loop:</p>2675 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
2648 {#code_begin|test#}2676 {#code_begin|test#}
2649const std = @import("std");2677const std = @import("std");
2650const assert = std.debug.assert;2678const assert = std.debug.assert;
...@@ -2704,7 +2732,7 @@ fn typeNameLength(comptime T: type) usize {...@@ -2704,7 +2732,7 @@ fn typeNameLength(comptime T: type) usize {
2704}2732}
2705 {#code_end#}2733 {#code_end#}
2706 <p>2734 <p>
2707 It is recommended to use <code>inline</code> loops only for one of these reasons:2735 It is recommended to use {#syntax#}inline{#endsyntax#} loops only for one of these reasons:
2708 </p>2736 </p>
2709 <ul>2737 <ul>
2710 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>2738 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>
...@@ -2904,13 +2932,13 @@ test "errdefer unwinding" {...@@ -2904,13 +2932,13 @@ test "errdefer unwinding" {
2904 {#header_close#}2932 {#header_close#}
2905 {#header_open|unreachable#}2933 {#header_open|unreachable#}
2906 <p>2934 <p>
2907 In <code>Debug</code> and <code>ReleaseSafe</code> mode, and when using <code>zig test</code>,2935 In {#syntax#}Debug{#endsyntax#} and {#syntax#}ReleaseSafe{#endsyntax#} mode, and when using <code>zig test</code>,
2908 <code>unreachable</code> emits a call to <code>panic</code> with the message <code>reached unreachable code</code>.2936 {#syntax#}unreachable{#endsyntax#} emits a call to {#syntax#}panic{#endsyntax#} with the message <code>reached unreachable code</code>.
2909 </p>2937 </p>
2910 <p>2938 <p>
2911 In <code>ReleaseFast</code> mode, the optimizer uses the assumption that <code>unreachable</code> code2939 In {#syntax#}ReleaseFast{#endsyntax#} mode, the optimizer uses the assumption that {#syntax#}unreachable{#endsyntax#} code
2912 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode2940 will never be hit to perform optimizations. However, <code>zig test</code> even in {#syntax#}ReleaseFast{#endsyntax#} mode
2913 still emits <code>unreachable</code> as calls to <code>panic</code>.2941 still emits {#syntax#}unreachable{#endsyntax#} as calls to {#syntax#}panic{#endsyntax#}.
2914 </p>2942 </p>
2915 {#header_open|Basics#}2943 {#header_open|Basics#}
2916 {#code_begin|test#}2944 {#code_begin|test#}
...@@ -2956,17 +2984,17 @@ test "type of unreachable" {...@@ -2956,17 +2984,17 @@ test "type of unreachable" {
2956 {#header_close#}2984 {#header_close#}
2957 {#header_open|noreturn#}2985 {#header_open|noreturn#}
2958 <p>2986 <p>
2959 <code>noreturn</code> is the type of:2987 {#syntax#}noreturn{#endsyntax#} is the type of:
2960 </p>2988 </p>
2961 <ul>2989 <ul>
2962 <li><code>break</code></li>2990 <li>{#syntax#}break{#endsyntax#}</li>
2963 <li><code>continue</code></li>2991 <li>{#syntax#}continue{#endsyntax#}</li>
2964 <li><code>return</code></li>2992 <li>{#syntax#}return{#endsyntax#}</li>
2965 <li><code>unreachable</code></li>2993 <li>{#syntax#}unreachable{#endsyntax#}</li>
2966 <li><code>while (true) {}</code></li>2994 <li>{#syntax#}while (true) {}{#endsyntax#}</li>
2967 </ul>2995 </ul>
2968 <p>When resolving types together, such as <code>if</code> clauses or <code>switch</code> prongs,2996 <p>When resolving types together, such as {#syntax#}if{#endsyntax#} clauses or {#syntax#}switch{#endsyntax#} prongs,
2969 the <code>noreturn</code> type is compatible with every other type. Consider:2997 the {#syntax#}noreturn{#endsyntax#} type is compatible with every other type. Consider:
2970 </p>2998 </p>
2971 {#code_begin|test#}2999 {#code_begin|test#}
2972fn foo(condition: bool, b: u32) void {3000fn foo(condition: bool, b: u32) void {
...@@ -2977,7 +3005,7 @@ test "noreturn" {...@@ -2977,7 +3005,7 @@ test "noreturn" {
2977 foo(false, 1);3005 foo(false, 1);
2978}3006}
2979 {#code_end#}3007 {#code_end#}
2980 <p>Another use case for <code>noreturn</code> is the <code>exit</code> function:</p>3008 <p>Another use case for {#syntax#}noreturn{#endsyntax#} is the {#syntax#}exit{#endsyntax#} function:</p>
2981 {#code_begin|test#}3009 {#code_begin|test#}
2982 {#target_windows#}3010 {#target_windows#}
2983pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn;3011pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn;
...@@ -3106,7 +3134,7 @@ test "fn reflection" {...@@ -3106,7 +3134,7 @@ test "fn reflection" {
3106 </p>3134 </p>
3107 <p>3135 <p>
3108 The number of unique error values across the entire compilation should determine the size of the error set type.3136 The number of unique error values across the entire compilation should determine the size of the error set type.
3109 However right now it is hard coded to be a <code>u16</code>. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>.3137 However right now it is hard coded to be a {#syntax#}u16{#endsyntax#}. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>.
3110 </p>3138 </p>
3111 <p>3139 <p>
3112 You can {#link|implicitly cast|Implicit Casts#} an error from a subset to its superset:3140 You can {#link|implicitly cast|Implicit Casts#} an error from a subset to its superset:
...@@ -3169,7 +3197,7 @@ const err = (error {FileNotFound}).FileNotFound;...@@ -3169,7 +3197,7 @@ const err = (error {FileNotFound}).FileNotFound;
3169 This becomes useful when using {#link|Inferred Error Sets#}.3197 This becomes useful when using {#link|Inferred Error Sets#}.
3170 </p>3198 </p>
3171 {#header_open|The Global Error Set#}3199 {#header_open|The Global Error Set#}
3172 <p><code>error</code> refers to the global error set.3200 <p>{#syntax#}error{#endsyntax#} refers to the global error set.
3173 This is the error set that contains all errors in the entire compilation unit.3201 This is the error set that contains all errors in the entire compilation unit.
3174 It is a superset of all other error sets and a subset of none of them.3202 It is a superset of all other error sets and a subset of none of them.
3175 </p>3203 </p>
...@@ -3188,7 +3216,7 @@ const err = (error {FileNotFound}).FileNotFound;...@@ -3188,7 +3216,7 @@ const err = (error {FileNotFound}).FileNotFound;
3188 {#header_close#}3216 {#header_close#}
3189 {#header_open|Error Union Type#}3217 {#header_open|Error Union Type#}
3190 <p>3218 <p>
3191 An error set type and normal type can be combined with the <code>!</code>3219 An error set type and normal type can be combined with the {#syntax#}!{#endsyntax#}
3192 binary operator to form an error union type. You are likely to use an3220 binary operator to form an error union type. You are likely to use an
3193 error union type more often than an error set type by itself.3221 error union type more often than an error set type by itself.
3194 </p>3222 </p>
...@@ -3235,14 +3263,14 @@ test "parse u64" {...@@ -3235,14 +3263,14 @@ test "parse u64" {
3235}3263}
3236 {#code_end#}3264 {#code_end#}
3237 <p>3265 <p>
3238 Notice the return type is <code>!u64</code>. This means that the function3266 Notice the return type is {#syntax#}!u64{#endsyntax#}. This means that the function
3239 either returns an unsigned 64 bit integer, or an error. We left off the error set3267 either returns an unsigned 64 bit integer, or an error. We left off the error set
3240 to the left of the <code>!</code>, so the error set is inferred.3268 to the left of the {#syntax#}!{#endsyntax#}, so the error set is inferred.
3241 </p>3269 </p>
3242 <p>3270 <p>
3243 Within the function definition, you can see some return statements that return3271 Within the function definition, you can see some return statements that return
3244 an error, and at the bottom a return statement that returns a <code>u64</code>.3272 an error, and at the bottom a return statement that returns a {#syntax#}u64{#endsyntax#}.
3245 Both types {#link|implicitly cast|Implicit Casts#} to <code>error!u64</code>.3273 Both types {#link|implicitly cast|Implicit Casts#} to {#syntax#}error!u64{#endsyntax#}.
3246 </p>3274 </p>
3247 <p>3275 <p>
3248 What it looks like to use this function varies depending on what you're3276 What it looks like to use this function varies depending on what you're
...@@ -3255,7 +3283,7 @@ test "parse u64" {...@@ -3255,7 +3283,7 @@ test "parse u64" {
3255 <li>You want to take a different action for each possible error.</li>3283 <li>You want to take a different action for each possible error.</li>
3256 </ul>3284 </ul>
3257 {#header_open|catch#}3285 {#header_open|catch#}
3258 <p>If you want to provide a default value, you can use the <code>catch</code> binary operator:</p>3286 <p>If you want to provide a default value, you can use the {#syntax#}catch{#endsyntax#} binary operator:</p>
3259 {#code_begin|syntax#}3287 {#code_begin|syntax#}
3260fn doAThing(str: []u8) void {3288fn doAThing(str: []u8) void {
3261 const number = parseU64(str, 10) catch 13;3289 const number = parseU64(str, 10) catch 13;
...@@ -3263,9 +3291,9 @@ fn doAThing(str: []u8) void {...@@ -3263,9 +3291,9 @@ fn doAThing(str: []u8) void {
3263}3291}
3264 {#code_end#}3292 {#code_end#}
3265 <p>3293 <p>
3266 In this code, <code>number</code> will be equal to the successfully parsed string, or3294 In this code, {#syntax#}number{#endsyntax#} will be equal to the successfully parsed string, or
3267 a default value of 13. The type of the right hand side of the binary <code>catch</code> operator must3295 a default value of 13. The type of the right hand side of the binary {#syntax#}catch{#endsyntax#} operator must
3268 match the unwrapped error union type, or be of type <code>noreturn</code>.3296 match the unwrapped error union type, or be of type {#syntax#}noreturn{#endsyntax#}.
3269 </p>3297 </p>
3270 {#header_close#}3298 {#header_close#}
3271 {#header_open|try#}3299 {#header_open|try#}
...@@ -3278,7 +3306,7 @@ fn doAThing(str: []u8) !void {...@@ -3278,7 +3306,7 @@ fn doAThing(str: []u8) !void {
3278}3306}
3279 {#code_end#}3307 {#code_end#}
3280 <p>3308 <p>
3281 There is a shortcut for this. The <code>try</code> expression:3309 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:
3282 </p>3310 </p>
3283 {#code_begin|syntax#}3311 {#code_begin|syntax#}
3284fn doAThing(str: []u8) !void {3312fn doAThing(str: []u8) !void {
...@@ -3287,7 +3315,7 @@ fn doAThing(str: []u8) !void {...@@ -3287,7 +3315,7 @@ fn doAThing(str: []u8) !void {
3287}3315}
3288 {#code_end#}3316 {#code_end#}
3289 <p>3317 <p>
3290 <code>try</code> evaluates an error union expression. If it is an error, it returns3318 {#syntax#}try{#endsyntax#} evaluates an error union expression. If it is an error, it returns
3291 from the current function with the same error. Otherwise, the expression results in3319 from the current function with the same error. Otherwise, the expression results in
3292 the unwrapped value.3320 the unwrapped value.
3293 </p>3321 </p>
...@@ -3299,7 +3327,7 @@ fn doAThing(str: []u8) !void {...@@ -3299,7 +3327,7 @@ fn doAThing(str: []u8) !void {
3299 {#code_begin|syntax#}const number = parseU64("1234", 10) catch unreachable;{#code_end#}3327 {#code_begin|syntax#}const number = parseU64("1234", 10) catch unreachable;{#code_end#}
3300 <p>3328 <p>
3301 Here we know for sure that "1234" will parse successfully. So we put the3329 Here we know for sure that "1234" will parse successfully. So we put the
3302 <code>unreachable</code> value on the right hand side. <code>unreachable</code> generates3330 {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates
3303 a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the3331 a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
3304 application, if there <em>was</em> a surprise error here, the application would crash3332 application, if there <em>was</em> a surprise error here, the application would crash
3305 appropriately.3333 appropriately.
...@@ -3324,7 +3352,7 @@ fn doAThing(str: []u8) void {...@@ -3324,7 +3352,7 @@ fn doAThing(str: []u8) void {
3324 {#header_open|errdefer#}3352 {#header_open|errdefer#}
3325 <p>3353 <p>
3326 The other component to error handling is defer statements.3354 The other component to error handling is defer statements.
3327 In addition to an unconditional {#link|defer#}, Zig has <code>errdefer</code>,3355 In addition to an unconditional {#link|defer#}, Zig has {#syntax#}errdefer{#endsyntax#},
3328 which evaluates the deferred expression on block exit path if and only if3356 which evaluates the deferred expression on block exit path if and only if
3329 the function returned with an error from the block.3357 the function returned with an error from the block.
3330 </p>3358 </p>
...@@ -3362,7 +3390,7 @@ fn createFoo(param: i32) !Foo {...@@ -3362,7 +3390,7 @@ fn createFoo(param: i32) !Foo {
3362 <ul>3390 <ul>
3363 <li>These primitives give enough expressiveness that it's completely practical3391 <li>These primitives give enough expressiveness that it's completely practical
3364 to have failing to check for an error be a compile error. If you really want3392 to have failing to check for an error be a compile error. If you really want
3365 to ignore the error, you can add <code>catch unreachable</code> and3393 to ignore the error, you can add {#syntax#}catch unreachable{#endsyntax#} and
3366 get the added benefit of crashing in Debug and ReleaseSafe modes if your assumption was wrong.3394 get the added benefit of crashing in Debug and ReleaseSafe modes if your assumption was wrong.
3367 </li>3395 </li>
3368 <li>3396 <li>
...@@ -3373,7 +3401,7 @@ fn createFoo(param: i32) !Foo {...@@ -3373,7 +3401,7 @@ fn createFoo(param: i32) !Foo {
3373 </ul>3401 </ul>
3374 {#see_also|defer|if|switch#}3402 {#see_also|defer|if|switch#}
33753403
3376 <p>An error union is created with the <code>!</code> binary operator.3404 <p>An error union is created with the {#syntax#}!{#endsyntax#} binary operator.
3377 You can use compile-time reflection to access the child type of an error union:</p>3405 You can use compile-time reflection to access the child type of an error union:</p>
3378 {#code_begin|test#}3406 {#code_begin|test#}
3379const assert = @import("std").debug.assert;3407const assert = @import("std").debug.assert;
...@@ -3396,15 +3424,15 @@ test "error union" {...@@ -3396,15 +3424,15 @@ test "error union" {
3396 {#code_end#}3424 {#code_end#}
3397 {#header_open|Merging Error Sets#}3425 {#header_open|Merging Error Sets#}
3398 <p>3426 <p>
3399 Use the <code>||</code> operator to merge two error sets together. The resulting3427 Use the {#syntax#}||{#endsyntax#} operator to merge two error sets together. The resulting
3400 error set contains the errors of both error sets. Doc comments from the left-hand3428 error set contains the errors of both error sets. Doc comments from the left-hand
3401 side override doc comments from the right-hand side. In this example, the doc3429 side override doc comments from the right-hand side. In this example, the doc
3402 comments for <code>C.PathNotFound</code> is <code>A doc comment</code>.3430 comments for {#syntax#}C.PathNotFound{#endsyntax#} is <code>A doc comment</code>.
3403 </p>3431 </p>
3404 <p>3432 <p>
3405 This is especially useful for functions which return different error sets depending3433 This is especially useful for functions which return different error sets depending
3406 on {#link|comptime#} branches. For example, the Zig standard library uses3434 on {#link|comptime#} branches. For example, the Zig standard library uses
3407 <code>LinuxFileOpenError || WindowsFileOpenError</code> for the error set of opening3435 {#syntax#}LinuxFileOpenError || WindowsFileOpenError{#endsyntax#} for the error set of opening
3408 files.3436 files.
3409 </p>3437 </p>
3410 {#code_begin|test#}3438 {#code_begin|test#}
...@@ -3537,8 +3565,8 @@ fn bang2() !void {...@@ -3537,8 +3565,8 @@ fn bang2() !void {
3537 Look closely at this example. This is no stack trace.3565 Look closely at this example. This is no stack trace.
3538 </p>3566 </p>
3539 <p>3567 <p>
3540 You can see that the final error bubbled up was <code>PermissionDenied</code>,3568 You can see that the final error bubbled up was {#syntax#}PermissionDenied{#endsyntax#},
3541 but the original error that started this whole thing was <code>FileNotFound</code>. In the <code>bar</code> function, the code handles the original error code,3569 but the original error that started this whole thing was {#syntax#}FileNotFound{#endsyntax#}. In the {#syntax#}bar{#endsyntax#} function, the code handles the original error code,
3542 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:3570 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:
3543 </p>3571 </p>
3544 {#code_begin|exe_err#}3572 {#code_begin|exe_err#}
...@@ -3584,7 +3612,7 @@ fn bang2() void {...@@ -3584,7 +3612,7 @@ fn bang2() void {
3584 {#code_end#}3612 {#code_end#}
3585 <p>3613 <p>
3586 Here, the stack trace does not explain how the control3614 Here, the stack trace does not explain how the control
3587 flow in <code>bar</code> got to the <code>hello()</code> call.3615 flow in {#syntax#}bar{#endsyntax#} got to the {#syntax#}hello(){#endsyntax#} call.
3588 One would have to open a debugger or further instrument the application3616 One would have to open a debugger or further instrument the application
3589 in order to find out. The error return trace, on the other hand, 3617 in order to find out. The error return trace, on the other hand,
3590 shows exactly how the error bubbled up.3618 shows exactly how the error bubbled up.
...@@ -3603,8 +3631,8 @@ fn bang2() void {...@@ -3603,8 +3631,8 @@ fn bang2() void {
3603 </p>3631 </p>
3604 <ul>3632 <ul>
3605 <li>Return an error from main</li>3633 <li>Return an error from main</li>
3606 <li>An error makes its way to <code>catch unreachable</code> and you have not overridden the default panic handler</li>3634 <li>An error makes its way to {#syntax#}catch unreachable{#endsyntax#} and you have not overridden the default panic handler</li>
3607 <li>Use {#link|errorReturnTrace#} to access the current return trace. You can use <code>std.debug.dumpStackTrace</code> to print it. This function returns comptime-known {#link|null#} when building without error return tracing support.</li>3635 <li>Use {#link|errorReturnTrace#} to access the current return trace. You can use {#syntax#}std.debug.dumpStackTrace{#endsyntax#} to print it. This function returns comptime-known {#link|null#} when building without error return tracing support.</li>
3608 </ul>3636 </ul>
3609 {#header_open|Implementation Details#}3637 {#header_open|Implementation Details#}
3610 <p>3638 <p>
...@@ -3615,7 +3643,7 @@ fn bang2() void {...@@ -3615,7 +3643,7 @@ fn bang2() void {
3615 <li>when returning errors</li>3643 <li>when returning errors</li>
3616 </ul>3644 </ul>
3617 <p>3645 <p>
3618 For the case when no errors are returned, the cost is a single memory write operation, only in the first non-failable function in the call graph that calls a failable function, i.e. when a function returning <code>void</code> calls a function returning <code>error</code>.3646 For the case when no errors are returned, the cost is a single memory write operation, only in the first non-failable function in the call graph that calls a failable function, i.e. when a function returning {#syntax#}void{#endsyntax#} calls a function returning {#syntax#}error{#endsyntax#}.
3619 This is to initialize this struct in the stack memory:3647 This is to initialize this struct in the stack memory:
3620 </p>3648 </p>
3621 {#code_begin|syntax#}3649 {#code_begin|syntax#}
...@@ -3628,13 +3656,13 @@ pub const StackTrace = struct {...@@ -3628,13 +3656,13 @@ pub const StackTrace = struct {
3628 Here, N is the maximum function call depth as determined by call graph analysis. Recursion is ignored and counts for 2.3656 Here, N is the maximum function call depth as determined by call graph analysis. Recursion is ignored and counts for 2.
3629 </p>3657 </p>
3630 <p>3658 <p>
3631 A pointer to <code>StackTrace</code> is passed as a secret parameter to every function that can return an error, but it's always the first parameter, so it can likely sit in a register and stay there.3659 A pointer to {#syntax#}StackTrace{#endsyntax#} is passed as a secret parameter to every function that can return an error, but it's always the first parameter, so it can likely sit in a register and stay there.
3632 </p>3660 </p>
3633 <p>3661 <p>
3634 That's it for the path when no errors occur. It's practically free in terms of performance.3662 That's it for the path when no errors occur. It's practically free in terms of performance.
3635 </p>3663 </p>
3636 <p>3664 <p>
3637 When generating the code for a function that returns an error, just before the <code>return</code> statement (only for the <code>return</code> statements that return errors), Zig generates a call to this function:3665 When generating the code for a function that returns an error, just before the {#syntax#}return{#endsyntax#} statement (only for the {#syntax#}return{#endsyntax#} statements that return errors), Zig generates a call to this function:
3638 </p>3666 </p>
3639 {#code_begin|syntax#}3667 {#code_begin|syntax#}
3640// marked as "no-inline" in LLVM IR3668// marked as "no-inline" in LLVM IR
...@@ -3649,7 +3677,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {...@@ -3649,7 +3677,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {
3649 <p>3677 <p>
3650 As for code size cost, 1 function call before a return statement is no big deal. Even so,3678 As for code size cost, 1 function call before a return statement is no big deal. Even so,
3651 I have <a href="https://github.com/ziglang/zig/issues/690">a plan</a> to make the call to3679 I have <a href="https://github.com/ziglang/zig/issues/690">a plan</a> to make the call to
3652 <code>__zig_return_error</code> a tail call, which brings the code size cost down to actually zero. What is a return statement in code without error return tracing can become a jump instruction in code with error return tracing.3680 {#syntax#}__zig_return_error{#endsyntax#} a tail call, which brings the code size cost down to actually zero. What is a return statement in code without error return tracing can become a jump instruction in code with error return tracing.
3653 </p>3681 </p>
3654 {#header_close#}3682 {#header_close#}
3655 {#header_close#}3683 {#header_close#}
...@@ -3671,7 +3699,7 @@ const normal_int: i32 = 1234;...@@ -3671,7 +3699,7 @@ const normal_int: i32 = 1234;
3671const optional_int: ?i32 = 5678;3699const optional_int: ?i32 = 5678;
3672 {#code_end#}3700 {#code_end#}
3673 <p>3701 <p>
3674 Now the variable <code>optional_int</code> could be an <code>i32</code>, or <code>null</code>.3702 Now the variable {#syntax#}optional_int{#endsyntax#} could be an {#syntax#}i32{#endsyntax#}, or {#syntax#}null{#endsyntax#}.
3675 </p>3703 </p>
3676 <p>3704 <p>
3677 Instead of integers, let's talk about pointers. Null references are the source of many runtime3705 Instead of integers, let's talk about pointers. Null references are the source of many runtime
...@@ -3712,8 +3740,8 @@ fn doAThing() ?*Foo {...@@ -3712,8 +3740,8 @@ fn doAThing() ?*Foo {
3712 {#code_end#}3740 {#code_end#}
3713 <p>3741 <p>
3714 Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"3742 Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"
3715 is <code>*u8</code> <em>not</em> <code>?*u8</code>. The <code>orelse</code> keyword3743 is {#syntax#}*u8{#endsyntax#} <em>not</em> {#syntax#}?*u8{#endsyntax#}. The {#syntax#}orelse{#endsyntax#} keyword
3716 unwrapped the optional type and therefore <code>ptr</code> is guaranteed to be non-null everywhere3744 unwrapped the optional type and therefore {#syntax#}ptr{#endsyntax#} is guaranteed to be non-null everywhere
3717 it is used in the function.3745 it is used in the function.
3718 </p>3746 </p>
3719 <p>3747 <p>
...@@ -3744,7 +3772,7 @@ fn doAThing(optional_foo: ?*Foo) void {...@@ -3744,7 +3772,7 @@ fn doAThing(optional_foo: ?*Foo) void {
3744 {#code_end#}3772 {#code_end#}
3745 <p>3773 <p>
3746 Once again, the notable thing here is that inside the if block,3774 Once again, the notable thing here is that inside the if block,
3747 <code>foo</code> is no longer an optional pointer, it is a pointer, which3775 {#syntax#}foo{#endsyntax#} is no longer an optional pointer, it is a pointer, which
3748 cannot be null.3776 cannot be null.
3749 </p>3777 </p>
3750 <p>3778 <p>
...@@ -3755,7 +3783,7 @@ fn doAThing(optional_foo: ?*Foo) void {...@@ -3755,7 +3783,7 @@ fn doAThing(optional_foo: ?*Foo) void {
3755 cannot be null.3783 cannot be null.
3756 </p>3784 </p>
3757 {#header_open|Optional Type#}3785 {#header_open|Optional Type#}
3758 <p>An optional is created by putting <code>?</code> in front of a type. You can use compile-time3786 <p>An optional is created by putting {#syntax#}?{#endsyntax#} in front of a type. You can use compile-time
3759 reflection to access the child type of an optional:</p>3787 reflection to access the child type of an optional:</p>
3760 {#code_begin|test#}3788 {#code_begin|test#}
3761const assert = @import("std").debug.assert;3789const assert = @import("std").debug.assert;
...@@ -3774,7 +3802,7 @@ test "optional type" {...@@ -3774,7 +3802,7 @@ test "optional type" {
3774 {#header_close#}3802 {#header_close#}
3775 {#header_open|null#}3803 {#header_open|null#}
3776 <p>3804 <p>
3777 Just like {#link|undefined#}, <code>null</code> has its own type, and the only way to use it is to3805 Just like {#link|undefined#}, {#syntax#}null{#endsyntax#} has its own type, and the only way to use it is to
3778 cast it to a different type:3806 cast it to a different type:
3779 </p>3807 </p>
3780 {#code_begin|syntax#}3808 {#code_begin|syntax#}
...@@ -3822,9 +3850,9 @@ test "implicit cast - invoke a type as a function" {...@@ -3822,9 +3850,9 @@ test "implicit cast - invoke a type as a function" {
3822 of the qualifiers, no matter how nested the qualifiers are:3850 of the qualifiers, no matter how nested the qualifiers are:
3823 </p>3851 </p>
3824 <ul>3852 <ul>
3825 <li><code>const</code> - non-const to const is allowed</li>3853 <li>{#syntax#}const{#endsyntax#} - non-const to const is allowed</li>
3826 <li><code>volatile</code> - non-volatile to volatile is allowed</li>3854 <li>{#syntax#}volatile{#endsyntax#} - non-volatile to volatile is allowed</li>
3827 <li><code>align</code> - bigger to smaller alignment is allowed </li>3855 <li>{#syntax#}align{#endsyntax#} - bigger to smaller alignment is allowed </li>
3828 <li>{#link|error sets|Error Set Type#} to supersets is allowed</li>3856 <li>{#link|error sets|Error Set Type#} to supersets is allowed</li>
3829 </ul>3857 </ul>
3830 <p>3858 <p>
...@@ -4072,7 +4100,7 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 {...@@ -4072,7 +4100,7 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 {
40724100
4073 {#header_open|void#}4101 {#header_open|void#}
4074 <p>4102 <p>
4075 <code>void</code> represents a type that has no value. Code that makes use of void values is4103 {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is
4076 not included in the final generated code:4104 not included in the final generated code:
4077 </p>4105 </p>
4078 {#code_begin|syntax#}4106 {#code_begin|syntax#}
...@@ -4082,7 +4110,7 @@ export fn entry() void {...@@ -4082,7 +4110,7 @@ export fn entry() void {
4082 x = y;4110 x = y;
4083}4111}
4084 {#code_end#}4112 {#code_end#}
4085 <p>When this turns into LLVM IR, there is no code generated in the body of <code>entry</code>,4113 <p>When this turns into LLVM IR, there is no code generated in the body of {#syntax#}entry{#endsyntax#},
4086 even in debug mode. For example, on x86_64:</p>4114 even in debug mode. For example, on x86_64:</p>
4087 <pre><code>0000000000000010 &lt;entry&gt;:4115 <pre><code>0000000000000010 &lt;entry&gt;:
4088 10: 55 push %rbp4116 10: 55 push %rbp
...@@ -4092,9 +4120,9 @@ export fn entry() void {...@@ -4092,9 +4120,9 @@ export fn entry() void {
4092 <p>These assembly instructions do not have any code associated with the void values -4120 <p>These assembly instructions do not have any code associated with the void values -
4093 they only perform the function call prologue and epilog.</p>4121 they only perform the function call prologue and epilog.</p>
4094 <p>4122 <p>
4095 <code>void</code> can be useful for instantiating generic types. For example, given a4123 {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a
4096 <code>Map(Key, Value)</code>, one can pass <code>void</code> for the <code>Value</code>4124 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}
4097 type to make it into a <code>Set</code>:4125 type to make it into a {#syntax#}Set{#endsyntax#}:
4098 </p>4126 </p>
4099 {#code_begin|test#}4127 {#code_begin|test#}
4100const std = @import("std");4128const std = @import("std");
...@@ -4123,17 +4151,17 @@ fn eql_i32(a: i32, b: i32) bool {...@@ -4123,17 +4151,17 @@ fn eql_i32(a: i32, b: i32) bool {
4123}4151}
4124 {#code_end#}4152 {#code_end#}
4125 <p>Note that this is different than using a dummy value for the hash map value.4153 <p>Note that this is different than using a dummy value for the hash map value.
4126 By using <code>void</code> as the type of the value, the hash map entry type has no value field, and4154 By using {#syntax#}void{#endsyntax#} as the type of the value, the hash map entry type has no value field, and
4127 thus the hash map takes up less space. Further, all the code that deals with storing and loading the4155 thus the hash map takes up less space. Further, all the code that deals with storing and loading the
4128 value is deleted, as seen above.4156 value is deleted, as seen above.
4129 </p>4157 </p>
4130 <p>4158 <p>
4131 <code>void</code> is distinct from <code>c_void</code>, which is defined like this:4159 {#syntax#}void{#endsyntax#} is distinct from {#syntax#}c_void{#endsyntax#}, which is defined like this:
4132 <code>pub const c_void = @OpaqueType();</code>.4160 {#syntax#}pub const c_void = @OpaqueType();{#endsyntax#}.
4133 <code>void</code> has a known size of 0 bytes, and <code>c_void</code> has an unknown, but non-zero, size.4161 {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}c_void{#endsyntax#} has an unknown, but non-zero, size.
4134 </p>4162 </p>
4135 <p>4163 <p>
4136 Expressions of type <code>void</code> are the only ones whose value can be ignored. For example:4164 Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:
4137 </p>4165 </p>
4138 {#code_begin|test_err|expression value is ignored#}4166 {#code_begin|test_err|expression value is ignored#}
4139test "ignoring expression value" {4167test "ignoring expression value" {
...@@ -4144,7 +4172,7 @@ fn foo() i32 {...@@ -4144,7 +4172,7 @@ fn foo() i32 {
4144 return 1234;4172 return 1234;
4145}4173}
4146 {#code_end#}4174 {#code_end#}
4147 <p>However, if the expression has type <code>void</code>:</p>4175 <p>However, if the expression has type {#syntax#}void{#endsyntax#}:</p>
4148 {#code_begin|test#}4176 {#code_begin|test#}
4149test "ignoring expression value" {4177test "ignoring expression value" {
4150 foo();4178 foo();
...@@ -4154,11 +4182,6 @@ fn foo() void {}...@@ -4154,11 +4182,6 @@ fn foo() void {}
4154 {#code_end#}4182 {#code_end#}
4155 {#header_close#}4183 {#header_close#}
41564184
4157 {#header_open|this#}
4158 <p>TODO: example of this referring to Self struct</p>
4159 <p>TODO: example of this referring to recursion function</p>
4160 <p>TODO: example of this referring to basic block for @setRuntimeSafety</p>
4161 {#header_close#}
4162 {#header_open|comptime#}4185 {#header_open|comptime#}
4163 <p>4186 <p>
4164 Zig places importance on the concept of whether an expression is known at compile-time.4187 Zig places importance on the concept of whether an expression is known at compile-time.
...@@ -4184,10 +4207,10 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -4184,10 +4207,10 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
4184 <p>4207 <p>
4185 In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions,4208 In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions,
4186 and returned from functions. However, they can only be used in expressions which are known at <em>compile-time</em>,4209 and returned from functions. However, they can only be used in expressions which are known at <em>compile-time</em>,
4187 which is why the parameter <code>T</code> in the above snippet must be marked with <code>comptime</code>.4210 which is why the parameter {#syntax#}T{#endsyntax#} in the above snippet must be marked with {#syntax#}comptime{#endsyntax#}.
4188 </p>4211 </p>
4189 <p>4212 <p>
4190 A <code>comptime</code> parameter means that:4213 A {#syntax#}comptime{#endsyntax#} parameter means that:
4191 </p>4214 </p>
4192 <ul>4215 <ul>
4193 <li>At the callsite, the value must be known at compile-time, or it is a compile error.</li>4216 <li>At the callsite, the value must be known at compile-time, or it is a compile error.</li>
...@@ -4232,7 +4255,7 @@ test "try to compare bools" {...@@ -4232,7 +4255,7 @@ test "try to compare bools" {
4232}4255}
4233 {#code_end#}4256 {#code_end#}
4234 <p>4257 <p>
4235 On the flip side, inside the function definition with the <code>comptime</code> parameter, the4258 On the flip side, inside the function definition with the {#syntax#}comptime{#endsyntax#} parameter, the
4236 value is known at compile-time. This means that we actually could make this work for the bool type4259 value is known at compile-time. This means that we actually could make this work for the bool type
4237 if we wanted to:4260 if we wanted to:
4238 </p>4261 </p>
...@@ -4251,12 +4274,12 @@ test "try to compare bools" {...@@ -4251,12 +4274,12 @@ test "try to compare bools" {
4251}4274}
4252 {#code_end#}4275 {#code_end#}
4253 <p>4276 <p>
4254 This works because Zig implicitly inlines <code>if</code> expressions when the condition4277 This works because Zig implicitly inlines {#syntax#}if{#endsyntax#} expressions when the condition
4255 is known at compile-time, and the compiler guarantees that it will skip analysis of4278 is known at compile-time, and the compiler guarantees that it will skip analysis of
4256 the branch not taken.4279 the branch not taken.
4257 </p>4280 </p>
4258 <p>4281 <p>
4259 This means that the actual function generated for <code>max</code> in this situation looks like4282 This means that the actual function generated for {#syntax#}max{#endsyntax#} in this situation looks like
4260 this:4283 this:
4261 </p>4284 </p>
4262 {#code_begin|syntax#}4285 {#code_begin|syntax#}
...@@ -4269,18 +4292,18 @@ fn max(a: bool, b: bool) bool {...@@ -4269,18 +4292,18 @@ fn max(a: bool, b: bool) bool {
4269 the necessary run-time code to accomplish the task.4292 the necessary run-time code to accomplish the task.
4270 </p>4293 </p>
4271 <p>4294 <p>
4272 This works the same way for <code>switch</code> expressions - they are implicitly inlined4295 This works the same way for {#syntax#}switch{#endsyntax#} expressions - they are implicitly inlined
4273 when the target expression is compile-time known.4296 when the target expression is compile-time known.
4274 </p>4297 </p>
4275 {#header_close#}4298 {#header_close#}
4276 {#header_open|Compile-Time Variables#}4299 {#header_open|Compile-Time Variables#}
4277 <p>4300 <p>
4278 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler4301 In Zig, the programmer can label variables as {#syntax#}comptime{#endsyntax#}. This guarantees to the compiler
4279 that every load and store of the variable is performed at compile-time. Any violation of this results in a4302 that every load and store of the variable is performed at compile-time. Any violation of this results in a
4280 compile error.4303 compile error.
4281 </p>4304 </p>
4282 <p>4305 <p>
4283 This combined with the fact that we can <code>inline</code> loops allows us to write4306 This combined with the fact that we can {#syntax#}inline{#endsyntax#} loops allows us to write
4284 a function which is partially evaluated at compile-time and partially at run-time.4307 a function which is partially evaluated at compile-time and partially at run-time.
4285 </p>4308 </p>
4286 <p>4309 <p>
...@@ -4323,8 +4346,8 @@ test "perform fn" {...@@ -4323,8 +4346,8 @@ test "perform fn" {
4323 <p>4346 <p>
4324 This example is a bit contrived, because the compile-time evaluation component is unnecessary;4347 This example is a bit contrived, because the compile-time evaluation component is unnecessary;
4325 this code would work fine if it was all done at run-time. But it does end up generating4348 this code would work fine if it was all done at run-time. But it does end up generating
4326 different code. In this example, the function <code>performFn</code> is generated three different times,4349 different code. In this example, the function {#syntax#}performFn{#endsyntax#} is generated three different times,
4327 for the different values of <code>prefix_char</code> provided:4350 for the different values of {#syntax#}prefix_char{#endsyntax#} provided:
4328 </p>4351 </p>
4329 {#code_begin|syntax#}4352 {#code_begin|syntax#}
4330// From the line:4353// From the line:
...@@ -4365,7 +4388,7 @@ fn performFn(start_value: i32) i32 {...@@ -4365,7 +4388,7 @@ fn performFn(start_value: i32) i32 {
4365 {#header_open|Compile-Time Expressions#}4388 {#header_open|Compile-Time Expressions#}
4366 <p>4389 <p>
4367 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can4390 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can
4368 use a <code>comptime</code> expression to guarantee that the expression will be evaluated at compile-time.4391 use a {#syntax#}comptime{#endsyntax#} expression to guarantee that the expression will be evaluated at compile-time.
4369 If this cannot be accomplished, the compiler will emit an error. For example:4392 If this cannot be accomplished, the compiler will emit an error. For example:
4370 </p>4393 </p>
4371 {#code_begin|test_err|unable to evaluate constant expression#}4394 {#code_begin|test_err|unable to evaluate constant expression#}
...@@ -4378,16 +4401,16 @@ test "foo" {...@@ -4378,16 +4401,16 @@ test "foo" {
4378}4401}
4379 {#code_end#}4402 {#code_end#}
4380 <p>4403 <p>
4381 It doesn't make sense that a program could call <code>exit()</code> (or any other external function)4404 It doesn't make sense that a program could call {#syntax#}exit(){#endsyntax#} (or any other external function)
4382 at compile-time, so this is a compile error. However, a <code>comptime</code> expression does much4405 at compile-time, so this is a compile error. However, a {#syntax#}comptime{#endsyntax#} expression does much
4383 more than sometimes cause a compile error.4406 more than sometimes cause a compile error.
4384 </p>4407 </p>
4385 <p>4408 <p>
4386 Within a <code>comptime</code> expression:4409 Within a {#syntax#}comptime{#endsyntax#} expression:
4387 </p>4410 </p>
4388 <ul>4411 <ul>
4389 <li>All variables are <code>comptime</code> variables.</li>4412 <li>All variables are {#syntax#}comptime{#endsyntax#} variables.</li>
4390 <li>All <code>if</code>, <code>while</code>, <code>for</code>, and <code>switch</code>4413 <li>All {#syntax#}if{#endsyntax#}, {#syntax#}while{#endsyntax#}, {#syntax#}for{#endsyntax#}, and {#syntax#}switch{#endsyntax#}
4391 expressions are evaluated at compile-time, or emit a compile error if this is not possible.</li>4414 expressions are evaluated at compile-time, or emit a compile error if this is not possible.</li>
4392 <li>All function calls cause the compiler to interpret the function at compile-time, emitting a4415 <li>All function calls cause the compiler to interpret the function at compile-time, emitting a
4393 compile error if the function tries to do something that has global run-time side effects.</li>4416 compile error if the function tries to do something that has global run-time side effects.</li>
...@@ -4464,7 +4487,7 @@ test "fibonacci" {...@@ -4464,7 +4487,7 @@ test "fibonacci" {
4464 {#link|@setEvalBranchQuota#} to change the default number 1000 to something else.4487 {#link|@setEvalBranchQuota#} to change the default number 1000 to something else.
4465 </p>4488 </p>
4466 <p>4489 <p>
4467 What if we fix the base case, but put the wrong value in the <code>assert</code> line?4490 What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line?
4468 </p>4491 </p>
4469 {#code_begin|test_err|encountered @panic at compile-time#}4492 {#code_begin|test_err|encountered @panic at compile-time#}
4470const assert = @import("std").debug.assert;4493const assert = @import("std").debug.assert;
...@@ -4481,16 +4504,16 @@ test "fibonacci" {...@@ -4481,16 +4504,16 @@ test "fibonacci" {
4481}4504}
4482 {#code_end#}4505 {#code_end#}
4483 <p>4506 <p>
4484 What happened is Zig started interpreting the <code>assert</code> function with the4507 What happened is Zig started interpreting the {#syntax#}assert{#endsyntax#} function with the
4485 parameter <code>ok</code> set to <code>false</code>. When the interpreter hit4508 parameter {#syntax#}ok{#endsyntax#} set to {#syntax#}false{#endsyntax#}. When the interpreter hit
4486 <code>unreachable</code> it emitted a compile error, because reaching unreachable4509 {#syntax#}unreachable{#endsyntax#} it emitted a compile error, because reaching unreachable
4487 code is undefined behavior, and undefined behavior causes a compile error if it is detected4510 code is undefined behavior, and undefined behavior causes a compile error if it is detected
4488 at compile-time.4511 at compile-time.
4489 </p>4512 </p>
44904513
4491 <p>4514 <p>
4492 In the global scope (outside of any function), all expressions are implicitly4515 In the global scope (outside of any function), all expressions are implicitly
4493 <code>comptime</code> expressions. This means that we can use functions to4516 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to
4494 initialize complex static data. For example:4517 initialize complex static data. For example:
4495 </p>4518 </p>
4496 {#code_begin|test#}4519 {#code_begin|test#}
...@@ -4538,7 +4561,7 @@ test "variable values" {...@@ -4538,7 +4561,7 @@ test "variable values" {
4538@1 = internal unnamed_addr constant i32 1060</code></pre>4561@1 = internal unnamed_addr constant i32 1060</code></pre>
4539 <p>4562 <p>
4540 Note that we did not have to do anything special with the syntax of these functions. For example,4563 Note that we did not have to do anything special with the syntax of these functions. For example,
4541 we could call the <code>sum</code> function as is with a slice of numbers whose length and values were4564 we could call the {#syntax#}sum{#endsyntax#} function as is with a slice of numbers whose length and values were
4542 only known at run-time.4565 only known at run-time.
4543 </p>4566 </p>
4544 {#header_close#}4567 {#header_close#}
...@@ -4550,8 +4573,8 @@ test "variable values" {...@@ -4550,8 +4573,8 @@ test "variable values" {
4550 generic data structure.4573 generic data structure.
4551 </p>4574 </p>
4552 <p>4575 <p>
4553 Here is an example of a generic <code>List</code> data structure, that we will instantiate with4576 Here is an example of a generic {#syntax#}List{#endsyntax#} data structure, that we will instantiate with
4554 the type <code>i32</code>. In Zig we refer to the type as <code>List(i32)</code>.4577 the type {#syntax#}i32{#endsyntax#}. In Zig we refer to the type as {#syntax#}List(i32){#endsyntax#}.
4555 </p>4578 </p>
4556 {#code_begin|syntax#}4579 {#code_begin|syntax#}
4557fn List(comptime T: type) type {4580fn List(comptime T: type) type {
...@@ -4562,8 +4585,8 @@ fn List(comptime T: type) type {...@@ -4562,8 +4585,8 @@ fn List(comptime T: type) type {
4562}4585}
4563 {#code_end#}4586 {#code_end#}
4564 <p>4587 <p>
4565 That's it. It's a function that returns an anonymous <code>struct</code>. For the purposes of error messages4588 That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. For the purposes of error messages
4566 and debugging, Zig infers the name <code>"List(i32)"</code> from the function name and parameters invoked when creating4589 and debugging, Zig infers the name {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating
4567 the anonymous struct.4590 the anonymous struct.
4568 </p>4591 </p>
4569 <p>4592 <p>
...@@ -4579,13 +4602,13 @@ const Node = struct {...@@ -4579,13 +4602,13 @@ const Node = struct {
4579 <p>4602 <p>
4580 This works because all top level declarations are order-independent, and as long as there isn't4603 This works because all top level declarations are order-independent, and as long as there isn't
4581 an actual infinite regression, values can refer to themselves, directly or indirectly. In this case,4604 an actual infinite regression, values can refer to themselves, directly or indirectly. In this case,
4582 <code>Node</code> refers to itself as a pointer, which is not actually an infinite regression, so4605 {#syntax#}Node{#endsyntax#} refers to itself as a pointer, which is not actually an infinite regression, so
4583 it works fine.4606 it works fine.
4584 </p>4607 </p>
4585 {#header_close#}4608 {#header_close#}
4586 {#header_open|Case Study: printf in Zig#}4609 {#header_open|Case Study: printf in Zig#}
4587 <p>4610 <p>
4588 Putting all of this together, let's see how <code>printf</code> works in Zig.4611 Putting all of this together, let's see how {#syntax#}printf{#endsyntax#} works in Zig.
4589 </p>4612 </p>
4590 {#code_begin|exe|printf#}4613 {#code_begin|exe|printf#}
4591const warn = @import("std").debug.warn;4614const warn = @import("std").debug.warn;
...@@ -4686,7 +4709,7 @@ pub fn printf(self: *OutStream, arg0: i32, arg1: []const u8) !void {...@@ -4686,7 +4709,7 @@ pub fn printf(self: *OutStream, arg0: i32, arg1: []const u8) !void {
4686}4709}
4687 {#code_end#}4710 {#code_end#}
4688 <p>4711 <p>
4689 <code>printValue</code> is a function that takes a parameter of any type, and does different things depending4712 {#syntax#}printValue{#endsyntax#} is a function that takes a parameter of any type, and does different things depending
4690 on the type:4713 on the type:
4691 </p>4714 </p>
4692 {#code_begin|syntax#}4715 {#code_begin|syntax#}
...@@ -4702,7 +4725,7 @@ pub fn printValue(self: *OutStream, value: var) !void {...@@ -4702,7 +4725,7 @@ pub fn printValue(self: *OutStream, value: var) !void {
4702}4725}
4703 {#code_end#}4726 {#code_end#}
4704 <p>4727 <p>
4705 And now, what happens if we give too many arguments to <code>printf</code>?4728 And now, what happens if we give too many arguments to {#syntax#}printf{#endsyntax#}?
4706 </p>4729 </p>
4707 {#code_begin|test_err|Unused arguments#}4730 {#code_begin|test_err|Unused arguments#}
4708const warn = @import("std").debug.warn;4731const warn = @import("std").debug.warn;
...@@ -4720,7 +4743,7 @@ test "printf too many arguments" {...@@ -4720,7 +4743,7 @@ test "printf too many arguments" {
4720 </p>4743 </p>
4721 <p>4744 <p>
4722 Zig doesn't care whether the format argument is a string literal,4745 Zig doesn't care whether the format argument is a string literal,
4723 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:4746 only that it is a compile-time known value that is implicitly castable to a {#syntax#}[]const u8{#endsyntax#}:
4724 </p>4747 </p>
4725 {#code_begin|exe|printf#}4748 {#code_begin|exe|printf#}
4726const warn = @import("std").debug.warn;4749const warn = @import("std").debug.warn;
...@@ -4774,16 +4797,16 @@ pub fn main() void {...@@ -4774,16 +4797,16 @@ pub fn main() void {
4774 </p>4797 </p>
4775 {#header_open|Minimal Coroutine Example#}4798 {#header_open|Minimal Coroutine Example#}
4776 <p>4799 <p>
4777 Declare a coroutine with the <code>async</code> keyword.4800 Declare a coroutine with the {#syntax#}async{#endsyntax#} keyword.
4778 The expression in angle brackets must evaluate to a struct4801 The expression in angle brackets must evaluate to a struct
4779 which has these fields:4802 which has these fields:
4780 </p>4803 </p>
4781 <ul>4804 <ul>
4782 <li><code>allocFn: fn (self: *Allocator, byte_count: usize, alignment: u29) Error![]u8</code> - where <code>Error</code> can be any error set.</li>4805 <li>{#syntax#}allocFn: fn (self: *Allocator, byte_count: usize, alignment: u29) Error![]u8{#endsyntax#} - where {#syntax#}Error{#endsyntax#} can be any error set.</li>
4783 <li><code>freeFn: fn (self: *Allocator, old_mem: []u8) void</code></li>4806 <li>{#syntax#}freeFn: fn (self: *Allocator, old_mem: []u8) void{#endsyntax#}</li>
4784 </ul>4807 </ul>
4785 <p>4808 <p>
4786 You may notice that this corresponds to the <code>std.mem.Allocator</code> interface.4809 You may notice that this corresponds to the {#syntax#}std.mem.Allocator{#endsyntax#} interface.
4787 This makes it convenient to integrate with existing allocators. Note, however,4810 This makes it convenient to integrate with existing allocators. Note, however,
4788 that the language feature does not depend on the standard library, and any struct which4811 that the language feature does not depend on the standard library, and any struct which
4789 has these fields is allowed.4812 has these fields is allowed.
...@@ -4793,13 +4816,13 @@ pub fn main() void {...@@ -4793,13 +4816,13 @@ pub fn main() void {
4793 the function generic. Zig will infer the allocator type when the async function is called.4816 the function generic. Zig will infer the allocator type when the async function is called.
4794 </p>4817 </p>
4795 <p>4818 <p>
4796 Call a coroutine with the <code>async</code> keyword. Here, the expression in angle brackets4819 Call a coroutine with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets
4797 is a pointer to the allocator struct that the coroutine expects.4820 is a pointer to the allocator struct that the coroutine expects.
4798 </p>4821 </p>
4799 <p>4822 <p>
4800 The result of an async function call is a <code>promise->T</code> type, where <code>T</code>4823 The result of an async function call is a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#}
4801 is the return type of the async function. Once a promise has been created, it must be4824 is the return type of the async function. Once a promise has been created, it must be
4802 consumed, either with <code>cancel</code> or <code>await</code>:4825 consumed, either with {#syntax#}cancel{#endsyntax#} or {#syntax#}await{#endsyntax#}:
4803 </p>4826 </p>
4804 <p>4827 <p>
4805 Async functions start executing when created, so in the following example, the entire4828 Async functions start executing when created, so in the following example, the entire
...@@ -4888,18 +4911,18 @@ async fn testSuspendBlock() void {...@@ -4888,18 +4911,18 @@ async fn testSuspendBlock() void {
4888 {#code_end#}4911 {#code_end#}
4889 <p>4912 <p>
4890 Every suspend point in an async function represents a point at which the coroutine4913 Every suspend point in an async function represents a point at which the coroutine
4891 could be destroyed. If that happens, <code>defer</code> expressions that are in4914 could be destroyed. If that happens, {#syntax#}defer{#endsyntax#} expressions that are in
4892 scope are run, as well as <code>errdefer</code> expressions.4915 scope are run, as well as {#syntax#}errdefer{#endsyntax#} expressions.
4893 </p>4916 </p>
4894 <p>4917 <p>
4895 {#link|Await#} counts as a suspend point.4918 {#link|Await#} counts as a suspend point.
4896 </p>4919 </p>
4897 {#header_open|Resuming from Suspend Blocks#}4920 {#header_open|Resuming from Suspend Blocks#}
4898 <p>4921 <p>
4899 Upon entering a <code>suspend</code> block, the coroutine is already considered4922 Upon entering a {#syntax#}suspend{#endsyntax#} block, the coroutine is already considered
4900 suspended, and can be resumed. For example, if you started another kernel thread,4923 suspended, and can be resumed. For example, if you started another kernel thread,
4901 and had that thread call <code>resume</code> on the promise handle provided by the4924 and had that thread call {#syntax#}resume{#endsyntax#} on the promise handle provided by the
4902 <code>suspend</code> block, the new thread would begin executing after the suspend4925 {#syntax#}suspend{#endsyntax#} block, the new thread would begin executing after the suspend
4903 block, while the old thread continued executing the suspend block.4926 block, while the old thread continued executing the suspend block.
4904 </p>4927 </p>
4905 <p>4928 <p>
...@@ -4934,26 +4957,26 @@ async fn testResumeFromSuspend(my_result: *i32) void {...@@ -4934,26 +4957,26 @@ async fn testResumeFromSuspend(my_result: *i32) void {
4934 {#header_close#}4957 {#header_close#}
4935 {#header_open|Await#}4958 {#header_open|Await#}
4936 <p>4959 <p>
4937 The <code>await</code> keyword is used to coordinate with an async function's4960 The {#syntax#}await{#endsyntax#} keyword is used to coordinate with an async function's
4938 <code>return</code> statement.4961 {#syntax#}return{#endsyntax#} statement.
4939 </p>4962 </p>
4940 <p>4963 <p>
4941 <code>await</code> is valid only in an <code>async</code> function, and it takes4964 {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes
4942 as an operand a promise handle.4965 as an operand a promise handle.
4943 If the async function associated with the promise handle has already returned, 4966 If the async function associated with the promise handle has already returned,
4944 then <code>await</code> destroys the target async function, and gives the return value.4967 then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.
4945 Otherwise, <code>await</code> suspends the current async function, registering its4968 Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its
4946 promise handle with the target coroutine. It becomes the target coroutine's responsibility4969 promise handle with the target coroutine. It becomes the target coroutine's responsibility
4947 to have ensured that it will be resumed or destroyed. When the target coroutine reaches4970 to have ensured that it will be resumed or destroyed. When the target coroutine reaches
4948 its return statement, it gives the return value to the awaiter, destroys itself, and then4971 its return statement, it gives the return value to the awaiter, destroys itself, and then
4949 resumes the awaiter.4972 resumes the awaiter.
4950 </p>4973 </p>
4951 <p>4974 <p>
4952 A promise handle must be consumed exactly once after it is created, either by <code>cancel</code> or <code>await</code>.4975 A promise handle must be consumed exactly once after it is created, either by {#syntax#}cancel{#endsyntax#} or {#syntax#}await{#endsyntax#}.
4953 </p>4976 </p>
4954 <p>4977 <p>
4955 <code>await</code> counts as a suspend point, and therefore at every <code>await</code>,4978 {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},
4956 a coroutine can be potentially destroyed, which would run <code>defer</code> and <code>errdefer</code> expressions.4979 a coroutine can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions.
4957 </p>4980 </p>
4958 {#code_begin|test#}4981 {#code_begin|test#}
4959const std = @import("std");4982const std = @import("std");
...@@ -4997,9 +5020,9 @@ fn seq(c: u8) void {...@@ -4997,9 +5020,9 @@ fn seq(c: u8) void {
4997}5020}
4998 {#code_end#}5021 {#code_end#}
4999 <p>5022 <p>
5000 In general, <code>suspend</code> is lower level than <code>await</code>. Most application5023 In general, {#syntax#}suspend{#endsyntax#} is lower level than {#syntax#}await{#endsyntax#}. Most application
5001 code will use only <code>async</code> and <code>await</code>, but event loop5024 code will use only {#syntax#}async{#endsyntax#} and {#syntax#}await{#endsyntax#}, but event loop
5002 implementations will make use of <code>suspend</code> internally.5025 implementations will make use of {#syntax#}suspend{#endsyntax#} internally.
5003 </p>5026 </p>
5004 {#header_close#}5027 {#header_close#}
5005 {#header_open|Open Issues#}5028 {#header_open|Open Issues#}
...@@ -5029,36 +5052,36 @@ fn seq(c: u8) void {...@@ -5029,36 +5052,36 @@ fn seq(c: u8) void {
5029 {#header_open|Builtin Functions#}5052 {#header_open|Builtin Functions#}
5030 <p>5053 <p>
5031 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.5054 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
5032 The <code>comptime</code> keyword on a parameter means that the parameter must be known5055 The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known
5033 at compile time.5056 at compile time.
5034 </p>5057 </p>
5035 {#header_open|@addWithOverflow#}5058 {#header_open|@addWithOverflow#}
5036 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: *T) bool</code></pre>5059 <pre>{#syntax#}@addWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
5037 <p>5060 <p>
5038 Performs <code>result.* = a + b</code>. If overflow or underflow occurs,5061 Performs {#syntax#}result.* = a + b{#endsyntax#}. If overflow or underflow occurs,
5039 stores the overflowed bits in <code>result</code> and returns <code>true</code>.5062 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
5040 If no overflow or underflow occurs, returns <code>false</code>.5063 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5041 </p>5064 </p>
5042 {#header_close#}5065 {#header_close#}
5043 {#header_open|@ArgType#}5066 {#header_open|@ArgType#}
5044 <pre><code class="zig">@ArgType(comptime T: type, comptime n: usize) type</code></pre>5067 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
5045 <p>5068 <p>
5046 This builtin function takes a function type and returns the type of the parameter at index <code>n</code>.5069 This builtin function takes a function type and returns the type of the parameter at index {#syntax#}n{#endsyntax#}.
5047 </p>5070 </p>
5048 <p>5071 <p>
5049 <code>T</code> must be a function type.5072 {#syntax#}T{#endsyntax#} must be a function type.
5050 </p>5073 </p>
5051 <p>5074 <p>
5052 Note: This function is deprecated. Use {#link|@typeInfo#} instead.5075 Note: This function is deprecated. Use {#link|@typeInfo#} instead.
5053 </p>5076 </p>
5054 {#header_close#}5077 {#header_close#}
5055 {#header_open|@atomicLoad#}5078 {#header_open|@atomicLoad#}
5056 <pre><code class="zig">@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T</code></pre>5079 <pre>{#syntax#}@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre>
5057 <p>5080 <p>
5058 This builtin function atomically dereferences a pointer and returns the value.5081 This builtin function atomically dereferences a pointer and returns the value.
5059 </p>5082 </p>
5060 <p>5083 <p>
5061 <code>T</code> must be a pointer type, a <code>bool</code>,5084 {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#},
5062 or an integer whose bit count meets these requirements:5085 or an integer whose bit count meets these requirements:
5063 </p>5086 </p>
5064 <ul>5087 <ul>
...@@ -5072,12 +5095,12 @@ fn seq(c: u8) void {...@@ -5072,12 +5095,12 @@ fn seq(c: u8) void {
5072 </p>5095 </p>
5073 {#header_close#}5096 {#header_close#}
5074 {#header_open|@atomicRmw#}5097 {#header_open|@atomicRmw#}
5075 <pre><code class="zig">@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T</code></pre>5098 <pre>{#syntax#}@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre>
5076 <p>5099 <p>
5077 This builtin function atomically modifies memory and then returns the previous value.5100 This builtin function atomically modifies memory and then returns the previous value.
5078 </p>5101 </p>
5079 <p>5102 <p>
5080 <code>T</code> must be a pointer type, a <code>bool</code>,5103 {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#},
5081 or an integer whose bit count meets these requirements:5104 or an integer whose bit count meets these requirements:
5082 </p>5105 </p>
5083 <ul>5106 <ul>
...@@ -5091,29 +5114,29 @@ fn seq(c: u8) void {...@@ -5091,29 +5114,29 @@ fn seq(c: u8) void {
5091 </p>5114 </p>
5092 {#header_close#}5115 {#header_close#}
5093 {#header_open|@bitCast#}5116 {#header_open|@bitCast#}
5094 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) DestType</code></pre>5117 <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
5095 <p>5118 <p>
5096 Converts a value of one type to another type.5119 Converts a value of one type to another type.
5097 </p>5120 </p>
5098 <p>5121 <p>
5099 Asserts that <code>@sizeOf(@typeOf(value)) == @sizeOf(DestType)</code>.5122 Asserts that {#syntax#}@sizeOf(@typeOf(value)) == @sizeOf(DestType){#endsyntax#}.
5100 </p>5123 </p>
5101 <p>5124 <p>
5102 Asserts that <code>@typeId(DestType) != @import("builtin").TypeId.Pointer</code>. Use <code>@ptrCast</code> or <code>@intToPtr</code> if you need this.5125 Asserts that {#syntax#}@typeId(DestType) != @import("builtin").TypeId.Pointer{#endsyntax#}. Use {#syntax#}@ptrCast{#endsyntax#} or {#syntax#}@intToPtr{#endsyntax#} if you need this.
5103 </p>5126 </p>
5104 <p>5127 <p>
5105 Can be used for these things for example:5128 Can be used for these things for example:
5106 </p>5129 </p>
5107 <ul>5130 <ul>
5108 <li>Convert <code>f32</code> to <code>u32</code> bits</li>5131 <li>Convert {#syntax#}f32{#endsyntax#} to {#syntax#}u32{#endsyntax#} bits</li>
5109 <li>Convert <code>i32</code> to <code>u32</code> preserving twos complement</li>5132 <li>Convert {#syntax#}i32{#endsyntax#} to {#syntax#}u32{#endsyntax#} preserving twos complement</li>
5110 </ul>5133 </ul>
5111 <p>5134 <p>
5112 Works at compile-time if <code>value</code> is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.5135 Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
5113 </p>5136 </p>
5114 {#header_close#}5137 {#header_close#}
5115 {#header_open|@breakpoint#}5138 {#header_open|@breakpoint#}
5116 <pre><code class="zig">@breakpoint()</code></pre>5139 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
5117 <p>5140 <p>
5118 This function inserts a platform-specific debug trap instruction which causes5141 This function inserts a platform-specific debug trap instruction which causes
5119 debuggers to break there.5142 debuggers to break there.
...@@ -5124,10 +5147,10 @@ fn seq(c: u8) void {...@@ -5124,10 +5147,10 @@ fn seq(c: u8) void {
51245147
5125 {#header_close#}5148 {#header_close#}
5126 {#header_open|@alignCast#}5149 {#header_open|@alignCast#}
5127 <pre><code class="zig">@alignCast(comptime alignment: u29, ptr: var) var</code></pre>5150 <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
5128 <p>5151 <p>
5129 <code>ptr</code> can be <code>*T</code>, <code>fn()</code>, <code>?*T</code>,5152 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5130 <code>?fn()</code>, or <code>[]T</code>. It returns the same type as <code>ptr</code>5153 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
5131 except with the alignment adjusted to the new value.5154 except with the alignment adjusted to the new value.
5132 </p>5155 </p>
5133 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added5156 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
...@@ -5135,16 +5158,16 @@ fn seq(c: u8) void {...@@ -5135,16 +5158,16 @@ fn seq(c: u8) void {
51355158
5136 {#header_close#}5159 {#header_close#}
5137 {#header_open|@alignOf#}5160 {#header_open|@alignOf#}
5138 <pre><code class="zig">@alignOf(comptime T: type) (number literal)</code></pre>5161 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
5139 <p>5162 <p>
5140 This function returns the number of bytes that this type should be aligned to5163 This function returns the number of bytes that this type should be aligned to
5141 for the current target to match the C ABI. When the child type of a pointer has5164 for the current target to match the C ABI. When the child type of a pointer has
5142 this alignment, the alignment can be omitted from the type.5165 this alignment, the alignment can be omitted from the type.
5143 </p>5166 </p>
5144 <pre><code class="zig">const assert = @import("std").debug.assert;5167 <pre>{#syntax#}const assert = @import("std").debug.assert;
5145comptime {5168comptime {
5146 assert(*u32 == *align(@alignOf(u32)) u32);5169 assert(*u32 == *align(@alignOf(u32)) u32);
5147}</code></pre>5170}{#endsyntax#}</pre>
5148 <p>5171 <p>
5149 The result is a target-specific compile time constant. It is guaranteed to be5172 The result is a target-specific compile time constant. It is guaranteed to be
5150 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.5173 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
...@@ -5153,21 +5176,21 @@ comptime {...@@ -5153,21 +5176,21 @@ comptime {
5153 {#header_close#}5176 {#header_close#}
51545177
5155 {#header_open|@boolToInt#}5178 {#header_open|@boolToInt#}
5156 <pre><code class="zig">@boolToInt(value: bool) u1</code></pre>5179 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
5157 <p>5180 <p>
5158 Converts <code>true</code> to <code>u1(1)</code> and <code>false</code> to5181 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5159 <code>u1(0)</code>.5182 {#syntax#}u1(0){#endsyntax#}.
5160 </p>5183 </p>
5161 <p>5184 <p>
5162 If the value is known at compile-time, the return type is <code>comptime_int</code>5185 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
5163 instead of <code>u1</code>.5186 instead of {#syntax#}u1{#endsyntax#}.
5164 </p>5187 </p>
5165 {#header_close#}5188 {#header_close#}
51665189
5167 {#header_open|@bytesToSlice#}5190 {#header_open|@bytesToSlice#}
5168 <pre><code class="zig">@bytesToSlice(comptime Element: type, bytes: []u8) []Element</code></pre>5191 <pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
5169 <p>5192 <p>
5170 Converts a slice of bytes or array of bytes into a slice of <code>Element</code>.5193 Converts a slice of bytes or array of bytes into a slice of {#syntax#}Element{#endsyntax#}.
5171 The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.5194 The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.
5172 </p>5195 </p>
5173 <p>5196 <p>
...@@ -5177,12 +5200,12 @@ comptime {...@@ -5177,12 +5200,12 @@ comptime {
5177 {#header_close#}5200 {#header_close#}
51785201
5179 {#header_open|@cDefine#}5202 {#header_open|@cDefine#}
5180 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>5203 <pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>
5181 <p>5204 <p>
5182 This function can only occur inside <code>@cImport</code>.5205 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5183 </p>5206 </p>
5184 <p>5207 <p>
5185 This appends <code>#define $name $value</code> to the <code>@cImport</code>5208 This appends <code>#define $name $value</code> to the {#syntax#}@cImport{#endsyntax#}
5186 temporary buffer.5209 temporary buffer.
5187 </p>5210 </p>
5188 <p>5211 <p>
...@@ -5192,72 +5215,72 @@ comptime {...@@ -5192,72 +5215,72 @@ comptime {
5192 <p>5215 <p>
5193 Use the void value, like this:5216 Use the void value, like this:
5194 </p>5217 </p>
5195 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>5218 <pre>{#syntax#}@cDefine("_GNU_SOURCE", {}){#endsyntax#}</pre>
5196 {#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}5219 {#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}
5197 {#header_close#}5220 {#header_close#}
5198 {#header_open|@cImport#}5221 {#header_open|@cImport#}
5199 <pre><code class="zig">@cImport(expression) (namespace)</code></pre>5222 <pre>{#syntax#}@cImport(expression) (namespace){#endsyntax#}</pre>
5200 <p>5223 <p>
5201 This function parses C code and imports the functions, types, variables, and5224 This function parses C code and imports the functions, types, variables, and
5202 compatible macro definitions into the result namespace.5225 compatible macro definitions into the result namespace.
5203 </p>5226 </p>
5204 <p>5227 <p>
5205 <code>expression</code> is interpreted at compile time. The builtin functions5228 {#syntax#}expression{#endsyntax#} is interpreted at compile time. The builtin functions
5206 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work5229 {#syntax#}@cInclude{#endsyntax#}, {#syntax#}@cDefine{#endsyntax#}, and {#syntax#}@cUndef{#endsyntax#} work
5207 within this expression, appending to a temporary buffer which is then parsed as C code.5230 within this expression, appending to a temporary buffer which is then parsed as C code.
5208 </p>5231 </p>
5209 <p>5232 <p>
5210 Usually you should only have one <code>@cImport</code> in your entire application, because it saves the compiler5233 Usually you should only have one {#syntax#}@cImport{#endsyntax#} in your entire application, because it saves the compiler
5211 from invoking clang multiple times, and prevents inline functions from being duplicated.5234 from invoking clang multiple times, and prevents inline functions from being duplicated.
5212 </p>5235 </p>
5213 <p>5236 <p>
5214 Reasons for having multiple <code>@cImport</code> expressions would be:5237 Reasons for having multiple {#syntax#}@cImport{#endsyntax#} expressions would be:
5215 </p>5238 </p>
5216 <ul>5239 <ul>
5217 <li>To avoid a symbol collision, for example if foo.h and bar.h both <code>#define CONNECTION_COUNT</code></li>5240 <li>To avoid a symbol collision, for example if foo.h and bar.h both <code>#define CONNECTION_COUNT</code></li>
5218 <li>To analyze the C code with different preprocessor defines</li>5241 <li>To analyze the C code with different preprocessor defines</li>
5219 </ul>5242 </ul>
5220 {#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}5243 {#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
5221 {#header_close#}5244 {#header_close#}
5222 {#header_open|@cInclude#}5245 {#header_open|@cInclude#}
5223 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>5246 <pre>{#syntax#}@cInclude(comptime path: []u8){#endsyntax#}</pre>
5224 <p>5247 <p>
5225 This function can only occur inside <code>@cImport</code>.5248 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5226 </p>5249 </p>
5227 <p>5250 <p>
5228 This appends <code>#include <$path>\n</code> to the <code>c_import</code>5251 This appends <code>#include <$path>\n</code> to the {#syntax#}c_import{#endsyntax#}
5229 temporary buffer.5252 temporary buffer.
5230 </p>5253 </p>
5231 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}5254 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
5232 {#header_close#}5255 {#header_close#}
5233 {#header_open|@cUndef#}5256 {#header_open|@cUndef#}
5234 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>5257 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
5235 <p>5258 <p>
5236 This function can only occur inside <code>@cImport</code>.5259 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5237 </p>5260 </p>
5238 <p>5261 <p>
5239 This appends <code>#undef $name</code> to the <code>@cImport</code>5262 This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
5240 temporary buffer.5263 temporary buffer.
5241 </p>5264 </p>
5242 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}5265 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
5243 {#header_close#}5266 {#header_close#}
5244 {#header_open|@clz#}5267 {#header_open|@clz#}
5245 <pre><code class="zig">@clz(x: T) U</code></pre>5268 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
5246 <p>5269 <p>
5247 This function counts the number of leading zeroes in <code>x</code> which is an integer5270 This function counts the number of leading zeroes in {#syntax#}x{#endsyntax#} which is an integer
5248 type <code>T</code>.5271 type {#syntax#}T{#endsyntax#}.
5249 </p>5272 </p>
5250 <p>5273 <p>
5251 The return type <code>U</code> is an unsigned integer with the minimum number5274 The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
5252 of bits that can represent the value <code>T.bit_count</code>.5275 of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
5253 </p>5276 </p>
5254 <p>5277 <p>
5255 If <code>x</code> is zero, <code>@clz</code> returns <code>T.bit_count</code>.5278 If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@clz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}.
5256 </p>5279 </p>
5257 {#see_also|@ctz|@popCount#}5280 {#see_also|@ctz|@popCount#}
5258 {#header_close#}5281 {#header_close#}
5259 {#header_open|@cmpxchgStrong#}5282 {#header_open|@cmpxchgStrong#}
5260 <pre><code class="zig">@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T</code></pre>5283 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
5261 <p>5284 <p>
5262 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,5285 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,
5263 except atomic:5286 except atomic:
...@@ -5278,13 +5301,13 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v...@@ -5278,13 +5301,13 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
5278 more efficiently in machine instructions.5301 more efficiently in machine instructions.
5279 </p>5302 </p>
5280 <p>5303 <p>
5281 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.5304 {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
5282 </p>5305 </p>
5283 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>5306 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
5284 {#see_also|Compile Variables|cmpxchgWeak#}5307 {#see_also|Compile Variables|cmpxchgWeak#}
5285 {#header_close#}5308 {#header_close#}
5286 {#header_open|@cmpxchgWeak#}5309 {#header_open|@cmpxchgWeak#}
5287 <pre><code class="zig">@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T</code></pre>5310 <pre>{#syntax#}@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
5288 <p>5311 <p>
5289 This function performs a weak atomic compare exchange operation. It's the equivalent of this code,5312 This function performs a weak atomic compare exchange operation. It's the equivalent of this code,
5290 except atomic:5313 except atomic:
...@@ -5301,30 +5324,30 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5301,30 +5324,30 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5301}5324}
5302 {#code_end#}5325 {#code_end#}
5303 <p>5326 <p>
5304 If you are using cmpxchg in a loop, the sporadic failure will be no problem, and <code>cmpxchgWeak</code>5327 If you are using cmpxchg in a loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#}
5305 is the better choice, because it can be implemented more efficiently in machine instructions.5328 is the better choice, because it can be implemented more efficiently in machine instructions.
5306 However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.5329 However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
5307 </p>5330 </p>
5308 <p>5331 <p>
5309 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.5332 {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
5310 </p>5333 </p>
5311 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>5334 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
5312 {#see_also|Compile Variables|cmpxchgStrong#}5335 {#see_also|Compile Variables|cmpxchgStrong#}
5313 {#header_close#}5336 {#header_close#}
5314 {#header_open|@compileError#}5337 {#header_open|@compileError#}
5315 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>5338 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
5316 <p>5339 <p>
5317 This function, when semantically analyzed, causes a compile error with the5340 This function, when semantically analyzed, causes a compile error with the
5318 message <code>msg</code>.5341 message {#syntax#}msg{#endsyntax#}.
5319 </p>5342 </p>
5320 <p>5343 <p>
5321 There are several ways that code avoids being semantically checked, such as5344 There are several ways that code avoids being semantically checked, such as
5322 using <code>if</code> or <code>switch</code> with compile time constants,5345 using {#syntax#}if{#endsyntax#} or {#syntax#}switch{#endsyntax#} with compile time constants,
5323 and <code>comptime</code> functions.5346 and {#syntax#}comptime{#endsyntax#} functions.
5324 </p>5347 </p>
5325 {#header_close#}5348 {#header_close#}
5326 {#header_open|@compileLog#}5349 {#header_open|@compileLog#}
5327 <pre><code class="zig">@compileLog(args: ...)</code></pre>5350 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
5328 <p>5351 <p>
5329 This function prints the arguments passed to it at compile-time.5352 This function prints the arguments passed to it at compile-time.
5330 </p>5353 </p>
...@@ -5359,7 +5382,7 @@ test "main" {...@@ -5359,7 +5382,7 @@ test "main" {
5359 will ouput:5382 will ouput:
5360 </p>5383 </p>
5361 <p>5384 <p>
5362 If all <code>@compileLog</code> calls are removed or 5385 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or
5363 not encountered by analysis, the5386 not encountered by analysis, the
5364 program compiles successfully and the generated executable prints:5387 program compiles successfully and the generated executable prints:
5365 </p> 5388 </p>
...@@ -5378,84 +5401,88 @@ test "main" {...@@ -5378,84 +5401,88 @@ test "main" {
5378 {#code_end#}5401 {#code_end#}
5379 {#header_close#}5402 {#header_close#}
5380 {#header_open|@ctz#}5403 {#header_open|@ctz#}
5381 <pre><code class="zig">@ctz(x: T) U</code></pre>5404 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
5382 <p>5405 <p>
5383 This function counts the number of trailing zeroes in <code>x</code> which is an integer5406 This function counts the number of trailing zeroes in {#syntax#}x{#endsyntax#} which is an integer
5384 type <code>T</code>.5407 type {#syntax#}T{#endsyntax#}.
5385 </p>5408 </p>
5386 <p>5409 <p>
5387 The return type <code>U</code> is an unsigned integer with the minimum number5410 The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
5388 of bits that can represent the value <code>T.bit_count</code>.5411 of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
5389 </p>5412 </p>
5390 <p>5413 <p>
5391 If <code>x</code> is zero, <code>@ctz</code> returns <code>T.bit_count</code>.5414 If {#syntax#}x{#endsyntax#} is zero, {#syntax#}@ctz{#endsyntax#} returns {#syntax#}T.bit_count{#endsyntax#}.
5392 </p>5415 </p>
5393 {#see_also|@clz|@popCount#}5416 {#see_also|@clz|@popCount#}
5394 {#header_close#}5417 {#header_close#}
5395 {#header_open|@divExact#}5418 {#header_open|@divExact#}
5396 <pre><code class="zig">@divExact(numerator: T, denominator: T) T</code></pre>5419 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
5397 <p>5420 <p>
5398 Exact division. Caller guarantees <code>denominator != 0</code> and5421 Exact division. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5399 <code>@divTrunc(numerator, denominator) * denominator == numerator</code>.5422 {#syntax#}@divTrunc(numerator, denominator) * denominator == numerator{#endsyntax#}.
5400 </p>5423 </p>
5401 <ul>5424 <ul>
5402 <li><code>@divExact(6, 3) == 2</code></li>5425 <li>{#syntax#}@divExact(6, 3) == 2{#endsyntax#}</li>
5403 <li><code>@divExact(a, b) * b == a</code></li>5426 <li>{#syntax#}@divExact(a, b) * b == a{#endsyntax#}</li>
5404 </ul>5427 </ul>
5405 <p>For a function that returns a possible error code, use <code>@import("std").math.divExact</code>.</p>5428 <p>For a function that returns a possible error code, use {#syntax#}@import("std").math.divExact{#endsyntax#}.</p>
5406 {#see_also|@divTrunc|@divFloor#}5429 {#see_also|@divTrunc|@divFloor#}
5407 {#header_close#}5430 {#header_close#}
5408 {#header_open|@divFloor#}5431 {#header_open|@divFloor#}
5409 <pre><code class="zig">@divFloor(numerator: T, denominator: T) T</code></pre>5432 <pre>{#syntax#}@divFloor(numerator: T, denominator: T) T{#endsyntax#}</pre>
5410 <p>5433 <p>
5411 Floored division. Rounds toward negative infinity. For unsigned integers it is5434 Floored division. Rounds toward negative infinity. For unsigned integers it is
5412 the same as <code>numerator / denominator</code>. Caller guarantees <code>denominator != 0</code> and5435 the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5413 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.5436 {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1){#endsyntax#}.
5414 </p>5437 </p>
5415 <ul>5438 <ul>
5416 <li><code>@divFloor(-5, 3) == -2</code></li>5439 <li>{#syntax#}@divFloor(-5, 3) == -2{#endsyntax#}</li>
5417 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>5440 <li>{#syntax#}@divFloor(a, b) + @mod(a, b) == a{#endsyntax#}</li>
5418 </ul>5441 </ul>
5419 <p>For a function that returns a possible error code, use <code>@import("std").math.divFloor</code>.</p>5442 <p>For a function that returns a possible error code, use {#syntax#}@import("std").math.divFloor{#endsyntax#}.</p>
5420 {#see_also|@divTrunc|@divExact#}5443 {#see_also|@divTrunc|@divExact#}
5421 {#header_close#}5444 {#header_close#}
5422 {#header_open|@divTrunc#}5445 {#header_open|@divTrunc#}
5423 <pre><code class="zig">@divTrunc(numerator: T, denominator: T) T</code></pre>5446 <pre>{#syntax#}@divTrunc(numerator: T, denominator: T) T{#endsyntax#}</pre>
5424 <p>5447 <p>
5425 Truncated division. Rounds toward zero. For unsigned integers it is5448 Truncated division. Rounds toward zero. For unsigned integers it is
5426 the same as <code>numerator / denominator</code>. Caller guarantees <code>denominator != 0</code> and5449 the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5427 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.5450 {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1){#endsyntax#}.
5428 </p>5451 </p>
5429 <ul>5452 <ul>
5430 <li><code>@divTrunc(-5, 3) == -1</code></li>5453 <li>{#syntax#}@divTrunc(-5, 3) == -1{#endsyntax#}</li>
5431 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>5454 <li>{#syntax#}@divTrunc(a, b) + @rem(a, b) == a{#endsyntax#}</li>
5432 </ul>5455 </ul>
5433 <p>For a function that returns a possible error code, use <code>@import("std").math.divTrunc</code>.</p>5456 <p>For a function that returns a possible error code, use {#syntax#}@import("std").math.divTrunc{#endsyntax#}.</p>
5434 {#see_also|@divFloor|@divExact#}5457 {#see_also|@divFloor|@divExact#}
5435 {#header_close#}5458 {#header_close#}
5436 {#header_open|@embedFile#}5459 {#header_open|@embedFile#}
5437 <pre><code class="zig">@embedFile(comptime path: []const u8) [X]u8</code></pre>5460 <pre>{#syntax#}@embedFile(comptime path: []const u8) [X]u8{#endsyntax#}</pre>
5438 <p>5461 <p>
5439 This function returns a compile time constant fixed-size array with length5462 This function returns a compile time constant fixed-size array with length
5440 equal to the byte count of the file given by <code>path</code>. The contents of the array5463 equal to the byte count of the file given by {#syntax#}path{#endsyntax#}. The contents of the array
5441 are the contents of the file.5464 are the contents of the file.
5442 </p>5465 </p>
5443 <p>5466 <p>
5444 <code>path</code> is absolute or relative to the current file, just like <code>@import</code>.5467 {#syntax#}path{#endsyntax#} is absolute or relative to the current file, just like {#syntax#}@import{#endsyntax#}.
5445 </p>5468 </p>
5446 {#see_also|@import#}5469 {#see_also|@import#}
5447 {#header_close#}5470 {#header_close#}
54485471
5449 {#header_open|@enumToInt#}5472 {#header_open|@enumToInt#}
5450 <pre><code class="zig">@enumToInt(enum_value: var) var</code></pre>5473 <pre>{#syntax#}@enumToInt(enum_value: var) var{#endsyntax#}</pre>
5451 <p>5474 <p>
5452 Converts an enumeration value into its integer tag type.5475 Converts an enumeration value into its integer tag type.
5453 </p>5476 </p>
5477 <p>
5478 If the enum has only 1 possible value, the resut is a {#syntax#}comptime_int{#endsyntax#}
5479 known at {#link|comptime#}.
5480 </p>
5454 {#see_also|@intToEnum#}5481 {#see_also|@intToEnum#}
5455 {#header_close#}5482 {#header_close#}
54565483
5457 {#header_open|@errSetCast#}5484 {#header_open|@errSetCast#}
5458 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>5485 <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
5459 <p>5486 <p>
5460 Converts an error value from one error set to another error set. Attempting to convert an error5487 Converts an error value from one error set to another error set. Attempting to convert an error
5461 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.5488 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
...@@ -5463,24 +5490,24 @@ test "main" {...@@ -5463,24 +5490,24 @@ test "main" {
5463 {#header_close#}5490 {#header_close#}
54645491
5465 {#header_open|@errorName#}5492 {#header_open|@errorName#}
5466 <pre><code class="zig">@errorName(err: error) []u8</code></pre>5493 <pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre>
5467 <p>5494 <p>
5468 This function returns the string representation of an error. If an error5495 This function returns the string representation of an error. If an error
5469 declaration is:5496 declaration is:
5470 </p>5497 </p>
5471 <pre><code class="zig">error OutOfMem</code></pre>5498 <pre>{#syntax#}error OutOfMem{#endsyntax#}</pre>
5472 <p>5499 <p>
5473 Then the string representation is <code>"OutOfMem"</code>.5500 Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}.
5474 </p>5501 </p>
5475 <p>5502 <p>
5476 If there are no calls to <code>@errorName</code> in an entire application,5503 If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,
5477 or all calls have a compile-time known value for <code>err</code>, then no5504 or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no
5478 error name table will be generated.5505 error name table will be generated.
5479 </p>5506 </p>
5480 {#header_close#}5507 {#header_close#}
54815508
5482 {#header_open|@errorReturnTrace#}5509 {#header_open|@errorReturnTrace#}
5483 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>5510 <pre>{#syntax#}@errorReturnTrace() ?*builtin.StackTrace{#endsyntax#}</pre>
5484 <p>5511 <p>
5485 If the binary is built with error return tracing, and this function is invoked in a5512 If the binary is built with error return tracing, and this function is invoked in a
5486 function that calls a function with an error or error union return type, returns a5513 function that calls a function with an error or error union return type, returns a
...@@ -5489,13 +5516,13 @@ test "main" {...@@ -5489,13 +5516,13 @@ test "main" {
5489 {#header_close#}5516 {#header_close#}
54905517
5491 {#header_open|@errorToInt#}5518 {#header_open|@errorToInt#}
5492 <pre><code class="zig">@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8)</code></pre>5519 <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8){#endsyntax#}</pre>
5493 <p>5520 <p>
5494 Supports the following types:5521 Supports the following types:
5495 </p>5522 </p>
5496 <ul>5523 <ul>
5497 <li>error unions</li>5524 <li>error unions</li>
5498 <li><code>E!void</code></li>5525 <li>{#syntax#}E!void{#endsyntax#}</li>
5499 </ul>5526 </ul>
5500 <p>5527 <p>
5501 Converts an error to the integer representation of an error.5528 Converts an error to the integer representation of an error.
...@@ -5508,38 +5535,41 @@ test "main" {...@@ -5508,38 +5535,41 @@ test "main" {
5508 {#header_close#}5535 {#header_close#}
55095536
5510 {#header_open|@export#}5537 {#header_open|@export#}
5511 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>5538 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
5512 <p>5539 <p>
5513 Creates a symbol in the output object file.5540 Creates a symbol in the output object file.
5514 </p>5541 </p>
5515 {#header_close#}5542 {#header_close#}
55165543
5517 {#header_open|@fence#}5544 {#header_open|@fence#}
5518 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>5545 <pre>{#syntax#}@fence(order: AtomicOrder){#endsyntax#}</pre>
5519 <p>5546 <p>
5520 The <code>fence</code> function is used to introduce happens-before edges between operations.5547 The {#syntax#}fence{#endsyntax#} function is used to introduce happens-before edges between operations.
5521 </p>5548 </p>
5522 <p>5549 <p>
5523 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.5550 {#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("builtin").AtomicOrder{#endsyntax#}.
5524 </p>5551 </p>
5525 {#see_also|Compile Variables#}5552 {#see_also|Compile Variables#}
5526 {#header_close#}5553 {#header_close#}
55275554
5528 {#header_open|@field#}5555 {#header_open|@field#}
5529 <pre><code class="zig">@field(lhs: var, comptime field_name: []const u8) (field)</code></pre>5556 <pre>{#syntax#}@field(lhs: var, comptime field_name: []const u8) (field){#endsyntax#}</pre>
5530 <p>Preforms field access equivalent to <code>lhs.-&gtfield_name-&lt</code>.</p>5557 <p>Preforms field access equivalent to {#syntax#}lhs.field_name{#endsyntax#}, except instead
5558 of the field {#syntax#}"field_name"{#endsyntax#}, it accesses the field named by the string
5559 value of {#syntax#}field_name{#endsyntax#}.
5560 </p>
5531 {#header_close#}5561 {#header_close#}
55325562
5533 {#header_open|@fieldParentPtr#}5563 {#header_open|@fieldParentPtr#}
5534 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,5564 <pre>{#syntax#}@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
5535 field_ptr: *T) *ParentType</code></pre>5565 field_ptr: *T) *ParentType{#endsyntax#}</pre>
5536 <p>5566 <p>
5537 Given a pointer to a field, returns the base pointer of a struct.5567 Given a pointer to a field, returns the base pointer of a struct.
5538 </p>5568 </p>
5539 {#header_close#}5569 {#header_close#}
55405570
5541 {#header_open|@floatCast#}5571 {#header_open|@floatCast#}
5542 <pre><code class="zig">@floatCast(comptime DestType: type, value: var) DestType</code></pre>5572 <pre>{#syntax#}@floatCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
5543 <p>5573 <p>
5544 Convert from one float type to another. This cast is safe, but may cause the5574 Convert from one float type to another. This cast is safe, but may cause the
5545 numeric value to lose precision.5575 numeric value to lose precision.
...@@ -5547,7 +5577,7 @@ test "main" {...@@ -5547,7 +5577,7 @@ test "main" {
5547 {#header_close#}5577 {#header_close#}
55485578
5549 {#header_open|@floatToInt#}5579 {#header_open|@floatToInt#}
5550 <pre><code class="zig">@floatToInt(comptime DestType: type, float: var) DestType</code></pre>5580 <pre>{#syntax#}@floatToInt(comptime DestType: type, float: var) DestType{#endsyntax#}</pre>
5551 <p>5581 <p>
5552 Converts the integer part of a floating point number to the destination type.5582 Converts the integer part of a floating point number to the destination type.
5553 </p>5583 </p>
...@@ -5559,7 +5589,7 @@ test "main" {...@@ -5559,7 +5589,7 @@ test "main" {
5559 {#header_close#}5589 {#header_close#}
55605590
5561 {#header_open|@frameAddress#}5591 {#header_open|@frameAddress#}
5562 <pre><code class="zig">@frameAddress()</code></pre>5592 <pre>{#syntax#}@frameAddress(){#endsyntax#}</pre>
5563 <p>5593 <p>
5564 This function returns the base pointer of the current stack frame.5594 This function returns the base pointer of the current stack frame.
5565 </p>5595 </p>
...@@ -5573,9 +5603,9 @@ test "main" {...@@ -5573,9 +5603,9 @@ test "main" {
5573 </p>5603 </p>
5574 {#header_close#}5604 {#header_close#}
5575 {#header_open|@handle#}5605 {#header_open|@handle#}
5576 <pre><code class="zig">@handle()</code></pre>5606 <pre>{#syntax#}@handle(){#endsyntax#}</pre>
5577 <p>5607 <p>
5578 This function returns a <code>promise->T</code> type, where <code>T</code>5608 This function returns a {#syntax#}promise->T{#endsyntax#} type, where {#syntax#}T{#endsyntax#}
5579 is the return type of the async function in scope.5609 is the return type of the async function in scope.
5580 </p>5610 </p>
5581 <p>5611 <p>
...@@ -5583,27 +5613,27 @@ test "main" {...@@ -5583,27 +5613,27 @@ test "main" {
5583 </p>5613 </p>
5584 {#header_close#}5614 {#header_close#}
5585 {#header_open|@import#}5615 {#header_open|@import#}
5586 <pre><code class="zig">@import(comptime path: []u8) (namespace)</code></pre>5616 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
5587 <p>5617 <p>
5588 This function finds a zig file corresponding to <code>path</code> and imports all the5618 This function finds a zig file corresponding to {#syntax#}path{#endsyntax#} and imports all the
5589 public top level declarations into the resulting namespace.5619 public top level declarations into the resulting namespace.
5590 </p>5620 </p>
5591 <p>5621 <p>
5592 <code>path</code> can be a relative or absolute path, or it can be the name of a package.5622 {#syntax#}path{#endsyntax#} can be a relative or absolute path, or it can be the name of a package.
5593 If it is a relative path, it is relative to the file that contains the <code>@import</code>5623 If it is a relative path, it is relative to the file that contains the {#syntax#}@import{#endsyntax#}
5594 function call.5624 function call.
5595 </p>5625 </p>
5596 <p>5626 <p>
5597 The following packages are always available:5627 The following packages are always available:
5598 </p>5628 </p>
5599 <ul>5629 <ul>
5600 <li><code>@import("std")</code> - Zig Standard Library</li>5630 <li>{#syntax#}@import("std"){#endsyntax#} - Zig Standard Library</li>
5601 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>5631 <li>{#syntax#}@import("builtin"){#endsyntax#} - Compiler-provided types and variables</li>
5602 </ul>5632 </ul>
5603 {#see_also|Compile Variables|@embedFile#}5633 {#see_also|Compile Variables|@embedFile#}
5604 {#header_close#}5634 {#header_close#}
5605 {#header_open|@inlineCall#}5635 {#header_open|@inlineCall#}
5606 <pre><code class="zig">@inlineCall(function: X, args: ...) Y</code></pre>5636 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
5607 <p>5637 <p>
5608 This calls a function, in the same way that invoking an expression with parentheses does:5638 This calls a function, in the same way that invoking an expression with parentheses does:
5609 </p>5639 </p>
...@@ -5617,14 +5647,14 @@ test "inline function call" {...@@ -5617,14 +5647,14 @@ test "inline function call" {
5617fn add(a: i32, b: i32) i32 { return a + b; }5647fn add(a: i32, b: i32) i32 { return a + b; }
5618 {#code_end#}5648 {#code_end#}
5619 <p>5649 <p>
5620 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call5650 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
5621 will be inlined. If the call cannot be inlined, a compile error is emitted.5651 will be inlined. If the call cannot be inlined, a compile error is emitted.
5622 </p>5652 </p>
5623 {#see_also|@noInlineCall#}5653 {#see_also|@noInlineCall#}
5624 {#header_close#}5654 {#header_close#}
56255655
5626 {#header_open|@intCast#}5656 {#header_open|@intCast#}
5627 <pre><code class="zig">@intCast(comptime DestType: type, int: var) DestType</code></pre>5657 <pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>
5628 <p>5658 <p>
5629 Converts an integer to another integer while keeping the same numerical value.5659 Converts an integer to another integer while keeping the same numerical value.
5630 Attempting to convert a number which is out of range of the destination type results in5660 Attempting to convert a number which is out of range of the destination type results in
...@@ -5633,7 +5663,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5633,7 +5663,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5633 {#header_close#}5663 {#header_close#}
56345664
5635 {#header_open|@intToEnum#}5665 {#header_open|@intToEnum#}
5636 <pre><code class="zig">@intToEnum(comptime DestType: type, int_value: @TagType(DestType)) DestType</code></pre>5666 <pre>{#syntax#}@intToEnum(comptime DestType: type, int_value: @TagType(DestType)) DestType{#endsyntax#}</pre>
5637 <p>5667 <p>
5638 Converts an integer into an {#link|enum#} value.5668 Converts an integer into an {#link|enum#} value.
5639 </p>5669 </p>
...@@ -5645,7 +5675,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5645,7 +5675,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5645 {#header_close#}5675 {#header_close#}
56465676
5647 {#header_open|@intToError#}5677 {#header_open|@intToError#}
5648 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>5678 <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(error) * 8)) error{#endsyntax#}</pre>
5649 <p>5679 <p>
5650 Converts from the integer representation of an error into the global error set type.5680 Converts from the integer representation of an error into the global error set type.
5651 </p>5681 </p>
...@@ -5661,36 +5691,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5661,36 +5691,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5661 {#header_close#}5691 {#header_close#}
56625692
5663 {#header_open|@intToFloat#}5693 {#header_open|@intToFloat#}
5664 <pre><code class="zig">@intToFloat(comptime DestType: type, int: var) DestType</code></pre>5694 <pre>{#syntax#}@intToFloat(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>
5665 <p>5695 <p>
5666 Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.5696 Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.
5667 </p>5697 </p>
5668 {#header_close#}5698 {#header_close#}
56695699
5670 {#header_open|@intToPtr#}5700 {#header_open|@intToPtr#}
5671 <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) DestType</code></pre>5701 <pre>{#syntax#}@intToPtr(comptime DestType: type, int: usize) DestType{#endsyntax#}</pre>
5672 <p>5702 <p>
5673 Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.5703 Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.
5674 </p>5704 </p>
5675 {#header_close#}5705 {#header_close#}
56765706
5677 {#header_open|@IntType#}5707 {#header_open|@IntType#}
5678 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u32) type</code></pre>5708 <pre>{#syntax#}@IntType(comptime is_signed: bool, comptime bit_count: u32) type{#endsyntax#}</pre>
5679 <p>5709 <p>
5680 This function returns an integer type with the given signness and bit count.5710 This function returns an integer type with the given signness and bit count.
5681 </p>5711 </p>
5682 {#header_close#}5712 {#header_close#}
5683 {#header_open|@maxValue#}5713 {#header_open|@maxValue#}
5684 <pre><code class="zig">@maxValue(comptime T: type) (number literal)</code></pre>5714 <pre>{#syntax#}@maxValue(comptime T: type) comptime_int{#endsyntax#}</pre>
5685 <p>5715 <p>
5686 This function returns the maximum value of the integer type <code>T</code>.5716 This function returns the maximum value of the integer type {#syntax#}T{#endsyntax#}.
5687 </p>5717 </p>
5688 <p>5718 <p>
5689 The result is a compile time constant.5719 The result is a compile time constant.
5690 </p>5720 </p>
5691 {#header_close#}5721 {#header_close#}
5692 {#header_open|@memberCount#}5722 {#header_open|@memberCount#}
5693 <pre><code class="zig">@memberCount(comptime T: type) (number literal)</code></pre>5723 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
5694 <p>5724 <p>
5695 This function returns the number of members in a struct, enum, or union type.5725 This function returns the number of members in a struct, enum, or union type.
5696 </p>5726 </p>
...@@ -5702,7 +5732,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5702,7 +5732,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5702 </p>5732 </p>
5703 {#header_close#}5733 {#header_close#}
5704 {#header_open|@memberName#}5734 {#header_open|@memberName#}
5705 <pre><code class="zig">@memberName(comptime T: type, comptime index: usize) [N]u8</code></pre>5735 <pre>{#syntax#}@memberName(comptime T: type, comptime index: usize) [N]u8{#endsyntax#}</pre>
5706 <p>Returns the field name of a struct, union, or enum.</p>5736 <p>Returns the field name of a struct, union, or enum.</p>
5707 <p>5737 <p>
5708 The result is a compile time constant.5738 The result is a compile time constant.
...@@ -5712,46 +5742,46 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5712,46 +5742,46 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5712 </p>5742 </p>
5713 {#header_close#}5743 {#header_close#}
5714 {#header_open|@memberType#}5744 {#header_open|@memberType#}
5715 <pre><code class="zig">@memberType(comptime T: type, comptime index: usize) type</code></pre>5745 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
5716 <p>Returns the field type of a struct or union.</p>5746 <p>Returns the field type of a struct or union.</p>
5717 {#header_close#}5747 {#header_close#}
5718 {#header_open|@memcpy#}5748 {#header_open|@memcpy#}
5719 <pre><code class="zig">@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize)</code></pre>5749 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
5720 <p>5750 <p>
5721 This function copies bytes from one region of memory to another. <code>dest</code> and5751 This function copies bytes from one region of memory to another. {#syntax#}dest{#endsyntax#} and
5722 <code>source</code> are both pointers and must not overlap.5752 {#syntax#}source{#endsyntax#} are both pointers and must not overlap.
5723 </p>5753 </p>
5724 <p>5754 <p>
5725 This function is a low level intrinsic with no safety mechanisms. Most code5755 This function is a low level intrinsic with no safety mechanisms. Most code
5726 should not use this function, instead using something like this:5756 should not use this function, instead using something like this:
5727 </p>5757 </p>
5728 <pre><code class="zig">for (source[0...byte_count]) |b, i| dest[i] = b;</code></pre>5758 <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
5729 <p>5759 <p>
5730 The optimizer is intelligent enough to turn the above snippet into a memcpy.5760 The optimizer is intelligent enough to turn the above snippet into a memcpy.
5731 </p>5761 </p>
5732 <p>There is also a standard library function for this:</p>5762 <p>There is also a standard library function for this:</p>
5733 <pre><code class="zig">const mem = @import("std").mem;5763 <pre>{#syntax#}const mem = @import("std").mem;
5734mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>5764mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5735 {#header_close#}5765 {#header_close#}
5736 {#header_open|@memset#}5766 {#header_open|@memset#}
5737 <pre><code class="zig">@memset(dest: [*]u8, c: u8, byte_count: usize)</code></pre>5767 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
5738 <p>5768 <p>
5739 This function sets a region of memory to <code>c</code>. <code>dest</code> is a pointer.5769 This function sets a region of memory to {#syntax#}c{#endsyntax#}. {#syntax#}dest{#endsyntax#} is a pointer.
5740 </p>5770 </p>
5741 <p>5771 <p>
5742 This function is a low level intrinsic with no safety mechanisms. Most5772 This function is a low level intrinsic with no safety mechanisms. Most
5743 code should not use this function, instead using something like this:5773 code should not use this function, instead using something like this:
5744 </p>5774 </p>
5745 <pre><code class="zig">for (dest[0...byte_count]) |*b| b.* = c;</code></pre>5775 <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
5746 <p>5776 <p>
5747 The optimizer is intelligent enough to turn the above snippet into a memset.5777 The optimizer is intelligent enough to turn the above snippet into a memset.
5748 </p>5778 </p>
5749 <p>There is also a standard library function for this:</p>5779 <p>There is also a standard library function for this:</p>
5750 <pre><code>const mem = @import("std").mem;5780 <pre>{#syntax#}const mem = @import("std").mem;
5751mem.set(u8, dest, c);</code></pre>5781mem.set(u8, dest, c);{#endsyntax#}</pre>
5752 {#header_close#}5782 {#header_close#}
5753 {#header_open|@minValue#}5783 {#header_open|@minValue#}
5754 <pre><code class="zig">@minValue(comptime T: type) (number literal)</code></pre>5784 <pre>{#syntax#}@minValue(comptime T: type) comptime_int{#endsyntax#}</pre>
5755 <p>5785 <p>
5756 This function returns the minimum value of the integer type T.5786 This function returns the minimum value of the integer type T.
5757 </p>5787 </p>
...@@ -5760,31 +5790,31 @@ mem.set(u8, dest, c);</code></pre>...@@ -5760,31 +5790,31 @@ mem.set(u8, dest, c);</code></pre>
5760 </p>5790 </p>
5761 {#header_close#}5791 {#header_close#}
5762 {#header_open|@mod#}5792 {#header_open|@mod#}
5763 <pre><code class="zig">@mod(numerator: T, denominator: T) T</code></pre>5793 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
5764 <p>5794 <p>
5765 Modulus division. For unsigned integers this is the same as5795 Modulus division. For unsigned integers this is the same as
5766 <code>numerator % denominator</code>. Caller guarantees <code>denominator &gt; 0</code>.5796 {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator &gt; 0{#endsyntax#}.
5767 </p>5797 </p>
5768 <ul>5798 <ul>
5769 <li><code>@mod(-5, 3) == 1</code></li>5799 <li>{#syntax#}@mod(-5, 3) == 1{#endsyntax#}</li>
5770 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>5800 <li>{#syntax#}@divFloor(a, b) + @mod(a, b) == a{#endsyntax#}</li>
5771 </ul>5801 </ul>
5772 <p>For a function that returns an error code, see <code>@import("std").math.mod</code>.</p>5802 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
5773 {#see_also|@rem#}5803 {#see_also|@rem#}
5774 {#header_close#}5804 {#header_close#}
5775 {#header_open|@mulWithOverflow#}5805 {#header_open|@mulWithOverflow#}
5776 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool</code></pre>5806 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
5777 <p>5807 <p>
5778 Performs <code>result.* = a * b</code>. If overflow or underflow occurs,5808 Performs {#syntax#}result.* = a * b{#endsyntax#}. If overflow or underflow occurs,
5779 stores the overflowed bits in <code>result</code> and returns <code>true</code>.5809 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
5780 If no overflow or underflow occurs, returns <code>false</code>.5810 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5781 </p>5811 </p>
5782 {#header_close#}5812 {#header_close#}
5783 {#header_open|@newStackCall#}5813 {#header_open|@newStackCall#}
5784 <pre><code class="zig">@newStackCall(new_stack: []u8, function: var, args: ...) var</code></pre>5814 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
5785 <p>5815 <p>
5786 This calls a function, in the same way that invoking an expression with parentheses does. However,5816 This calls a function, in the same way that invoking an expression with parentheses does. However,
5787 instead of using the same stack as the caller, the function uses the stack provided in the <code>new_stack</code>5817 instead of using the same stack as the caller, the function uses the stack provided in the {#syntax#}new_stack{#endsyntax#}
5788 parameter.5818 parameter.
5789 </p>5819 </p>
5790 {#code_begin|test#}5820 {#code_begin|test#}
...@@ -5817,7 +5847,7 @@ fn targetFunction(x: i32) usize {...@@ -5817,7 +5847,7 @@ fn targetFunction(x: i32) usize {
5817 {#code_end#}5847 {#code_end#}
5818 {#header_close#}5848 {#header_close#}
5819 {#header_open|@noInlineCall#}5849 {#header_open|@noInlineCall#}
5820 <pre><code class="zig">@noInlineCall(function: var, args: ...) var</code></pre>5850 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
5821 <p>5851 <p>
5822 This calls a function, in the same way that invoking an expression with parentheses does:5852 This calls a function, in the same way that invoking an expression with parentheses does:
5823 </p>5853 </p>
...@@ -5833,19 +5863,19 @@ fn add(a: i32, b: i32) i32 {...@@ -5833,19 +5863,19 @@ fn add(a: i32, b: i32) i32 {
5833}5863}
5834 {#code_end#}5864 {#code_end#}
5835 <p>5865 <p>
5836 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call5866 Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
5837 will not be inlined. If the call must be inlined, a compile error is emitted.5867 will not be inlined. If the call must be inlined, a compile error is emitted.
5838 </p>5868 </p>
5839 {#see_also|@inlineCall#}5869 {#see_also|@inlineCall#}
5840 {#header_close#}5870 {#header_close#}
5841 {#header_open|@offsetOf#}5871 {#header_open|@offsetOf#}
5842 <pre><code class="zig">@offsetOf(comptime T: type, comptime field_name: [] const u8) (number literal)</code></pre>5872 <pre>{#syntax#}@offsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5843 <p>5873 <p>
5844 This function returns the byte offset of a field relative to its containing struct.5874 This function returns the byte offset of a field relative to its containing struct.
5845 </p>5875 </p>
5846 {#header_close#}5876 {#header_close#}
5847 {#header_open|@OpaqueType#}5877 {#header_open|@OpaqueType#}
5848 <pre><code class="zig">@OpaqueType() type</code></pre>5878 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
5849 <p>5879 <p>
5850 Creates a new type with an unknown size and alignment.5880 Creates a new type with an unknown size and alignment.
5851 </p>5881 </p>
...@@ -5868,14 +5898,14 @@ test "call foo" {...@@ -5868,14 +5898,14 @@ test "call foo" {
5868 {#code_end#}5898 {#code_end#}
5869 {#header_close#}5899 {#header_close#}
5870 {#header_open|@panic#}5900 {#header_open|@panic#}
5871 <pre><code class="zig">@panic(message: []const u8) noreturn</code></pre>5901 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
5872 <p>5902 <p>
5873 Invokes the panic handler function. By default the panic handler function5903 Invokes the panic handler function. By default the panic handler function
5874 calls the public <code>panic</code> function exposed in the root source file, or5904 calls the public {#syntax#}panic{#endsyntax#} function exposed in the root source file, or
5875 if there is not one specified, invokes the one provided in <code>std/special/panic.zig</code>.5905 if there is not one specified, invokes the one provided in {#syntax#}std/special/panic.zig{#endsyntax#}.
5876 </p>5906 </p>
5877 <p>Generally it is better to use <code>@import("std").debug.panic</code>.5907 <p>Generally it is better to use {#syntax#}@import("std").debug.panic{#endsyntax#}.
5878 However, <code>@panic</code> can be useful for 2 scenarios:5908 However, {#syntax#}@panic{#endsyntax#} can be useful for 2 scenarios:
5879 </p>5909 </p>
5880 <ul>5910 <ul>
5881 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>5911 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>
...@@ -5884,50 +5914,50 @@ test "call foo" {...@@ -5884,50 +5914,50 @@ test "call foo" {
5884 {#see_also|Root Source File#}5914 {#see_also|Root Source File#}
5885 {#header_close#}5915 {#header_close#}
5886 {#header_open|@popCount#}5916 {#header_open|@popCount#}
5887 <pre><code class="zig">@popCount(integer: var) var</code></pre>5917 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
5888 <p>Counts the number of bits set in an integer.</p>5918 <p>Counts the number of bits set in an integer.</p>
5889 <p>5919 <p>
5890 If <code>integer</code> is known at {#link|comptime#}, the return type is <code>comptime_int</code>.5920 If {#syntax#}integer{#endsyntax#} is known at {#link|comptime#}, the return type is {#syntax#}comptime_int{#endsyntax#}.
5891 Otherwise, the return type is an unsigned integer with the minimum number5921 Otherwise, the return type is an unsigned integer with the minimum number
5892 of bits that can represent the bit count of the integer type.5922 of bits that can represent the bit count of the integer type.
5893 </p>5923 </p>
5894 {#see_also|@ctz|@clz#}5924 {#see_also|@ctz|@clz#}
5895 {#header_close#}5925 {#header_close#}
5896 {#header_open|@ptrCast#}5926 {#header_open|@ptrCast#}
5897 <pre><code class="zig">@ptrCast(comptime DestType: type, value: var) DestType</code></pre>5927 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
5898 <p>5928 <p>
5899 Converts a pointer of one type to a pointer of another type.5929 Converts a pointer of one type to a pointer of another type.
5900 </p>5930 </p>
5901 {#header_close#}5931 {#header_close#}
5902 {#header_open|@ptrToInt#}5932 {#header_open|@ptrToInt#}
5903 <pre><code class="zig">@ptrToInt(value: var) usize</code></pre>5933 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
5904 <p>5934 <p>
5905 Converts <code>value</code> to a <code>usize</code> which is the address of the pointer. <code>value</code> can be one of these types:5935 Converts {#syntax#}value{#endsyntax#} to a {#syntax#}usize{#endsyntax#} which is the address of the pointer. {#syntax#}value{#endsyntax#} can be one of these types:
5906 </p>5936 </p>
5907 <ul>5937 <ul>
5908 <li><code>*T</code></li>5938 <li>{#syntax#}*T{#endsyntax#}</li>
5909 <li><code>?*T</code></li>5939 <li>{#syntax#}?*T{#endsyntax#}</li>
5910 <li><code>fn()</code></li>5940 <li>{#syntax#}fn(){#endsyntax#}</li>
5911 <li><code>?fn()</code></li>5941 <li>{#syntax#}?fn(){#endsyntax#}</li>
5912 </ul>5942 </ul>
5913 <p>To convert the other way, use {#link|@intToPtr#}</p>5943 <p>To convert the other way, use {#link|@intToPtr#}</p>
59145944
5915 {#header_close#}5945 {#header_close#}
5916 {#header_open|@rem#}5946 {#header_open|@rem#}
5917 <pre><code class="zig">@rem(numerator: T, denominator: T) T</code></pre>5947 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
5918 <p>5948 <p>
5919 Remainder division. For unsigned integers this is the same as5949 Remainder division. For unsigned integers this is the same as
5920 <code>numerator % denominator</code>. Caller guarantees <code>denominator &gt; 0</code>.5950 {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}.
5921 </p>5951 </p>
5922 <ul>5952 <ul>
5923 <li><code>@rem(-5, 3) == -2</code></li>5953 <li>{#syntax#}@rem(-5, 3) == -2{#endsyntax#}</li>
5924 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>5954 <li>{#syntax#}@divTrunc(a, b) + @rem(a, b) == a{#endsyntax#}</li>
5925 </ul>5955 </ul>
5926 <p>For a function that returns an error code, see <code>@import("std").math.rem</code>.</p>5956 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
5927 {#see_also|@mod#}5957 {#see_also|@mod#}
5928 {#header_close#}5958 {#header_close#}
5929 {#header_open|@returnAddress#}5959 {#header_open|@returnAddress#}
5930 <pre><code class="zig">@returnAddress()</code></pre>5960 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
5931 <p>5961 <p>
5932 This function returns a pointer to the return address of the current stack5962 This function returns a pointer to the return address of the current stack
5933 frame.5963 frame.
...@@ -5941,32 +5971,32 @@ test "call foo" {...@@ -5941,32 +5971,32 @@ test "call foo" {
5941 </p>5971 </p>
5942 {#header_close#}5972 {#header_close#}
5943 {#header_open|@setAlignStack#}5973 {#header_open|@setAlignStack#}
5944 <pre><code class="zig">@setAlignStack(comptime alignment: u29)</code></pre>5974 <pre>{#syntax#}@setAlignStack(comptime alignment: u29){#endsyntax#}</pre>
5945 <p>5975 <p>
5946 Ensures that a function will have a stack alignment of at least <code>alignment</code> bytes.5976 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
5947 </p>5977 </p>
5948 {#header_close#}5978 {#header_close#}
5949 {#header_open|@setCold#}5979 {#header_open|@setCold#}
5950 <pre><code class="zig">@setCold(is_cold: bool)</code></pre>5980 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
5951 <p>5981 <p>
5952 Tells the optimizer that a function is rarely called.5982 Tells the optimizer that a function is rarely called.
5953 </p>5983 </p>
5954 {#header_close#}5984 {#header_close#}
5955 {#header_open|@setRuntimeSafety#}5985 {#header_open|@setRuntimeSafety#}
5956 <pre><code class="zig">@setRuntimeSafety(safety_on: bool)</code></pre>5986 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
5957 <p>5987 <p>
5958 Sets whether runtime safety checks are on for the scope that contains the function call.5988 Sets whether runtime safety checks are on for the scope that contains the function call.
5959 </p>5989 </p>
59605990
5961 {#header_close#}5991 {#header_close#}
5962 {#header_open|@setEvalBranchQuota#}5992 {#header_open|@setEvalBranchQuota#}
5963 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>5993 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
5964 <p>5994 <p>
5965 Changes the maximum number of backwards branches that compile-time code5995 Changes the maximum number of backwards branches that compile-time code
5966 execution can use before giving up and making a compile error.5996 execution can use before giving up and making a compile error.
5967 </p>5997 </p>
5968 <p>5998 <p>
5969 If the <code>new_quota</code> is smaller than the default quota (<code>1000</code>) or5999 If the {#syntax#}new_quota{#endsyntax#} is smaller than the default quota ({#syntax#}1000{#endsyntax#}) or
5970 a previously explicitly set quota, it is ignored.6000 a previously explicitly set quota, it is ignored.
5971 </p>6001 </p>
5972 <p>6002 <p>
...@@ -5980,7 +6010,7 @@ test "foo" {...@@ -5980,7 +6010,7 @@ test "foo" {
5980 }6010 }
5981}6011}
5982 {#code_end#}6012 {#code_end#}
5983 <p>Now we use <code class="zig">@setEvalBranchQuota</code>:</p>6013 <p>Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:</p>
5984 {#code_begin|test#}6014 {#code_begin|test#}
5985test "foo" {6015test "foo" {
5986 comptime {6016 comptime {
...@@ -5994,19 +6024,22 @@ test "foo" {...@@ -5994,19 +6024,22 @@ test "foo" {
5994 {#see_also|comptime#}6024 {#see_also|comptime#}
5995 {#header_close#}6025 {#header_close#}
5996 {#header_open|@setFloatMode#}6026 {#header_open|@setFloatMode#}
5997 <pre><code class="zig">@setFloatMode(scope, mode: @import("builtin").FloatMode)</code></pre>6027 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
5998 <p>6028 <p>
5999 Sets the floating point mode for a given scope. Possible values are:6029 Sets the floating point mode of the current scope. Possible values are:
6000 </p>6030 </p>
6001 {#code_begin|syntax#}6031 {#code_begin|syntax#}
6002pub const FloatMode = enum {6032pub const FloatMode = enum {
6003 Optimized,
6004 Strict,6033 Strict,
6034 Optimized,
6005};6035};
6006 {#code_end#}6036 {#code_end#}
6007 <ul>6037 <ul>
6008 <li>6038 <li>
6009 <code>Optimized</code> - Floating point operations may do all of the following:6039 {#syntax#}Strict{#endsyntax#} (default) - Floating point operations follow strict IEEE compliance.
6040 </li>
6041 <li>
6042 {#syntax#}Optimized{#endsyntax#} - Floating point operations may do all of the following:
6010 <ul>6043 <ul>
6011 <li>Assume the arguments and result are not NaN. Optimizations are required to retain defined behavior over NaNs, but the value of the result is undefined.</li>6044 <li>Assume the arguments and result are not NaN. Optimizations are required to retain defined behavior over NaNs, but the value of the result is undefined.</li>
6012 <li>Assume the arguments and result are not +/-Inf. Optimizations are required to retain defined behavior over +/-Inf, but the value of the result is undefined.</li>6045 <li>Assume the arguments and result are not +/-Inf. Optimizations are required to retain defined behavior over +/-Inf, but the value of the result is undefined.</li>
...@@ -6017,61 +6050,62 @@ pub const FloatMode = enum {...@@ -6017,61 +6050,62 @@ pub const FloatMode = enum {
6017 </ul>6050 </ul>
6018 This is equivalent to <code>-ffast-math</code> in GCC.6051 This is equivalent to <code>-ffast-math</code> in GCC.
6019 </li>6052 </li>
6020 <li>
6021 <code>Strict</code> (default) - Floating point operations follow strict IEEE compliance.
6022 </li>
6023 </ul>6053 </ul>
6054 <p>
6055 The floating point mode is inherited by child scopes, and can be overridden in any scope.
6056 You can set the floating point mode in a struct or module scope by using a comptime block.
6057 </p>
6024 {#see_also|Floating Point Operations#}6058 {#see_also|Floating Point Operations#}
6025 {#header_close#}6059 {#header_close#}
6026 {#header_open|@setGlobalLinkage#}6060 {#header_open|@setGlobalLinkage#}
6027 <pre><code class="zig">@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)</code></pre>6061 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
6028 <p>6062 <p>
6029 <code>GlobalLinkage</code> can be found with <code>@import("builtin").GlobalLinkage</code>.6063 {#syntax#}GlobalLinkage{#endsyntax#} can be found with {#syntax#}@import("builtin").GlobalLinkage{#endsyntax#}.
6030 </p>6064 </p>
6031 {#see_also|Compile Variables#}6065 {#see_also|Compile Variables#}
6032 {#header_close#}6066 {#header_close#}
6033 {#header_open|@shlExact#}6067 {#header_open|@shlExact#}
6034 <pre><code class="zig">@shlExact(value: T, shift_amt: Log2T) T</code></pre>6068 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6035 <p>6069 <p>
6036 Performs the left shift operation (<code>&lt;&lt;</code>). Caller guarantees6070 Performs the left shift operation ({#syntax#}<<{#endsyntax#}). Caller guarantees
6037 that the shift will not shift any 1 bits out.6071 that the shift will not shift any 1 bits out.
6038 </p>6072 </p>
6039 <p>6073 <p>
6040 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.6074 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6041 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.6075 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
6042 </p>6076 </p>
6043 {#see_also|@shrExact|@shlWithOverflow#}6077 {#see_also|@shrExact|@shlWithOverflow#}
6044 {#header_close#}6078 {#header_close#}
6045 {#header_open|@shlWithOverflow#}6079 {#header_open|@shlWithOverflow#}
6046 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool</code></pre>6080 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
6047 <p>6081 <p>
6048 Performs <code>result.* = a &lt;&lt; b</code>. If overflow or underflow occurs,6082 Performs {#syntax#}result.* = a << b{#endsyntax#}. If overflow or underflow occurs,
6049 stores the overflowed bits in <code>result</code> and returns <code>true</code>.6083 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
6050 If no overflow or underflow occurs, returns <code>false</code>.6084 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
6051 </p>6085 </p>
6052 <p>6086 <p>
6053 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.6087 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6054 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.6088 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
6055 </p>6089 </p>
6056 {#see_also|@shlExact|@shrExact#}6090 {#see_also|@shlExact|@shrExact#}
6057 {#header_close#}6091 {#header_close#}
6058 {#header_open|@shrExact#}6092 {#header_open|@shrExact#}
6059 <pre><code class="zig">@shrExact(value: T, shift_amt: Log2T) T</code></pre>6093 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6060 <p>6094 <p>
6061 Performs the right shift operation (<code>&gt;&gt;</code>). Caller guarantees6095 Performs the right shift operation ({#syntax#}>>{#endsyntax#}). Caller guarantees
6062 that the shift will not shift any 1 bits out.6096 that the shift will not shift any 1 bits out.
6063 </p>6097 </p>
6064 <p>6098 <p>
6065 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.6099 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6066 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.6100 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
6067 </p>6101 </p>
6068 {#see_also|@shlExact|@shlWithOverflow#}6102 {#see_also|@shlExact|@shlWithOverflow#}
6069 {#header_close#}6103 {#header_close#}
60706104
6071 {#header_open|@sizeOf#}6105 {#header_open|@sizeOf#}
6072 <pre><code class="zig">@sizeOf(comptime T: type) comptime_int</code></pre>6106 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
6073 <p>6107 <p>
6074 This function returns the number of bytes it takes to store <code>T</code> in memory.6108 This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory.
6075 </p>6109 </p>
6076 <p>6110 <p>
6077 The result is a target-specific compile time constant.6111 The result is a target-specific compile time constant.
...@@ -6079,39 +6113,39 @@ pub const FloatMode = enum {...@@ -6079,39 +6113,39 @@ pub const FloatMode = enum {
6079 {#header_close#}6113 {#header_close#}
60806114
6081 {#header_open|@sliceToBytes#}6115 {#header_open|@sliceToBytes#}
6082 <pre><code class="zig">@sliceToBytes(value: var) []u8</code></pre>6116 <pre>{#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}</pre>
6083 <p>6117 <p>
6084 Converts a slice or array to a slice of <code>u8</code>. The resulting slice has the same6118 Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same
6085 {#link|pointer|Pointers#} properties as the parameter.6119 {#link|pointer|Pointers#} properties as the parameter.
6086 </p>6120 </p>
6087 {#header_close#}6121 {#header_close#}
60886122
6089 {#header_open|@sqrt#}6123 {#header_open|@sqrt#}
6090 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>6124 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
6091 <p>6125 <p>
6092 Performs the square root of a floating point number. Uses a dedicated hardware instruction6126 Performs the square root of a floating point number. Uses a dedicated hardware instruction
6093 when available. Currently only supports f32 and f64 at runtime. f128 at runtime is TODO.6127 when available. Currently only supports f32 and f64 at runtime. f128 at runtime is TODO.
6094 </p>6128 </p>
6095 <p>6129 <p>
6096 This is a low-level intrinsic. Most code can use <code>std.math.sqrt</code> instead.6130 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
6097 </p>6131 </p>
6098 {#header_close#}6132 {#header_close#}
6099 {#header_open|@subWithOverflow#}6133 {#header_open|@subWithOverflow#}
6100 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool</code></pre>6134 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
6101 <p>6135 <p>
6102 Performs <code>result.* = a - b</code>. If overflow or underflow occurs,6136 Performs {#syntax#}result.* = a - b{#endsyntax#}. If overflow or underflow occurs,
6103 stores the overflowed bits in <code>result</code> and returns <code>true</code>.6137 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
6104 If no overflow or underflow occurs, returns <code>false</code>.6138 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
6105 </p>6139 </p>
6106 {#header_close#}6140 {#header_close#}
6107 {#header_open|@tagName#}6141 {#header_open|@tagName#}
6108 <pre><code class="zig">@tagName(value: var) []const u8</code></pre>6142 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
6109 <p>6143 <p>
6110 Converts an enum value or union value to a slice of bytes representing the name.6144 Converts an enum value or union value to a slice of bytes representing the name.
6111 </p>6145 </p>
6112 {#header_close#}6146 {#header_close#}
6113 {#header_open|@TagType#}6147 {#header_open|@TagType#}
6114 <pre><code class="zig">@TagType(T: type) type</code></pre>6148 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
6115 <p>6149 <p>
6116 For an enum, returns the integer type that is used to store the enumeration value.6150 For an enum, returns the integer type that is used to store the enumeration value.
6117 </p>6151 </p>
...@@ -6119,8 +6153,43 @@ pub const FloatMode = enum {...@@ -6119,8 +6153,43 @@ pub const FloatMode = enum {
6119 For a union, returns the enum type that is used to store the tag value.6153 For a union, returns the enum type that is used to store the tag value.
6120 </p>6154 </p>
6121 {#header_close#}6155 {#header_close#}
6156 {#header_open|@This#}
6157 <pre>{#syntax#}@This() type{#endsyntax#}</pre>
6158 <p>
6159 Returns the innermost struct or union that this function call is inside.
6160 This can be useful for an anonymous struct that needs to refer to itself:
6161 </p>
6162 {#code_begin|test#}
6163const std = @import("std");
6164const assert = std.debug.assert;
6165
6166test "@This()" {
6167 var items = []i32{ 1, 2, 3, 4 };
6168 const list = List(i32){ .items = items[0..] };
6169 assert(list.length() == 4);
6170}
6171
6172fn List(comptime T: type) type {
6173 return struct {
6174 const Self = @This();
6175
6176 items: []T,
6177
6178 fn length(self: Self) usize {
6179 return self.items.len;
6180 }
6181 };
6182}
6183 {#code_end#}
6184 <p>
6185 When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the
6186 current import. There is a proposal to remove the import type and use an empty struct
6187 type instead. See
6188 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
6189 </p>
6190 {#header_close#}
6122 {#header_open|@truncate#}6191 {#header_open|@truncate#}
6123 <pre><code class="zig">@truncate(comptime T: type, integer) T</code></pre>6192 <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
6124 <p>6193 <p>
6125 This function truncates bits from an integer type, resulting in a smaller6194 This function truncates bits from an integer type, resulting in a smaller
6126 integer type.6195 integer type.
...@@ -6129,14 +6198,14 @@ pub const FloatMode = enum {...@@ -6129,14 +6198,14 @@ pub const FloatMode = enum {
6129 The following produces a crash in debug mode and undefined behavior in6198 The following produces a crash in debug mode and undefined behavior in
6130 release mode:6199 release mode:
6131 </p>6200 </p>
6132 <pre><code class="zig">const a: u16 = 0xabcd;6201 <pre>{#syntax#}const a: u16 = 0xabcd;
6133const b: u8 = u8(a);</code></pre>6202const b: u8 = u8(a);{#endsyntax#}</pre>
6134 <p>6203 <p>
6135 However this is well defined and working code:6204 However this is well defined and working code:
6136 </p>6205 </p>
6137 <pre><code class="zig">const a: u16 = 0xabcd;6206 <pre>{#syntax#}const a: u16 = 0xabcd;
6138const b: u8 = @truncate(u8, a);6207const b: u8 = @truncate(u8, a);
6139// b is now 0xcd</code></pre>6208// b is now 0xcd{#endsyntax#}</pre>
6140 <p>6209 <p>
6141 This function always truncates the significant bits of the integer, regardless6210 This function always truncates the significant bits of the integer, regardless
6142 of endianness on the target platform.6211 of endianness on the target platform.
...@@ -6144,7 +6213,7 @@ const b: u8 = @truncate(u8, a);...@@ -6144,7 +6213,7 @@ const b: u8 = @truncate(u8, a);
61446213
6145 {#header_close#}6214 {#header_close#}
6146 {#header_open|@typeId#}6215 {#header_open|@typeId#}
6147 <pre><code class="zig">@typeId(comptime T: type) @import("builtin").TypeId</code></pre>6216 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
6148 <p>6217 <p>
6149 Returns which kind of type something is. Possible values:6218 Returns which kind of type something is. Possible values:
6150 </p>6219 </p>
...@@ -6178,7 +6247,7 @@ pub const TypeId = enum {...@@ -6178,7 +6247,7 @@ pub const TypeId = enum {
6178 {#code_end#}6247 {#code_end#}
6179 {#header_close#}6248 {#header_close#}
6180 {#header_open|@typeInfo#}6249 {#header_open|@typeInfo#}
6181 <pre><code class="zig">@typeInfo(comptime T: type) @import("builtin").TypeInfo</code></pre>6250 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
6182 <p>6251 <p>
6183 Returns information on the type. Returns a value of the following union:6252 Returns information on the type. Returns a value of the following union:
6184 </p>6253 </p>
...@@ -6361,14 +6430,14 @@ pub const TypeInfo = union(TypeId) {...@@ -6361,14 +6430,14 @@ pub const TypeInfo = union(TypeId) {
6361 {#code_end#}6430 {#code_end#}
6362 {#header_close#}6431 {#header_close#}
6363 {#header_open|@typeName#}6432 {#header_open|@typeName#}
6364 <pre><code class="zig">@typeName(T: type) []u8</code></pre>6433 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
6365 <p>6434 <p>
6366 This function returns the string representation of a type.6435 This function returns the string representation of a type.
6367 </p>6436 </p>
63686437
6369 {#header_close#}6438 {#header_close#}
6370 {#header_open|@typeOf#}6439 {#header_open|@typeOf#}
6371 <pre><code class="zig">@typeOf(expression) type</code></pre>6440 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
6372 <p>6441 <p>
6373 This function returns a compile-time constant, which is the type of the6442 This function returns a compile-time constant, which is the type of the
6374 expression passed as an argument. The expression is evaluated.6443 expression passed as an argument. The expression is evaluated.
...@@ -6545,11 +6614,11 @@ pub fn main() void {...@@ -6545,11 +6614,11 @@ pub fn main() void {
6545 {#header_open|Default Operations#}6614 {#header_open|Default Operations#}
6546 <p>The following operators can cause integer overflow:</p>6615 <p>The following operators can cause integer overflow:</p>
6547 <ul>6616 <ul>
6548 <li><code>+</code> (addition)</li>6617 <li>{#syntax#}+{#endsyntax#} (addition)</li>
6549 <li><code>-</code> (subtraction)</li>6618 <li>{#syntax#}-{#endsyntax#} (subtraction)</li>
6550 <li><code>-</code> (negation)</li>6619 <li>{#syntax#}-{#endsyntax#} (negation)</li>
6551 <li><code>*</code> (multiplication)</li>6620 <li>{#syntax#}*{#endsyntax#} (multiplication)</li>
6552 <li><code>/</code> (division)</li>6621 <li>{#syntax#}/{#endsyntax#} (division)</li>
6553 <li>{#link|@divTrunc#} (division)</li>6622 <li>{#link|@divTrunc#} (division)</li>
6554 <li>{#link|@divFloor#} (division)</li>6623 <li>{#link|@divFloor#} (division)</li>
6555 <li>{#link|@divExact#} (division)</li>6624 <li>{#link|@divExact#} (division)</li>
...@@ -6575,13 +6644,13 @@ pub fn main() void {...@@ -6575,13 +6644,13 @@ pub fn main() void {
6575 {#header_open|Standard Library Math Functions#}6644 {#header_open|Standard Library Math Functions#}
6576 <p>These functions provided by the standard library return possible errors.</p>6645 <p>These functions provided by the standard library return possible errors.</p>
6577 <ul>6646 <ul>
6578 <li><code>@import("std").math.add</code></li>6647 <li>{#syntax#}@import("std").math.add{#endsyntax#}</li>
6579 <li><code>@import("std").math.sub</code></li>6648 <li>{#syntax#}@import("std").math.sub{#endsyntax#}</li>
6580 <li><code>@import("std").math.mul</code></li>6649 <li>{#syntax#}@import("std").math.mul{#endsyntax#}</li>
6581 <li><code>@import("std").math.divTrunc</code></li>6650 <li>{#syntax#}@import("std").math.divTrunc{#endsyntax#}</li>
6582 <li><code>@import("std").math.divFloor</code></li>6651 <li>{#syntax#}@import("std").math.divFloor{#endsyntax#}</li>
6583 <li><code>@import("std").math.divExact</code></li>6652 <li>{#syntax#}@import("std").math.divExact{#endsyntax#}</li>
6584 <li><code>@import("std").math.shl</code></li>6653 <li>{#syntax#}@import("std").math.shl{#endsyntax#}</li>
6585 </ul>6654 </ul>
6586 <p>Example of catching an overflow for addition:</p>6655 <p>Example of catching an overflow for addition:</p>
6587 {#code_begin|exe_err#}6656 {#code_begin|exe_err#}
...@@ -6601,7 +6670,7 @@ pub fn main() !void {...@@ -6601,7 +6670,7 @@ pub fn main() !void {
6601 {#header_close#}6670 {#header_close#}
6602 {#header_open|Builtin Overflow Functions#}6671 {#header_open|Builtin Overflow Functions#}
6603 <p>6672 <p>
6604 These builtins return a <code>bool</code> of whether or not overflow6673 These builtins return a {#syntax#}bool{#endsyntax#} of whether or not overflow
6605 occurred, as well as returning the overflowed bits:6674 occurred, as well as returning the overflowed bits:
6606 </p>6675 </p>
6607 <ul>6676 <ul>
...@@ -6632,10 +6701,10 @@ pub fn main() void {...@@ -6632,10 +6701,10 @@ pub fn main() void {
6632 These operations have guaranteed wraparound semantics.6701 These operations have guaranteed wraparound semantics.
6633 </p>6702 </p>
6634 <ul>6703 <ul>
6635 <li><code>+%</code> (wraparound addition)</li>6704 <li>{#syntax#}+%{#endsyntax#} (wraparound addition)</li>
6636 <li><code>-%</code> (wraparound subtraction)</li>6705 <li>{#syntax#}-%{#endsyntax#} (wraparound subtraction)</li>
6637 <li><code>-%</code> (wraparound negation)</li>6706 <li>{#syntax#}-%{#endsyntax#} (wraparound negation)</li>
6638 <li><code>*%</code> (wraparound multiplication)</li>6707 <li>{#syntax#}*%{#endsyntax#} (wraparound multiplication)</li>
6639 </ul>6708 </ul>
6640 {#code_begin|test#}6709 {#code_begin|test#}
6641const assert = @import("std").debug.assert;6710const assert = @import("std").debug.assert;
...@@ -6787,7 +6856,7 @@ pub fn main() void {...@@ -6787,7 +6856,7 @@ pub fn main() void {
6787}6856}
6788 {#code_end#}6857 {#code_end#}
6789 <p>One way to avoid this crash is to test for null instead of assuming non-null, with6858 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
6790 the <code>if</code> expression:</p>6859 the {#syntax#}if{#endsyntax#} expression:</p>
6791 {#code_begin|exe|test#}6860 {#code_begin|exe|test#}
6792const warn = @import("std").debug.warn;6861const warn = @import("std").debug.warn;
6793pub fn main() void {6862pub fn main() void {
...@@ -6827,7 +6896,7 @@ fn getNumberOrFail() !i32 {...@@ -6827,7 +6896,7 @@ fn getNumberOrFail() !i32 {
6827}6896}
6828 {#code_end#}6897 {#code_end#}
6829 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with6898 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
6830 the <code>if</code> expression:</p>6899 the {#syntax#}if{#endsyntax#} expression:</p>
6831 {#code_begin|exe#}6900 {#code_begin|exe#}
6832const warn = @import("std").debug.warn;6901const warn = @import("std").debug.warn;
68336902
...@@ -6991,7 +7060,7 @@ fn bar(f: *Foo) void {...@@ -6991,7 +7060,7 @@ fn bar(f: *Foo) void {
6991}7060}
6992 {#code_end#}7061 {#code_end#}
6993 <p>7062 <p>
6994 This safety is not available for <code>extern</code> or <code>packed</code> unions.7063 This safety is not available for {#syntax#}extern{#endsyntax#} or {#syntax#}packed{#endsyntax#} unions.
6995 </p>7064 </p>
6996 <p>7065 <p>
6997 To change the active field of a union, assign the entire union, like this:7066 To change the active field of a union, assign the entire union, like this:
...@@ -7056,7 +7125,7 @@ fn bar(f: *Foo) void {...@@ -7056,7 +7125,7 @@ fn bar(f: *Foo) void {
7056 {#header_close#}7125 {#header_close#}
7057 {#header_open|Compile Variables#}7126 {#header_open|Compile Variables#}
7058 <p>7127 <p>
7059 Compile variables are accessible by importing the <code>"builtin"</code> package,7128 Compile variables are accessible by importing the {#syntax#}"builtin"{#endsyntax#} package,
7060 which the compiler makes available to every Zig source file. It contains7129 which the compiler makes available to every Zig source file. It contains
7061 compile-time constants such as the current target, endianness, and release mode.7130 compile-time constants such as the current target, endianness, and release mode.
7062 </p>7131 </p>
...@@ -7065,7 +7134,7 @@ const builtin = @import("builtin");...@@ -7065,7 +7134,7 @@ const builtin = @import("builtin");
7065const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';7134const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';
7066 {#code_end#}7135 {#code_end#}
7067 <p>7136 <p>
7068 Example of what is imported with <code>@import("builtin")</code>:7137 Example of what is imported with {#syntax#}@import("builtin"){#endsyntax#}:
7069 </p>7138 </p>
7070 {#builtin#}7139 {#builtin#}
7071 {#see_also|Build Mode#}7140 {#see_also|Build Mode#}
...@@ -7104,16 +7173,16 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';...@@ -7104,16 +7173,16 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';
7104 These have guaranteed C ABI compatibility and can be used like any other type.7173 These have guaranteed C ABI compatibility and can be used like any other type.
7105 </p>7174 </p>
7106 <ul>7175 <ul>
7107 <li><code>c_short</code></li>7176 <li>{#syntax#}c_short{#endsyntax#}</li>
7108 <li><code>c_ushort</code></li>7177 <li>{#syntax#}c_ushort{#endsyntax#}</li>
7109 <li><code>c_int</code></li>7178 <li>{#syntax#}c_int{#endsyntax#}</li>
7110 <li><code>c_uint</code></li>7179 <li>{#syntax#}c_uint{#endsyntax#}</li>
7111 <li><code>c_long</code></li>7180 <li>{#syntax#}c_long{#endsyntax#}</li>
7112 <li><code>c_ulong</code></li>7181 <li>{#syntax#}c_ulong{#endsyntax#}</li>
7113 <li><code>c_longlong</code></li>7182 <li>{#syntax#}c_longlong{#endsyntax#}</li>
7114 <li><code>c_ulonglong</code></li>7183 <li>{#syntax#}c_ulonglong{#endsyntax#}</li>
7115 <li><code>c_longdouble</code></li>7184 <li>{#syntax#}c_longdouble{#endsyntax#}</li>
7116 <li><code>c_void</code></li>7185 <li>{#syntax#}c_void{#endsyntax#}</li>
7117 </ul>7186 </ul>
7118 {#see_also|Primitive Types#}7187 {#see_also|Primitive Types#}
7119 {#header_close#}7188 {#header_close#}
...@@ -7135,7 +7204,7 @@ pub fn main() void {...@@ -7135,7 +7204,7 @@ pub fn main() void {
7135 {#header_close#}7204 {#header_close#}
7136 {#header_open|Import from C Header File#}7205 {#header_open|Import from C Header File#}
7137 <p>7206 <p>
7138 The <code>@cImport</code> builtin function can be used7207 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
7139 to directly import symbols from .h files:7208 to directly import symbols from .h files:
7140 </p>7209 </p>
7141 {#code_begin|exe#}7210 {#code_begin|exe#}
...@@ -7150,7 +7219,7 @@ pub fn main() void {...@@ -7150,7 +7219,7 @@ pub fn main() void {
7150}7219}
7151 {#code_end#}7220 {#code_end#}
7152 <p>7221 <p>
7153 The <code>@cImport</code> function takes an expression as a parameter.7222 The {#syntax#}@cImport{#endsyntax#} function takes an expression as a parameter.
7154 This expression is evaluated at compile-time and is used to control7223 This expression is evaluated at compile-time and is used to control
7155 preprocessor directives and include multiple .h files:7224 preprocessor directives and include multiple .h files:
7156 </p>7225 </p>
...@@ -7174,7 +7243,7 @@ const c = @cImport({...@@ -7174,7 +7243,7 @@ const c = @cImport({
7174 {#header_open|Exporting a C Library#}7243 {#header_open|Exporting a C Library#}
7175 <p>7244 <p>
7176 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages7245 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages
7177 to call into. The <code>export</code> keyword in front of functions, variables, and types causes them to7246 to call into. The {#syntax#}export{#endsyntax#} keyword in front of functions, variables, and types causes them to
7178 be part of the library API:7247 be part of the library API:
7179 </p>7248 </p>
7180 <p class="file">mathtest.zig</p>7249 <p class="file">mathtest.zig</p>
...@@ -7423,7 +7492,7 @@ Environments:...@@ -7423,7 +7492,7 @@ Environments:
7423 coreclr7492 coreclr
7424 opencl</code></pre>7493 opencl</code></pre>
7425 <p>7494 <p>
7426 The Zig Standard Library (<code>@import("std")</code>) has architecture, environment, and operating sytsem7495 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem
7427 abstractions, and thus takes additional work to support more platforms.7496 abstractions, and thus takes additional work to support more platforms.
7428 Not all standard library code requires operating system abstractions, however,7497 Not all standard library code requires operating system abstractions, however,
7429 so things such as generic data structures work an all above platforms.7498 so things such as generic data structures work an all above platforms.
...@@ -7460,25 +7529,25 @@ coding style....@@ -7460,25 +7529,25 @@ coding style.
7460 {#header_close#}7529 {#header_close#}
7461 {#header_open|Names#}7530 {#header_open|Names#}
7462 <p>7531 <p>
7463 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,7532 Roughly speaking: {#syntax#}camelCaseFunctionName{#endsyntax#}, {#syntax#}TitleCaseTypeName{#endsyntax#},
7464 <code>snake_case_variable_name</code>. More precisely:7533 {#syntax#}snake_case_variable_name{#endsyntax#}. More precisely:
7465 </p>7534 </p>
7466 <ul>7535 <ul>
7467 <li>7536 <li>
7468 If <code>x</code> is a <code>struct</code> (or an alias of a <code>struct</code>),7537 If {#syntax#}x{#endsyntax#} is a {#syntax#}struct{#endsyntax#} (or an alias of a {#syntax#}struct{#endsyntax#}),
7469 then <code>x</code> should be <code>TitleCase</code>.7538 then {#syntax#}x{#endsyntax#} should be {#syntax#}TitleCase{#endsyntax#}.
7470 </li>7539 </li>
7471 <li>7540 <li>
7472 If <code>x</code> otherwise identifies a type, <code>x</code> should have <code>snake_case</code>.7541 If {#syntax#}x{#endsyntax#} otherwise identifies a type, {#syntax#}x{#endsyntax#} should have {#syntax#}snake_case{#endsyntax#}.
7473 </li>7542 </li>
7474 <li>7543 <li>
7475 If <code>x</code> is callable, and <code>x</code>'s return type is <code>type</code>, then <code>x</code> should be <code>TitleCase</code>.7544 If {#syntax#}x{#endsyntax#} is callable, and {#syntax#}x{#endsyntax#}'s return type is {#syntax#}type{#endsyntax#}, then {#syntax#}x{#endsyntax#} should be {#syntax#}TitleCase{#endsyntax#}.
7476 </li>7545 </li>
7477 <li>7546 <li>
7478 If <code>x</code> is otherwise callable, then <code>x</code> should be <code>camelCase</code>.7547 If {#syntax#}x{#endsyntax#} is otherwise callable, then {#syntax#}x{#endsyntax#} should be {#syntax#}camelCase{#endsyntax#}.
7479 </li>7548 </li>
7480 <li>7549 <li>
7481 Otherwise, <code>x</code> should be <code>snake_case</code>.7550 Otherwise, {#syntax#}x{#endsyntax#} should be {#syntax#}snake_case{#endsyntax#}.
7482 </li>7551 </li>
7483 </ul>7552 </ul>
7484 <p>7553 <p>
...@@ -7490,7 +7559,7 @@ coding style....@@ -7490,7 +7559,7 @@ coding style.
7490 <p>7559 <p>
7491 These are general rules of thumb; if it makes sense to do something different,7560 These are general rules of thumb; if it makes sense to do something different,
7492 do what makes sense. For example, if there is an established convention such as7561 do what makes sense. For example, if there is an established convention such as
7493 <code>ENOENT</code>, follow the established convention.7562 {#syntax#}ENOENT{#endsyntax#}, follow the established convention.
7494 </p>7563 </p>
7495 {#header_close#}7564 {#header_close#}
7496 {#header_open|Examples#}7565 {#header_open|Examples#}
...@@ -7704,7 +7773,7 @@ ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":"...@@ -7704,7 +7773,7 @@ ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":"
77047773
7705GroupedExpression = "(" Expression ")"7774GroupedExpression = "(" Expression ")"
77067775
7707KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"7776KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend"
77087777
7709ErrorSetDecl = "error" "{" list(Symbol, ",") "}"7778ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
77107779
...@@ -7728,141 +7797,5 @@ ContainerDecl = option("extern" | "packed")...@@ -7728,141 +7797,5 @@ ContainerDecl = option("extern" | "packed")
7728 </ul>7797 </ul>
7729 {#header_close#}7798 {#header_close#}
7730 </div>7799 </div>
7731 <script>
7732/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */
7733!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value).replace('"',"&quot;")+'"'}s+="<"+t(e)+E.map.call(e.attributes,r).join("")+">"}function u(e){s+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='<span class="'+a,o=t?"":C;return i+=e+'">',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"<br>":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"</",c:n.concat([i,{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b:/</,e:/>/,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("llvm",function(e){var n="([-a-zA-Z$._][\\w\\-$.]*)";return{k:"begin end true false declare define global constant private linker_private internal available_externally linkonce linkonce_odr weak weak_odr appending dllimport dllexport common default hidden protected extern_weak external thread_local zeroinitializer undef null to tail target triple datalayout volatile nuw nsw nnan ninf nsz arcp fast exact inbounds align addrspace section alias module asm sideeffect gc dbg linker_private_weak attributes blockaddress initialexec localdynamic localexec prefix unnamed_addr ccc fastcc coldcc x86_stdcallcc x86_fastcallcc arm_apcscc arm_aapcscc arm_aapcs_vfpcc ptx_device ptx_kernel intel_ocl_bicc msp430_intrcc spir_func spir_kernel x86_64_sysvcc x86_64_win64cc x86_thiscallcc cc c signext zeroext inreg sret nounwind noreturn noalias nocapture byval nest readnone readonly inlinehint noinline alwaysinline optsize ssp sspreq noredzone noimplicitfloat naked builtin cold nobuiltin noduplicate nonlazybind optnone returns_twice sanitize_address sanitize_memory sanitize_thread sspstrong uwtable returned type opaque eq ne slt sgt sle sge ult ugt ule uge oeq one olt ogt ole oge ord uno ueq une x acq_rel acquire alignstack atomic catch cleanup filter inteldialect max min monotonic nand personality release seq_cst singlethread umax umin unordered xchg add fadd sub fsub mul fmul udiv sdiv fdiv urem srem frem shl lshr ashr and or xor icmp fcmp phi call trunc zext sext fptrunc fpext uitofp sitofp fptoui fptosi inttoptr ptrtoint bitcast addrspacecast select va_arg ret br switch invoke unwind unreachable indirectbr landingpad resume malloc alloca free load store getelementptr extractelement insertelement shufflevector getresult extractvalue insertvalue atomicrmw cmpxchg fence argmemonly double",c:[{cN:"keyword",b:"i\\d+"},e.C(";","\\n",{r:0}),e.QSM,{cN:"string",v:[{b:'"',e:'[^\\\\]"'}],r:0},{cN:"title",v:[{b:"@"+n},{b:"@\\d+"},{b:"!"+n},{b:"!\\d+"+n}]},{cN:"symbol",v:[{b:"%"+n},{b:"%\\d+"},{b:"#\\d+"}]},{cN:"number",v:[{b:"0[xX][a-fA-F0-9]+"},{b:"-?\\d+(?:[.]\\d+)?(?:[eE][-+]?\\d+(?:[.]\\d+)?)?"}],r:0}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}});
7734 </script>
7735 <script>
7736hljs.registerLanguage("zig", function(t) {
7737 var e = {
7738 cN: "keyword",
7739 b: "\\b[a-z\\d_]*_t\\b"
7740 },
7741 r = {
7742 cN: "string",
7743 v: [{
7744 b: '(u8?|U)?L?"',
7745 e: '"',
7746 i: "\\n",
7747 c: [t.BE]
7748 }, {
7749 b: '(u8?|U)?R"',
7750 e: '"',
7751 c: [t.BE]
7752 }, {
7753 b: "'\\\\?.",
7754 e: "'",
7755 i: "."
7756 }]
7757 },
7758 s = {
7759 cN: "number",
7760 v: [{
7761 b: "\\b(0b[01']+)"
7762 }, {
7763 b: "(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"
7764 }, {
7765 b: "(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"
7766 }],
7767 r: 0
7768 },
7769 i = {
7770 cN: "meta",
7771 b: /#\s*[a-z]+\b/,
7772 e: /$/,
7773 k: {
7774 "meta-keyword": "zzzzzzdisable"
7775 },
7776 c: [{
7777 b: /\\\n/,
7778 r: 0
7779 }, t.inherit(r, {
7780 cN: "meta-string"
7781 }), {
7782 cN: "meta-string",
7783 b: /<[^\n>]*>/,
7784 e: /$/,
7785 i: "\\n"
7786 }, t.CLCM, t.CBCM]
7787 },
7788 a = t.IR + "\\s*\\(",
7789 c = {
7790 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume suspend cancel await async orelse",
7791 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz popCount import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall errorToInt intToError enumToInt intToEnum handle",
7792 literal: "true false null undefined"
7793 },
7794 n = [e, t.CLCM, t.CBCM, s, r];
7795 return {
7796 aliases: ["c", "cc", "h", "c++", "h++", "hpp"],
7797 k: c,
7798 i: "</",
7799 c: n.concat([i, {
7800 b: "\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",
7801 e: ">",
7802 k: c,
7803 c: ["self", e]
7804 }, {
7805 b: t.IR + "::",
7806 k: c
7807 }, {
7808 v: [{
7809 b: /=/,
7810 e: /;/
7811 }, {
7812 b: /\(/,
7813 e: /\)/
7814 }, {
7815 bK: "new throw return else",
7816 e: /;/
7817 }],
7818 k: c,
7819 c: n.concat([{
7820 b: /\(/,
7821 e: /\)/,
7822 k: c,
7823 c: n.concat(["self"]),
7824 r: 0
7825 }]),
7826 r: 0
7827 }, {
7828 cN: "function",
7829 b: "(" + t.IR + "[\\*&\\s]+)+" + a,
7830 rB: !0,
7831 e: /[{;=]/,
7832 eE: !0,
7833 k: c,
7834 i: /[^\w\s\*&]/,
7835 c: [{
7836 b: a,
7837 rB: !0,
7838 c: [t.TM],
7839 r: 0
7840 }, {
7841 cN: "params",
7842 b: /\(/,
7843 e: /\)/,
7844 k: c,
7845 r: 0,
7846 c: [t.CLCM, t.CBCM, r, s, e]
7847 }, t.CLCM, t.CBCM, i]
7848 }, {
7849 cN: "class",
7850 bK: "class struct",
7851 e: /[{;:]/,
7852 c: [{
7853 b: /</,
7854 e: />/,
7855 c: ["self"]
7856 }, t.TM]
7857 }]),
7858 exports: {
7859 preprocessor: i,
7860 strings: r,
7861 k: c
7862 }
7863 }
7864});
7865 hljs.initHighlightingOnLoad();
7866 </script>
7867 </body>7800 </body>
7868</html>7801</html>
src-self-hosted/main.zig+1-1
...@@ -737,7 +737,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {...@@ -737,7 +737,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {
737 file_path,737 file_path,
738 max_src_size,738 max_src_size,
739 )) catch |err| switch (err) {739 )) catch |err| switch (err) {
740 error.IsDir => {740 error.IsDir, error.AccessDenied => {
741 // TODO make event based (and dir.next())741 // TODO make event based (and dir.next())
742 var dir = try std.os.Dir.open(fmt.loop.allocator, file_path);742 var dir = try std.os.Dir.open(fmt.loop.allocator, file_path);
743 defer dir.close();743 defer dir.close();
src-self-hosted/type.zig-12
...@@ -40,7 +40,6 @@ pub const Type = struct {...@@ -40,7 +40,6 @@ pub const Type = struct {
40 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),40 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
41 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),41 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
42 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),42 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
43 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
44 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),43 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
45 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
46 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
...@@ -74,7 +73,6 @@ pub const Type = struct {...@@ -74,7 +73,6 @@ pub const Type = struct {
74 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),73 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
75 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),74 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
76 Id.Namespace => unreachable,75 Id.Namespace => unreachable,
77 Id.Block => unreachable,
78 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),76 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
79 Id.ArgTuple => unreachable,77 Id.ArgTuple => unreachable,
80 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),78 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
...@@ -90,7 +88,6 @@ pub const Type = struct {...@@ -90,7 +88,6 @@ pub const Type = struct {
90 Id.Undefined,88 Id.Undefined,
91 Id.Null,89 Id.Null,
92 Id.Namespace,90 Id.Namespace,
93 Id.Block,
94 Id.BoundFn,91 Id.BoundFn,
95 Id.ArgTuple,92 Id.ArgTuple,
96 Id.Opaque,93 Id.Opaque,
...@@ -124,7 +121,6 @@ pub const Type = struct {...@@ -124,7 +121,6 @@ pub const Type = struct {
124 Id.Undefined,121 Id.Undefined,
125 Id.Null,122 Id.Null,
126 Id.Namespace,123 Id.Namespace,
127 Id.Block,
128 Id.BoundFn,124 Id.BoundFn,
129 Id.ArgTuple,125 Id.ArgTuple,
130 Id.Opaque,126 Id.Opaque,
...@@ -1012,14 +1008,6 @@ pub const Type = struct {...@@ -1012,14 +1008,6 @@ pub const Type = struct {
1012 }1008 }
1013 };1009 };
10141010
1015 pub const Block = struct {
1016 base: Type,
1017
1018 pub fn destroy(self: *Block, comp: *Compilation) void {
1019 comp.gpa().destroy(self);
1020 }
1021 };
1022
1023 pub const BoundFn = struct {1011 pub const BoundFn = struct {
1024 base: Type,1012 base: Type,
10251013
src/all_types.hpp+164-161
...@@ -10,6 +10,7 @@...@@ -10,6 +10,7 @@
1010
11#include "list.hpp"11#include "list.hpp"
12#include "buffer.hpp"12#include "buffer.hpp"
13#include "cache_hash.hpp"
13#include "zig_llvm.h"14#include "zig_llvm.h"
14#include "hash_map.hpp"15#include "hash_map.hpp"
15#include "errmsg.hpp"16#include "errmsg.hpp"
...@@ -282,7 +283,6 @@ struct ConstExprValue {...@@ -282,7 +283,6 @@ struct ConstExprValue {
282 ConstArrayValue x_array;283 ConstArrayValue x_array;
283 ConstPtrValue x_ptr;284 ConstPtrValue x_ptr;
284 ImportTableEntry *x_import;285 ImportTableEntry *x_import;
285 Scope *x_block;
286 ConstArgTuple x_arg_tuple;286 ConstArgTuple x_arg_tuple;
287287
288 // populated if special == ConstValSpecialRuntime288 // populated if special == ConstValSpecialRuntime
...@@ -412,7 +412,6 @@ enum NodeType {...@@ -412,7 +412,6 @@ enum NodeType {
412 NodeTypeBoolLiteral,412 NodeTypeBoolLiteral,
413 NodeTypeNullLiteral,413 NodeTypeNullLiteral,
414 NodeTypeUndefinedLiteral,414 NodeTypeUndefinedLiteral,
415 NodeTypeThisLiteral,
416 NodeTypeUnreachable,415 NodeTypeUnreachable,
417 NodeTypeIfBoolExpr,416 NodeTypeIfBoolExpr,
418 NodeTypeWhileExpr,417 NodeTypeWhileExpr,
...@@ -1013,13 +1012,13 @@ enum PtrLen {...@@ -1013,13 +1012,13 @@ enum PtrLen {
10131012
1014struct ZigTypePointer {1013struct ZigTypePointer {
1015 ZigType *child_type;1014 ZigType *child_type;
1015 ZigType *slice_parent;
1016 PtrLen ptr_len;1016 PtrLen ptr_len;
1017 bool is_const;1017 uint32_t explicit_alignment; // 0 means use ABI alignment
1018 bool is_volatile;
1019 uint32_t alignment;
1020 uint32_t bit_offset;1018 uint32_t bit_offset;
1021 uint32_t unaligned_bit_count;1019 uint32_t unaligned_bit_count;
1022 ZigType *slice_parent;1020 bool is_const;
1021 bool is_volatile;
1023};1022};
10241023
1025struct ZigTypeInt {1024struct ZigTypeInt {
...@@ -1047,32 +1046,35 @@ struct TypeStructField {...@@ -1047,32 +1046,35 @@ struct TypeStructField {
1047 size_t unaligned_bit_count;1046 size_t unaligned_bit_count;
1048 AstNode *decl_node;1047 AstNode *decl_node;
1049};1048};
1049
1050enum ResolveStatus {
1051 ResolveStatusUnstarted,
1052 ResolveStatusInvalid,
1053 ResolveStatusZeroBitsKnown,
1054 ResolveStatusAlignmentKnown,
1055 ResolveStatusSizeKnown,
1056};
1057
1050struct ZigTypeStruct {1058struct ZigTypeStruct {
1051 AstNode *decl_node;1059 AstNode *decl_node;
1052 ContainerLayout layout;
1053 uint32_t src_field_count;
1054 uint32_t gen_field_count;
1055 TypeStructField *fields;1060 TypeStructField *fields;
1056 uint64_t size_bytes;
1057 bool is_invalid; // true if any fields are invalid
1058 bool is_slice;
1059 ScopeDecls *decls_scope;1061 ScopeDecls *decls_scope;
1062 uint64_t size_bytes;
1063 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
10601064
1061 // set this flag temporarily to detect infinite loops1065 uint32_t src_field_count;
1062 bool embedded_in_current;1066 uint32_t gen_field_count;
1063 bool reported_infinite_err;1067
1064 // whether we've finished resolving it1068 uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown
1065 bool complete;1069 ContainerLayout layout;
1070 ResolveStatus resolve_status;
10661071
1072 bool is_slice;
1073 bool resolve_loop_flag; // set this flag temporarily to detect infinite loops
1074 bool reported_infinite_err;
1067 // whether any of the fields require comptime1075 // whether any of the fields require comptime
1068 // the value is not valid until zero_bits_known == true1076 // known after ResolveStatusZeroBitsKnown
1069 bool requires_comptime;1077 bool requires_comptime;
1070
1071 bool zero_bits_loop_flag;
1072 bool zero_bits_known;
1073 uint32_t abi_alignment; // also figured out with zero_bits pass
1074
1075 HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
1076};1078};
10771079
1078struct ZigTypeOptional {1080struct ZigTypeOptional {
...@@ -1204,7 +1206,6 @@ enum ZigTypeId {...@@ -1204,7 +1206,6 @@ enum ZigTypeId {
1204 ZigTypeIdUnion,1206 ZigTypeIdUnion,
1205 ZigTypeIdFn,1207 ZigTypeIdFn,
1206 ZigTypeIdNamespace,1208 ZigTypeIdNamespace,
1207 ZigTypeIdBlock,
1208 ZigTypeIdBoundFn,1209 ZigTypeIdBoundFn,
1209 ZigTypeIdArgTuple,1210 ZigTypeIdArgTuple,
1210 ZigTypeIdOpaque,1211 ZigTypeIdOpaque,
...@@ -1412,6 +1413,7 @@ enum BuiltinFnId {...@@ -1412,6 +1413,7 @@ enum BuiltinFnId {
1412 BuiltinFnIdSetEvalBranchQuota,1413 BuiltinFnIdSetEvalBranchQuota,
1413 BuiltinFnIdAlignCast,1414 BuiltinFnIdAlignCast,
1414 BuiltinFnIdOpaqueType,1415 BuiltinFnIdOpaqueType,
1416 BuiltinFnIdThis,
1415 BuiltinFnIdSetAlignStack,1417 BuiltinFnIdSetAlignStack,
1416 BuiltinFnIdArgType,1418 BuiltinFnIdArgType,
1417 BuiltinFnIdExport,1419 BuiltinFnIdExport,
...@@ -1550,22 +1552,50 @@ struct LinkLib {...@@ -1550,22 +1552,50 @@ struct LinkLib {
1550 bool provided_explicitly;1552 bool provided_explicitly;
1551};1553};
15521554
1555// When adding fields, check if they should be added to the hash computation in build_with_cache
1553struct CodeGen {1556struct CodeGen {
1557 //////////////////////////// Runtime State
1554 LLVMModuleRef module;1558 LLVMModuleRef module;
1555 ZigList<ErrorMsg*> errors;1559 ZigList<ErrorMsg*> errors;
1556 LLVMBuilderRef builder;1560 LLVMBuilderRef builder;
1557 ZigLLVMDIBuilder *dbuilder;1561 ZigLLVMDIBuilder *dbuilder;
1558 ZigLLVMDICompileUnit *compile_unit;1562 ZigLLVMDICompileUnit *compile_unit;
1559 ZigLLVMDIFile *compile_unit_file;1563 ZigLLVMDIFile *compile_unit_file;
1560
1561 ZigList<LinkLib *> link_libs_list;
1562 LinkLib *libc_link_lib;1564 LinkLib *libc_link_lib;
15631565 LLVMTargetDataRef target_data_ref;
1564 // add -framework [name] args to linker1566 LLVMTargetMachineRef target_machine;
1565 ZigList<Buf *> darwin_frameworks;1567 ZigLLVMDIFile *dummy_di_file;
1566 // add -rpath [name] args to linker1568 LLVMValueRef cur_ret_ptr;
1567 ZigList<Buf *> rpath_list;1569 LLVMValueRef cur_fn_val;
15681570 LLVMValueRef cur_err_ret_trace_val_arg;
1571 LLVMValueRef cur_err_ret_trace_val_stack;
1572 LLVMValueRef memcpy_fn_val;
1573 LLVMValueRef memset_fn_val;
1574 LLVMValueRef trap_fn_val;
1575 LLVMValueRef return_address_fn_val;
1576 LLVMValueRef frame_address_fn_val;
1577 LLVMValueRef coro_destroy_fn_val;
1578 LLVMValueRef coro_id_fn_val;
1579 LLVMValueRef coro_alloc_fn_val;
1580 LLVMValueRef coro_size_fn_val;
1581 LLVMValueRef coro_begin_fn_val;
1582 LLVMValueRef coro_suspend_fn_val;
1583 LLVMValueRef coro_end_fn_val;
1584 LLVMValueRef coro_free_fn_val;
1585 LLVMValueRef coro_resume_fn_val;
1586 LLVMValueRef coro_save_fn_val;
1587 LLVMValueRef coro_promise_fn_val;
1588 LLVMValueRef coro_alloc_helper_fn_val;
1589 LLVMValueRef coro_frame_fn_val;
1590 LLVMValueRef merge_err_ret_traces_fn_val;
1591 LLVMValueRef add_error_return_trace_addr_fn_val;
1592 LLVMValueRef stacksave_fn_val;
1593 LLVMValueRef stackrestore_fn_val;
1594 LLVMValueRef write_register_fn_val;
1595 LLVMValueRef sp_md_node;
1596 LLVMValueRef err_name_table;
1597 LLVMValueRef safety_crash_err_fn;
1598 LLVMValueRef return_err_fn;
15691599
1570 // reminder: hash tables must be initialized before use1600 // reminder: hash tables must be initialized before use
1571 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;1601 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
...@@ -1582,15 +1612,29 @@ struct CodeGen {...@@ -1582,15 +1612,29 @@ struct CodeGen {
1582 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;1612 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
1583 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;1613 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
15841614
1585
1586 ZigList<ImportTableEntry *> import_queue;1615 ZigList<ImportTableEntry *> import_queue;
1587 size_t import_queue_index;1616 size_t import_queue_index;
1588 ZigList<Tld *> resolve_queue;1617 ZigList<Tld *> resolve_queue;
1589 size_t resolve_queue_index;1618 size_t resolve_queue_index;
1590 ZigList<AstNode *> use_queue;1619 ZigList<AstNode *> use_queue;
1591 size_t use_queue_index;1620 size_t use_queue_index;
1621 ZigList<TimeEvent> timing_events;
1622 ZigList<ZigLLVMDIType **> error_di_types;
1623 ZigList<AstNode *> tld_ref_source_node_stack;
1624 ZigList<ZigFn *> inline_fns;
1625 ZigList<ZigFn *> test_fns;
1626 ZigList<ZigLLVMDIEnumerator *> err_enumerators;
1627 ZigList<ErrorTableEntry *> errors_by_index;
1628 size_t largest_err_name_len;
15921629
1593 uint32_t next_unresolved_index;1630 PackageTableEntry *std_package;
1631 PackageTableEntry *panic_package;
1632 PackageTableEntry *test_runner_package;
1633 PackageTableEntry *compile_var_package;
1634 ImportTableEntry *compile_var_import;
1635 ImportTableEntry *root_import;
1636 ImportTableEntry *bootstrap_import;
1637 ImportTableEntry *test_runner_import;
15941638
1595 struct {1639 struct {
1596 ZigType *entry_bool;1640 ZigType *entry_bool;
...@@ -1626,163 +1670,122 @@ struct CodeGen {...@@ -1626,163 +1670,122 @@ struct CodeGen {
1626 ZigType *entry_arg_tuple;1670 ZigType *entry_arg_tuple;
1627 ZigType *entry_promise;1671 ZigType *entry_promise;
1628 } builtin_types;1672 } builtin_types;
1673 ZigType *align_amt_type;
1674 ZigType *stack_trace_type;
1675 ZigType *ptr_to_stack_trace_type;
1676 ZigType *err_tag_type;
1677 ZigType *test_fn_type;
16291678
1630 EmitFileType emit_file_type;
1631 ZigTarget zig_target;
1632 LLVMTargetDataRef target_data_ref;
1633 unsigned pointer_size_bytes;
1634 bool is_big_endian;
1635 bool is_static;
1636 bool strip_debug_symbols;
1637 bool want_h_file;
1638 bool have_pub_main;
1639 bool have_c_main;
1640 bool have_winmain;
1641 bool have_winmain_crt_startup;
1642 bool have_dllmain_crt_startup;
1643 bool have_pub_panic;
1644 Buf *libc_lib_dir;
1645 Buf *libc_static_lib_dir;
1646 Buf *libc_include_dir;
1647 Buf *msvc_lib_dir;
1648 Buf *kernel32_lib_dir;
1649 Buf *zig_lib_dir;
1650 Buf *zig_std_dir;
1651 Buf *zig_c_headers_dir;
1652 Buf *zig_std_special_dir;
1653 Buf *dynamic_linker;
1654 Buf *ar_path;
1655 ZigWindowsSDK *win_sdk;
1656 Buf triple_str;1679 Buf triple_str;
1657 BuildMode build_mode;1680 Buf global_asm;
1658 bool is_test_build;1681 Buf *out_h_path;
1659 bool have_err_ret_tracing;1682 Buf artifact_dir;
1660 uint32_t target_os_index;1683 Buf output_file_path;
1661 uint32_t target_arch_index;1684 Buf o_file_output_path;
1662 uint32_t target_environ_index;1685 Buf *wanted_output_file_path;
1663 uint32_t target_oformat_index;1686 Buf cache_dir;
1664 LLVMTargetMachineRef target_machine;1687
1665 ZigLLVMDIFile *dummy_di_file;1688 IrInstruction *invalid_instruction;
1666 bool is_native_target;1689
1667 PackageTableEntry *root_package;1690 ConstExprValue const_void_val;
1668 PackageTableEntry *std_package;1691 ConstExprValue panic_msg_vals[PanicMsgIdCount];
1669 PackageTableEntry *panic_package;
1670 PackageTableEntry *test_runner_package;
1671 PackageTableEntry *compile_var_package;
1672 ImportTableEntry *compile_var_import;
1673 Buf *root_out_name;
1674 bool windows_subsystem_windows;
1675 bool windows_subsystem_console;
1676 Buf *mmacosx_version_min;
1677 Buf *mios_version_min;
1678 bool linker_rdynamic;
1679 const char *linker_script;
16801692
1681 // The function definitions this module includes.1693 // The function definitions this module includes.
1682 ZigList<ZigFn *> fn_defs;1694 ZigList<ZigFn *> fn_defs;
1683 size_t fn_defs_index;1695 size_t fn_defs_index;
1684 ZigList<TldVar *> global_vars;1696 ZigList<TldVar *> global_vars;
16851697
1686 OutType out_type;
1687 ZigFn *cur_fn;1698 ZigFn *cur_fn;
1688 ZigFn *main_fn;1699 ZigFn *main_fn;
1689 ZigFn *panic_fn;1700 ZigFn *panic_fn;
1690 LLVMValueRef cur_ret_ptr;1701 AstNode *root_export_decl;
1691 LLVMValueRef cur_fn_val;1702
1692 LLVMValueRef cur_err_ret_trace_val_arg;1703 CacheHash cache_hash;
1693 LLVMValueRef cur_err_ret_trace_val_stack;1704 ErrColor err_color;
1705 uint32_t next_unresolved_index;
1706 unsigned pointer_size_bytes;
1707 uint32_t target_os_index;
1708 uint32_t target_arch_index;
1709 uint32_t target_environ_index;
1710 uint32_t target_oformat_index;
1711 bool is_big_endian;
1712 bool want_h_file;
1713 bool have_pub_main;
1714 bool have_c_main;
1715 bool have_winmain;
1716 bool have_winmain_crt_startup;
1717 bool have_dllmain_crt_startup;
1718 bool have_pub_panic;
1719 bool have_err_ret_tracing;
1694 bool c_want_stdint;1720 bool c_want_stdint;
1695 bool c_want_stdbool;1721 bool c_want_stdbool;
1696 AstNode *root_export_decl;
1697 size_t version_major;
1698 size_t version_minor;
1699 size_t version_patch;
1700 bool verbose_tokenize;1722 bool verbose_tokenize;
1701 bool verbose_ast;1723 bool verbose_ast;
1702 bool verbose_link;1724 bool verbose_link;
1703 bool verbose_ir;1725 bool verbose_ir;
1704 bool verbose_llvm_ir;1726 bool verbose_llvm_ir;
1705 bool verbose_cimport;1727 bool verbose_cimport;
1706 ErrColor err_color;
1707 ImportTableEntry *root_import;
1708 ImportTableEntry *bootstrap_import;
1709 ImportTableEntry *test_runner_import;
1710 LLVMValueRef trap_fn_val;
1711 LLVMValueRef return_address_fn_val;
1712 LLVMValueRef frame_address_fn_val;
1713 LLVMValueRef coro_destroy_fn_val;
1714 LLVMValueRef coro_id_fn_val;
1715 LLVMValueRef coro_alloc_fn_val;
1716 LLVMValueRef coro_size_fn_val;
1717 LLVMValueRef coro_begin_fn_val;
1718 LLVMValueRef coro_suspend_fn_val;
1719 LLVMValueRef coro_end_fn_val;
1720 LLVMValueRef coro_free_fn_val;
1721 LLVMValueRef coro_resume_fn_val;
1722 LLVMValueRef coro_save_fn_val;
1723 LLVMValueRef coro_promise_fn_val;
1724 LLVMValueRef coro_alloc_helper_fn_val;
1725 LLVMValueRef coro_frame_fn_val;
1726 LLVMValueRef merge_err_ret_traces_fn_val;
1727 LLVMValueRef add_error_return_trace_addr_fn_val;
1728 LLVMValueRef stacksave_fn_val;
1729 LLVMValueRef stackrestore_fn_val;
1730 LLVMValueRef write_register_fn_val;
1731 bool error_during_imports;1728 bool error_during_imports;
1729 bool generate_error_name_table;
1730 bool enable_cache;
1731 bool enable_time_report;
17321732
1733 LLVMValueRef sp_md_node;1733 //////////////////////////// Participates in Input Parameter Cache Hash
17341734 ZigList<LinkLib *> link_libs_list;
1735 const char **clang_argv;1735 // add -framework [name] args to linker
1736 size_t clang_argv_len;1736 ZigList<Buf *> darwin_frameworks;
1737 // add -rpath [name] args to linker
1738 ZigList<Buf *> rpath_list;
1739 ZigList<Buf *> forbidden_libs;
1740 ZigList<Buf *> link_objects;
1741 ZigList<Buf *> assembly_files;
1737 ZigList<const char *> lib_dirs;1742 ZigList<const char *> lib_dirs;
17381743
1739 const char **llvm_argv;1744 size_t version_major;
1740 size_t llvm_argv_len;1745 size_t version_minor;
17411746 size_t version_patch;
1742 ZigList<ZigFn *> test_fns;1747 const char *linker_script;
1743 ZigType *test_fn_type;
17441748
1749 EmitFileType emit_file_type;
1750 BuildMode build_mode;
1751 OutType out_type;
1752 ZigTarget zig_target;
1753 bool is_static;
1754 bool strip_debug_symbols;
1755 bool is_test_build;
1756 bool is_native_target;
1757 bool windows_subsystem_windows;
1758 bool windows_subsystem_console;
1759 bool linker_rdynamic;
1760 bool no_rosegment_workaround;
1745 bool each_lib_rpath;1761 bool each_lib_rpath;
17461762
1747 ZigType *err_tag_type;1763 Buf *mmacosx_version_min;
1748 ZigList<ZigLLVMDIEnumerator *> err_enumerators;1764 Buf *mios_version_min;
1749 ZigList<ErrorTableEntry *> errors_by_index;1765 Buf *root_out_name;
1750 bool generate_error_name_table;
1751 LLVMValueRef err_name_table;
1752 size_t largest_err_name_len;
1753 LLVMValueRef safety_crash_err_fn;
1754
1755 LLVMValueRef return_err_fn;
1756
1757 IrInstruction *invalid_instruction;
1758 ConstExprValue const_void_val;
1759
1760 ConstExprValue panic_msg_vals[PanicMsgIdCount];
1761
1762 Buf global_asm;
1763 ZigList<Buf *> link_objects;
1764 ZigList<Buf *> assembly_files;
1765
1766 Buf *test_filter;1766 Buf *test_filter;
1767 Buf *test_name_prefix;1767 Buf *test_name_prefix;
1768 PackageTableEntry *root_package;
17681769
1769 ZigList<TimeEvent> timing_events;1770 const char **llvm_argv;
17701771 size_t llvm_argv_len;
1771 Buf cache_dir;
1772 Buf *out_h_path;
1773
1774 ZigList<ZigFn *> inline_fns;
1775 ZigList<AstNode *> tld_ref_source_node_stack;
1776
1777 ZigType *align_amt_type;
1778 ZigType *stack_trace_type;
1779 ZigType *ptr_to_stack_trace_type;
17801772
1781 ZigList<ZigLLVMDIType **> error_di_types;1773 const char **clang_argv;
1774 size_t clang_argv_len;
17821775
1783 ZigList<Buf *> forbidden_libs;1776 //////////////////////////// Unsorted
17841777
1785 bool no_rosegment_workaround;1778 Buf *libc_lib_dir;
1779 Buf *libc_static_lib_dir;
1780 Buf *libc_include_dir;
1781 Buf *msvc_lib_dir;
1782 Buf *kernel32_lib_dir;
1783 Buf *zig_lib_dir;
1784 Buf *zig_std_dir;
1785 Buf *zig_c_headers_dir;
1786 Buf *zig_std_special_dir;
1787 Buf *dynamic_linker;
1788 ZigWindowsSDK *win_sdk;
1786};1789};
17871790
1788enum VarLinkage {1791enum VarLinkage {
...@@ -3285,8 +3288,8 @@ static const size_t stack_trace_ptr_count = 30;...@@ -3285,8 +3288,8 @@ static const size_t stack_trace_ptr_count = 30;
32853288
32863289
3287enum FloatMode {3290enum FloatMode {
3288 FloatModeOptimized,
3289 FloatModeStrict,3291 FloatModeStrict,
3292 FloatModeOptimized,
3290};3293};
32913294
3292enum FnWalkId {3295enum FnWalkId {
src/analyze.cpp+265-243
...@@ -23,6 +23,7 @@ static Error resolve_enum_type(CodeGen *g, ZigType *enum_type);...@@ -23,6 +23,7 @@ static Error resolve_enum_type(CodeGen *g, ZigType *enum_type);
23static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);23static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);
2424
25static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);25static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type);
26static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type);
26static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type);27static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type);
27static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);28static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
28static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);29static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
...@@ -246,7 +247,6 @@ AstNode *type_decl_node(ZigType *type_entry) {...@@ -246,7 +247,6 @@ AstNode *type_decl_node(ZigType *type_entry) {
246 case ZigTypeIdErrorSet:247 case ZigTypeIdErrorSet:
247 case ZigTypeIdFn:248 case ZigTypeIdFn:
248 case ZigTypeIdNamespace:249 case ZigTypeIdNamespace:
249 case ZigTypeIdBlock:
250 case ZigTypeIdBoundFn:250 case ZigTypeIdBoundFn:
251 case ZigTypeIdArgTuple:251 case ZigTypeIdArgTuple:
252 case ZigTypeIdPromise:252 case ZigTypeIdPromise:
...@@ -255,18 +255,42 @@ AstNode *type_decl_node(ZigType *type_entry) {...@@ -255,18 +255,42 @@ AstNode *type_decl_node(ZigType *type_entry) {
255 zig_unreachable();255 zig_unreachable();
256}256}
257257
258bool type_is_complete(ZigType *type_entry) {258bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
259 switch (type_entry->id) {259 switch (type_entry->id) {
260 case ZigTypeIdInvalid:260 case ZigTypeIdInvalid:
261 zig_unreachable();261 zig_unreachable();
262 case ZigTypeIdStruct:262 case ZigTypeIdStruct:
263 return type_entry->data.structure.complete;263 return type_entry->data.structure.resolve_status >= status;
264 case ZigTypeIdEnum:264 case ZigTypeIdEnum:
265 return type_entry->data.enumeration.complete;265 switch (status) {
266 case ResolveStatusUnstarted:
267 return true;
268 case ResolveStatusInvalid:
269 zig_unreachable();
270 case ResolveStatusZeroBitsKnown:
271 return type_entry->data.enumeration.zero_bits_known;
272 case ResolveStatusAlignmentKnown:
273 return type_entry->data.enumeration.zero_bits_known;
274 case ResolveStatusSizeKnown:
275 return type_entry->data.enumeration.complete;
276 }
277 zig_unreachable();
266 case ZigTypeIdUnion:278 case ZigTypeIdUnion:
267 return type_entry->data.unionation.complete;279 switch (status) {
280 case ResolveStatusUnstarted:
281 return true;
282 case ResolveStatusInvalid:
283 zig_unreachable();
284 case ResolveStatusZeroBitsKnown:
285 return type_entry->data.unionation.zero_bits_known;
286 case ResolveStatusAlignmentKnown:
287 return type_entry->data.unionation.zero_bits_known;
288 case ResolveStatusSizeKnown:
289 return type_entry->data.unionation.complete;
290 }
291 zig_unreachable();
268 case ZigTypeIdOpaque:292 case ZigTypeIdOpaque:
269 return false;293 return status < ResolveStatusSizeKnown;
270 case ZigTypeIdMetaType:294 case ZigTypeIdMetaType:
271 case ZigTypeIdVoid:295 case ZigTypeIdVoid:
272 case ZigTypeIdBool:296 case ZigTypeIdBool:
...@@ -284,7 +308,6 @@ bool type_is_complete(ZigType *type_entry) {...@@ -284,7 +308,6 @@ bool type_is_complete(ZigType *type_entry) {
284 case ZigTypeIdErrorSet:308 case ZigTypeIdErrorSet:
285 case ZigTypeIdFn:309 case ZigTypeIdFn:
286 case ZigTypeIdNamespace:310 case ZigTypeIdNamespace:
287 case ZigTypeIdBlock:
288 case ZigTypeIdBoundFn:311 case ZigTypeIdBoundFn:
289 case ZigTypeIdArgTuple:312 case ZigTypeIdArgTuple:
290 case ZigTypeIdPromise:313 case ZigTypeIdPromise:
...@@ -293,44 +316,10 @@ bool type_is_complete(ZigType *type_entry) {...@@ -293,44 +316,10 @@ bool type_is_complete(ZigType *type_entry) {
293 zig_unreachable();316 zig_unreachable();
294}317}
295318
296bool type_has_zero_bits_known(ZigType *type_entry) {319bool type_is_complete(ZigType *type_entry) {
297 switch (type_entry->id) {320 return type_is_resolved(type_entry, ResolveStatusSizeKnown);
298 case ZigTypeIdInvalid:
299 zig_unreachable();
300 case ZigTypeIdStruct:
301 return type_entry->data.structure.zero_bits_known;
302 case ZigTypeIdEnum:
303 return type_entry->data.enumeration.zero_bits_known;
304 case ZigTypeIdUnion:
305 return type_entry->data.unionation.zero_bits_known;
306 case ZigTypeIdMetaType:
307 case ZigTypeIdVoid:
308 case ZigTypeIdBool:
309 case ZigTypeIdUnreachable:
310 case ZigTypeIdInt:
311 case ZigTypeIdFloat:
312 case ZigTypeIdPointer:
313 case ZigTypeIdArray:
314 case ZigTypeIdComptimeFloat:
315 case ZigTypeIdComptimeInt:
316 case ZigTypeIdUndefined:
317 case ZigTypeIdNull:
318 case ZigTypeIdOptional:
319 case ZigTypeIdErrorUnion:
320 case ZigTypeIdErrorSet:
321 case ZigTypeIdFn:
322 case ZigTypeIdNamespace:
323 case ZigTypeIdBlock:
324 case ZigTypeIdBoundFn:
325 case ZigTypeIdArgTuple:
326 case ZigTypeIdOpaque:
327 case ZigTypeIdPromise:
328 return true;
329 }
330 zig_unreachable();
331}321}
332322
333
334uint64_t type_size(CodeGen *g, ZigType *type_entry) {323uint64_t type_size(CodeGen *g, ZigType *type_entry) {
335 assert(type_is_complete(type_entry));324 assert(type_is_complete(type_entry));
336325
...@@ -379,7 +368,7 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {...@@ -379,7 +368,7 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
379368
380Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {369Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {
381 Error err;370 Error err;
382 if ((err = type_ensure_zero_bits_known(g, type_entry)))371 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
383 return err;372 return err;
384373
385 if (!type_has_bits(type_entry))374 if (!type_has_bits(type_entry))
...@@ -434,10 +423,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -434,10 +423,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
434 assert(!type_is_invalid(child_type));423 assert(!type_is_invalid(child_type));
435 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);424 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
436425
426 if (byte_alignment != 0) {
427 uint32_t abi_alignment = get_abi_alignment(g, child_type);
428 if (byte_alignment == abi_alignment)
429 byte_alignment = 0;
430 }
431
437 TypeId type_id = {};432 TypeId type_id = {};
438 ZigType **parent_pointer = nullptr;433 ZigType **parent_pointer = nullptr;
439 uint32_t abi_alignment = get_abi_alignment(g, child_type);434 if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
440 if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment || ptr_len != PtrLenSingle) {
441 type_id.id = ZigTypeIdPointer;435 type_id.id = ZigTypeIdPointer;
442 type_id.data.pointer.child_type = child_type;436 type_id.data.pointer.child_type = child_type;
443 type_id.data.pointer.is_const = is_const;437 type_id.data.pointer.is_const = is_const;
...@@ -454,12 +448,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -454,12 +448,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
454 assert(bit_offset == 0);448 assert(bit_offset == 0);
455 parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];449 parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
456 if (*parent_pointer) {450 if (*parent_pointer) {
457 assert((*parent_pointer)->data.pointer.alignment == byte_alignment);451 assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
458 return *parent_pointer;452 return *parent_pointer;
459 }453 }
460 }454 }
461455
462 assertNoError(type_ensure_zero_bits_known(g, child_type));456 assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
463457
464 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);458 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
465 entry->is_copyable = true;459 entry->is_copyable = true;
...@@ -468,11 +462,14 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -468,11 +462,14 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
468 const char *const_str = is_const ? "const " : "";462 const char *const_str = is_const ? "const " : "";
469 const char *volatile_str = is_volatile ? "volatile " : "";463 const char *volatile_str = is_volatile ? "volatile " : "";
470 buf_resize(&entry->name, 0);464 buf_resize(&entry->name, 0);
471 if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) {465 if (unaligned_bit_count == 0 && byte_alignment == 0) {
472 buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));466 buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
473 } else if (unaligned_bit_count == 0) {467 } else if (unaligned_bit_count == 0) {
474 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,468 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
475 const_str, volatile_str, buf_ptr(&child_type->name));469 const_str, volatile_str, buf_ptr(&child_type->name));
470 } else if (byte_alignment == 0) {
471 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
472 bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
476 } else {473 } else {
477 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,474 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
478 bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));475 bit_offset, bit_offset + unaligned_bit_count, const_str, volatile_str, buf_ptr(&child_type->name));
...@@ -483,8 +480,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -483,8 +480,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
483 entry->zero_bits = !type_has_bits(child_type);480 entry->zero_bits = !type_has_bits(child_type);
484481
485 if (!entry->zero_bits) {482 if (!entry->zero_bits) {
486 assert(byte_alignment > 0);483 if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 ||
487 if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment ||
488 ptr_len != PtrLenSingle)484 ptr_len != PtrLenSingle)
489 {485 {
490 ZigType *peer_type = get_pointer_to_type(g, child_type, false);486 ZigType *peer_type = get_pointer_to_type(g, child_type, false);
...@@ -508,7 +504,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -508,7 +504,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
508 entry->data.pointer.child_type = child_type;504 entry->data.pointer.child_type = child_type;
509 entry->data.pointer.is_const = is_const;505 entry->data.pointer.is_const = is_const;
510 entry->data.pointer.is_volatile = is_volatile;506 entry->data.pointer.is_volatile = is_volatile;
511 entry->data.pointer.alignment = byte_alignment;507 entry->data.pointer.explicit_alignment = byte_alignment;
512 entry->data.pointer.bit_offset = bit_offset;508 entry->data.pointer.bit_offset = bit_offset;
513 entry->data.pointer.unaligned_bit_count = unaligned_bit_count;509 entry->data.pointer.unaligned_bit_count = unaligned_bit_count;
514510
...@@ -521,8 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -521,8 +517,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
521}517}
522518
523ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {519ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
524 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle,520 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0);
525 get_abi_alignment(g, child_type), 0, 0);
526}521}
527522
528ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) {523ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) {
...@@ -803,8 +798,7 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e...@@ -803,8 +798,7 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e
803 entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);798 entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);
804 entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);799 entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);
805800
806 assert(type_has_zero_bits_known(pointer_type->data.pointer.child_type));801 if (!type_has_bits(pointer_type->data.pointer.child_type)) {
807 if (pointer_type->data.pointer.child_type->zero_bits) {
808 entry->data.structure.gen_field_count = 1;802 entry->data.structure.gen_field_count = 1;
809 entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;803 entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;
810 entry->data.structure.fields[slice_len_index].gen_index = 0;804 entry->data.structure.fields[slice_len_index].gen_index = 0;
...@@ -829,20 +823,18 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -829,20 +823,18 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
829 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);823 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
830824
831 ZigType *child_type = ptr_type->data.pointer.child_type;825 ZigType *child_type = ptr_type->data.pointer.child_type;
832 uint32_t abi_alignment = get_abi_alignment(g, child_type);
833 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||826 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
834 ptr_type->data.pointer.alignment != abi_alignment)827 ptr_type->data.pointer.explicit_alignment != 0)
835 {828 {
836 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,829 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
837 PtrLenUnknown, abi_alignment, 0, 0);830 PtrLenUnknown, 0, 0, 0);
838 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);831 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
839832
840 slice_type_common_init(g, ptr_type, entry);833 slice_type_common_init(g, ptr_type, entry);
841834
842 entry->type_ref = peer_slice_type->type_ref;835 entry->type_ref = peer_slice_type->type_ref;
843 entry->di_type = peer_slice_type->di_type;836 entry->di_type = peer_slice_type->di_type;
844 entry->data.structure.complete = true;837 entry->data.structure.resolve_status = ResolveStatusSizeKnown;
845 entry->data.structure.zero_bits_known = true;
846 entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment;838 entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment;
847839
848 *parent_pointer = entry;840 *parent_pointer = entry;
...@@ -854,15 +846,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -854,15 +846,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
854 if (is_slice(child_type)) {846 if (is_slice(child_type)) {
855 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;847 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
856 assert(child_ptr_type->id == ZigTypeIdPointer);848 assert(child_ptr_type->id == ZigTypeIdPointer);
857 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
858 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||849 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
859 child_ptr_type->data.pointer.alignment != get_abi_alignment(g, grand_child_type))850 child_ptr_type->data.pointer.explicit_alignment != 0)
860 {851 {
852 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
861 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,853 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
862 PtrLenUnknown, get_abi_alignment(g, grand_child_type), 0, 0);854 PtrLenUnknown, 0, 0, 0);
863 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);855 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
864 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,856 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false,
865 PtrLenUnknown, get_abi_alignment(g, bland_child_slice), 0, 0);857 PtrLenUnknown, 0, 0, 0);
866 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);858 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
867859
868 entry->type_ref = peer_slice_type->type_ref;860 entry->type_ref = peer_slice_type->type_ref;
...@@ -964,8 +956,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -964,8 +956,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
964 }956 }
965957
966958
967 entry->data.structure.complete = true;959 entry->data.structure.resolve_status = ResolveStatusSizeKnown;
968 entry->data.structure.zero_bits_known = true;
969960
970 *parent_pointer = entry;961 *parent_pointer = entry;
971 return entry;962 return entry;
...@@ -1370,7 +1361,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_...@@ -1370,7 +1361,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
13701361
1371static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {1362static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
1372 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1363 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1373 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);1364 PtrLenUnknown, 0, 0, 0);
1374 ZigType *str_type = get_slice_type(g, ptr_type);1365 ZigType *str_type = get_slice_type(g, ptr_type);
1375 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);1366 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
1376 if (type_is_invalid(instr->value.type))1367 if (type_is_invalid(instr->value.type))
...@@ -1414,7 +1405,6 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {...@@ -1414,7 +1405,6 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1414 case ZigTypeIdErrorUnion:1405 case ZigTypeIdErrorUnion:
1415 case ZigTypeIdErrorSet:1406 case ZigTypeIdErrorSet:
1416 case ZigTypeIdNamespace:1407 case ZigTypeIdNamespace:
1417 case ZigTypeIdBlock:
1418 case ZigTypeIdBoundFn:1408 case ZigTypeIdBoundFn:
1419 case ZigTypeIdArgTuple:1409 case ZigTypeIdArgTuple:
1420 case ZigTypeIdOpaque:1410 case ZigTypeIdOpaque:
...@@ -1455,7 +1445,6 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {...@@ -1455,7 +1445,6 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1455 case ZigTypeIdErrorUnion:1445 case ZigTypeIdErrorUnion:
1456 case ZigTypeIdErrorSet:1446 case ZigTypeIdErrorSet:
1457 case ZigTypeIdNamespace:1447 case ZigTypeIdNamespace:
1458 case ZigTypeIdBlock:
1459 case ZigTypeIdBoundFn:1448 case ZigTypeIdBoundFn:
1460 case ZigTypeIdArgTuple:1449 case ZigTypeIdArgTuple:
1461 case ZigTypeIdPromise:1450 case ZigTypeIdPromise:
...@@ -1581,7 +1570,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1581,7 +1570,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1581 return g->builtin_types.entry_invalid;1570 return g->builtin_types.entry_invalid;
1582 }1571 }
1583 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {1572 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
1584 if ((err = type_ensure_zero_bits_known(g, type_entry)))1573 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1585 return g->builtin_types.entry_invalid;1574 return g->builtin_types.entry_invalid;
1586 if (!type_has_bits(type_entry)) {1575 if (!type_has_bits(type_entry)) {
1587 add_node_error(g, param_node->data.param_decl.type,1576 add_node_error(g, param_node->data.param_decl.type,
...@@ -1613,7 +1602,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1613,7 +1602,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1613 case ZigTypeIdComptimeFloat:1602 case ZigTypeIdComptimeFloat:
1614 case ZigTypeIdComptimeInt:1603 case ZigTypeIdComptimeInt:
1615 case ZigTypeIdNamespace:1604 case ZigTypeIdNamespace:
1616 case ZigTypeIdBlock:
1617 case ZigTypeIdBoundFn:1605 case ZigTypeIdBoundFn:
1618 case ZigTypeIdMetaType:1606 case ZigTypeIdMetaType:
1619 case ZigTypeIdVoid:1607 case ZigTypeIdVoid:
...@@ -1630,7 +1618,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1630,7 +1618,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1630 case ZigTypeIdUnion:1618 case ZigTypeIdUnion:
1631 case ZigTypeIdFn:1619 case ZigTypeIdFn:
1632 case ZigTypeIdPromise:1620 case ZigTypeIdPromise:
1633 if ((err = type_ensure_zero_bits_known(g, type_entry)))1621 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
1634 return g->builtin_types.entry_invalid;1622 return g->builtin_types.entry_invalid;
1635 if (type_requires_comptime(type_entry)) {1623 if (type_requires_comptime(type_entry)) {
1636 add_node_error(g, param_node->data.param_decl.type,1624 add_node_error(g, param_node->data.param_decl.type,
...@@ -1703,7 +1691,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1703,7 +1691,6 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1703 case ZigTypeIdComptimeFloat:1691 case ZigTypeIdComptimeFloat:
1704 case ZigTypeIdComptimeInt:1692 case ZigTypeIdComptimeInt:
1705 case ZigTypeIdNamespace:1693 case ZigTypeIdNamespace:
1706 case ZigTypeIdBlock:
1707 case ZigTypeIdBoundFn:1694 case ZigTypeIdBoundFn:
1708 case ZigTypeIdMetaType:1695 case ZigTypeIdMetaType:
1709 case ZigTypeIdUnreachable:1696 case ZigTypeIdUnreachable:
...@@ -1721,7 +1708,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1721,7 +1708,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1721 case ZigTypeIdUnion:1708 case ZigTypeIdUnion:
1722 case ZigTypeIdFn:1709 case ZigTypeIdFn:
1723 case ZigTypeIdPromise:1710 case ZigTypeIdPromise:
1724 if ((err = type_ensure_zero_bits_known(g, fn_type_id.return_type)))1711 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown)))
1725 return g->builtin_types.entry_invalid;1712 return g->builtin_types.entry_invalid;
1726 if (type_requires_comptime(fn_type_id.return_type)) {1713 if (type_requires_comptime(fn_type_id.return_type)) {
1727 return get_generic_fn_type(g, &fn_type_id);1714 return get_generic_fn_type(g, &fn_type_id);
...@@ -1747,7 +1734,7 @@ bool type_is_invalid(ZigType *type_entry) {...@@ -1747,7 +1734,7 @@ bool type_is_invalid(ZigType *type_entry) {
1747 case ZigTypeIdInvalid:1734 case ZigTypeIdInvalid:
1748 return true;1735 return true;
1749 case ZigTypeIdStruct:1736 case ZigTypeIdStruct:
1750 return type_entry->data.structure.is_invalid;1737 return type_entry->data.structure.resolve_status == ResolveStatusInvalid;
1751 case ZigTypeIdEnum:1738 case ZigTypeIdEnum:
1752 return type_entry->data.enumeration.is_invalid;1739 return type_entry->data.enumeration.is_invalid;
1753 case ZigTypeIdUnion:1740 case ZigTypeIdUnion:
...@@ -1862,8 +1849,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na...@@ -1862,8 +1849,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
18621849
1863 struct_type->data.structure.src_field_count = field_count;1850 struct_type->data.structure.src_field_count = field_count;
1864 struct_type->data.structure.gen_field_count = 0;1851 struct_type->data.structure.gen_field_count = 0;
1865 struct_type->data.structure.zero_bits_known = true;1852 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
1866 struct_type->data.structure.complete = true;
1867 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);1853 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
1868 struct_type->data.structure.fields_by_name.init(field_count);1854 struct_type->data.structure.fields_by_name.init(field_count);
18691855
...@@ -1935,26 +1921,29 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na...@@ -1935,26 +1921,29 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
1935static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {1921static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1936 assert(struct_type->id == ZigTypeIdStruct);1922 assert(struct_type->id == ZigTypeIdStruct);
19371923
1938 if (struct_type->data.structure.complete)1924 Error err;
1925
1926 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
1927 return ErrorSemanticAnalyzeFail;
1928 if (struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown)
1939 return ErrorNone;1929 return ErrorNone;
19401930
1941 Error err;1931 if ((err = resolve_struct_alignment(g, struct_type)))
1942 if ((err = resolve_struct_zero_bits(g, struct_type)))
1943 return err;1932 return err;
19441933
1945 AstNode *decl_node = struct_type->data.structure.decl_node;1934 AstNode *decl_node = struct_type->data.structure.decl_node;
19461935
1947 if (struct_type->data.structure.embedded_in_current) {1936 if (struct_type->data.structure.resolve_loop_flag) {
1948 struct_type->data.structure.is_invalid = true;1937 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
1949 if (!struct_type->data.structure.reported_infinite_err) {1938 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1950 struct_type->data.structure.reported_infinite_err = true;
1951 add_node_error(g, decl_node,1939 add_node_error(g, decl_node,
1952 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));1940 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
1953 }1941 }
1954 return ErrorSemanticAnalyzeFail;1942 return ErrorSemanticAnalyzeFail;
1955 }1943 }
19561944
1957 assert(!struct_type->data.structure.zero_bits_loop_flag);1945 struct_type->data.structure.resolve_loop_flag = true;
1946
1958 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);1947 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
1959 assert(decl_node->type == NodeTypeContainerDecl);1948 assert(decl_node->type == NodeTypeContainerDecl);
19601949
...@@ -1963,9 +1952,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1963,9 +1952,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1963 size_t gen_field_count = struct_type->data.structure.gen_field_count;1952 size_t gen_field_count = struct_type->data.structure.gen_field_count;
1964 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(gen_field_count);1953 LLVMTypeRef *element_types = allocate<LLVMTypeRef>(gen_field_count);
19651954
1966 // this field should be set to true only during the recursive calls to resolve_struct_type
1967 struct_type->data.structure.embedded_in_current = true;
1968
1969 Scope *scope = &struct_type->data.structure.decls_scope->base;1955 Scope *scope = &struct_type->data.structure.decls_scope->base;
19701956
1971 size_t gen_field_index = 0;1957 size_t gen_field_index = 0;
...@@ -1979,7 +1965,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1979,7 +1965,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1979 ZigType *field_type = type_struct_field->type_entry;1965 ZigType *field_type = type_struct_field->type_entry;
19801966
1981 if ((err = ensure_complete_type(g, field_type))) {1967 if ((err = ensure_complete_type(g, field_type))) {
1982 struct_type->data.structure.is_invalid = true;1968 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1983 break;1969 break;
1984 }1970 }
19851971
...@@ -1989,7 +1975,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -1989,7 +1975,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
1989 add_node_error(g, field_source_node,1975 add_node_error(g, field_source_node,
1990 buf_sprintf("extern structs cannot contain fields of type '%s'",1976 buf_sprintf("extern structs cannot contain fields of type '%s'",
1991 buf_ptr(&field_type->name)));1977 buf_ptr(&field_type->name)));
1992 struct_type->data.structure.is_invalid = true;1978 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
1993 break;1979 break;
1994 }1980 }
1995 }1981 }
...@@ -2005,7 +1991,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2005,7 +1991,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2005 add_node_error(g, field_source_node,1991 add_node_error(g, field_source_node,
2006 buf_sprintf("packed structs cannot contain fields of type '%s'",1992 buf_sprintf("packed structs cannot contain fields of type '%s'",
2007 buf_ptr(&field_type->name)));1993 buf_ptr(&field_type->name)));
2008 struct_type->data.structure.is_invalid = true;1994 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2009 break;1995 break;
2010 }1996 }
20111997
...@@ -2056,12 +2042,13 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2056,12 +2042,13 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
2056 gen_field_index += 1;2042 gen_field_index += 1;
2057 }2043 }
20582044
2059 struct_type->data.structure.embedded_in_current = false;2045 struct_type->data.structure.resolve_loop_flag = false;
2060 struct_type->data.structure.complete = true;
20612046
2062 if (struct_type->data.structure.is_invalid)2047 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2063 return ErrorSemanticAnalyzeFail;2048 return ErrorSemanticAnalyzeFail;
20642049
2050 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
2051
2065 if (struct_type->zero_bits) {2052 if (struct_type->zero_bits) {
2066 struct_type->type_ref = LLVMVoidType();2053 struct_type->type_ref = LLVMVoidType();
20672054
...@@ -2123,7 +2110,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {...@@ -2123,7 +2110,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
21232110
2124 assert(field_type->type_ref);2111 assert(field_type->type_ref);
2125 assert(struct_type->type_ref);2112 assert(struct_type->type_ref);
2126 assert(struct_type->data.structure.complete);2113 assert(struct_type->data.structure.resolve_status == ResolveStatusSizeKnown);
2127 uint64_t debug_size_in_bits;2114 uint64_t debug_size_in_bits;
2128 uint64_t debug_align_in_bits;2115 uint64_t debug_align_in_bits;
2129 uint64_t debug_offset_in_bits;2116 uint64_t debug_offset_in_bits;
...@@ -2450,6 +2437,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2450,6 +2437,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2450 ZigType *tag_int_type;2437 ZigType *tag_int_type;
2451 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {2438 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
2452 tag_int_type = get_c_int_type(g, CIntTypeInt);2439 tag_int_type = get_c_int_type(g, CIntTypeInt);
2440 } else if (enum_type->data.enumeration.layout == ContainerLayoutAuto && field_count == 1) {
2441 tag_int_type = g->builtin_types.entry_num_lit_int;
2453 } else {2442 } else {
2454 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);2443 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
2455 }2444 }
...@@ -2513,7 +2502,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2513,7 +2502,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2513 continue;2502 continue;
2514 }2503 }
2515 assert(result_inst->value.special != ConstValSpecialRuntime);2504 assert(result_inst->value.special != ConstValSpecialRuntime);
2516 assert(result_inst->value.type->id == ZigTypeIdInt);2505 assert(result_inst->value.type->id == ZigTypeIdInt ||
2506 result_inst->value.type->id == ZigTypeIdComptimeInt);
2517 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2507 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2518 if (entry == nullptr) {2508 if (entry == nullptr) {
2519 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);2509 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
...@@ -2574,30 +2564,18 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2574,30 +2564,18 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
25742564
2575 Error err;2565 Error err;
25762566
2577 if (struct_type->data.structure.is_invalid)2567 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2578 return ErrorSemanticAnalyzeFail;2568 return ErrorSemanticAnalyzeFail;
25792569 if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
2580 if (struct_type->data.structure.zero_bits_known)
2581 return ErrorNone;2570 return ErrorNone;
25822571
2583 if (struct_type->data.structure.zero_bits_loop_flag) {2572 if (struct_type->data.structure.resolve_loop_flag) {
2584 // If we get here it's due to recursion. This is a design flaw in the compiler,2573 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
2585 // we should be able to still figure out alignment, but here we give up and say that2574 struct_type->data.structure.resolve_loop_flag = false;
2586 // the alignment is pointer width, then assert that the first field is within that
2587 // alignment
2588 struct_type->data.structure.zero_bits_known = true;
2589 struct_type->data.structure.zero_bits_loop_flag = false;
2590 if (struct_type->data.structure.abi_alignment == 0) {
2591 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2592 struct_type->data.structure.abi_alignment = 1;
2593 } else {
2594 struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
2595 }
2596 }
2597 return ErrorNone;2575 return ErrorNone;
2598 }2576 }
25992577
2600 struct_type->data.structure.zero_bits_loop_flag = true;2578 struct_type->data.structure.resolve_loop_flag = true;
26012579
2602 AstNode *decl_node = struct_type->data.structure.decl_node;2580 AstNode *decl_node = struct_type->data.structure.decl_node;
2603 assert(decl_node->type == NodeTypeContainerDecl);2581 assert(decl_node->type == NodeTypeContainerDecl);
...@@ -2620,7 +2598,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2620,7 +2598,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26202598
2621 if (field_node->data.struct_field.type == nullptr) {2599 if (field_node->data.struct_field.type == nullptr) {
2622 add_node_error(g, field_node, buf_sprintf("struct field missing type"));2600 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
2623 struct_type->data.structure.is_invalid = true;2601 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2624 continue;2602 continue;
2625 }2603 }
26262604
...@@ -2629,7 +2607,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2629,7 +2607,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2629 ErrorMsg *msg = add_node_error(g, field_node,2607 ErrorMsg *msg = add_node_error(g, field_node,
2630 buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));2608 buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));
2631 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));2609 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2632 struct_type->data.structure.is_invalid = true;2610 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2633 continue;2611 continue;
2634 }2612 }
26352613
...@@ -2643,8 +2621,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2643,8 +2621,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2643 buf_sprintf("enums, not structs, support field assignment"));2621 buf_sprintf("enums, not structs, support field assignment"));
2644 }2622 }
26452623
2646 if ((err = type_ensure_zero_bits_known(g, field_type))) {2624 if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) {
2647 struct_type->data.structure.is_invalid = true;2625 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2648 continue;2626 continue;
2649 }2627 }
26502628
...@@ -2655,36 +2633,87 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2655,36 +2633,87 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2655 if (!type_has_bits(field_type))2633 if (!type_has_bits(field_type))
2656 continue;2634 continue;
26572635
2658 if (gen_field_index == 0) {
2659 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2660 struct_type->data.structure.abi_alignment = 1;
2661 } else if (struct_type->data.structure.abi_alignment == 0) {
2662 // Alignment of structs is the alignment of the first field, for now.
2663 // TODO change this when we re-order struct fields (issue #168)
2664 struct_type->data.structure.abi_alignment = get_abi_alignment(g, field_type);
2665 assert(struct_type->data.structure.abi_alignment != 0);
2666 } else {
2667 // due to a design flaw in the compiler we assumed that alignment was
2668 // pointer width, so we assert that this wasn't violated.
2669 if (get_abi_alignment(g, field_type) > struct_type->data.structure.abi_alignment) {
2670 zig_panic("compiler design flaw: incorrect alignment assumption");
2671 }
2672 }
2673 }
2674
2675 type_struct_field->gen_index = gen_field_index;2636 type_struct_field->gen_index = gen_field_index;
2676 gen_field_index += 1;2637 gen_field_index += 1;
2677 }2638 }
26782639
2679 struct_type->data.structure.zero_bits_loop_flag = false;2640 struct_type->data.structure.resolve_loop_flag = false;
2680 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;2641 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
2681 struct_type->zero_bits = (gen_field_index == 0);2642 struct_type->zero_bits = (gen_field_index == 0);
2682 struct_type->data.structure.zero_bits_known = true;
26832643
2684 if (struct_type->data.structure.is_invalid) {2644 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2645 return ErrorSemanticAnalyzeFail;
2646
2647 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
2648 return ErrorNone;
2649}
2650
2651static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2652 assert(struct_type->id == ZigTypeIdStruct);
2653
2654 Error err;
2655
2656 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2657 return ErrorSemanticAnalyzeFail;
2658 if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown)
2659 return ErrorNone;
2660
2661 if ((err = resolve_struct_zero_bits(g, struct_type)))
2662 return err;
2663
2664 AstNode *decl_node = struct_type->data.structure.decl_node;
2665
2666 if (struct_type->data.structure.resolve_loop_flag) {
2667 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
2668 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2669 add_node_error(g, decl_node,
2670 buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name)));
2671 }
2672 return ErrorSemanticAnalyzeFail;
2673 }
2674
2675 struct_type->data.structure.resolve_loop_flag = true;
2676 assert(decl_node->type == NodeTypeContainerDecl);
2677 assert(struct_type->di_type);
2678
2679 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2680 struct_type->data.structure.abi_alignment = 1;
2681 }
2682
2683 size_t field_count = struct_type->data.structure.src_field_count;
2684 for (size_t i = 0; i < field_count; i += 1) {
2685 TypeStructField *field = &struct_type->data.structure.fields[i];
2686
2687 // If this assertion trips, look up the call stack. Probably something is
2688 // calling type_resolve with ResolveStatusAlignmentKnown when it should only
2689 // be resolving ResolveStatusZeroBitsKnown
2690 assert(field->type_entry != nullptr);
2691
2692 if (!type_has_bits(field->type_entry))
2693 continue;
2694
2695 // alignment of structs is the alignment of the most-aligned field
2696 if (struct_type->data.structure.layout != ContainerLayoutPacked) {
2697 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
2698 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2699 break;
2700 }
2701
2702 uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
2703 assert(this_field_align != 0);
2704 if (this_field_align > struct_type->data.structure.abi_alignment) {
2705 struct_type->data.structure.abi_alignment = this_field_align;
2706 }
2707 }
2708 }
2709
2710 struct_type->data.structure.resolve_loop_flag = false;
2711
2712 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
2685 return ErrorSemanticAnalyzeFail;2713 return ErrorSemanticAnalyzeFail;
2686 }2714 }
26872715
2716 struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown;
2688 return ErrorNone;2717 return ErrorNone;
2689}2718}
26902719
...@@ -2776,6 +2805,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2776,6 +2805,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2776 union_type->data.unionation.is_invalid = true;2805 union_type->data.unionation.is_invalid = true;
2777 return ErrorSemanticAnalyzeFail;2806 return ErrorSemanticAnalyzeFail;
2778 }2807 }
2808 } else if (auto_layout && field_count == 1) {
2809 tag_int_type = g->builtin_types.entry_num_lit_int;
2779 } else {2810 } else {
2780 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);2811 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
2781 }2812 }
...@@ -2809,6 +2840,10 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2809,6 +2840,10 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2809 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));2840 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));
2810 return ErrorSemanticAnalyzeFail;2841 return ErrorSemanticAnalyzeFail;
2811 }2842 }
2843 if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) {
2844 assert(g->errors.length != 0);
2845 return err;
2846 }
2812 tag_type = enum_type;2847 tag_type = enum_type;
2813 abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count2848 abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count
2814 covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);2849 covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);
...@@ -2846,7 +2881,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2846,7 +2881,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2846 }2881 }
2847 } else {2882 } else {
2848 field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);2883 field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
2849 if ((err = type_ensure_zero_bits_known(g, field_type))) {2884 if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) {
2850 union_type->data.unionation.is_invalid = true;2885 union_type->data.unionation.is_invalid = true;
2851 continue;2886 continue;
2852 }2887 }
...@@ -3109,7 +3144,7 @@ static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {...@@ -3109,7 +3144,7 @@ static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
3109 return wrong_panic_prototype(g, proto_node, fn_type);3144 return wrong_panic_prototype(g, proto_node, fn_type);
3110 }3145 }
3111 ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,3146 ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
3112 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);3147 PtrLenUnknown, 0, 0, 0);
3113 ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);3148 ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
3114 if (fn_type_id->param_info[0].type != const_u8_slice) {3149 if (fn_type_id->param_info[0].type != const_u8_slice) {
3115 return wrong_panic_prototype(g, proto_node, fn_type);3150 return wrong_panic_prototype(g, proto_node, fn_type);
...@@ -3428,7 +3463,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3428,7 +3463,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3428 case NodeTypeBoolLiteral:3463 case NodeTypeBoolLiteral:
3429 case NodeTypeNullLiteral:3464 case NodeTypeNullLiteral:
3430 case NodeTypeUndefinedLiteral:3465 case NodeTypeUndefinedLiteral:
3431 case NodeTypeThisLiteral:
3432 case NodeTypeSymbol:3466 case NodeTypeSymbol:
3433 case NodeTypePrefixOpExpr:3467 case NodeTypePrefixOpExpr:
3434 case NodeTypePointerType:3468 case NodeTypePointerType:
...@@ -3488,7 +3522,6 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3488,7 +3522,6 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3488 case ZigTypeIdUnreachable:3522 case ZigTypeIdUnreachable:
3489 case ZigTypeIdUndefined:3523 case ZigTypeIdUndefined:
3490 case ZigTypeIdNull:3524 case ZigTypeIdNull:
3491 case ZigTypeIdBlock:
3492 case ZigTypeIdArgTuple:3525 case ZigTypeIdArgTuple:
3493 case ZigTypeIdOpaque:3526 case ZigTypeIdOpaque:
3494 add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",3527 add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
...@@ -3789,34 +3822,6 @@ ZigFn *scope_fn_entry(Scope *scope) {...@@ -3789,34 +3822,6 @@ ZigFn *scope_fn_entry(Scope *scope) {
3789 return nullptr;3822 return nullptr;
3790}3823}
37913824
3792ZigFn *scope_get_fn_if_root(Scope *scope) {
3793 assert(scope);
3794 scope = scope->parent;
3795 while (scope) {
3796 switch (scope->id) {
3797 case ScopeIdBlock:
3798 return nullptr;
3799 case ScopeIdDecls:
3800 case ScopeIdDefer:
3801 case ScopeIdDeferExpr:
3802 case ScopeIdVarDecl:
3803 case ScopeIdCImport:
3804 case ScopeIdLoop:
3805 case ScopeIdSuspend:
3806 case ScopeIdCompTime:
3807 case ScopeIdCoroPrelude:
3808 case ScopeIdRuntime:
3809 scope = scope->parent;
3810 continue;
3811 case ScopeIdFnDef:
3812 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
3813 return fn_scope->fn_entry;
3814 }
3815 zig_unreachable();
3816 }
3817 return nullptr;
3818}
3819
3820TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {3825TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
3821 assert(enum_type->id == ZigTypeIdEnum);3826 assert(enum_type->id == ZigTypeIdEnum);
3822 if (enum_type->data.enumeration.src_field_count == 0)3827 if (enum_type->data.enumeration.src_field_count == 0)
...@@ -3829,7 +3834,7 @@ TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {...@@ -3829,7 +3834,7 @@ TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
38293834
3830TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) {3835TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) {
3831 assert(type_entry->id == ZigTypeIdStruct);3836 assert(type_entry->id == ZigTypeIdStruct);
3832 assert(type_entry->data.structure.complete);3837 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
3833 if (type_entry->data.structure.src_field_count == 0)3838 if (type_entry->data.structure.src_field_count == 0)
3834 return nullptr;3839 return nullptr;
3835 auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);3840 auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);
...@@ -3898,7 +3903,6 @@ static bool is_container(ZigType *type_entry) {...@@ -3898,7 +3903,6 @@ static bool is_container(ZigType *type_entry) {
3898 case ZigTypeIdErrorSet:3903 case ZigTypeIdErrorSet:
3899 case ZigTypeIdFn:3904 case ZigTypeIdFn:
3900 case ZigTypeIdNamespace:3905 case ZigTypeIdNamespace:
3901 case ZigTypeIdBlock:
3902 case ZigTypeIdBoundFn:3906 case ZigTypeIdBoundFn:
3903 case ZigTypeIdArgTuple:3907 case ZigTypeIdArgTuple:
3904 case ZigTypeIdOpaque:3908 case ZigTypeIdOpaque:
...@@ -3957,7 +3961,6 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {...@@ -3957,7 +3961,6 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
3957 case ZigTypeIdErrorSet:3961 case ZigTypeIdErrorSet:
3958 case ZigTypeIdFn:3962 case ZigTypeIdFn:
3959 case ZigTypeIdNamespace:3963 case ZigTypeIdNamespace:
3960 case ZigTypeIdBlock:
3961 case ZigTypeIdBoundFn:3964 case ZigTypeIdBoundFn:
3962 case ZigTypeIdInvalid:3965 case ZigTypeIdInvalid:
3963 case ZigTypeIdArgTuple:3966 case ZigTypeIdArgTuple:
...@@ -3983,14 +3986,17 @@ bool type_is_codegen_pointer(ZigType *type) {...@@ -3983,14 +3986,17 @@ bool type_is_codegen_pointer(ZigType *type) {
3983 return get_codegen_ptr_type(type) == type;3986 return get_codegen_ptr_type(type) == type;
3984}3987}
39853988
3986uint32_t get_ptr_align(ZigType *type) {3989uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
3987 ZigType *ptr_type = get_codegen_ptr_type(type);3990 ZigType *ptr_type = get_codegen_ptr_type(type);
3988 if (ptr_type->id == ZigTypeIdPointer) {3991 if (ptr_type->id == ZigTypeIdPointer) {
3989 return ptr_type->data.pointer.alignment;3992 return (ptr_type->data.pointer.explicit_alignment == 0) ?
3993 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
3990 } else if (ptr_type->id == ZigTypeIdFn) {3994 } else if (ptr_type->id == ZigTypeIdFn) {
3991 return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;3995 return (ptr_type->data.fn.fn_type_id.alignment == 0) ?
3996 LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) :
3997 ptr_type->data.fn.fn_type_id.alignment;
3992 } else if (ptr_type->id == ZigTypeIdPromise) {3998 } else if (ptr_type->id == ZigTypeIdPromise) {
3993 return 1;3999 return get_coro_frame_align_bytes(g);
3994 } else {4000 } else {
3995 zig_unreachable();4001 zig_unreachable();
3996 }4002 }
...@@ -4060,6 +4066,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {...@@ -4060,6 +4066,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
4060}4066}
40614067
4062bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {4068bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {
4069 assert(err_set_type->id == ZigTypeIdErrorSet);
4063 ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;4070 ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;
4064 if (infer_fn != nullptr) {4071 if (infer_fn != nullptr) {
4065 if (infer_fn->anal_state == FnAnalStateInvalid) {4072 if (infer_fn->anal_state == FnAnalStateInvalid) {
...@@ -4417,7 +4424,6 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4417,7 +4424,6 @@ bool handle_is_ptr(ZigType *type_entry) {
4417 case ZigTypeIdUndefined:4424 case ZigTypeIdUndefined:
4418 case ZigTypeIdNull:4425 case ZigTypeIdNull:
4419 case ZigTypeIdNamespace:4426 case ZigTypeIdNamespace:
4420 case ZigTypeIdBlock:
4421 case ZigTypeIdBoundFn:4427 case ZigTypeIdBoundFn:
4422 case ZigTypeIdArgTuple:4428 case ZigTypeIdArgTuple:
4423 case ZigTypeIdOpaque:4429 case ZigTypeIdOpaque:
...@@ -4832,8 +4838,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4832,8 +4838,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4832 return const_val->data.x_err_set->value ^ 2630160122;4838 return const_val->data.x_err_set->value ^ 2630160122;
4833 case ZigTypeIdNamespace:4839 case ZigTypeIdNamespace:
4834 return hash_ptr(const_val->data.x_import);4840 return hash_ptr(const_val->data.x_import);
4835 case ZigTypeIdBlock:
4836 return hash_ptr(const_val->data.x_block);
4837 case ZigTypeIdBoundFn:4841 case ZigTypeIdBoundFn:
4838 case ZigTypeIdInvalid:4842 case ZigTypeIdInvalid:
4839 case ZigTypeIdUnreachable:4843 case ZigTypeIdUnreachable:
...@@ -4894,7 +4898,6 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4894,7 +4898,6 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4894 case ZigTypeIdNamespace:4898 case ZigTypeIdNamespace:
4895 case ZigTypeIdBoundFn:4899 case ZigTypeIdBoundFn:
4896 case ZigTypeIdFn:4900 case ZigTypeIdFn:
4897 case ZigTypeIdBlock:
4898 case ZigTypeIdOpaque:4901 case ZigTypeIdOpaque:
4899 case ZigTypeIdPromise:4902 case ZigTypeIdPromise:
4900 case ZigTypeIdErrorSet:4903 case ZigTypeIdErrorSet:
...@@ -4961,7 +4964,6 @@ static bool return_type_is_cacheable(ZigType *return_type) {...@@ -4961,7 +4964,6 @@ static bool return_type_is_cacheable(ZigType *return_type) {
4961 case ZigTypeIdNamespace:4964 case ZigTypeIdNamespace:
4962 case ZigTypeIdBoundFn:4965 case ZigTypeIdBoundFn:
4963 case ZigTypeIdFn:4966 case ZigTypeIdFn:
4964 case ZigTypeIdBlock:
4965 case ZigTypeIdOpaque:4967 case ZigTypeIdOpaque:
4966 case ZigTypeIdPromise:4968 case ZigTypeIdPromise:
4967 case ZigTypeIdErrorSet:4969 case ZigTypeIdErrorSet:
...@@ -5057,8 +5059,8 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5057,8 +5059,8 @@ bool fn_eval_eql(Scope *a, Scope *b) {
50575059
5058bool type_has_bits(ZigType *type_entry) {5060bool type_has_bits(ZigType *type_entry) {
5059 assert(type_entry);5061 assert(type_entry);
5060 assert(type_entry->id != ZigTypeIdInvalid);5062 assert(!type_is_invalid(type_entry));
5061 assert(type_has_zero_bits_known(type_entry));5063 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
5062 return !type_entry->zero_bits;5064 return !type_entry->zero_bits;
5063}5065}
50645066
...@@ -5073,17 +5075,16 @@ bool type_requires_comptime(ZigType *type_entry) {...@@ -5073,17 +5075,16 @@ bool type_requires_comptime(ZigType *type_entry) {
5073 case ZigTypeIdNull:5075 case ZigTypeIdNull:
5074 case ZigTypeIdMetaType:5076 case ZigTypeIdMetaType:
5075 case ZigTypeIdNamespace:5077 case ZigTypeIdNamespace:
5076 case ZigTypeIdBlock:
5077 case ZigTypeIdBoundFn:5078 case ZigTypeIdBoundFn:
5078 case ZigTypeIdArgTuple:5079 case ZigTypeIdArgTuple:
5079 return true;5080 return true;
5080 case ZigTypeIdArray:5081 case ZigTypeIdArray:
5081 return type_requires_comptime(type_entry->data.array.child_type);5082 return type_requires_comptime(type_entry->data.array.child_type);
5082 case ZigTypeIdStruct:5083 case ZigTypeIdStruct:
5083 assert(type_has_zero_bits_known(type_entry));5084 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
5084 return type_entry->data.structure.requires_comptime;5085 return type_entry->data.structure.requires_comptime;
5085 case ZigTypeIdUnion:5086 case ZigTypeIdUnion:
5086 assert(type_has_zero_bits_known(type_entry));5087 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
5087 return type_entry->data.unionation.requires_comptime;5088 return type_entry->data.unionation.requires_comptime;
5088 case ZigTypeIdOptional:5089 case ZigTypeIdOptional:
5089 return type_requires_comptime(type_entry->data.maybe.child_type);5090 return type_requires_comptime(type_entry->data.maybe.child_type);
...@@ -5159,7 +5160,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5159,7 +5160,7 @@ void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5159 const_val->special = ConstValSpecialStatic;5160 const_val->special = ConstValSpecialStatic;
5160 // TODO make this `[*]null u8` instead of `[*]u8`5161 // TODO make this `[*]null u8` instead of `[*]u8`
5161 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,5162 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
5162 PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0);5163 PtrLenUnknown, 0, 0, 0);
5163 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;5164 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
5164 const_val->data.x_ptr.data.base_array.array_val = array_val;5165 const_val->data.x_ptr.data.base_array.array_val = array_val;
5165 const_val->data.x_ptr.data.base_array.elem_index = 0;5166 const_val->data.x_ptr.data.base_array.elem_index = 0;
...@@ -5304,8 +5305,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr...@@ -5304,8 +5305,7 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
5304 assert(array_val->type->id == ZigTypeIdArray);5305 assert(array_val->type->id == ZigTypeIdArray);
53055306
5306 ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,5307 ZigType *ptr_type = get_pointer_to_type_extra(g, array_val->type->data.array.child_type,
5307 is_const, false, PtrLenUnknown, get_abi_alignment(g, array_val->type->data.array.child_type),5308 is_const, false, PtrLenUnknown, 0, 0, 0);
5308 0, 0);
53095309
5310 const_val->special = ConstValSpecialStatic;5310 const_val->special = ConstValSpecialStatic;
5311 const_val->type = get_slice_type(g, ptr_type);5311 const_val->type = get_slice_type(g, ptr_type);
...@@ -5330,7 +5330,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue...@@ -5330,7 +5330,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue
53305330
5331 const_val->special = ConstValSpecialStatic;5331 const_val->special = ConstValSpecialStatic;
5332 const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,5332 const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
5333 ptr_len, get_abi_alignment(g, child_type), 0, 0);5333 ptr_len, 0, 0, 0);
5334 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;5334 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
5335 const_val->data.x_ptr.data.base_array.array_val = array_val;5335 const_val->data.x_ptr.data.base_array.array_val = array_val;
5336 const_val->data.x_ptr.data.base_array.elem_index = elem_index;5336 const_val->data.x_ptr.data.base_array.elem_index = elem_index;
...@@ -5429,32 +5429,46 @@ ConstExprValue *create_const_vals(size_t count) {...@@ -5429,32 +5429,46 @@ ConstExprValue *create_const_vals(size_t count) {
5429}5429}
54305430
5431Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {5431Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
5432 if (type_is_invalid(type_entry))5432 return type_resolve(g, type_entry, ResolveStatusSizeKnown);
5433 return ErrorSemanticAnalyzeFail;
5434 if (type_entry->id == ZigTypeIdStruct) {
5435 if (!type_entry->data.structure.complete)
5436 return resolve_struct_type(g, type_entry);
5437 } else if (type_entry->id == ZigTypeIdEnum) {
5438 if (!type_entry->data.enumeration.complete)
5439 return resolve_enum_type(g, type_entry);
5440 } else if (type_entry->id == ZigTypeIdUnion) {
5441 if (!type_entry->data.unionation.complete)
5442 return resolve_union_type(g, type_entry);
5443 }
5444 return ErrorNone;
5445}5433}
54465434
5447Error type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry) {5435Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
5448 if (type_is_invalid(type_entry))5436 if (type_is_invalid(ty))
5449 return ErrorSemanticAnalyzeFail;5437 return ErrorSemanticAnalyzeFail;
5450 if (type_entry->id == ZigTypeIdStruct) {5438 switch (status) {
5451 return resolve_struct_zero_bits(g, type_entry);5439 case ResolveStatusUnstarted:
5452 } else if (type_entry->id == ZigTypeIdEnum) {5440 return ErrorNone;
5453 return resolve_enum_zero_bits(g, type_entry);5441 case ResolveStatusInvalid:
5454 } else if (type_entry->id == ZigTypeIdUnion) {5442 zig_unreachable();
5455 return resolve_union_zero_bits(g, type_entry);5443 case ResolveStatusZeroBitsKnown:
5444 if (ty->id == ZigTypeIdStruct) {
5445 return resolve_struct_zero_bits(g, ty);
5446 } else if (ty->id == ZigTypeIdEnum) {
5447 return resolve_enum_zero_bits(g, ty);
5448 } else if (ty->id == ZigTypeIdUnion) {
5449 return resolve_union_zero_bits(g, ty);
5450 }
5451 return ErrorNone;
5452 case ResolveStatusAlignmentKnown:
5453 if (ty->id == ZigTypeIdStruct) {
5454 return resolve_struct_alignment(g, ty);
5455 } else if (ty->id == ZigTypeIdEnum) {
5456 return resolve_enum_zero_bits(g, ty);
5457 } else if (ty->id == ZigTypeIdUnion) {
5458 return resolve_union_zero_bits(g, ty);
5459 }
5460 return ErrorNone;
5461 case ResolveStatusSizeKnown:
5462 if (ty->id == ZigTypeIdStruct) {
5463 return resolve_struct_type(g, ty);
5464 } else if (ty->id == ZigTypeIdEnum) {
5465 return resolve_enum_type(g, ty);
5466 } else if (ty->id == ZigTypeIdUnion) {
5467 return resolve_union_type(g, ty);
5468 }
5469 return ErrorNone;
5456 }5470 }
5457 return ErrorNone;5471 zig_unreachable();
5458}5472}
54595473
5460bool ir_get_var_is_comptime(ZigVar *var) {5474bool ir_get_var_is_comptime(ZigVar *var) {
...@@ -5605,8 +5619,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {...@@ -5605,8 +5619,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
5605 zig_panic("TODO");5619 zig_panic("TODO");
5606 case ZigTypeIdNamespace:5620 case ZigTypeIdNamespace:
5607 return a->data.x_import == b->data.x_import;5621 return a->data.x_import == b->data.x_import;
5608 case ZigTypeIdBlock:
5609 return a->data.x_block == b->data.x_block;
5610 case ZigTypeIdArgTuple:5622 case ZigTypeIdArgTuple:
5611 return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index &&5623 return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index &&
5612 a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index;5624 a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index;
...@@ -5785,12 +5797,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5785,12 +5797,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5785 }5797 }
5786 case ZigTypeIdPointer:5798 case ZigTypeIdPointer:
5787 return render_const_val_ptr(g, buf, const_val, type_entry);5799 return render_const_val_ptr(g, buf, const_val, type_entry);
5788 case ZigTypeIdBlock:
5789 {
5790 AstNode *node = const_val->data.x_block->source_node;
5791 buf_appendf(buf, "(scope:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ")", node->line + 1, node->column + 1);
5792 return;
5793 }
5794 case ZigTypeIdArray:5800 case ZigTypeIdArray:
5795 {5801 {
5796 ZigType *child_type = type_entry->data.array.child_type;5802 ZigType *child_type = type_entry->data.array.child_type;
...@@ -5882,12 +5888,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5882,12 +5888,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5882 }5888 }
5883 case ZigTypeIdErrorUnion:5889 case ZigTypeIdErrorUnion:
5884 {5890 {
5885 buf_appendf(buf, "(error union %s constant)", buf_ptr(&type_entry->name));5891 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5892 if (const_val->data.x_err_union.err == nullptr) {
5893 render_const_value(g, buf, const_val->data.x_err_union.payload);
5894 } else {
5895 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5896 buf_ptr(&const_val->data.x_err_union.err->name));
5897 }
5898 buf_appendf(buf, ")");
5886 return;5899 return;
5887 }5900 }
5888 case ZigTypeIdUnion:5901 case ZigTypeIdUnion:
5889 {5902 {
5890 buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name));5903 uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);
5904 TypeUnionField *field = &type_entry->data.unionation.fields[tag];
5905 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
5906 render_const_value(g, buf, const_val->data.x_union.payload);
5907 buf_append_str(buf, "}");
5891 return;5908 return;
5892 }5909 }
5893 case ZigTypeIdErrorSet:5910 case ZigTypeIdErrorSet:
...@@ -5959,7 +5976,6 @@ uint32_t type_id_hash(TypeId x) {...@@ -5959,7 +5976,6 @@ uint32_t type_id_hash(TypeId x) {
5959 case ZigTypeIdUnion:5976 case ZigTypeIdUnion:
5960 case ZigTypeIdFn:5977 case ZigTypeIdFn:
5961 case ZigTypeIdNamespace:5978 case ZigTypeIdNamespace:
5962 case ZigTypeIdBlock:
5963 case ZigTypeIdBoundFn:5979 case ZigTypeIdBoundFn:
5964 case ZigTypeIdArgTuple:5980 case ZigTypeIdArgTuple:
5965 case ZigTypeIdPromise:5981 case ZigTypeIdPromise:
...@@ -6006,7 +6022,6 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6006,7 +6022,6 @@ bool type_id_eql(TypeId a, TypeId b) {
6006 case ZigTypeIdUnion:6022 case ZigTypeIdUnion:
6007 case ZigTypeIdFn:6023 case ZigTypeIdFn:
6008 case ZigTypeIdNamespace:6024 case ZigTypeIdNamespace:
6009 case ZigTypeIdBlock:
6010 case ZigTypeIdBoundFn:6025 case ZigTypeIdBoundFn:
6011 case ZigTypeIdArgTuple:6026 case ZigTypeIdArgTuple:
6012 case ZigTypeIdOpaque:6027 case ZigTypeIdOpaque:
...@@ -6132,7 +6147,6 @@ static const ZigTypeId all_type_ids[] = {...@@ -6132,7 +6147,6 @@ static const ZigTypeId all_type_ids[] = {
6132 ZigTypeIdUnion,6147 ZigTypeIdUnion,
6133 ZigTypeIdFn,6148 ZigTypeIdFn,
6134 ZigTypeIdNamespace,6149 ZigTypeIdNamespace,
6135 ZigTypeIdBlock,
6136 ZigTypeIdBoundFn,6150 ZigTypeIdBoundFn,
6137 ZigTypeIdArgTuple,6151 ZigTypeIdArgTuple,
6138 ZigTypeIdOpaque,6152 ZigTypeIdOpaque,
...@@ -6194,16 +6208,14 @@ size_t type_id_index(ZigType *entry) {...@@ -6194,16 +6208,14 @@ size_t type_id_index(ZigType *entry) {
6194 return 18;6208 return 18;
6195 case ZigTypeIdNamespace:6209 case ZigTypeIdNamespace:
6196 return 19;6210 return 19;
6197 case ZigTypeIdBlock:
6198 return 20;
6199 case ZigTypeIdBoundFn:6211 case ZigTypeIdBoundFn:
6200 return 21;6212 return 20;
6201 case ZigTypeIdArgTuple:6213 case ZigTypeIdArgTuple:
6202 return 22;6214 return 21;
6203 case ZigTypeIdOpaque:6215 case ZigTypeIdOpaque:
6204 return 23;6216 return 22;
6205 case ZigTypeIdPromise:6217 case ZigTypeIdPromise:
6206 return 24;6218 return 23;
6207 }6219 }
6208 zig_unreachable();6220 zig_unreachable();
6209}6221}
...@@ -6252,8 +6264,6 @@ const char *type_id_name(ZigTypeId id) {...@@ -6252,8 +6264,6 @@ const char *type_id_name(ZigTypeId id) {
6252 return "Fn";6264 return "Fn";
6253 case ZigTypeIdNamespace:6265 case ZigTypeIdNamespace:
6254 return "Namespace";6266 return "Namespace";
6255 case ZigTypeIdBlock:
6256 return "Block";
6257 case ZigTypeIdBoundFn:6267 case ZigTypeIdBoundFn:
6258 return "BoundFn";6268 return "BoundFn";
6259 case ZigTypeIdArgTuple:6269 case ZigTypeIdArgTuple:
...@@ -6278,6 +6288,12 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {...@@ -6278,6 +6288,12 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
6278 if (is_libc && g->libc_link_lib != nullptr)6288 if (is_libc && g->libc_link_lib != nullptr)
6279 return g->libc_link_lib;6289 return g->libc_link_lib;
62806290
6291 if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS) {
6292 fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
6293 "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
6294 exit(1);
6295 }
6296
6281 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {6297 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
6282 LinkLib *existing_lib = g->link_libs_list.at(i);6298 LinkLib *existing_lib = g->link_libs_list.at(i);
6283 if (buf_eql_buf(existing_lib->name, name)) {6299 if (buf_eql_buf(existing_lib->name, name)) {
...@@ -6295,7 +6311,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {...@@ -6295,7 +6311,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
6295}6311}
62966312
6297uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {6313uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {
6298 assertNoError(type_ensure_zero_bits_known(g, type_entry));6314 assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown));
6299 if (type_entry->zero_bits) return 0;6315 if (type_entry->zero_bits) return 0;
63006316
6301 // We need to make this function work without requiring ensure_complete_type6317 // We need to make this function work without requiring ensure_complete_type
...@@ -6310,10 +6326,6 @@ uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {...@@ -6310,10 +6326,6 @@ uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) {
6310 return 1;6326 return 1;
6311 } else {6327 } else {
6312 uint32_t llvm_alignment = LLVMABIAlignmentOfType(g->target_data_ref, type_entry->type_ref);6328 uint32_t llvm_alignment = LLVMABIAlignmentOfType(g->target_data_ref, type_entry->type_ref);
6313 // promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw
6314 if (type_entry->id == ZigTypeIdPromise && llvm_alignment < 8) {
6315 return 8;
6316 }
6317 return llvm_alignment;6329 return llvm_alignment;
6318 }6330 }
6319}6331}
...@@ -6351,7 +6363,10 @@ bool type_is_global_error_set(ZigType *err_set_type) {...@@ -6351,7 +6363,10 @@ bool type_is_global_error_set(ZigType *err_set_type) {
6351}6363}
63526364
6353uint32_t get_coro_frame_align_bytes(CodeGen *g) {6365uint32_t get_coro_frame_align_bytes(CodeGen *g) {
6354 return g->pointer_size_bytes * 2;6366 uint32_t a = g->pointer_size_bytes * 2;
6367 // promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw
6368 if (a < 8) a = 8;
6369 return a;
6355}6370}
63566371
6357bool type_can_fail(ZigType *type_entry) {6372bool type_can_fail(ZigType *type_entry) {
...@@ -6387,6 +6402,14 @@ not_integer:...@@ -6387,6 +6402,14 @@ not_integer:
6387 return nullptr;6402 return nullptr;
6388}6403}
63896404
6405Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents) {
6406 if (g->enable_cache) {
6407 return cache_add_file_fetch(&g->cache_hash, resolved_path, contents);
6408 } else {
6409 return os_fetch_file_path(resolved_path, contents, false);
6410 }
6411}
6412
6390X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {6413X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
6391 size_t ty_size = type_size(g, ty);6414 size_t ty_size = type_size(g, ty);
6392 if (get_codegen_ptr_type(ty) != nullptr)6415 if (get_codegen_ptr_type(ty) != nullptr)
...@@ -6467,4 +6490,3 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {...@@ -6467,4 +6490,3 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
6467 ty->id == ZigTypeIdUnreachable ||6490 ty->id == ZigTypeIdUnreachable ||
6468 get_codegen_ptr_type(ty) != nullptr);6491 get_codegen_ptr_type(ty) != nullptr);
6469}6492}
6470
src/analyze.hpp+5-4
...@@ -54,14 +54,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so...@@ -54,14 +54,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
54bool type_is_codegen_pointer(ZigType *type);54bool type_is_codegen_pointer(ZigType *type);
5555
56ZigType *get_codegen_ptr_type(ZigType *type);56ZigType *get_codegen_ptr_type(ZigType *type);
57uint32_t get_ptr_align(ZigType *type);57uint32_t get_ptr_align(CodeGen *g, ZigType *type);
58bool get_ptr_const(ZigType *type);58bool get_ptr_const(ZigType *type);
59ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);59ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
60ZigType *container_ref_type(ZigType *type_entry);60ZigType *container_ref_type(ZigType *type_entry);
61bool type_is_complete(ZigType *type_entry);61bool type_is_complete(ZigType *type_entry);
62bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
62bool type_is_invalid(ZigType *type_entry);63bool type_is_invalid(ZigType *type_entry);
63bool type_is_global_error_set(ZigType *err_set_type);64bool type_is_global_error_set(ZigType *err_set_type);
64bool type_has_zero_bits_known(ZigType *type_entry);
65void resolve_container_type(CodeGen *g, ZigType *type_entry);65void resolve_container_type(CodeGen *g, ZigType *type_entry);
66ScopeDecls *get_container_scope(ZigType *type_entry);66ScopeDecls *get_container_scope(ZigType *type_entry);
67TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);67TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
...@@ -87,10 +87,9 @@ ZigFn *create_fn(AstNode *proto_node);...@@ -87,10 +87,9 @@ ZigFn *create_fn(AstNode *proto_node);
87ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);87ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
88void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);88void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
89AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);89AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
90ZigFn *scope_get_fn_if_root(Scope *scope);
91bool type_requires_comptime(ZigType *type_entry);90bool type_requires_comptime(ZigType *type_entry);
92Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);91Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
93Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry);92Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
94void complete_enum(CodeGen *g, ZigType *enum_type);93void complete_enum(CodeGen *g, ZigType *enum_type);
95bool ir_get_var_is_comptime(ZigVar *var);94bool ir_get_var_is_comptime(ZigVar *var);
96bool const_values_equal(ConstExprValue *a, ConstExprValue *b);95bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
...@@ -209,6 +208,8 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name);...@@ -209,6 +208,8 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name);
209bool calling_convention_allows_zig_types(CallingConvention cc);208bool calling_convention_allows_zig_types(CallingConvention cc);
210const char *calling_convention_name(CallingConvention cc);209const char *calling_convention_name(CallingConvention cc);
211210
211Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
212
212void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);213void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
213X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);214X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
214bool type_is_c_abi_int(CodeGen *g, ZigType *ty);215bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
src/ast_render.cpp-7
...@@ -193,8 +193,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -193,8 +193,6 @@ static const char *node_type_str(NodeType node_type) {
193 return "NullLiteral";193 return "NullLiteral";
194 case NodeTypeUndefinedLiteral:194 case NodeTypeUndefinedLiteral:
195 return "UndefinedLiteral";195 return "UndefinedLiteral";
196 case NodeTypeThisLiteral:
197 return "ThisLiteral";
198 case NodeTypeIfBoolExpr:196 case NodeTypeIfBoolExpr:
199 return "IfBoolExpr";197 return "IfBoolExpr";
200 case NodeTypeWhileExpr:198 case NodeTypeWhileExpr:
...@@ -897,11 +895,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -897,11 +895,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
897 }895 }
898 break;896 break;
899 }897 }
900 case NodeTypeThisLiteral:
901 {
902 fprintf(ar->f, "this");
903 break;
904 }
905 case NodeTypeBoolLiteral:898 case NodeTypeBoolLiteral:
906 {899 {
907 const char *bool_str = node->data.bool_literal.value ? "true" : "false";900 const char *bool_str = node->data.bool_literal.value ? "true" : "false";
src/blake2.h created+196
...@@ -0,0 +1,196 @@
1/*
2 BLAKE2 reference source code package - reference C implementations
3
4 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
5 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6 your option. The terms of these licenses can be found at:
7
8 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9 - OpenSSL license : https://www.openssl.org/source/license.html
10 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
11
12 More information about the BLAKE2 hash function can be found at
13 https://blake2.net.
14*/
15#ifndef BLAKE2_H
16#define BLAKE2_H
17
18#include <stddef.h>
19#include <stdint.h>
20
21#if defined(_MSC_VER)
22#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
23#else
24#define BLAKE2_PACKED(x) x __attribute__((packed))
25#endif
26
27#if defined(__cplusplus)
28extern "C" {
29#endif
30
31 enum blake2s_constant
32 {
33 BLAKE2S_BLOCKBYTES = 64,
34 BLAKE2S_OUTBYTES = 32,
35 BLAKE2S_KEYBYTES = 32,
36 BLAKE2S_SALTBYTES = 8,
37 BLAKE2S_PERSONALBYTES = 8
38 };
39
40 enum blake2b_constant
41 {
42 BLAKE2B_BLOCKBYTES = 128,
43 BLAKE2B_OUTBYTES = 64,
44 BLAKE2B_KEYBYTES = 64,
45 BLAKE2B_SALTBYTES = 16,
46 BLAKE2B_PERSONALBYTES = 16
47 };
48
49 typedef struct blake2s_state__
50 {
51 uint32_t h[8];
52 uint32_t t[2];
53 uint32_t f[2];
54 uint8_t buf[BLAKE2S_BLOCKBYTES];
55 size_t buflen;
56 size_t outlen;
57 uint8_t last_node;
58 } blake2s_state;
59
60 typedef struct blake2b_state__
61 {
62 uint64_t h[8];
63 uint64_t t[2];
64 uint64_t f[2];
65 uint8_t buf[BLAKE2B_BLOCKBYTES];
66 size_t buflen;
67 size_t outlen;
68 uint8_t last_node;
69 } blake2b_state;
70
71 typedef struct blake2sp_state__
72 {
73 blake2s_state S[8][1];
74 blake2s_state R[1];
75 uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
76 size_t buflen;
77 size_t outlen;
78 } blake2sp_state;
79
80 typedef struct blake2bp_state__
81 {
82 blake2b_state S[4][1];
83 blake2b_state R[1];
84 uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
85 size_t buflen;
86 size_t outlen;
87 } blake2bp_state;
88
89
90 BLAKE2_PACKED(struct blake2s_param__
91 {
92 uint8_t digest_length; /* 1 */
93 uint8_t key_length; /* 2 */
94 uint8_t fanout; /* 3 */
95 uint8_t depth; /* 4 */
96 uint32_t leaf_length; /* 8 */
97 uint32_t node_offset; /* 12 */
98 uint16_t xof_length; /* 14 */
99 uint8_t node_depth; /* 15 */
100 uint8_t inner_length; /* 16 */
101 /* uint8_t reserved[0]; */
102 uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
103 uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
104 });
105
106 typedef struct blake2s_param__ blake2s_param;
107
108 BLAKE2_PACKED(struct blake2b_param__
109 {
110 uint8_t digest_length; /* 1 */
111 uint8_t key_length; /* 2 */
112 uint8_t fanout; /* 3 */
113 uint8_t depth; /* 4 */
114 uint32_t leaf_length; /* 8 */
115 uint32_t node_offset; /* 12 */
116 uint32_t xof_length; /* 16 */
117 uint8_t node_depth; /* 17 */
118 uint8_t inner_length; /* 18 */
119 uint8_t reserved[14]; /* 32 */
120 uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
121 uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
122 });
123
124 typedef struct blake2b_param__ blake2b_param;
125
126 typedef struct blake2xs_state__
127 {
128 blake2s_state S[1];
129 blake2s_param P[1];
130 } blake2xs_state;
131
132 typedef struct blake2xb_state__
133 {
134 blake2b_state S[1];
135 blake2b_param P[1];
136 } blake2xb_state;
137
138 /* Padded structs result in a compile-time error */
139 enum {
140 BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
141 BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
142 };
143
144 /* Streaming API */
145 int blake2s_init( blake2s_state *S, size_t outlen );
146 int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
147 int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
148 int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
149 int blake2s_final( blake2s_state *S, void *out, size_t outlen );
150
151 int blake2b_init( blake2b_state *S, size_t outlen );
152 int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
153 int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
154 int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
155 int blake2b_final( blake2b_state *S, void *out, size_t outlen );
156
157 int blake2sp_init( blake2sp_state *S, size_t outlen );
158 int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
159 int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
160 int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
161
162 int blake2bp_init( blake2bp_state *S, size_t outlen );
163 int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
164 int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
165 int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
166
167 /* Variable output length API */
168 int blake2xs_init( blake2xs_state *S, const size_t outlen );
169 int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
170 int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
171 int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
172
173 int blake2xb_init( blake2xb_state *S, const size_t outlen );
174 int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
175 int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
176 int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
177
178 /* Simple API */
179 int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
180 int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
181
182 int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
183 int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
184
185 int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
186 int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
187
188 /* This is simply an alias for blake2b */
189 int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
190
191#if defined(__cplusplus)
192}
193#endif
194
195#endif
196
src/blake2b.c created+539
...@@ -0,0 +1,539 @@
1/*
2 BLAKE2 reference source code package - reference C implementations
3
4 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
5 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6 your option. The terms of these licenses can be found at:
7
8 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9 - OpenSSL license : https://www.openssl.org/source/license.html
10 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
11
12 More information about the BLAKE2 hash function can be found at
13 https://blake2.net.
14*/
15
16#include <stdint.h>
17#include <string.h>
18#include <stdio.h>
19
20#include "blake2.h"
21/*
22 BLAKE2 reference source code package - reference C implementations
23
24 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
25 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
26 your option. The terms of these licenses can be found at:
27
28 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
29 - OpenSSL license : https://www.openssl.org/source/license.html
30 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
31
32 More information about the BLAKE2 hash function can be found at
33 https://blake2.net.
34*/
35#ifndef BLAKE2_IMPL_H
36#define BLAKE2_IMPL_H
37
38#include <stdint.h>
39#include <string.h>
40
41#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
42 #if defined(_MSC_VER)
43 #define BLAKE2_INLINE __inline
44 #elif defined(__GNUC__)
45 #define BLAKE2_INLINE __inline__
46 #else
47 #define BLAKE2_INLINE
48 #endif
49#else
50 #define BLAKE2_INLINE inline
51#endif
52
53static BLAKE2_INLINE uint32_t load32( const void *src )
54{
55#if defined(NATIVE_LITTLE_ENDIAN)
56 uint32_t w;
57 memcpy(&w, src, sizeof w);
58 return w;
59#else
60 const uint8_t *p = ( const uint8_t * )src;
61 return (( uint32_t )( p[0] ) << 0) |
62 (( uint32_t )( p[1] ) << 8) |
63 (( uint32_t )( p[2] ) << 16) |
64 (( uint32_t )( p[3] ) << 24) ;
65#endif
66}
67
68static BLAKE2_INLINE uint64_t load64( const void *src )
69{
70#if defined(NATIVE_LITTLE_ENDIAN)
71 uint64_t w;
72 memcpy(&w, src, sizeof w);
73 return w;
74#else
75 const uint8_t *p = ( const uint8_t * )src;
76 return (( uint64_t )( p[0] ) << 0) |
77 (( uint64_t )( p[1] ) << 8) |
78 (( uint64_t )( p[2] ) << 16) |
79 (( uint64_t )( p[3] ) << 24) |
80 (( uint64_t )( p[4] ) << 32) |
81 (( uint64_t )( p[5] ) << 40) |
82 (( uint64_t )( p[6] ) << 48) |
83 (( uint64_t )( p[7] ) << 56) ;
84#endif
85}
86
87static BLAKE2_INLINE uint16_t load16( const void *src )
88{
89#if defined(NATIVE_LITTLE_ENDIAN)
90 uint16_t w;
91 memcpy(&w, src, sizeof w);
92 return w;
93#else
94 const uint8_t *p = ( const uint8_t * )src;
95 return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
96 (( uint32_t )( p[1] ) << 8));
97#endif
98}
99
100static BLAKE2_INLINE void store16( void *dst, uint16_t w )
101{
102#if defined(NATIVE_LITTLE_ENDIAN)
103 memcpy(dst, &w, sizeof w);
104#else
105 uint8_t *p = ( uint8_t * )dst;
106 *p++ = ( uint8_t )w; w >>= 8;
107 *p++ = ( uint8_t )w;
108#endif
109}
110
111static BLAKE2_INLINE void store32( void *dst, uint32_t w )
112{
113#if defined(NATIVE_LITTLE_ENDIAN)
114 memcpy(dst, &w, sizeof w);
115#else
116 uint8_t *p = ( uint8_t * )dst;
117 p[0] = (uint8_t)(w >> 0);
118 p[1] = (uint8_t)(w >> 8);
119 p[2] = (uint8_t)(w >> 16);
120 p[3] = (uint8_t)(w >> 24);
121#endif
122}
123
124static BLAKE2_INLINE void store64( void *dst, uint64_t w )
125{
126#if defined(NATIVE_LITTLE_ENDIAN)
127 memcpy(dst, &w, sizeof w);
128#else
129 uint8_t *p = ( uint8_t * )dst;
130 p[0] = (uint8_t)(w >> 0);
131 p[1] = (uint8_t)(w >> 8);
132 p[2] = (uint8_t)(w >> 16);
133 p[3] = (uint8_t)(w >> 24);
134 p[4] = (uint8_t)(w >> 32);
135 p[5] = (uint8_t)(w >> 40);
136 p[6] = (uint8_t)(w >> 48);
137 p[7] = (uint8_t)(w >> 56);
138#endif
139}
140
141static BLAKE2_INLINE uint64_t load48( const void *src )
142{
143 const uint8_t *p = ( const uint8_t * )src;
144 return (( uint64_t )( p[0] ) << 0) |
145 (( uint64_t )( p[1] ) << 8) |
146 (( uint64_t )( p[2] ) << 16) |
147 (( uint64_t )( p[3] ) << 24) |
148 (( uint64_t )( p[4] ) << 32) |
149 (( uint64_t )( p[5] ) << 40) ;
150}
151
152static BLAKE2_INLINE void store48( void *dst, uint64_t w )
153{
154 uint8_t *p = ( uint8_t * )dst;
155 p[0] = (uint8_t)(w >> 0);
156 p[1] = (uint8_t)(w >> 8);
157 p[2] = (uint8_t)(w >> 16);
158 p[3] = (uint8_t)(w >> 24);
159 p[4] = (uint8_t)(w >> 32);
160 p[5] = (uint8_t)(w >> 40);
161}
162
163static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
164{
165 return ( w >> c ) | ( w << ( 32 - c ) );
166}
167
168static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
169{
170 return ( w >> c ) | ( w << ( 64 - c ) );
171}
172
173/* prevents compiler optimizing out memset() */
174static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
175{
176 static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
177 memset_v(v, 0, n);
178}
179
180#endif
181
182static const uint64_t blake2b_IV[8] =
183{
184 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
185 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
186 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
187 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
188};
189
190static const uint8_t blake2b_sigma[12][16] =
191{
192 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
193 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
194 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
195 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
196 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
197 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
198 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
199 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
200 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
201 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
202 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
203 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
204};
205
206
207static void blake2b_set_lastnode( blake2b_state *S )
208{
209 S->f[1] = (uint64_t)-1;
210}
211
212/* Some helper functions, not necessarily useful */
213static int blake2b_is_lastblock( const blake2b_state *S )
214{
215 return S->f[0] != 0;
216}
217
218static void blake2b_set_lastblock( blake2b_state *S )
219{
220 if( S->last_node ) blake2b_set_lastnode( S );
221
222 S->f[0] = (uint64_t)-1;
223}
224
225static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
226{
227 S->t[0] += inc;
228 S->t[1] += ( S->t[0] < inc );
229}
230
231static void blake2b_init0( blake2b_state *S )
232{
233 size_t i;
234 memset( S, 0, sizeof( blake2b_state ) );
235
236 for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
237}
238
239/* init xors IV with input parameter block */
240int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
241{
242 const uint8_t *p = ( const uint8_t * )( P );
243 size_t i;
244
245 blake2b_init0( S );
246
247 /* IV XOR ParamBlock */
248 for( i = 0; i < 8; ++i )
249 S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
250
251 S->outlen = P->digest_length;
252 return 0;
253}
254
255
256
257int blake2b_init( blake2b_state *S, size_t outlen )
258{
259 blake2b_param P[1];
260
261 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
262
263 P->digest_length = (uint8_t)outlen;
264 P->key_length = 0;
265 P->fanout = 1;
266 P->depth = 1;
267 store32( &P->leaf_length, 0 );
268 store32( &P->node_offset, 0 );
269 store32( &P->xof_length, 0 );
270 P->node_depth = 0;
271 P->inner_length = 0;
272 memset( P->reserved, 0, sizeof( P->reserved ) );
273 memset( P->salt, 0, sizeof( P->salt ) );
274 memset( P->personal, 0, sizeof( P->personal ) );
275 return blake2b_init_param( S, P );
276}
277
278
279int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
280{
281 blake2b_param P[1];
282
283 if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
284
285 if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
286
287 P->digest_length = (uint8_t)outlen;
288 P->key_length = (uint8_t)keylen;
289 P->fanout = 1;
290 P->depth = 1;
291 store32( &P->leaf_length, 0 );
292 store32( &P->node_offset, 0 );
293 store32( &P->xof_length, 0 );
294 P->node_depth = 0;
295 P->inner_length = 0;
296 memset( P->reserved, 0, sizeof( P->reserved ) );
297 memset( P->salt, 0, sizeof( P->salt ) );
298 memset( P->personal, 0, sizeof( P->personal ) );
299
300 if( blake2b_init_param( S, P ) < 0 ) return -1;
301
302 {
303 uint8_t block[BLAKE2B_BLOCKBYTES];
304 memset( block, 0, BLAKE2B_BLOCKBYTES );
305 memcpy( block, key, keylen );
306 blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
307 secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
308 }
309 return 0;
310}
311
312#define G(r,i,a,b,c,d) \
313 do { \
314 a = a + b + m[blake2b_sigma[r][2*i+0]]; \
315 d = rotr64(d ^ a, 32); \
316 c = c + d; \
317 b = rotr64(b ^ c, 24); \
318 a = a + b + m[blake2b_sigma[r][2*i+1]]; \
319 d = rotr64(d ^ a, 16); \
320 c = c + d; \
321 b = rotr64(b ^ c, 63); \
322 } while(0)
323
324#define ROUND(r) \
325 do { \
326 G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
327 G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
328 G(r,2,v[ 2],v[ 6],v[10],v[14]); \
329 G(r,3,v[ 3],v[ 7],v[11],v[15]); \
330 G(r,4,v[ 0],v[ 5],v[10],v[15]); \
331 G(r,5,v[ 1],v[ 6],v[11],v[12]); \
332 G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
333 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
334 } while(0)
335
336static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
337{
338 uint64_t m[16];
339 uint64_t v[16];
340 size_t i;
341
342 for( i = 0; i < 16; ++i ) {
343 m[i] = load64( block + i * sizeof( m[i] ) );
344 }
345
346 for( i = 0; i < 8; ++i ) {
347 v[i] = S->h[i];
348 }
349
350 v[ 8] = blake2b_IV[0];
351 v[ 9] = blake2b_IV[1];
352 v[10] = blake2b_IV[2];
353 v[11] = blake2b_IV[3];
354 v[12] = blake2b_IV[4] ^ S->t[0];
355 v[13] = blake2b_IV[5] ^ S->t[1];
356 v[14] = blake2b_IV[6] ^ S->f[0];
357 v[15] = blake2b_IV[7] ^ S->f[1];
358
359 ROUND( 0 );
360 ROUND( 1 );
361 ROUND( 2 );
362 ROUND( 3 );
363 ROUND( 4 );
364 ROUND( 5 );
365 ROUND( 6 );
366 ROUND( 7 );
367 ROUND( 8 );
368 ROUND( 9 );
369 ROUND( 10 );
370 ROUND( 11 );
371
372 for( i = 0; i < 8; ++i ) {
373 S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
374 }
375}
376
377#undef G
378#undef ROUND
379
380int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
381{
382 const unsigned char * in = (const unsigned char *)pin;
383 if( inlen > 0 )
384 {
385 size_t left = S->buflen;
386 size_t fill = BLAKE2B_BLOCKBYTES - left;
387 if( inlen > fill )
388 {
389 S->buflen = 0;
390 memcpy( S->buf + left, in, fill ); /* Fill buffer */
391 blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
392 blake2b_compress( S, S->buf ); /* Compress */
393 in += fill; inlen -= fill;
394 while(inlen > BLAKE2B_BLOCKBYTES) {
395 blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
396 blake2b_compress( S, in );
397 in += BLAKE2B_BLOCKBYTES;
398 inlen -= BLAKE2B_BLOCKBYTES;
399 }
400 }
401 memcpy( S->buf + S->buflen, in, inlen );
402 S->buflen += inlen;
403 }
404 return 0;
405}
406
407int blake2b_final( blake2b_state *S, void *out, size_t outlen )
408{
409 uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
410 size_t i;
411
412 if( out == NULL || outlen < S->outlen )
413 return -1;
414
415 if( blake2b_is_lastblock( S ) )
416 return -1;
417
418 blake2b_increment_counter( S, S->buflen );
419 blake2b_set_lastblock( S );
420 memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
421 blake2b_compress( S, S->buf );
422
423 for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
424 store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
425
426 memcpy( out, buffer, S->outlen );
427 secure_zero_memory(buffer, sizeof(buffer));
428 return 0;
429}
430
431/* inlen, at least, should be uint64_t. Others can be size_t. */
432int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
433{
434 blake2b_state S[1];
435
436 /* Verify parameters */
437 if ( NULL == in && inlen > 0 ) return -1;
438
439 if ( NULL == out ) return -1;
440
441 if( NULL == key && keylen > 0 ) return -1;
442
443 if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
444
445 if( keylen > BLAKE2B_KEYBYTES ) return -1;
446
447 if( keylen > 0 )
448 {
449 if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
450 }
451 else
452 {
453 if( blake2b_init( S, outlen ) < 0 ) return -1;
454 }
455
456 blake2b_update( S, ( const uint8_t * )in, inlen );
457 blake2b_final( S, out, outlen );
458 return 0;
459}
460
461int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
462 return blake2b(out, outlen, in, inlen, key, keylen);
463}
464
465#if defined(SUPERCOP)
466int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
467{
468 return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
469}
470#endif
471
472#if defined(BLAKE2B_SELFTEST)
473#include <string.h>
474#include "blake2-kat.h"
475int main( void )
476{
477 uint8_t key[BLAKE2B_KEYBYTES];
478 uint8_t buf[BLAKE2_KAT_LENGTH];
479 size_t i, step;
480
481 for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
482 key[i] = ( uint8_t )i;
483
484 for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
485 buf[i] = ( uint8_t )i;
486
487 /* Test simple API */
488 for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
489 {
490 uint8_t hash[BLAKE2B_OUTBYTES];
491 blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
492
493 if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
494 {
495 goto fail;
496 }
497 }
498
499 /* Test streaming API */
500 for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
501 for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
502 uint8_t hash[BLAKE2B_OUTBYTES];
503 blake2b_state S;
504 uint8_t * p = buf;
505 size_t mlen = i;
506 int err = 0;
507
508 if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
509 goto fail;
510 }
511
512 while (mlen >= step) {
513 if ( (err = blake2b_update(&S, p, step)) < 0 ) {
514 goto fail;
515 }
516 mlen -= step;
517 p += step;
518 }
519 if ( (err = blake2b_update(&S, p, mlen)) < 0) {
520 goto fail;
521 }
522 if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
523 goto fail;
524 }
525
526 if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
527 goto fail;
528 }
529 }
530 }
531
532 puts( "ok" );
533 return 0;
534fail:
535 puts("error");
536 return -1;
537}
538#endif
539
src/buffer.hpp+4
...@@ -78,6 +78,10 @@ static inline Buf *buf_create_from_mem(const char *ptr, size_t len) {...@@ -78,6 +78,10 @@ static inline Buf *buf_create_from_mem(const char *ptr, size_t len) {
78 return buf;78 return buf;
79}79}
8080
81static inline Buf *buf_create_from_slice(Slice<uint8_t> slice) {
82 return buf_create_from_mem((const char *)slice.ptr, slice.len);
83}
84
81static inline Buf *buf_create_from_str(const char *str) {85static inline Buf *buf_create_from_str(const char *str) {
82 return buf_create_from_mem(str, strlen(str));86 return buf_create_from_mem(str, strlen(str));
83}87}
src/cache_hash.cpp created+469
...@@ -0,0 +1,469 @@
1/*
2 * Copyright (c) 2018 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "cache_hash.hpp"
9#include "all_types.hpp"
10#include "buffer.hpp"
11#include "os.hpp"
12
13#include <stdio.h>
14
15void cache_init(CacheHash *ch, Buf *manifest_dir) {
16 int rc = blake2b_init(&ch->blake, 48);
17 assert(rc == 0);
18 ch->files = {};
19 ch->manifest_dir = manifest_dir;
20 ch->manifest_file_path = nullptr;
21 ch->manifest_dirty = false;
22}
23
24void cache_str(CacheHash *ch, const char *ptr) {
25 assert(ch->manifest_file_path == nullptr);
26 assert(ptr != nullptr);
27 // + 1 to include the null byte
28 blake2b_update(&ch->blake, ptr, strlen(ptr) + 1);
29}
30
31void cache_int(CacheHash *ch, int x) {
32 assert(ch->manifest_file_path == nullptr);
33 // + 1 to include the null byte
34 uint8_t buf[sizeof(int) + 1];
35 memcpy(buf, &x, sizeof(int));
36 buf[sizeof(int)] = 0;
37 blake2b_update(&ch->blake, buf, sizeof(int) + 1);
38}
39
40void cache_usize(CacheHash *ch, size_t x) {
41 assert(ch->manifest_file_path == nullptr);
42 // + 1 to include the null byte
43 uint8_t buf[sizeof(size_t) + 1];
44 memcpy(buf, &x, sizeof(size_t));
45 buf[sizeof(size_t)] = 0;
46 blake2b_update(&ch->blake, buf, sizeof(size_t) + 1);
47}
48
49void cache_bool(CacheHash *ch, bool x) {
50 assert(ch->manifest_file_path == nullptr);
51 blake2b_update(&ch->blake, &x, 1);
52}
53
54void cache_buf(CacheHash *ch, Buf *buf) {
55 assert(ch->manifest_file_path == nullptr);
56 assert(buf != nullptr);
57 // + 1 to include the null byte
58 blake2b_update(&ch->blake, buf_ptr(buf), buf_len(buf) + 1);
59}
60
61void cache_buf_opt(CacheHash *ch, Buf *buf) {
62 assert(ch->manifest_file_path == nullptr);
63 if (buf == nullptr) {
64 cache_str(ch, "");
65 cache_str(ch, "");
66 } else {
67 cache_buf(ch, buf);
68 }
69}
70
71void cache_list_of_link_lib(CacheHash *ch, LinkLib **ptr, size_t len) {
72 assert(ch->manifest_file_path == nullptr);
73 for (size_t i = 0; i < len; i += 1) {
74 LinkLib *lib = ptr[i];
75 if (lib->provided_explicitly) {
76 cache_buf(ch, lib->name);
77 }
78 }
79 cache_str(ch, "");
80}
81
82void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len) {
83 assert(ch->manifest_file_path == nullptr);
84 for (size_t i = 0; i < len; i += 1) {
85 Buf *buf = ptr[i];
86 cache_buf(ch, buf);
87 }
88 cache_str(ch, "");
89}
90
91void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len) {
92 assert(ch->manifest_file_path == nullptr);
93
94 for (size_t i = 0; i < len; i += 1) {
95 Buf *buf = ptr[i];
96 cache_file(ch, buf);
97 }
98 cache_str(ch, "");
99}
100
101void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len) {
102 assert(ch->manifest_file_path == nullptr);
103
104 for (size_t i = 0; i < len; i += 1) {
105 const char *s = ptr[i];
106 cache_str(ch, s);
107 }
108 cache_str(ch, "");
109}
110
111void cache_file(CacheHash *ch, Buf *file_path) {
112 assert(ch->manifest_file_path == nullptr);
113 assert(file_path != nullptr);
114 Buf *resolved_path = buf_alloc();
115 *resolved_path = os_path_resolve(&file_path, 1);
116 CacheHashFile *chf = ch->files.add_one();
117 chf->path = resolved_path;
118 cache_buf(ch, resolved_path);
119}
120
121void cache_file_opt(CacheHash *ch, Buf *file_path) {
122 assert(ch->manifest_file_path == nullptr);
123 if (file_path == nullptr) {
124 cache_str(ch, "");
125 cache_str(ch, "");
126 } else {
127 cache_file(ch, file_path);
128 }
129}
130
131// Ported from std/base64.zig
132static uint8_t base64_fs_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
133static void base64_encode(Slice<uint8_t> dest, Slice<uint8_t> source) {
134 size_t dest_len = ((source.len + 2) / 3) * 4;
135 assert(dest.len == dest_len);
136
137 size_t i = 0;
138 size_t out_index = 0;
139 for (; i + 2 < source.len; i += 3) {
140 dest.ptr[out_index] = base64_fs_alphabet[(source.ptr[i] >> 2) & 0x3f];
141 out_index += 1;
142
143 dest.ptr[out_index] = base64_fs_alphabet[((source.ptr[i] & 0x3) << 4) | ((source.ptr[i + 1] & 0xf0) >> 4)];
144 out_index += 1;
145
146 dest.ptr[out_index] = base64_fs_alphabet[((source.ptr[i + 1] & 0xf) << 2) | ((source.ptr[i + 2] & 0xc0) >> 6)];
147 out_index += 1;
148
149 dest.ptr[out_index] = base64_fs_alphabet[source.ptr[i + 2] & 0x3f];
150 out_index += 1;
151 }
152
153 // Assert that we never need pad characters.
154 assert(i == source.len);
155}
156
157// Ported from std/base64.zig
158static Error base64_decode(Slice<uint8_t> dest, Slice<uint8_t> source) {
159 assert(source.len % 4 == 0);
160 assert(dest.len == (source.len / 4) * 3);
161
162 // In Zig this is comptime computed. In C++ it's not worth it to do that.
163 uint8_t char_to_index[256];
164 bool char_in_alphabet[256] = {0};
165 for (size_t i = 0; i < 64; i += 1) {
166 uint8_t c = base64_fs_alphabet[i];
167 assert(!char_in_alphabet[c]);
168 char_in_alphabet[c] = true;
169 char_to_index[c] = i;
170 }
171
172 size_t src_cursor = 0;
173 size_t dest_cursor = 0;
174
175 for (;src_cursor < source.len; src_cursor += 4) {
176 if (!char_in_alphabet[source.ptr[src_cursor + 0]]) return ErrorInvalidFormat;
177 if (!char_in_alphabet[source.ptr[src_cursor + 1]]) return ErrorInvalidFormat;
178 if (!char_in_alphabet[source.ptr[src_cursor + 2]]) return ErrorInvalidFormat;
179 if (!char_in_alphabet[source.ptr[src_cursor + 3]]) return ErrorInvalidFormat;
180 dest.ptr[dest_cursor + 0] = (char_to_index[source.ptr[src_cursor + 0]] << 2) | (char_to_index[source.ptr[src_cursor + 1]] >> 4);
181 dest.ptr[dest_cursor + 1] = (char_to_index[source.ptr[src_cursor + 1]] << 4) | (char_to_index[source.ptr[src_cursor + 2]] >> 2);
182 dest.ptr[dest_cursor + 2] = (char_to_index[source.ptr[src_cursor + 2]] << 6) | (char_to_index[source.ptr[src_cursor + 3]]);
183 dest_cursor += 3;
184 }
185
186 assert(src_cursor == source.len);
187 assert(dest_cursor == dest.len);
188 return ErrorNone;
189}
190
191static Error hash_file(uint8_t *digest, OsFile handle, Buf *contents) {
192 Error err;
193
194 if (contents) {
195 buf_resize(contents, 0);
196 }
197
198 blake2b_state blake;
199 int rc = blake2b_init(&blake, 48);
200 assert(rc == 0);
201
202 for (;;) {
203 uint8_t buf[4096];
204 size_t amt = 4096;
205 if ((err = os_file_read(handle, buf, &amt)))
206 return err;
207 if (amt == 0) {
208 rc = blake2b_final(&blake, digest, 48);
209 assert(rc == 0);
210 return ErrorNone;
211 }
212 blake2b_update(&blake, buf, amt);
213 if (contents) {
214 buf_append_mem(contents, (char*)buf, amt);
215 }
216 }
217}
218
219static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents) {
220 Error err;
221
222 assert(chf->path != nullptr);
223
224 OsFile this_file;
225 if ((err = os_file_open_r(chf->path, &this_file)))
226 return err;
227
228 if ((err = os_file_mtime(this_file, &chf->mtime))) {
229 os_file_close(this_file);
230 return err;
231 }
232
233 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
234 os_file_close(this_file);
235 return err;
236 }
237 os_file_close(this_file);
238
239 blake2b_update(&ch->blake, chf->bin_digest, 48);
240
241 return ErrorNone;
242}
243
244Error cache_hit(CacheHash *ch, Buf *out_digest) {
245 Error err;
246
247 uint8_t bin_digest[48];
248 int rc = blake2b_final(&ch->blake, bin_digest, 48);
249 assert(rc == 0);
250
251 if (ch->files.length == 0) {
252 buf_resize(out_digest, 64);
253 base64_encode(buf_to_slice(out_digest), {bin_digest, 48});
254 return ErrorNone;
255 }
256
257 Buf b64_digest = BUF_INIT;
258 buf_resize(&b64_digest, 64);
259 base64_encode(buf_to_slice(&b64_digest), {bin_digest, 48});
260
261 rc = blake2b_init(&ch->blake, 48);
262 assert(rc == 0);
263 blake2b_update(&ch->blake, bin_digest, 48);
264
265 ch->manifest_file_path = buf_alloc();
266 os_path_join(ch->manifest_dir, &b64_digest, ch->manifest_file_path);
267
268 buf_append_str(ch->manifest_file_path, ".txt");
269
270 if ((err = os_make_path(ch->manifest_dir)))
271 return err;
272
273 if ((err = os_file_open_lock_rw(ch->manifest_file_path, &ch->manifest_file)))
274 return err;
275
276 Buf line_buf = BUF_INIT;
277 buf_resize(&line_buf, 512);
278 if ((err = os_file_read_all(ch->manifest_file, &line_buf))) {
279 os_file_close(ch->manifest_file);
280 return err;
281 }
282
283 size_t input_file_count = ch->files.length;
284 bool any_file_changed = false;
285 size_t file_i = 0;
286 SplitIterator line_it = memSplit(buf_to_slice(&line_buf), str("\n"));
287 for (;; file_i += 1) {
288 Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&line_it);
289 if (!opt_line.is_some)
290 break;
291
292 CacheHashFile *chf;
293 if (file_i < input_file_count) {
294 chf = &ch->files.at(file_i);
295 } else if (any_file_changed) {
296 // cache miss.
297 // keep the the manifest file open with the rw lock
298 // reset the hash
299 rc = blake2b_init(&ch->blake, 48);
300 assert(rc == 0);
301 blake2b_update(&ch->blake, bin_digest, 48);
302 ch->files.resize(input_file_count);
303 // bring the hash up to the input file hashes
304 for (file_i = 0; file_i < input_file_count; file_i += 1) {
305 blake2b_update(&ch->blake, ch->files.at(file_i).bin_digest, 48);
306 }
307 // caller can notice that out_digest is unmodified.
308 return ErrorNone;
309 } else {
310 chf = ch->files.add_one();
311 chf->path = nullptr;
312 }
313
314 SplitIterator it = memSplit(opt_line.value, str(" "));
315
316 Optional<Slice<uint8_t>> opt_mtime_sec = SplitIterator_next(&it);
317 if (!opt_mtime_sec.is_some) {
318 os_file_close(ch->manifest_file);
319 return ErrorInvalidFormat;
320 }
321 chf->mtime.sec = strtoull((const char *)opt_mtime_sec.value.ptr, nullptr, 10);
322
323 Optional<Slice<uint8_t>> opt_mtime_nsec = SplitIterator_next(&it);
324 if (!opt_mtime_nsec.is_some) {
325 os_file_close(ch->manifest_file);
326 return ErrorInvalidFormat;
327 }
328 chf->mtime.nsec = strtoull((const char *)opt_mtime_nsec.value.ptr, nullptr, 10);
329
330 Optional<Slice<uint8_t>> opt_digest = SplitIterator_next(&it);
331 if (!opt_digest.is_some) {
332 os_file_close(ch->manifest_file);
333 return ErrorInvalidFormat;
334 }
335 if ((err = base64_decode({chf->bin_digest, 48}, opt_digest.value))) {
336 os_file_close(ch->manifest_file);
337 return ErrorInvalidFormat;
338 }
339
340 Slice<uint8_t> file_path = SplitIterator_rest(&it);
341 if (file_path.len == 0) {
342 os_file_close(ch->manifest_file);
343 return ErrorInvalidFormat;
344 }
345 Buf *this_path = buf_create_from_slice(file_path);
346 if (chf->path != nullptr && !buf_eql_buf(this_path, chf->path)) {
347 os_file_close(ch->manifest_file);
348 return ErrorInvalidFormat;
349 }
350 chf->path = this_path;
351
352 // if the mtime matches we can trust the digest
353 OsFile this_file;
354 if ((err = os_file_open_r(chf->path, &this_file))) {
355 os_file_close(ch->manifest_file);
356 return err;
357 }
358 OsTimeStamp actual_mtime;
359 if ((err = os_file_mtime(this_file, &actual_mtime))) {
360 os_file_close(this_file);
361 os_file_close(ch->manifest_file);
362 return err;
363 }
364 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
365 os_file_close(this_file);
366 } else {
367 // we have to recompute the digest.
368 // later we'll rewrite the manifest with the new mtime/digest values
369 ch->manifest_dirty = true;
370 chf->mtime = actual_mtime;
371
372 uint8_t actual_digest[48];
373 if ((err = hash_file(actual_digest, this_file, nullptr))) {
374 os_file_close(this_file);
375 os_file_close(ch->manifest_file);
376 return err;
377 }
378 os_file_close(this_file);
379 if (memcmp(chf->bin_digest, actual_digest, 48) != 0) {
380 memcpy(chf->bin_digest, actual_digest, 48);
381 // keep going until we have the input file digests
382 any_file_changed = true;
383 }
384 }
385 if (!any_file_changed) {
386 blake2b_update(&ch->blake, chf->bin_digest, 48);
387 }
388 }
389 if (file_i < input_file_count) {
390 // manifest file is empty or missing entries, so this is a cache miss
391 ch->manifest_dirty = true;
392 for (; file_i < input_file_count; file_i += 1) {
393 CacheHashFile *chf = &ch->files.at(file_i);
394 if ((err = populate_file_hash(ch, chf, nullptr))) {
395 os_file_close(ch->manifest_file);
396 return err;
397 }
398 }
399 return ErrorNone;
400 }
401 // Cache Hit
402 return cache_final(ch, out_digest);
403}
404
405Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) {
406 Error err;
407
408 assert(ch->manifest_file_path != nullptr);
409 CacheHashFile *chf = ch->files.add_one();
410 chf->path = resolved_path;
411 if ((err = populate_file_hash(ch, chf, contents))) {
412 os_file_close(ch->manifest_file);
413 return err;
414 }
415
416 return ErrorNone;
417}
418
419Error cache_add_file(CacheHash *ch, Buf *path) {
420 Buf *resolved_path = buf_alloc();
421 *resolved_path = os_path_resolve(&path, 1);
422 return cache_add_file_fetch(ch, resolved_path, nullptr);
423}
424
425static Error write_manifest_file(CacheHash *ch) {
426 Error err;
427 Buf contents = BUF_INIT;
428 buf_resize(&contents, 0);
429 uint8_t encoded_digest[65];
430 encoded_digest[64] = 0;
431 for (size_t i = 0; i < ch->files.length; i += 1) {
432 CacheHashFile *chf = &ch->files.at(i);
433 base64_encode({encoded_digest, 64}, {chf->bin_digest, 48});
434 buf_appendf(&contents, "%" ZIG_PRI_u64 " %" ZIG_PRI_u64 " %s %s\n",
435 chf->mtime.sec, chf->mtime.nsec, encoded_digest, buf_ptr(chf->path));
436 }
437 if ((err = os_file_overwrite(ch->manifest_file, &contents)))
438 return err;
439
440 return ErrorNone;
441}
442
443Error cache_final(CacheHash *ch, Buf *out_digest) {
444 Error err;
445
446 assert(ch->manifest_file_path != nullptr);
447
448 if (ch->manifest_dirty) {
449 if ((err = write_manifest_file(ch))) {
450 fprintf(stderr, "Warning: Unable to write cache file '%s': %s\n",
451 buf_ptr(ch->manifest_file_path), err_str(err));
452 }
453 }
454 // We don't close the manifest file yet, because we want to
455 // keep it locked until the API user is done using it.
456
457 uint8_t bin_digest[48];
458 int rc = blake2b_final(&ch->blake, bin_digest, 48);
459 assert(rc == 0);
460 buf_resize(out_digest, 64);
461 base64_encode(buf_to_slice(out_digest), {bin_digest, 48});
462
463 return ErrorNone;
464}
465
466void cache_release(CacheHash *ch) {
467 assert(ch->manifest_file_path != nullptr);
468 os_file_close(ch->manifest_file);
469}
src/cache_hash.hpp created+71
...@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) 2018 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_CACHE_HASH_HPP
9#define ZIG_CACHE_HASH_HPP
10
11#include "blake2.h"
12#include "os.hpp"
13
14struct LinkLib;
15
16struct CacheHashFile {
17 Buf *path;
18 OsTimeStamp mtime;
19 uint8_t bin_digest[48];
20 Buf *contents;
21};
22
23struct CacheHash {
24 blake2b_state blake;
25 ZigList<CacheHashFile> files;
26 Buf *manifest_dir;
27 Buf *manifest_file_path;
28 OsFile manifest_file;
29 bool manifest_dirty;
30};
31
32// Always call this first to set up.
33void cache_init(CacheHash *ch, Buf *manifest_dir);
34
35// Next, use the hash population functions to add the initial parameters.
36void cache_str(CacheHash *ch, const char *ptr);
37void cache_int(CacheHash *ch, int x);
38void cache_bool(CacheHash *ch, bool x);
39void cache_usize(CacheHash *ch, size_t x);
40void cache_buf(CacheHash *ch, Buf *buf);
41void cache_buf_opt(CacheHash *ch, Buf *buf);
42void cache_list_of_link_lib(CacheHash *ch, LinkLib **ptr, size_t len);
43void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len);
44void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len);
45void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len);
46void cache_file(CacheHash *ch, Buf *path);
47void cache_file_opt(CacheHash *ch, Buf *path);
48
49// Then call cache_hit when you're ready to see if you can skip the next step.
50// out_b64_digest will be left unchanged if it was a cache miss.
51// If you got a cache hit, the next step is cache_release.
52// From this point on, there is a lock on the input params. Release
53// the lock with cache_release.
54Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
55
56// If you did not get a cache hit, call this function for every file
57// that is depended on, and then finish with cache_final.
58Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path);
59
60// This variant of cache_add_file returns the file contents.
61// Also the file path argument must be already resolved.
62Error ATTRIBUTE_MUST_USE cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents);
63
64// out_b64_digest will be the same thing that cache_hit returns if you got a cache hit
65Error ATTRIBUTE_MUST_USE cache_final(CacheHash *ch, Buf *out_b64_digest);
66
67// Until this function is called, no one will be able to get a lock on your input params.
68void cache_release(CacheHash *ch);
69
70
71#endif
src/codegen.cpp+394-136
...@@ -8,12 +8,12 @@...@@ -8,12 +8,12 @@
8#include "analyze.hpp"8#include "analyze.hpp"
9#include "ast_render.hpp"9#include "ast_render.hpp"
10#include "codegen.hpp"10#include "codegen.hpp"
11#include "compiler.hpp"
11#include "config.h"12#include "config.h"
12#include "errmsg.hpp"13#include "errmsg.hpp"
13#include "error.hpp"14#include "error.hpp"
14#include "hash_map.hpp"15#include "hash_map.hpp"
15#include "ir.hpp"16#include "ir.hpp"
16#include "link.hpp"
17#include "os.hpp"17#include "os.hpp"
18#include "translate_c.hpp"18#include "translate_c.hpp"
19#include "target.hpp"19#include "target.hpp"
...@@ -183,14 +183,14 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -183,14 +183,14 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
183 return g;183 return g;
184}184}
185185
186void codegen_destroy(CodeGen *codegen) {
187 LLVMDisposeTargetMachine(codegen->target_machine);
188}
189
190void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {186void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
191 g->out_h_path = h_path;187 g->out_h_path = h_path;
192}188}
193189
190void codegen_set_output_path(CodeGen *g, Buf *path) {
191 g->wanted_output_file_path = path;
192}
193
194void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {194void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
195 g->clang_argv = args;195 g->clang_argv = args;
196 g->clang_argv_len = len;196 g->clang_argv_len = len;
...@@ -243,10 +243,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {...@@ -243,10 +243,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
243 g->root_out_name = out_name;243 g->root_out_name = out_name;
244}244}
245245
246void codegen_set_cache_dir(CodeGen *g, Buf cache_dir) {
247 g->cache_dir = cache_dir;
248}
249
250void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {246void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
251 g->libc_lib_dir = libc_lib_dir;247 g->libc_lib_dir = libc_lib_dir;
252}248}
...@@ -779,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR...@@ -779,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
779775
780static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {776static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
781 assert(ptr_type->id == ZigTypeIdPointer);777 assert(ptr_type->id == ZigTypeIdPointer);
782 return gen_store_untyped(g, value, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);778 uint32_t alignment = get_ptr_align(g, ptr_type);
779 return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile);
783}780}
784781
785static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile,782static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile,
...@@ -797,7 +794,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig...@@ -797,7 +794,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig
797794
798static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {795static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
799 assert(ptr_type->id == ZigTypeIdPointer);796 assert(ptr_type->id == ZigTypeIdPointer);
800 return gen_load_untyped(g, ptr, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile, name);797 uint32_t alignment = get_ptr_align(g, ptr_type);
798 return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name);
801}799}
802800
803static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {801static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) {
...@@ -1772,7 +1770,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty...@@ -1772,7 +1770,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty
17721770
1773 ZigType *usize = g->builtin_types.entry_usize;1771 ZigType *usize = g->builtin_types.entry_usize;
1774 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);1772 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref);
1775 uint64_t align_bytes = ptr_type->data.pointer.alignment;1773 uint64_t align_bytes = get_ptr_align(g, ptr_type);
1776 assert(size_bytes > 0);1774 assert(size_bytes > 0);
1777 assert(align_bytes > 0);1775 assert(align_bytes > 0);
17781776
...@@ -3162,7 +3160,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3162,7 +3160,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3162 assert(var->value->type == init_value->value.type);3160 assert(var->value->type == init_value->value.type);
3163 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,3161 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3164 PtrLenSingle, var->align_bytes, 0, 0);3162 PtrLenSingle, var->align_bytes, 0, 0);
3165 gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value));3163 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3164 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3166 } else {3165 } else {
3167 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);3166 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
3168 if (want_safe) {3167 if (want_safe) {
...@@ -4022,7 +4021,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I...@@ -4022,7 +4021,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
4022 LLVMValueRef ptr_val;4021 LLVMValueRef ptr_val;
40234022
4024 if (target_type->id == ZigTypeIdPointer) {4023 if (target_type->id == ZigTypeIdPointer) {
4025 align_bytes = target_type->data.pointer.alignment;4024 align_bytes = get_ptr_align(g, target_type);
4026 ptr_val = target_val;4025 ptr_val = target_val;
4027 } else if (target_type->id == ZigTypeIdFn) {4026 } else if (target_type->id == ZigTypeIdFn) {
4028 align_bytes = target_type->data.fn.fn_type_id.alignment;4027 align_bytes = target_type->data.fn.fn_type_id.alignment;
...@@ -4030,7 +4029,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I...@@ -4030,7 +4029,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
4030 } else if (target_type->id == ZigTypeIdOptional &&4029 } else if (target_type->id == ZigTypeIdOptional &&
4031 target_type->data.maybe.child_type->id == ZigTypeIdPointer)4030 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
4032 {4031 {
4033 align_bytes = target_type->data.maybe.child_type->data.pointer.alignment;4032 align_bytes = get_ptr_align(g, target_type->data.maybe.child_type);
4034 ptr_val = target_val;4033 ptr_val = target_val;
4035 } else if (target_type->id == ZigTypeIdOptional &&4034 } else if (target_type->id == ZigTypeIdOptional &&
4036 target_type->data.maybe.child_type->id == ZigTypeIdFn)4035 target_type->data.maybe.child_type->id == ZigTypeIdFn)
...@@ -4043,7 +4042,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I...@@ -4043,7 +4042,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
4043 zig_panic("TODO audit this function");4042 zig_panic("TODO audit this function");
4044 } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {4043 } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
4045 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;4044 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
4046 align_bytes = slice_ptr_type->data.pointer.alignment;4045 align_bytes = get_ptr_align(g, slice_ptr_type);
40474046
4048 size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;4047 size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
4049 LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, "");4048 LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, "");
...@@ -4195,7 +4194,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns...@@ -4195,7 +4194,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns
4195 ZigType *ptr_type = instruction->dest_ptr->value.type;4194 ZigType *ptr_type = instruction->dest_ptr->value.type;
4196 assert(ptr_type->id == ZigTypeIdPointer);4195 assert(ptr_type->id == ZigTypeIdPointer);
41974196
4198 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, ptr_type->data.pointer.alignment, ptr_type->data.pointer.is_volatile);4197 ZigLLVMBuildMemSet(g->builder, dest_ptr_casted, char_val, len_val, get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile);
4199 return nullptr;4198 return nullptr;
4200}4199}
42014200
...@@ -4216,9 +4215,8 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns...@@ -4216,9 +4215,8 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
4216 assert(src_ptr_type->id == ZigTypeIdPointer);4215 assert(src_ptr_type->id == ZigTypeIdPointer);
42174216
4218 bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);4217 bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);
42194218 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, get_ptr_align(g, dest_ptr_type),
4220 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, dest_ptr_type->data.pointer.alignment,4219 src_ptr_casted, get_ptr_align(g, src_ptr_type), len_val, is_volatile);
4221 src_ptr_casted, src_ptr_type->data.pointer.alignment, len_val, is_volatile);
4222 return nullptr;4220 return nullptr;
4223}4221}
42244222
...@@ -4629,7 +4627,6 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa...@@ -4629,7 +4627,6 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
46294627
4630static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {4628static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
4631 ZigType *union_type = instruction->value->value.type;4629 ZigType *union_type = instruction->value->value.type;
4632 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
46334630
4634 ZigType *tag_type = union_type->data.unionation.tag_type;4631 ZigType *tag_type = union_type->data.unionation.tag_type;
4635 if (!type_has_bits(tag_type))4632 if (!type_has_bits(tag_type))
...@@ -4639,6 +4636,7 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir...@@ -4639,6 +4636,7 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
4639 if (union_type->data.unionation.gen_field_count == 0)4636 if (union_type->data.unionation.gen_field_count == 0)
4640 return union_val;4637 return union_val;
46414638
4639 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
4642 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,4640 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,
4643 union_type->data.unionation.gen_tag_index, "");4641 union_type->data.unionation.gen_tag_index, "");
4644 ZigType *ptr_type = get_pointer_to_type(g, tag_type, false);4642 ZigType *ptr_type = get_pointer_to_type(g, tag_type, false);
...@@ -5393,7 +5391,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -5393,7 +5391,6 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
5393 case ZigTypeIdErrorUnion:5391 case ZigTypeIdErrorUnion:
5394 case ZigTypeIdErrorSet:5392 case ZigTypeIdErrorSet:
5395 case ZigTypeIdNamespace:5393 case ZigTypeIdNamespace:
5396 case ZigTypeIdBlock:
5397 case ZigTypeIdBoundFn:5394 case ZigTypeIdBoundFn:
5398 case ZigTypeIdArgTuple:5395 case ZigTypeIdArgTuple:
5399 case ZigTypeIdVoid:5396 case ZigTypeIdVoid:
...@@ -5774,12 +5771,24 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5774,12 +5771,24 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5774 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,5771 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
5775 &const_val->data.x_union.tag);5772 &const_val->data.x_union.tag);
57765773
5777 LLVMValueRef fields[2];5774 LLVMValueRef fields[3];
5778 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;5775 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
5779 fields[type_entry->data.unionation.gen_tag_index] = tag_value;5776 fields[type_entry->data.unionation.gen_tag_index] = tag_value;
57805777
5781 if (make_unnamed_struct) {5778 if (make_unnamed_struct) {
5782 return LLVMConstStruct(fields, 2, false);5779 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
5780 uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
5781 uint64_t end_offset = last_field_offset +
5782 LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
5783 uint64_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
5784 unsigned pad_sz = expected_sz - end_offset;
5785 if (pad_sz != 0) {
5786 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
5787 result = LLVMConstStruct(fields, 3, false);
5788 }
5789 uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
5790 assert(actual_sz == expected_sz);
5791 return result;
5783 } else {5792 } else {
5784 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);5793 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
5785 }5794 }
...@@ -5789,9 +5798,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5789,9 +5798,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5789 case ZigTypeIdEnum:5798 case ZigTypeIdEnum:
5790 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);5799 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
5791 case ZigTypeIdFn:5800 case ZigTypeIdFn:
5792 assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);5801 if (const_val->data.x_ptr.special == ConstPtrSpecialFunction) {
5793 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);5802 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
5794 return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry);5803 return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry);
5804 } else if (const_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
5805 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref;
5806 uint64_t addr = const_val->data.x_ptr.data.hard_coded_addr.addr;
5807 return LLVMConstIntToPtr(LLVMConstInt(usize_type_ref, addr, false), type_entry->type_ref);
5808 } else {
5809 zig_unreachable();
5810 }
5795 case ZigTypeIdPointer:5811 case ZigTypeIdPointer:
5796 return gen_const_val_ptr(g, const_val, name);5812 return gen_const_val_ptr(g, const_val, name);
5797 case ZigTypeIdErrorUnion:5813 case ZigTypeIdErrorUnion:
...@@ -5819,13 +5835,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5819,13 +5835,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5819 err_payload_value = gen_const_val(g, payload_val, "");5835 err_payload_value = gen_const_val(g, payload_val, "");
5820 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);5836 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);
5821 }5837 }
5822 LLVMValueRef fields[] = {
5823 err_tag_value,
5824 err_payload_value,
5825 };
5826 if (make_unnamed_struct) {5838 if (make_unnamed_struct) {
5827 return LLVMConstStruct(fields, 2, false);5839 uint64_t payload_off = LLVMOffsetOfElement(g->target_data_ref, type_entry->type_ref, 1);
5840 uint64_t err_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(err_tag_value));
5841 unsigned pad_sz = payload_off - err_sz;
5842 if (pad_sz == 0) {
5843 LLVMValueRef fields[] = {
5844 err_tag_value,
5845 err_payload_value,
5846 };
5847 return LLVMConstStruct(fields, 2, false);
5848 } else {
5849 LLVMValueRef fields[] = {
5850 err_tag_value,
5851 LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz)),
5852 err_payload_value,
5853 };
5854 return LLVMConstStruct(fields, 3, false);
5855 }
5828 } else {5856 } else {
5857 LLVMValueRef fields[] = {
5858 err_tag_value,
5859 err_payload_value,
5860 };
5829 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);5861 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
5830 }5862 }
5831 }5863 }
...@@ -5840,7 +5872,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5840,7 +5872,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5840 case ZigTypeIdUndefined:5872 case ZigTypeIdUndefined:
5841 case ZigTypeIdNull:5873 case ZigTypeIdNull:
5842 case ZigTypeIdNamespace:5874 case ZigTypeIdNamespace:
5843 case ZigTypeIdBlock:
5844 case ZigTypeIdBoundFn:5875 case ZigTypeIdBoundFn:
5845 case ZigTypeIdArgTuple:5876 case ZigTypeIdArgTuple:
5846 case ZigTypeIdOpaque:5877 case ZigTypeIdOpaque:
...@@ -5958,13 +5989,6 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,...@@ -5958,13 +5989,6 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
5958 // TODO ^^ make an actual global variable5989 // TODO ^^ make an actual global variable
5959}5990}
59605991
5961static void ensure_cache_dir(CodeGen *g) {
5962 int err;
5963 if ((err = os_make_path(&g->cache_dir))) {
5964 zig_panic("unable to make cache dir: %s", err_str(err));
5965 }
5966}
5967
5968static void validate_inline_fns(CodeGen *g) {5992static void validate_inline_fns(CodeGen *g) {
5969 for (size_t i = 0; i < g->inline_fns.length; i += 1) {5993 for (size_t i = 0; i < g->inline_fns.length; i += 1) {
5970 ZigFn *fn_entry = g->inline_fns.at(i);5994 ZigFn *fn_entry = g->inline_fns.at(i);
...@@ -5979,8 +6003,6 @@ static void validate_inline_fns(CodeGen *g) {...@@ -5979,8 +6003,6 @@ static void validate_inline_fns(CodeGen *g) {
5979static void do_code_gen(CodeGen *g) {6003static void do_code_gen(CodeGen *g) {
5980 assert(!g->errors.length);6004 assert(!g->errors.length);
59816005
5982 codegen_add_time_event(g, "Code Generation");
5983
5984 {6006 {
5985 // create debug type for error sets6007 // create debug type for error sets
5986 assert(g->err_enumerators.length == g->errors_by_index.length);6008 assert(g->err_enumerators.length == g->errors_by_index.length);
...@@ -6283,45 +6305,18 @@ static void do_code_gen(CodeGen *g) {...@@ -6283,45 +6305,18 @@ static void do_code_gen(CodeGen *g) {
6283 char *error = nullptr;6305 char *error = nullptr;
6284 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);6306 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
6285#endif6307#endif
6308}
62866309
6287 codegen_add_time_event(g, "LLVM Emit Output");6310static void zig_llvm_emit_output(CodeGen *g) {
6288
6289 char *err_msg = nullptr;
6290 Buf *o_basename = buf_create_from_buf(g->root_out_name);
6291
6292 switch (g->emit_file_type) {
6293 case EmitFileTypeBinary:
6294 {
6295 const char *o_ext = target_o_file_ext(&g->zig_target);
6296 buf_append_str(o_basename, o_ext);
6297 break;
6298 }
6299 case EmitFileTypeAssembly:
6300 {
6301 const char *asm_ext = target_asm_file_ext(&g->zig_target);
6302 buf_append_str(o_basename, asm_ext);
6303 break;
6304 }
6305 case EmitFileTypeLLVMIr:
6306 {
6307 const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
6308 buf_append_str(o_basename, llvm_ir_ext);
6309 break;
6310 }
6311 default:
6312 zig_unreachable();
6313 }
6314
6315 Buf *output_path = buf_alloc();
6316 os_path_join(&g->cache_dir, o_basename, output_path);
6317 ensure_cache_dir(g);
6318
6319 bool is_small = g->build_mode == BuildModeSmallRelease;6311 bool is_small = g->build_mode == BuildModeSmallRelease;
63206312
6313 Buf *output_path = &g->o_file_output_path;
6314 char *err_msg = nullptr;
6321 switch (g->emit_file_type) {6315 switch (g->emit_file_type) {
6322 case EmitFileTypeBinary:6316 case EmitFileTypeBinary:
6323 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),6317 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
6324 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small))6318 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
6319 g->enable_time_report))
6325 {6320 {
6326 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);6321 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
6327 }6322 }
...@@ -6331,22 +6326,22 @@ static void do_code_gen(CodeGen *g) {...@@ -6331,22 +6326,22 @@ static void do_code_gen(CodeGen *g) {
63316326
6332 case EmitFileTypeAssembly:6327 case EmitFileTypeAssembly:
6333 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),6328 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
6334 ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small))6329 ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small,
6330 g->enable_time_report))
6335 {6331 {
6336 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);6332 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
6337 }6333 }
6338 validate_inline_fns(g);6334 validate_inline_fns(g);
6339 g->link_objects.append(output_path);
6340 break;6335 break;
63416336
6342 case EmitFileTypeLLVMIr:6337 case EmitFileTypeLLVMIr:
6343 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),6338 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
6344 ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small))6339 ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small,
6340 g->enable_time_report))
6345 {6341 {
6346 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);6342 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
6347 }6343 }
6348 validate_inline_fns(g);6344 validate_inline_fns(g);
6349 g->link_objects.append(output_path);
6350 break;6345 break;
63516346
6352 default:6347 default:
...@@ -6399,12 +6394,6 @@ static void define_builtin_types(CodeGen *g) {...@@ -6399,12 +6394,6 @@ static void define_builtin_types(CodeGen *g) {
6399 entry->zero_bits = true;6394 entry->zero_bits = true;
6400 g->builtin_types.entry_namespace = entry;6395 g->builtin_types.entry_namespace = entry;
6401 }6396 }
6402 {
6403 ZigType *entry = new_type_table_entry(ZigTypeIdBlock);
6404 buf_init_from_str(&entry->name, "(block)");
6405 entry->zero_bits = true;
6406 g->builtin_types.entry_block = entry;
6407 }
6408 {6397 {
6409 ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat);6398 ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat);
6410 buf_init_from_str(&entry->name, "comptime_float");6399 buf_init_from_str(&entry->name, "comptime_float");
...@@ -6651,7 +6640,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6651,7 +6640,7 @@ static void define_builtin_fns(CodeGen *g) {
6651 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int6640 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
6652 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);6641 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
6653 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);6642 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
6654 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);6643 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
6655 create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);6644 create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
6656 create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2);6645 create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2);
6657 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);6646 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
...@@ -6685,6 +6674,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6685,6 +6674,7 @@ static void define_builtin_fns(CodeGen *g) {
6685 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);6674 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
6686 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);6675 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6687 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);6676 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6677 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
6688}6678}
66896679
6690static const char *bool_to_str(bool b) {6680static const char *bool_to_str(bool b) {
...@@ -6866,7 +6856,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -6866,7 +6856,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
6866 " Union: Union,\n"6856 " Union: Union,\n"
6867 " Fn: Fn,\n"6857 " Fn: Fn,\n"
6868 " Namespace: void,\n"6858 " Namespace: void,\n"
6869 " Block: void,\n"
6870 " BoundFn: Fn,\n"6859 " BoundFn: Fn,\n"
6871 " ArgTuple: void,\n"6860 " ArgTuple: void,\n"
6872 " Opaque: void,\n"6861 " Opaque: void,\n"
...@@ -7037,11 +7026,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7037,11 +7026,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7037 {7026 {
7038 buf_appendf(contents,7027 buf_appendf(contents,
7039 "pub const FloatMode = enum {\n"7028 "pub const FloatMode = enum {\n"
7040 " Optimized,\n"
7041 " Strict,\n"7029 " Strict,\n"
7030 " Optimized,\n"
7042 "};\n\n");7031 "};\n\n");
7043 assert(FloatModeOptimized == 0);7032 assert(FloatModeStrict == 0);
7044 assert(FloatModeStrict == 1);7033 assert(FloatModeOptimized == 1);
7045 }7034 }
7046 {7035 {
7047 buf_appendf(contents,7036 buf_appendf(contents,
...@@ -7049,8 +7038,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7049,8 +7038,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7049 " Big,\n"7038 " Big,\n"
7050 " Little,\n"7039 " Little,\n"
7051 "};\n\n");7040 "};\n\n");
7052 assert(FloatModeOptimized == 0);7041 //assert(EndianBig == 0);
7053 assert(FloatModeStrict == 1);7042 //assert(EndianLittle == 1);
7054 }7043 }
7055 {7044 {
7056 const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";7045 const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
...@@ -7071,36 +7060,84 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7071,36 +7060,84 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7071 return contents;7060 return contents;
7072}7061}
70737062
7074static void define_builtin_compile_vars(CodeGen *g) {7063static Error define_builtin_compile_vars(CodeGen *g) {
7075 if (g->std_package == nullptr)7064 if (g->std_package == nullptr)
7076 return;7065 return ErrorNone;
70777066
7078 const char *builtin_zig_basename = "builtin.zig";7067 Error err;
7079 Buf *builtin_zig_path = buf_alloc();
7080 os_path_join(&g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
70817068
7082 Buf *contents = codegen_generate_builtin_source(g);7069 Buf *manifest_dir = buf_alloc();
7083 ensure_cache_dir(g);7070 os_path_join(get_stage1_cache_path(), buf_create_from_str("builtin"), manifest_dir);
7084 os_write_file(builtin_zig_path, contents);
70857071
7086 Buf *resolved_path = buf_alloc();7072 CacheHash cache_hash;
7087 Buf *resolve_paths[] = {builtin_zig_path};7073 cache_init(&cache_hash, manifest_dir);
7088 *resolved_path = os_path_resolve(resolve_paths, 1);7074
7075 Buf *compiler_id;
7076 if ((err = get_compiler_id(&compiler_id)))
7077 return err;
7078
7079 // Only a few things affect builtin.zig
7080 cache_buf(&cache_hash, compiler_id);
7081 cache_int(&cache_hash, g->build_mode);
7082 cache_bool(&cache_hash, g->is_test_build);
7083 cache_int(&cache_hash, g->zig_target.arch.arch);
7084 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
7085 cache_int(&cache_hash, g->zig_target.vendor);
7086 cache_int(&cache_hash, g->zig_target.os);
7087 cache_int(&cache_hash, g->zig_target.env_type);
7088 cache_int(&cache_hash, g->zig_target.oformat);
7089 cache_bool(&cache_hash, g->have_err_ret_tracing);
7090 cache_bool(&cache_hash, g->libc_link_lib != nullptr);
7091
7092 Buf digest = BUF_INIT;
7093 buf_resize(&digest, 0);
7094 if ((err = cache_hit(&cache_hash, &digest)))
7095 return err;
7096
7097 // We should always get a cache hit because there are no
7098 // files in the input hash.
7099 assert(buf_len(&digest) != 0);
7100
7101 Buf *this_dir = buf_alloc();
7102 os_path_join(manifest_dir, &digest, this_dir);
7103
7104 if ((err = os_make_path(this_dir)))
7105 return err;
7106
7107 const char *builtin_zig_basename = "builtin.zig";
7108 Buf *builtin_zig_path = buf_alloc();
7109 os_path_join(this_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
7110
7111 bool hit;
7112 if ((err = os_file_exists(builtin_zig_path, &hit)))
7113 return err;
7114 Buf *contents;
7115 if (hit) {
7116 contents = buf_alloc();
7117 if ((err = os_fetch_file_path(builtin_zig_path, contents, false))) {
7118 fprintf(stderr, "Unable to open '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
7119 exit(1);
7120 }
7121 } else {
7122 contents = codegen_generate_builtin_source(g);
7123 os_write_file(builtin_zig_path, contents);
7124 }
70897125
7090 assert(g->root_package);7126 assert(g->root_package);
7091 assert(g->std_package);7127 assert(g->std_package);
7092 g->compile_var_package = new_package(buf_ptr(&g->cache_dir), builtin_zig_basename);7128 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename);
7093 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);7129 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
7094 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);7130 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
7095 g->compile_var_import = add_source_file(g, g->compile_var_package, resolved_path, contents);7131 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents);
7096 scan_import(g, g->compile_var_import);7132 scan_import(g, g->compile_var_import);
7133
7134 return ErrorNone;
7097}7135}
70987136
7099static void init(CodeGen *g) {7137static void init(CodeGen *g) {
7100 if (g->module)7138 if (g->module)
7101 return;7139 return;
71027140
7103
7104 if (g->llvm_argv_len > 0) {7141 if (g->llvm_argv_len > 0) {
7105 const char **args = allocate_nonzero<const char *>(g->llvm_argv_len + 2);7142 const char **args = allocate_nonzero<const char *>(g->llvm_argv_len + 2);
7106 args[0] = "zig (LLVM option parsing)";7143 args[0] = "zig (LLVM option parsing)";
...@@ -7207,7 +7244,11 @@ static void init(CodeGen *g) {...@@ -7207,7 +7244,11 @@ static void init(CodeGen *g) {
7207 g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease;7244 g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease;
72087245
7209 define_builtin_fns(g);7246 define_builtin_fns(g);
7210 define_builtin_compile_vars(g);7247 Error err;
7248 if ((err = define_builtin_compile_vars(g))) {
7249 fprintf(stderr, "Unable to create builtin.zig: %s\n", err_str(err));
7250 exit(1);
7251 }
7211}7252}
72127253
7213void codegen_translate_c(CodeGen *g, Buf *full_path) {7254void codegen_translate_c(CodeGen *g, Buf *full_path) {
...@@ -7253,8 +7294,8 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package...@@ -7253,8 +7294,8 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
7253 Buf *resolved_path = buf_alloc();7294 Buf *resolved_path = buf_alloc();
7254 *resolved_path = os_path_resolve(resolve_paths, 1);7295 *resolved_path = os_path_resolve(resolve_paths, 1);
7255 Buf *import_code = buf_alloc();7296 Buf *import_code = buf_alloc();
7256 int err;7297 Error err;
7257 if ((err = os_fetch_file_path(resolved_path, import_code, false))) {7298 if ((err = file_fetch(g, resolved_path, import_code))) {
7258 zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));7299 zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
7259 }7300 }
72607301
...@@ -7327,23 +7368,32 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -7327,23 +7368,32 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
7327 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");7368 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");
7328}7369}
73297370
7330static void gen_root_source(CodeGen *g) {7371static Buf *get_resolved_root_src_path(CodeGen *g) {
7372 // TODO memoize
7331 if (buf_len(&g->root_package->root_src_path) == 0)7373 if (buf_len(&g->root_package->root_src_path) == 0)
7332 return;7374 return nullptr;
73337375
7334 codegen_add_time_event(g, "Semantic Analysis");7376 Buf rel_full_path = BUF_INIT;
73357377 os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, &rel_full_path);
7336 Buf *rel_full_path = buf_alloc();
7337 os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, rel_full_path);
73387378
7339 Buf *resolved_path = buf_alloc();7379 Buf *resolved_path = buf_alloc();
7340 Buf *resolve_paths[] = {rel_full_path};7380 Buf *resolve_paths[] = {&rel_full_path};
7341 *resolved_path = os_path_resolve(resolve_paths, 1);7381 *resolved_path = os_path_resolve(resolve_paths, 1);
73427382
7383 return resolved_path;
7384}
7385
7386static void gen_root_source(CodeGen *g) {
7387 Buf *resolved_path = get_resolved_root_src_path(g);
7388 if (resolved_path == nullptr)
7389 return;
7390
7343 Buf *source_code = buf_alloc();7391 Buf *source_code = buf_alloc();
7344 int err;7392 int err;
7345 if ((err = os_fetch_file_path(rel_full_path, source_code, true))) {7393 // No need for using the caching system for this file fetch because it is handled
7346 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));7394 // separately.
7395 if ((err = os_fetch_file_path(resolved_path, source_code, true))) {
7396 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));
7347 exit(1);7397 exit(1);
7348 }7398 }
73497399
...@@ -7408,6 +7458,8 @@ static void gen_global_asm(CodeGen *g) {...@@ -7408,6 +7458,8 @@ static void gen_global_asm(CodeGen *g) {
7408 int err;7458 int err;
7409 for (size_t i = 0; i < g->assembly_files.length; i += 1) {7459 for (size_t i = 0; i < g->assembly_files.length; i += 1) {
7410 Buf *asm_file = g->assembly_files.at(i);7460 Buf *asm_file = g->assembly_files.at(i);
7461 // No need to use the caching system for these fetches because they
7462 // are handled separately.
7411 if ((err = os_fetch_file_path(asm_file, &contents, false))) {7463 if ((err = os_fetch_file_path(asm_file, &contents, false))) {
7412 zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));7464 zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
7413 }7465 }
...@@ -7448,7 +7500,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e...@@ -7448,7 +7500,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
7448 case ZigTypeIdUndefined:7500 case ZigTypeIdUndefined:
7449 case ZigTypeIdNull:7501 case ZigTypeIdNull:
7450 case ZigTypeIdNamespace:7502 case ZigTypeIdNamespace:
7451 case ZigTypeIdBlock:
7452 case ZigTypeIdBoundFn:7503 case ZigTypeIdBoundFn:
7453 case ZigTypeIdArgTuple:7504 case ZigTypeIdArgTuple:
7454 case ZigTypeIdErrorUnion:7505 case ZigTypeIdErrorUnion:
...@@ -7627,7 +7678,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu...@@ -7627,7 +7678,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
7627 case ZigTypeIdMetaType:7678 case ZigTypeIdMetaType:
7628 case ZigTypeIdBoundFn:7679 case ZigTypeIdBoundFn:
7629 case ZigTypeIdNamespace:7680 case ZigTypeIdNamespace:
7630 case ZigTypeIdBlock:
7631 case ZigTypeIdComptimeFloat:7681 case ZigTypeIdComptimeFloat:
7632 case ZigTypeIdComptimeInt:7682 case ZigTypeIdComptimeInt:
7633 case ZigTypeIdUndefined:7683 case ZigTypeIdUndefined:
...@@ -7671,19 +7721,11 @@ static Buf *preprocessor_mangle(Buf *src) {...@@ -7671,19 +7721,11 @@ static Buf *preprocessor_mangle(Buf *src) {
7671}7721}
76727722
7673static void gen_h_file(CodeGen *g) {7723static void gen_h_file(CodeGen *g) {
7674 if (!g->want_h_file)
7675 return;
7676
7677 GenH gen_h_data = {0};7724 GenH gen_h_data = {0};
7678 GenH *gen_h = &gen_h_data;7725 GenH *gen_h = &gen_h_data;
76797726
7680 codegen_add_time_event(g, "Generate .h");
7681
7682 assert(!g->is_test_build);7727 assert(!g->is_test_build);
76837728 assert(g->out_h_path != nullptr);
7684 if (!g->out_h_path) {
7685 g->out_h_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
7686 }
76877729
7688 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");7730 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");
7689 if (!out_h)7731 if (!out_h)
...@@ -7788,7 +7830,6 @@ static void gen_h_file(CodeGen *g) {...@@ -7788,7 +7830,6 @@ static void gen_h_file(CodeGen *g) {
7788 case ZigTypeIdErrorUnion:7830 case ZigTypeIdErrorUnion:
7789 case ZigTypeIdErrorSet:7831 case ZigTypeIdErrorSet:
7790 case ZigTypeIdNamespace:7832 case ZigTypeIdNamespace:
7791 case ZigTypeIdBlock:
7792 case ZigTypeIdBoundFn:7833 case ZigTypeIdBoundFn:
7793 case ZigTypeIdArgTuple:7834 case ZigTypeIdArgTuple:
7794 case ZigTypeIdOptional:7835 case ZigTypeIdOptional:
...@@ -7886,14 +7927,231 @@ void codegen_add_time_event(CodeGen *g, const char *name) {...@@ -7886,14 +7927,231 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
7886 g->timing_events.append({os_get_time(), name});7927 g->timing_events.append({os_get_time(), name});
7887}7928}
78887929
7889void codegen_build(CodeGen *g) {7930static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
7931 if (buf_len(&pkg->root_src_path) == 0)
7932 return;
7933
7934 Buf *rel_full_path = buf_alloc();
7935 os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);
7936 cache_file(ch, rel_full_path);
7937
7938 auto it = pkg->package_table.entry_iterator();
7939 for (;;) {
7940 auto *entry = it.next();
7941 if (!entry)
7942 break;
7943
7944 cache_buf(ch, entry->key);
7945 add_cache_pkg(g, ch, entry->value);
7946 }
7947}
7948
7949// Called before init()
7950static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
7951 Error err;
7952
7953 Buf *compiler_id;
7954 if ((err = get_compiler_id(&compiler_id)))
7955 return err;
7956
7957 CacheHash *ch = &g->cache_hash;
7958 cache_init(ch, manifest_dir);
7959
7960 add_cache_pkg(g, ch, g->root_package);
7961 if (g->linker_script != nullptr) {
7962 cache_file(ch, buf_create_from_str(g->linker_script));
7963 }
7964 cache_buf(ch, compiler_id);
7965 cache_buf(ch, g->root_out_name);
7966 cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
7967 cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
7968 cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
7969 cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);
7970 cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
7971 cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length);
7972 cache_int(ch, g->emit_file_type);
7973 cache_int(ch, g->build_mode);
7974 cache_int(ch, g->out_type);
7975 cache_int(ch, g->zig_target.arch.arch);
7976 cache_int(ch, g->zig_target.arch.sub_arch);
7977 cache_int(ch, g->zig_target.vendor);
7978 cache_int(ch, g->zig_target.os);
7979 cache_int(ch, g->zig_target.env_type);
7980 cache_int(ch, g->zig_target.oformat);
7981 cache_bool(ch, g->is_static);
7982 cache_bool(ch, g->strip_debug_symbols);
7983 cache_bool(ch, g->is_test_build);
7984 cache_bool(ch, g->is_native_target);
7985 cache_bool(ch, g->windows_subsystem_windows);
7986 cache_bool(ch, g->windows_subsystem_console);
7987 cache_bool(ch, g->linker_rdynamic);
7988 cache_bool(ch, g->no_rosegment_workaround);
7989 cache_bool(ch, g->each_lib_rpath);
7990 cache_buf_opt(ch, g->mmacosx_version_min);
7991 cache_buf_opt(ch, g->mios_version_min);
7992 cache_usize(ch, g->version_major);
7993 cache_usize(ch, g->version_minor);
7994 cache_usize(ch, g->version_patch);
7995 cache_buf_opt(ch, g->test_filter);
7996 cache_buf_opt(ch, g->test_name_prefix);
7997 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
7998 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
7999 cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
8000
8001 buf_resize(digest, 0);
8002 if ((err = cache_hit(ch, digest)))
8003 return err;
8004
8005 return ErrorNone;
8006}
8007
8008static void resolve_out_paths(CodeGen *g) {
8009 Buf *o_basename = buf_create_from_buf(g->root_out_name);
8010
8011 switch (g->emit_file_type) {
8012 case EmitFileTypeBinary:
8013 {
8014 const char *o_ext = target_o_file_ext(&g->zig_target);
8015 buf_append_str(o_basename, o_ext);
8016 break;
8017 }
8018 case EmitFileTypeAssembly:
8019 {
8020 const char *asm_ext = target_asm_file_ext(&g->zig_target);
8021 buf_append_str(o_basename, asm_ext);
8022 break;
8023 }
8024 case EmitFileTypeLLVMIr:
8025 {
8026 const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
8027 buf_append_str(o_basename, llvm_ir_ext);
8028 break;
8029 }
8030 default:
8031 zig_unreachable();
8032 }
8033
8034 if (g->enable_cache || g->out_type != OutTypeObj) {
8035 os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path);
8036 } else if (g->wanted_output_file_path != nullptr && g->out_type == OutTypeObj) {
8037 buf_init_from_buf(&g->o_file_output_path, g->wanted_output_file_path);
8038 } else {
8039 buf_init_from_buf(&g->o_file_output_path, o_basename);
8040 }
8041
8042 if (g->out_type == OutTypeObj) {
8043 buf_init_from_buf(&g->output_file_path, &g->o_file_output_path);
8044 } else if (g->out_type == OutTypeExe) {
8045 if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
8046 buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
8047 } else {
8048 assert(g->root_out_name);
8049
8050 Buf basename = BUF_INIT;
8051 buf_init_from_buf(&basename, g->root_out_name);
8052 buf_append_str(&basename, target_exe_file_ext(&g->zig_target));
8053 if (g->enable_cache || g->is_test_build) {
8054 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
8055 } else {
8056 buf_init_from_buf(&g->output_file_path, &basename);
8057 }
8058 }
8059 } else if (g->out_type == OutTypeLib) {
8060 if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
8061 buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
8062 } else {
8063 Buf basename = BUF_INIT;
8064 buf_init_from_buf(&basename, g->root_out_name);
8065 buf_append_str(&basename, target_lib_file_ext(&g->zig_target, g->is_static,
8066 g->version_major, g->version_minor, g->version_patch));
8067 if (g->enable_cache) {
8068 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
8069 } else {
8070 buf_init_from_buf(&g->output_file_path, &basename);
8071 }
8072 }
8073 } else {
8074 zig_unreachable();
8075 }
8076
8077 if (g->want_h_file && !g->out_h_path) {
8078 assert(g->root_out_name);
8079 Buf *h_basename = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
8080 if (g->enable_cache) {
8081 g->out_h_path = buf_alloc();
8082 os_path_join(&g->artifact_dir, h_basename, g->out_h_path);
8083 } else {
8084 g->out_h_path = h_basename;
8085 }
8086 }
8087}
8088
8089
8090void codegen_build_and_link(CodeGen *g) {
8091 Error err;
7890 assert(g->out_type != OutTypeUnknown);8092 assert(g->out_type != OutTypeUnknown);
7891 init(g);
78928093
7893 gen_global_asm(g);8094 Buf *stage1_dir = get_stage1_cache_path();
7894 gen_root_source(g);8095 Buf *artifact_dir = buf_alloc();
7895 do_code_gen(g);8096 Buf digest = BUF_INIT;
7896 gen_h_file(g);8097 if (g->enable_cache) {
8098 codegen_add_time_event(g, "Check Cache");
8099
8100 Buf *manifest_dir = buf_alloc();
8101 os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);
8102
8103 if ((err = check_cache(g, manifest_dir, &digest))) {
8104 fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
8105 exit(1);
8106 }
8107
8108 os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir);
8109 }
8110
8111 if (g->enable_cache && buf_len(&digest) != 0) {
8112 os_path_join(artifact_dir, &digest, &g->artifact_dir);
8113 resolve_out_paths(g);
8114 } else {
8115 init(g);
8116
8117 codegen_add_time_event(g, "Semantic Analysis");
8118
8119 gen_global_asm(g);
8120 gen_root_source(g);
8121
8122 if (g->enable_cache) {
8123 if ((err = cache_final(&g->cache_hash, &digest))) {
8124 fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err));
8125 exit(1);
8126 }
8127 os_path_join(artifact_dir, &digest, &g->artifact_dir);
8128 } else {
8129 buf_init_from_buf(&g->artifact_dir, &g->cache_dir);
8130 }
8131 if ((err = os_make_path(&g->artifact_dir))) {
8132 fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err));
8133 exit(1);
8134 }
8135 resolve_out_paths(g);
8136
8137 codegen_add_time_event(g, "Code Generation");
8138 do_code_gen(g);
8139 codegen_add_time_event(g, "LLVM Emit Output");
8140 zig_llvm_emit_output(g);
8141
8142 if (g->want_h_file) {
8143 codegen_add_time_event(g, "Generate .h");
8144 gen_h_file(g);
8145 }
8146 if (g->out_type != OutTypeObj) {
8147 codegen_link(g);
8148 }
8149 }
8150
8151 if (g->enable_cache) {
8152 cache_release(&g->cache_hash);
8153 }
8154 codegen_add_time_event(g, "Done");
7897}8155}
78988156
7899PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path) {8157PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path) {
src/codegen.hpp+3-3
...@@ -16,7 +16,6 @@...@@ -16,7 +16,6 @@
1616
17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
18 Buf *zig_lib_dir);18 Buf *zig_lib_dir);
19void codegen_destroy(CodeGen *codegen);
2019
21void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);20void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
22void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);21void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
...@@ -47,11 +46,12 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);...@@ -47,11 +46,12 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
47void codegen_set_test_filter(CodeGen *g, Buf *filter);46void codegen_set_test_filter(CodeGen *g, Buf *filter);
48void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);47void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);48void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
50void codegen_set_cache_dir(CodeGen *g, Buf cache_dir);
51void codegen_set_output_h_path(CodeGen *g, Buf *h_path);49void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
50void codegen_set_output_path(CodeGen *g, Buf *path);
52void codegen_add_time_event(CodeGen *g, const char *name);51void codegen_add_time_event(CodeGen *g, const char *name);
53void codegen_print_timing_report(CodeGen *g, FILE *f);52void codegen_print_timing_report(CodeGen *g, FILE *f);
54void codegen_build(CodeGen *g);53void codegen_link(CodeGen *g);
54void codegen_build_and_link(CodeGen *g);
5555
56PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path);56PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path);
57void codegen_add_assembly(CodeGen *g, Buf *path);57void codegen_add_assembly(CodeGen *g, Buf *path);
src/compiler.cpp created+66
...@@ -0,0 +1,66 @@
1#include "cache_hash.hpp"
2
3#include <stdio.h>
4
5static Buf saved_compiler_id = BUF_INIT;
6static Buf saved_app_data_dir = BUF_INIT;
7static Buf saved_stage1_path = BUF_INIT;
8
9Buf *get_stage1_cache_path() {
10 if (saved_stage1_path.list.length != 0) {
11 return &saved_stage1_path;
12 }
13 Error err;
14 if ((err = os_get_app_data_dir(&saved_app_data_dir, "zig"))) {
15 fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err));
16 exit(1);
17 }
18 os_path_join(&saved_app_data_dir, buf_create_from_str("stage1"), &saved_stage1_path);
19 return &saved_stage1_path;
20}
21
22Error get_compiler_id(Buf **result) {
23 if (saved_compiler_id.list.length != 0) {
24 *result = &saved_compiler_id;
25 return ErrorNone;
26 }
27
28 Error err;
29 Buf *stage1_dir = get_stage1_cache_path();
30 Buf *manifest_dir = buf_alloc();
31 os_path_join(stage1_dir, buf_create_from_str("exe"), manifest_dir);
32
33 CacheHash cache_hash;
34 CacheHash *ch = &cache_hash;
35 cache_init(ch, manifest_dir);
36 Buf self_exe_path = BUF_INIT;
37 if ((err = os_self_exe_path(&self_exe_path)))
38 return err;
39
40 cache_file(ch, &self_exe_path);
41
42 buf_resize(&saved_compiler_id, 0);
43 if ((err = cache_hit(ch, &saved_compiler_id)))
44 return err;
45 if (buf_len(&saved_compiler_id) != 0) {
46 cache_release(ch);
47 *result = &saved_compiler_id;
48 return ErrorNone;
49 }
50 ZigList<Buf *> lib_paths = {};
51 if ((err = os_self_exe_shared_libs(lib_paths)))
52 return err;
53 for (size_t i = 0; i < lib_paths.length; i += 1) {
54 Buf *lib_path = lib_paths.at(i);
55 if ((err = cache_add_file(ch, lib_path)))
56 return err;
57 }
58 if ((err = cache_final(ch, &saved_compiler_id)))
59 return err;
60
61 cache_release(ch);
62
63 *result = &saved_compiler_id;
64 return ErrorNone;
65}
66
src/compiler.hpp created+17
...@@ -0,0 +1,17 @@
1/*
2 * Copyright (c) 2018 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_COMPILER_HPP
9#define ZIG_COMPILER_HPP
10
11#include "buffer.hpp"
12#include "error.hpp"
13
14Buf *get_stage1_cache_path();
15Error get_compiler_id(Buf **result);
16
17#endif
src/error.cpp+5
...@@ -27,6 +27,11 @@ const char *err_str(int err) {...@@ -27,6 +27,11 @@ const char *err_str(int err) {
27 case ErrorNegativeDenominator: return "negative denominator";27 case ErrorNegativeDenominator: return "negative denominator";
28 case ErrorShiftedOutOneBits: return "exact shift shifted out one bits";28 case ErrorShiftedOutOneBits: return "exact shift shifted out one bits";
29 case ErrorCCompileErrors: return "C compile errors";29 case ErrorCCompileErrors: return "C compile errors";
30 case ErrorEndOfFile: return "end of file";
31 case ErrorIsDir: return "is directory";
32 case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
33 case ErrorSharingViolation: return "sharing violation";
34 case ErrorPipeBusy: return "pipe busy";
30 }35 }
31 return "(invalid error)";36 return "(invalid error)";
32}37}
src/error.hpp+5
...@@ -27,6 +27,11 @@ enum Error {...@@ -27,6 +27,11 @@ enum Error {
27 ErrorNegativeDenominator,27 ErrorNegativeDenominator,
28 ErrorShiftedOutOneBits,28 ErrorShiftedOutOneBits,
29 ErrorCCompileErrors,29 ErrorCCompileErrors,
30 ErrorEndOfFile,
31 ErrorIsDir,
32 ErrorUnsupportedOperatingSystem,
33 ErrorSharingViolation,
34 ErrorPipeBusy,
30};35};
3136
32const char *err_str(int err);37const char *err_str(int err);
src/ir.cpp+352-233
...@@ -40,6 +40,7 @@ struct IrAnalyze {...@@ -40,6 +40,7 @@ struct IrAnalyze {
4040
41enum ConstCastResultId {41enum ConstCastResultId {
42 ConstCastResultIdOk,42 ConstCastResultIdOk,
43 ConstCastResultIdInvalid,
43 ConstCastResultIdErrSet,44 ConstCastResultIdErrSet,
44 ConstCastResultIdErrSetGlobal,45 ConstCastResultIdErrSetGlobal,
45 ConstCastResultIdPointerChild,46 ConstCastResultIdPointerChild,
...@@ -1029,12 +1030,6 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *...@@ -1029,12 +1030,6 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *
1029 return &const_instruction->base;1030 return &const_instruction->base;
1030}1031}
10311032
1032static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigFn *fn_entry) {
1033 IrInstruction *instruction = ir_create_const_fn(irb, scope, source_node, fn_entry);
1034 ir_instruction_append(irb->current_basic_block, instruction);
1035 return instruction;
1036}
1037
1038static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) {1033static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) {
1039 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);1034 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
1040 const_instruction->base.value.type = irb->codegen->builtin_types.entry_namespace;1035 const_instruction->base.value.type = irb->codegen->builtin_types.entry_namespace;
...@@ -1043,16 +1038,6 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNod...@@ -1043,16 +1038,6 @@ static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNod
1043 return &const_instruction->base;1038 return &const_instruction->base;
1044}1039}
10451040
1046static IrInstruction *ir_build_const_scope(IrBuilder *irb, Scope *parent_scope, AstNode *source_node,
1047 Scope *target_scope)
1048{
1049 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, parent_scope, source_node);
1050 const_instruction->base.value.type = irb->codegen->builtin_types.entry_block;
1051 const_instruction->base.value.special = ConstValSpecialStatic;
1052 const_instruction->base.value.data.x_block = target_scope;
1053 return &const_instruction->base;
1054}
1055
1056static IrInstruction *ir_build_const_bool(IrBuilder *irb, Scope *scope, AstNode *source_node, bool value) {1041static IrInstruction *ir_build_const_bool(IrBuilder *irb, Scope *scope, AstNode *source_node, bool value) {
1057 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);1042 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
1058 const_instruction->base.value.type = irb->codegen->builtin_types.entry_bool;1043 const_instruction->base.value.type = irb->codegen->builtin_types.entry_bool;
...@@ -1577,13 +1562,11 @@ static IrInstruction *ir_build_set_runtime_safety(IrBuilder *irb, Scope *scope,...@@ -1577,13 +1562,11 @@ static IrInstruction *ir_build_set_runtime_safety(IrBuilder *irb, Scope *scope,
1577}1562}
15781563
1579static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node,1564static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node,
1580 IrInstruction *scope_value, IrInstruction *mode_value)1565 IrInstruction *mode_value)
1581{1566{
1582 IrInstructionSetFloatMode *instruction = ir_build_instruction<IrInstructionSetFloatMode>(irb, scope, source_node);1567 IrInstructionSetFloatMode *instruction = ir_build_instruction<IrInstructionSetFloatMode>(irb, scope, source_node);
1583 instruction->scope_value = scope_value;
1584 instruction->mode_value = mode_value;1568 instruction->mode_value = mode_value;
15851569
1586 ir_ref_instruction(scope_value, irb->current_basic_block);
1587 ir_ref_instruction(mode_value, irb->current_basic_block);1570 ir_ref_instruction(mode_value, irb->current_basic_block);
15881571
1589 return &instruction->base;1572 return &instruction->base;
...@@ -3894,6 +3877,21 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *...@@ -3894,6 +3877,21 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *
3894 return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);3877 return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);
3895}3878}
38963879
3880static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *node) {
3881 for (Scope *it_scope = orig_scope; it_scope != nullptr; it_scope = it_scope->parent) {
3882 if (it_scope->id == ScopeIdDecls) {
3883 ScopeDecls *decls_scope = (ScopeDecls *)it_scope;
3884 ZigType *container_type = decls_scope->container_type;
3885 if (container_type != nullptr) {
3886 return ir_build_const_type(irb, orig_scope, node, container_type);
3887 } else {
3888 return ir_build_const_import(irb, orig_scope, node, decls_scope->import);
3889 }
3890 }
3891 }
3892 zig_unreachable();
3893}
3894
3897static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {3895static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
3898 assert(node->type == NodeTypeFnCallExpr);3896 assert(node->type == NodeTypeFnCallExpr);
38993897
...@@ -3959,12 +3957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3959,12 +3957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3959 if (arg0_value == irb->codegen->invalid_instruction)3957 if (arg0_value == irb->codegen->invalid_instruction)
3960 return arg0_value;3958 return arg0_value;
39613959
3962 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);3960 IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);
3963 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
3964 if (arg1_value == irb->codegen->invalid_instruction)
3965 return arg1_value;
3966
3967 IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value, arg1_value);
3968 return ir_lval_wrap(irb, scope, set_float_mode, lval);3961 return ir_lval_wrap(irb, scope, set_float_mode, lval);
3969 }3962 }
3970 case BuiltinFnIdSizeof:3963 case BuiltinFnIdSizeof:
...@@ -4837,6 +4830,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4837,6 +4830,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4837 IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);4830 IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);
4838 return ir_lval_wrap(irb, scope, opaque_type, lval);4831 return ir_lval_wrap(irb, scope, opaque_type, lval);
4839 }4832 }
4833 case BuiltinFnIdThis:
4834 {
4835 IrInstruction *this_inst = ir_gen_this(irb, scope, node);
4836 return ir_lval_wrap(irb, scope, this_inst, lval);
4837 }
4840 case BuiltinFnIdSetAlignStack:4838 case BuiltinFnIdSetAlignStack:
4841 {4839 {
4842 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4840 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -5688,33 +5686,6 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5688,33 +5686,6 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5688 return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);5686 return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
5689}5687}
56905688
5691static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
5692 assert(node->type == NodeTypeThisLiteral);
5693
5694 if (!scope->parent)
5695 return ir_build_const_import(irb, scope, node, node->owner);
5696
5697 ZigFn *fn_entry = scope_get_fn_if_root(scope);
5698 if (fn_entry)
5699 return ir_build_const_fn(irb, scope, node, fn_entry);
5700
5701 while (scope->id != ScopeIdBlock && scope->id != ScopeIdDecls) {
5702 scope = scope->parent;
5703 }
5704
5705 if (scope->id == ScopeIdDecls) {
5706 ScopeDecls *decls_scope = (ScopeDecls *)scope;
5707 ZigType *container_type = decls_scope->container_type;
5708 assert(container_type);
5709 return ir_build_const_type(irb, scope, node, container_type);
5710 }
5711
5712 if (scope->id == ScopeIdBlock)
5713 return ir_build_const_scope(irb, scope, node, scope);
5714
5715 zig_unreachable();
5716}
5717
5718static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {5689static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
5719 assert(node->type == NodeTypeBoolLiteral);5690 assert(node->type == NodeTypeBoolLiteral);
5720 return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value);5691 return ir_build_const_bool(irb, scope, node, node->data.bool_literal.value);
...@@ -7292,8 +7263,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7292,8 +7263,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
72927263
7293 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);7264 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
7294 }7265 }
7295 case NodeTypeThisLiteral:
7296 return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
7297 case NodeTypeBoolLiteral:7266 case NodeTypeBoolLiteral:
7298 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);7267 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
7299 case NodeTypeArrayType:7268 case NodeTypeArrayType:
...@@ -7522,8 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7522,8 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7522 if (type_has_bits(return_type)) {7491 if (type_has_bits(return_type)) {
7523 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7492 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7524 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7493 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7525 false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),7494 false, false, PtrLenUnknown, 0, 0, 0));
7526 0, 0));
7527 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7495 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7528 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);7496 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7529 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,7497 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
...@@ -7576,8 +7544,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7576,8 +7544,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7576 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);7544 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
7577 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7545 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7578 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7546 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7579 false, false, PtrLenUnknown, get_abi_alignment(irb->codegen, irb->codegen->builtin_types.entry_u8),7547 false, false, PtrLenUnknown, 0, 0, 0));
7580 0, 0));
7581 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);7548 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
7582 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7549 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7583 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7550 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
...@@ -8548,6 +8515,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8548,6 +8515,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8548 ConstCastOnly result = {};8515 ConstCastOnly result = {};
8549 result.id = ConstCastResultIdOk;8516 result.id = ConstCastResultIdOk;
85508517
8518 Error err;
8519
8551 if (wanted_type == actual_type)8520 if (wanted_type == actual_type)
8552 return result;8521 return result;
85538522
...@@ -8560,6 +8529,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8560,6 +8529,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8560 {8529 {
8561 ConstCastOnly child = types_match_const_cast_only(ira,8530 ConstCastOnly child = types_match_const_cast_only(ira,
8562 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);8531 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
8532 if (child.id == ConstCastResultIdInvalid)
8533 return child;
8563 if (child.id != ConstCastResultIdOk) {8534 if (child.id != ConstCastResultIdOk) {
8564 result.id = ConstCastResultIdNullWrapPtr;8535 result.id = ConstCastResultIdNullWrapPtr;
8565 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);8536 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
...@@ -8576,7 +8547,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8576,7 +8547,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8576 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&8547 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8577 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))8548 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
8578 {8549 {
8579 assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment);
8580 return result;8550 return result;
8581 }8551 }
85828552
...@@ -8584,6 +8554,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8584,6 +8554,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8584 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {8554 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
8585 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,8555 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8586 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);8556 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8557 if (child.id == ConstCastResultIdInvalid)
8558 return child;
8587 if (child.id != ConstCastResultIdOk) {8559 if (child.id != ConstCastResultIdOk) {
8588 result.id = ConstCastResultIdPointerChild;8560 result.id = ConstCastResultIdPointerChild;
8589 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);8561 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
...@@ -8592,12 +8564,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8592,12 +8564,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8592 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;8564 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8593 return result;8565 return result;
8594 }8566 }
8567 if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8568 result.id = ConstCastResultIdInvalid;
8569 return result;
8570 }
8571 if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8572 result.id = ConstCastResultIdInvalid;
8573 return result;
8574 }
8595 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&8575 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8596 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&8576 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8597 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&8577 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8598 actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&8578 actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
8599 actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&8579 actual_type->data.pointer.unaligned_bit_count == wanted_type->data.pointer.unaligned_bit_count &&
8600 actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment)8580 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
8601 {8581 {
8602 return result;8582 return result;
8603 }8583 }
...@@ -8607,14 +8587,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8607,14 +8587,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8607 if (is_slice(wanted_type) && is_slice(actual_type)) {8587 if (is_slice(wanted_type) && is_slice(actual_type)) {
8608 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;8588 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
8609 ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;8589 ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
8590 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8591 result.id = ConstCastResultIdInvalid;
8592 return result;
8593 }
8594 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8595 result.id = ConstCastResultIdInvalid;
8596 return result;
8597 }
8610 if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&8598 if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8611 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&8599 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8612 actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset &&8600 actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset &&
8613 actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count &&8601 actual_ptr_type->data.pointer.unaligned_bit_count == wanted_ptr_type->data.pointer.unaligned_bit_count &&
8614 actual_ptr_type->data.pointer.alignment >= wanted_ptr_type->data.pointer.alignment)8602 get_ptr_align(g, actual_ptr_type) >= get_ptr_align(g, wanted_ptr_type))
8615 {8603 {
8616 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,8604 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8617 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);8605 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
8606 if (child.id == ConstCastResultIdInvalid)
8607 return child;
8618 if (child.id != ConstCastResultIdOk) {8608 if (child.id != ConstCastResultIdOk) {
8619 result.id = ConstCastResultIdSliceChild;8609 result.id = ConstCastResultIdSliceChild;
8620 result.data.slice_mismatch = allocate_nonzero<ConstCastSliceMismatch>(1);8610 result.data.slice_mismatch = allocate_nonzero<ConstCastSliceMismatch>(1);
...@@ -8630,6 +8620,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8630,6 +8620,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8630 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {8620 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
8631 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,8621 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
8632 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);8622 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
8623 if (child.id == ConstCastResultIdInvalid)
8624 return child;
8633 if (child.id != ConstCastResultIdOk) {8625 if (child.id != ConstCastResultIdOk) {
8634 result.id = ConstCastResultIdOptionalChild;8626 result.id = ConstCastResultIdOptionalChild;
8635 result.data.optional = allocate_nonzero<ConstCastOptionalMismatch>(1);8627 result.data.optional = allocate_nonzero<ConstCastOptionalMismatch>(1);
...@@ -8644,6 +8636,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8644,6 +8636,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8644 if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) {8636 if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) {
8645 ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type,8637 ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type,
8646 actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);8638 actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);
8639 if (payload_child.id == ConstCastResultIdInvalid)
8640 return payload_child;
8647 if (payload_child.id != ConstCastResultIdOk) {8641 if (payload_child.id != ConstCastResultIdOk) {
8648 result.id = ConstCastResultIdErrorUnionPayload;8642 result.id = ConstCastResultIdErrorUnionPayload;
8649 result.data.error_union_payload = allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);8643 result.data.error_union_payload = allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);
...@@ -8654,6 +8648,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8654,6 +8648,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8654 }8648 }
8655 ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,8649 ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,
8656 actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable);8650 actual_type->data.error_union.err_set_type, source_node, wanted_is_mutable);
8651 if (error_set_child.id == ConstCastResultIdInvalid)
8652 return error_set_child;
8657 if (error_set_child.id != ConstCastResultIdOk) {8653 if (error_set_child.id != ConstCastResultIdOk) {
8658 result.id = ConstCastResultIdErrorUnionErrorSet;8654 result.id = ConstCastResultIdErrorUnionErrorSet;
8659 result.data.error_union_error_set = allocate_nonzero<ConstCastErrUnionErrSetMismatch>(1);8655 result.data.error_union_error_set = allocate_nonzero<ConstCastErrUnionErrSetMismatch>(1);
...@@ -8741,6 +8737,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8741,6 +8737,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8741 {8737 {
8742 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type,8738 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type,
8743 actual_type->data.fn.fn_type_id.return_type, source_node, false);8739 actual_type->data.fn.fn_type_id.return_type, source_node, false);
8740 if (child.id == ConstCastResultIdInvalid)
8741 return child;
8744 if (child.id != ConstCastResultIdOk) {8742 if (child.id != ConstCastResultIdOk) {
8745 result.id = ConstCastResultIdFnReturnType;8743 result.id = ConstCastResultIdFnReturnType;
8746 result.data.return_type = allocate_nonzero<ConstCastOnly>(1);8744 result.data.return_type = allocate_nonzero<ConstCastOnly>(1);
...@@ -8753,6 +8751,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8753,6 +8751,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8753 actual_type->data.fn.fn_type_id.async_allocator_type,8751 actual_type->data.fn.fn_type_id.async_allocator_type,
8754 wanted_type->data.fn.fn_type_id.async_allocator_type,8752 wanted_type->data.fn.fn_type_id.async_allocator_type,
8755 source_node, false);8753 source_node, false);
8754 if (child.id == ConstCastResultIdInvalid)
8755 return child;
8756 if (child.id != ConstCastResultIdOk) {8756 if (child.id != ConstCastResultIdOk) {
8757 result.id = ConstCastResultIdAsyncAllocatorType;8757 result.id = ConstCastResultIdAsyncAllocatorType;
8758 result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);8758 result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);
...@@ -8777,6 +8777,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8777,6 +8777,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
87778777
8778 ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type,8778 ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type,
8779 expected_param_info->type, source_node, false);8779 expected_param_info->type, source_node, false);
8780 if (arg_child.id == ConstCastResultIdInvalid)
8781 return arg_child;
8780 if (arg_child.id != ConstCastResultIdOk) {8782 if (arg_child.id != ConstCastResultIdOk) {
8781 result.id = ConstCastResultIdFnArg;8783 result.id = ConstCastResultIdFnArg;
8782 result.data.fn_arg.arg_index = i;8784 result.data.fn_arg.arg_index = i;
...@@ -9270,7 +9272,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9270,7 +9272,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9270 if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdUnion &&9272 if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdUnion &&
9271 (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))9273 (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
9272 {9274 {
9273 if ((err = type_ensure_zero_bits_known(ira->codegen, cur_type)))9275 if ((err = type_resolve(ira->codegen, cur_type, ResolveStatusZeroBitsKnown)))
9274 return ira->codegen->builtin_types.entry_invalid;9276 return ira->codegen->builtin_types.entry_invalid;
9275 if (cur_type->data.unionation.tag_type == prev_type) {9277 if (cur_type->data.unionation.tag_type == prev_type) {
9276 continue;9278 continue;
...@@ -9280,7 +9282,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9280,7 +9282,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9280 if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdUnion &&9282 if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdUnion &&
9281 (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))9283 (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
9282 {9284 {
9283 if ((err = type_ensure_zero_bits_known(ira->codegen, prev_type)))9285 if ((err = type_resolve(ira->codegen, prev_type, ResolveStatusZeroBitsKnown)))
9284 return ira->codegen->builtin_types.entry_invalid;9286 return ira->codegen->builtin_types.entry_invalid;
9285 if (prev_type->data.unionation.tag_type == cur_type) {9287 if (prev_type->data.unionation.tag_type == cur_type) {
9286 prev_inst = cur_inst;9288 prev_inst = cur_inst;
...@@ -9306,8 +9308,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -9306,8 +9308,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
9306 ZigType *ptr_type = get_pointer_to_type_extra(9308 ZigType *ptr_type = get_pointer_to_type_extra(
9307 ira->codegen, prev_inst->value.type->data.array.child_type,9309 ira->codegen, prev_inst->value.type->data.array.child_type,
9308 true, false, PtrLenUnknown,9310 true, false, PtrLenUnknown,
9309 get_abi_alignment(ira->codegen, prev_inst->value.type->data.array.child_type),9311 0, 0, 0);
9310 0, 0);
9311 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);9312 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
9312 if (err_set_type != nullptr) {9313 if (err_set_type != nullptr) {
9313 return get_error_union_type(ira->codegen, err_set_type, slice_type);9314 return get_error_union_type(ira->codegen, err_set_type, slice_type);
...@@ -9504,7 +9505,16 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -9504,7 +9505,16 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
9504 IrInstruction *value, ZigType *wanted_type)9505 IrInstruction *value, ZigType *wanted_type)
9505{9506{
9506 assert(value->value.type->id == ZigTypeIdPointer);9507 assert(value->value.type->id == ZigTypeIdPointer);
9507 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);9508
9509 Error err;
9510
9511 if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
9512 ResolveStatusAlignmentKnown)))
9513 {
9514 return ira->codegen->invalid_instruction;
9515 }
9516
9517 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
95089518
9509 if (instr_is_comptime(value)) {9519 if (instr_is_comptime(value)) {
9510 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);9520 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
...@@ -9532,7 +9542,15 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -9532,7 +9542,15 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
9532static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,9542static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
9533 IrInstruction *value, ZigType *wanted_type)9543 IrInstruction *value, ZigType *wanted_type)
9534{9544{
9535 wanted_type = adjust_slice_align(ira->codegen, wanted_type, value->value.type->data.pointer.alignment);9545 Error err;
9546
9547 if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
9548 ResolveStatusAlignmentKnown)))
9549 {
9550 return ira->codegen->invalid_instruction;
9551 }
9552
9553 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
95369554
9537 if (instr_is_comptime(value)) {9555 if (instr_is_comptime(value)) {
9538 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);9556 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);
...@@ -9719,8 +9737,7 @@ static ZigType *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -9719,8 +9737,7 @@ static ZigType *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,
9719 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile)9737 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile)
9720{9738{
9721 IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee,9739 IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee,
9722 pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile,9740 pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, 0);
9723 get_abi_alignment(ira->codegen, pointee_type));
9724 ir_link_new_instruction(const_instr, instruction);9741 ir_link_new_instruction(const_instr, instruction);
9725 return const_instr->value.type;9742 return const_instr->value.type;
9726}9743}
...@@ -10037,20 +10054,24 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so...@@ -10037,20 +10054,24 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
10037static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,10054static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
10038 bool is_const, bool is_volatile)10055 bool is_const, bool is_volatile)
10039{10056{
10057 Error err;
10058
10040 if (type_is_invalid(value->value.type))10059 if (type_is_invalid(value->value.type))
10041 return ira->codegen->invalid_instruction;10060 return ira->codegen->invalid_instruction;
1004210061
10062 if ((err = type_resolve(ira->codegen, value->value.type, ResolveStatusZeroBitsKnown)))
10063 return ira->codegen->invalid_instruction;
10064
10043 if (instr_is_comptime(value)) {10065 if (instr_is_comptime(value)) {
10044 ConstExprValue *val = ir_resolve_const(ira, value, UndefOk);10066 ConstExprValue *val = ir_resolve_const(ira, value, UndefOk);
10045 if (!val)10067 if (!val)
10046 return ira->codegen->invalid_instruction;10068 return ira->codegen->invalid_instruction;
10047 return ir_get_const_ptr(ira, source_instruction, val, value->value.type,10069 return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
10048 ConstPtrMutComptimeConst, is_const, is_volatile,10070 ConstPtrMutComptimeConst, is_const, is_volatile, 0);
10049 get_abi_alignment(ira->codegen, value->value.type));
10050 }10071 }
1005110072
10052 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,10073 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type,
10053 is_const, is_volatile, PtrLenSingle, get_abi_alignment(ira->codegen, value->value.type), 0, 0);10074 is_const, is_volatile, PtrLenSingle, 0, 0, 0);
10054 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,10075 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
10055 source_instruction->source_node, value, is_const, is_volatile);10076 source_instruction->source_node, value, is_const, is_volatile);
10056 new_instruction->value.type = ptr_type;10077 new_instruction->value.type = ptr_type;
...@@ -10113,7 +10134,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10113,7 +10134,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10113 IrInstruction *target, ZigType *wanted_type)10134 IrInstruction *target, ZigType *wanted_type)
10114{10135{
10115 Error err;10136 Error err;
10116 assert(wanted_type->id == ZigTypeIdInt);10137 assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt);
1011710138
10118 ZigType *actual_type = target->value.type;10139 ZigType *actual_type = target->value.type;
10119 if ((err = ensure_complete_type(ira->codegen, actual_type)))10140 if ((err = ensure_complete_type(ira->codegen, actual_type)))
...@@ -10139,6 +10160,18 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10139,6 +10160,18 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10139 return result;10160 return result;
10140 }10161 }
1014110162
10163 // If there is only one possible tag, then we know at comptime what it is.
10164 if (actual_type->data.enumeration.layout == ContainerLayoutAuto &&
10165 actual_type->data.enumeration.src_field_count == 1)
10166 {
10167 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10168 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10169 source_instr->source_node, wanted_type);
10170 init_const_bigint(&result->value, wanted_type,
10171 &actual_type->data.enumeration.fields[0].value);
10172 return result;
10173 }
10174
10142 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,10175 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
10143 source_instr->source_node, target);10176 source_instr->source_node, target);
10144 result->value.type = wanted_type;10177 result->value.type = wanted_type;
...@@ -10164,6 +10197,19 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10164,6 +10197,19 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10164 return result;10197 return result;
10165 }10198 }
1016610199
10200 // If there is only 1 possible tag, then we know at comptime what it is.
10201 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
10202 wanted_type->data.enumeration.src_field_count == 1)
10203 {
10204 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10205 source_instr->source_node, wanted_type);
10206 result->value.special = ConstValSpecialStatic;
10207 result->value.type = wanted_type;
10208 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
10209 bigint_init_bigint(&result->value.data.x_enum_tag, &enum_field->value);
10210 return result;
10211 }
10212
10167 IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope,10213 IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope,
10168 source_instr->source_node, target);10214 source_instr->source_node, target);
10169 result->value.type = wanted_type;10215 result->value.type = wanted_type;
...@@ -10192,9 +10238,9 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -10192,9 +10238,9 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
10192 return ira->codegen->invalid_instruction;10238 return ira->codegen->invalid_instruction;
10193 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);10239 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
10194 assert(union_field != nullptr);10240 assert(union_field != nullptr);
10195 if ((err = type_ensure_zero_bits_known(ira->codegen, union_field->type_entry)))10241 if ((err = type_resolve(ira->codegen, union_field->type_entry, ResolveStatusZeroBitsKnown)))
10196 return ira->codegen->invalid_instruction;10242 return ira->codegen->invalid_instruction;
10197 if (!union_field->type_entry->zero_bits) {10243 if (type_has_bits(union_field->type_entry)) {
10198 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(10244 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(
10199 union_field->enum_field->decl_index);10245 union_field->enum_field->decl_index);
10200 ErrorMsg *msg = ir_add_error(ira, source_instr,10246 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -10497,7 +10543,10 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou...@@ -10497,7 +10543,10 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
10497 ZigType *wanted_type)10543 ZigType *wanted_type)
10498{10544{
10499 assert(wanted_type->id == ZigTypeIdPointer);10545 assert(wanted_type->id == ZigTypeIdPointer);
10500 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, target->value.type->data.pointer.alignment);10546 Error err;
10547 if ((err = type_resolve(ira->codegen, target->value.type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10548 return ira->codegen->invalid_instruction;
10549 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, target->value.type));
10501 ZigType *array_type = wanted_type->data.pointer.child_type;10550 ZigType *array_type = wanted_type->data.pointer.child_type;
10502 assert(array_type->id == ZigTypeIdArray);10551 assert(array_type->id == ZigTypeIdArray);
10503 assert(array_type->data.array.len == 1);10552 assert(array_type->data.array.len == 1);
...@@ -10544,6 +10593,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10544,6 +10593,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10544 switch (cast_result->id) {10593 switch (cast_result->id) {
10545 case ConstCastResultIdOk:10594 case ConstCastResultIdOk:
10546 zig_unreachable();10595 zig_unreachable();
10596 case ConstCastResultIdInvalid:
10597 zig_unreachable();
10547 case ConstCastResultIdOptionalChild: {10598 case ConstCastResultIdOptionalChild: {
10548 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,10599 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
10549 buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'",10600 buf_sprintf("optional type child '%s' cannot cast into optional type child '%s'",
...@@ -10643,6 +10694,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10643,6 +10694,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10643 // perfect match or non-const to const10694 // perfect match or non-const to const
10644 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,10695 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
10645 source_node, false);10696 source_node, false);
10697 if (const_cast_result.id == ConstCastResultIdInvalid)
10698 return ira->codegen->invalid_instruction;
10646 if (const_cast_result.id == ConstCastResultIdOk) {10699 if (const_cast_result.id == ConstCastResultIdOk) {
10647 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);10700 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
10648 }10701 }
...@@ -10758,13 +10811,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10758,13 +10811,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10758 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&10811 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
10759 actual_type->id == ZigTypeIdPointer &&10812 actual_type->id == ZigTypeIdPointer &&
10760 actual_type->data.pointer.ptr_len == PtrLenSingle &&10813 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10761 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&10814 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10762 actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment &&
10763 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
10764 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10765 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
10766 {10815 {
10767 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);10816 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10817 return ira->codegen->invalid_instruction;
10818 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10819 return ira->codegen->invalid_instruction;
10820 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
10821 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
10822 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10823 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
10824 {
10825 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
10826 }
10768 }10827 }
1076910828
10770 // *[N]T to []T10829 // *[N]T to []T
...@@ -10818,16 +10877,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10818,16 +10877,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10818 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&10877 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
10819 actual_type->id == ZigTypeIdPointer &&10878 actual_type->id == ZigTypeIdPointer &&
10820 actual_type->data.pointer.ptr_len == PtrLenSingle &&10879 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10821 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&10880 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10822 actual_type->data.pointer.alignment >= wanted_child_type->data.pointer.alignment &&
10823 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10824 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10825 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10826 {10881 {
10827 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type);10882 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10828 if (type_is_invalid(cast1->value.type))
10829 return ira->codegen->invalid_instruction;10883 return ira->codegen->invalid_instruction;
10830 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);10884 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10885 return ira->codegen->invalid_instruction;
10886 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
10887 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10888 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10889 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10890 {
10891 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
10892 wanted_child_type);
10893 if (type_is_invalid(cast1->value.type))
10894 return ira->codegen->invalid_instruction;
10895 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10896 }
10831 }10897 }
10832 }10898 }
1083310899
...@@ -10970,7 +11036,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10970,7 +11036,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1097011036
10971 // cast from union to the enum type of the union11037 // cast from union to the enum type of the union
10972 if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) {11038 if (actual_type->id == ZigTypeIdUnion && wanted_type->id == ZigTypeIdEnum) {
10973 if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type)))11039 if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown)))
10974 return ira->codegen->invalid_instruction;11040 return ira->codegen->invalid_instruction;
1097511041
10976 if (actual_type->data.unionation.tag_type == wanted_type) {11042 if (actual_type->data.unionation.tag_type == wanted_type) {
...@@ -10983,7 +11049,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10983,7 +11049,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10983 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||11049 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
10984 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))11050 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
10985 {11051 {
10986 if ((err = type_ensure_zero_bits_known(ira->codegen, wanted_type)))11052 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
10987 return ira->codegen->invalid_instruction;11053 return ira->codegen->invalid_instruction;
1098811054
10989 if (wanted_type->data.unionation.tag_type == actual_type) {11055 if (wanted_type->data.unionation.tag_type == actual_type) {
...@@ -10997,7 +11063,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10997,7 +11063,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10997 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||11063 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
10998 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)11064 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
10999 {11065 {
11000 if ((err = type_ensure_zero_bits_known(ira->codegen, union_type)))11066 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
11001 return ira->codegen->invalid_instruction;11067 return ira->codegen->invalid_instruction;
1100211068
11003 if (union_type->data.unionation.tag_type == actual_type) {11069 if (union_type->data.unionation.tag_type == actual_type) {
...@@ -11024,14 +11090,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11024,14 +11090,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11024 actual_type->data.pointer.child_type, source_node,11090 actual_type->data.pointer.child_type, source_node,
11025 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)11091 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
11026 {11092 {
11027 if (wanted_type->data.pointer.alignment > actual_type->data.pointer.alignment) {11093 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type,
11094 ResolveStatusAlignmentKnown)))
11095 {
11096 return ira->codegen->invalid_instruction;
11097 }
11098 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
11099 ResolveStatusAlignmentKnown)))
11100 {
11101 return ira->codegen->invalid_instruction;
11102 }
11103 uint32_t wanted_align = get_ptr_align(ira->codegen, wanted_type);
11104 uint32_t actual_align = get_ptr_align(ira->codegen, actual_type);
11105 if (wanted_align > actual_align) {
11028 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));11106 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
11029 add_error_note(ira->codegen, msg, value->source_node,11107 add_error_note(ira->codegen, msg, value->source_node,
11030 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name),11108 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), actual_align));
11031 actual_type->data.pointer.alignment));
11032 add_error_note(ira->codegen, msg, source_instr->source_node,11109 add_error_note(ira->codegen, msg, source_instr->source_node,
11033 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name),11110 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), wanted_align));
11034 wanted_type->data.pointer.alignment));
11035 return ira->codegen->invalid_instruction;11111 return ira->codegen->invalid_instruction;
11036 }11112 }
11037 return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);11113 return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
...@@ -11043,7 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -11043,7 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
11043 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,11119 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
11044 actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)11120 actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
11045 {11121 {
11046 if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) {11122 if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) {
11047 return ira->codegen->invalid_instruction;11123 return ira->codegen->invalid_instruction;
11048 }11124 }
11049 if (!type_has_bits(actual_type)) {11125 if (!type_has_bits(actual_type)) {
...@@ -11289,8 +11365,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {...@@ -11289,8 +11365,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
11289 return nullptr;11365 return nullptr;
1129011366
11291 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,11367 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
11292 true, false, PtrLenUnknown,11368 true, false, PtrLenUnknown, 0, 0, 0);
11293 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
11294 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);11369 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);
11295 IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);11370 IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);
11296 if (type_is_invalid(casted_value->value.type))11371 if (type_is_invalid(casted_value->value.type))
...@@ -11580,8 +11655,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op...@@ -11580,8 +11655,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
11580 ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);11655 ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
11581 if (type_is_invalid(resolved_type))11656 if (type_is_invalid(resolved_type))
11582 return resolved_type;11657 return resolved_type;
11583 if ((err = type_ensure_zero_bits_known(ira->codegen, resolved_type)))
11584 return resolved_type;
1158511658
11586 bool operator_allowed;11659 bool operator_allowed;
11587 switch (resolved_type->id) {11660 switch (resolved_type->id) {
...@@ -11603,7 +11676,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op...@@ -11603,7 +11676,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
11603 case ZigTypeIdFn:11676 case ZigTypeIdFn:
11604 case ZigTypeIdOpaque:11677 case ZigTypeIdOpaque:
11605 case ZigTypeIdNamespace:11678 case ZigTypeIdNamespace:
11606 case ZigTypeIdBlock:
11607 case ZigTypeIdBoundFn:11679 case ZigTypeIdBoundFn:
11608 case ZigTypeIdArgTuple:11680 case ZigTypeIdArgTuple:
11609 case ZigTypeIdPromise:11681 case ZigTypeIdPromise:
...@@ -11638,6 +11710,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op...@@ -11638,6 +11710,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
11638 if (casted_op2 == ira->codegen->invalid_instruction)11710 if (casted_op2 == ira->codegen->invalid_instruction)
11639 return ira->codegen->builtin_types.entry_invalid;11711 return ira->codegen->builtin_types.entry_invalid;
1164011712
11713 if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown)))
11714 return resolved_type;
11715
11641 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);11716 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
11642 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {11717 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
11643 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);11718 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
...@@ -12324,7 +12399,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc...@@ -12324,7 +12399,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
12324 out_array_val = out_val;12399 out_array_val = out_val;
12325 } else if (is_slice(op1_type) || is_slice(op2_type)) {12400 } else if (is_slice(op1_type) || is_slice(op2_type)) {
12326 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,12401 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
12327 true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);12402 true, false, PtrLenUnknown, 0, 0, 0);
12328 result_type = get_slice_type(ira->codegen, ptr_type);12403 result_type = get_slice_type(ira->codegen, ptr_type);
12329 out_array_val = create_const_vals(1);12404 out_array_val = create_const_vals(1);
12330 out_array_val->special = ConstValSpecialStatic;12405 out_array_val->special = ConstValSpecialStatic;
...@@ -12345,8 +12420,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc...@@ -12345,8 +12420,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
12345 new_len += 1; // null byte12420 new_len += 1; // null byte
1234612421
12347 // TODO make this `[*]null T` instead of `[*]T`12422 // TODO make this `[*]null T` instead of `[*]T`
12348 result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false,12423 result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);
12349 PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
1235012424
12351 out_array_val = create_const_vals(1);12425 out_array_val = create_const_vals(1);
12352 out_array_val->special = ConstValSpecialStatic;12426 out_array_val->special = ConstValSpecialStatic;
...@@ -12444,10 +12518,22 @@ static ZigType *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *...@@ -12444,10 +12518,22 @@ static ZigType *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *
12444 if (type_is_invalid(op1_type))12518 if (type_is_invalid(op1_type))
12445 return ira->codegen->builtin_types.entry_invalid;12519 return ira->codegen->builtin_types.entry_invalid;
1244612520
12521 if (op1_type->id != ZigTypeIdErrorSet) {
12522 ir_add_error(ira, instruction->op1,
12523 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name)));
12524 return ira->codegen->builtin_types.entry_invalid;
12525 }
12526
12447 ZigType *op2_type = ir_resolve_type(ira, instruction->op2->other);12527 ZigType *op2_type = ir_resolve_type(ira, instruction->op2->other);
12448 if (type_is_invalid(op2_type))12528 if (type_is_invalid(op2_type))
12449 return ira->codegen->builtin_types.entry_invalid;12529 return ira->codegen->builtin_types.entry_invalid;
1245012530
12531 if (op2_type->id != ZigTypeIdErrorSet) {
12532 ir_add_error(ira, instruction->op2,
12533 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name)));
12534 return ira->codegen->builtin_types.entry_invalid;
12535 }
12536
12451 if (type_is_global_error_set(op1_type) ||12537 if (type_is_global_error_set(op1_type) ||
12452 type_is_global_error_set(op2_type))12538 type_is_global_error_set(op2_type))
12453 {12539 {
...@@ -12559,7 +12645,7 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec...@@ -12559,7 +12645,7 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
12559 if (type_is_invalid(result_type)) {12645 if (type_is_invalid(result_type)) {
12560 result_type = ira->codegen->builtin_types.entry_invalid;12646 result_type = ira->codegen->builtin_types.entry_invalid;
12561 } else {12647 } else {
12562 if ((err = type_ensure_zero_bits_known(ira->codegen, result_type))) {12648 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) {
12563 result_type = ira->codegen->builtin_types.entry_invalid;12649 result_type = ira->codegen->builtin_types.entry_invalid;
12564 }12650 }
12565 }12651 }
...@@ -12627,6 +12713,11 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec...@@ -12627,6 +12713,11 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
12627 }12713 }
1262812714
12629 if (decl_var_instruction->align_value == nullptr) {12715 if (decl_var_instruction->align_value == nullptr) {
12716 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
12717 var->value->type = ira->codegen->builtin_types.entry_invalid;
12718 decl_var_instruction->base.other = &decl_var_instruction->base;
12719 return ira->codegen->builtin_types.entry_void;
12720 }
12630 var->align_bytes = get_abi_alignment(ira->codegen, result_type);12721 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
12631 } else {12722 } else {
12632 if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) {12723 if (!ir_resolve_align(ira, decl_var_instruction->align_value->other, &var->align_bytes)) {
...@@ -12792,7 +12883,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor...@@ -12792,7 +12883,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor
12792 case ZigTypeIdErrorUnion:12883 case ZigTypeIdErrorUnion:
12793 case ZigTypeIdErrorSet:12884 case ZigTypeIdErrorSet:
12794 case ZigTypeIdNamespace:12885 case ZigTypeIdNamespace:
12795 case ZigTypeIdBlock:
12796 case ZigTypeIdBoundFn:12886 case ZigTypeIdBoundFn:
12797 case ZigTypeIdArgTuple:12887 case ZigTypeIdArgTuple:
12798 case ZigTypeIdOpaque:12888 case ZigTypeIdOpaque:
...@@ -12817,7 +12907,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor...@@ -12817,7 +12907,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor
12817 case ZigTypeIdErrorSet:12907 case ZigTypeIdErrorSet:
12818 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));12908 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
12819 case ZigTypeIdNamespace:12909 case ZigTypeIdNamespace:
12820 case ZigTypeIdBlock:
12821 case ZigTypeIdBoundFn:12910 case ZigTypeIdBoundFn:
12822 case ZigTypeIdArgTuple:12911 case ZigTypeIdArgTuple:
12823 case ZigTypeIdOpaque:12912 case ZigTypeIdOpaque:
...@@ -13098,7 +13187,6 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {...@@ -13098,7 +13187,6 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
13098static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,13187static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13099 ZigVar *var)13188 ZigVar *var)
13100{13189{
13101 Error err;
13102 while (var->next_var != nullptr) {13190 while (var->next_var != nullptr) {
13103 var = var->next_var;13191 var = var->next_var;
13104 }13192 }
...@@ -13156,8 +13244,6 @@ no_mem_slot:...@@ -13156,8 +13244,6 @@ no_mem_slot:
13156 instruction->scope, instruction->source_node, var);13244 instruction->scope, instruction->source_node, var);
13157 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,13245 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
13158 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);13246 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
13159 if ((err = type_ensure_zero_bits_known(ira->codegen, var->value->type)))
13160 return ira->codegen->invalid_instruction;
1316113247
13162 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);13248 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
13163 var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;13249 var_ptr_instruction->value.data.rh_ptr = in_fn_scope ? RuntimeHintPtrStack : RuntimeHintPtrNonStack;
...@@ -13354,8 +13440,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr...@@ -13354,8 +13440,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
13354 IrInstruction *casted_new_stack = nullptr;13440 IrInstruction *casted_new_stack = nullptr;
13355 if (call_instruction->new_stack != nullptr) {13441 if (call_instruction->new_stack != nullptr) {
13356 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,13442 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
13357 false, false, PtrLenUnknown,13443 false, false, PtrLenUnknown, 0, 0, 0);
13358 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
13359 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);13444 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
13360 IrInstruction *new_stack = call_instruction->new_stack->other;13445 IrInstruction *new_stack = call_instruction->new_stack->other;
13361 if (type_is_invalid(new_stack->value.type))13446 if (type_is_invalid(new_stack->value.type))
...@@ -13534,7 +13619,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr...@@ -13534,7 +13619,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
13534 inst_fn_type_id.return_type = specified_return_type;13619 inst_fn_type_id.return_type = specified_return_type;
13535 }13620 }
1353613621
13537 if ((err = type_ensure_zero_bits_known(ira->codegen, specified_return_type)))13622 if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown)))
13538 return ira->codegen->builtin_types.entry_invalid;13623 return ira->codegen->builtin_types.entry_invalid;
1353913624
13540 if (type_requires_comptime(specified_return_type)) {13625 if (type_requires_comptime(specified_return_type)) {
...@@ -13875,7 +13960,6 @@ static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instru...@@ -13875,7 +13960,6 @@ static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instru
13875 case ZigTypeIdUnion:13960 case ZigTypeIdUnion:
13876 case ZigTypeIdFn:13961 case ZigTypeIdFn:
13877 case ZigTypeIdNamespace:13962 case ZigTypeIdNamespace:
13878 case ZigTypeIdBlock:
13879 case ZigTypeIdBoundFn:13963 case ZigTypeIdBoundFn:
13880 case ZigTypeIdArgTuple:13964 case ZigTypeIdArgTuple:
13881 case ZigTypeIdPromise:13965 case ZigTypeIdPromise:
...@@ -14211,7 +14295,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {...@@ -14211,7 +14295,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
14211 ptr_type->data.pointer.child_type,14295 ptr_type->data.pointer.child_type,
14212 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,14296 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14213 ptr_len,14297 ptr_len,
14214 ptr_type->data.pointer.alignment,14298 ptr_type->data.pointer.explicit_alignment,
14215 ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);14299 ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
14216}14300}
1421714301
...@@ -14263,7 +14347,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle...@@ -14263,7 +14347,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
14263 return_type = get_pointer_to_type_extra(ira->codegen, child_type,14347 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
14264 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,14348 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
14265 elem_ptr_instruction->ptr_len,14349 elem_ptr_instruction->ptr_len,
14266 ptr_type->data.pointer.alignment, 0, 0);14350 ptr_type->data.pointer.explicit_alignment, 0, 0);
14267 } else {14351 } else {
14268 uint64_t elem_val_scalar;14352 uint64_t elem_val_scalar;
14269 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))14353 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
...@@ -14335,7 +14419,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle...@@ -14335,7 +14419,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
1433514419
14336 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);14420 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
14337 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);14421 uint64_t abi_align = get_abi_alignment(ira->codegen, return_type->data.pointer.child_type);
14338 uint64_t ptr_align = return_type->data.pointer.alignment;14422 uint64_t ptr_align = get_ptr_align(ira->codegen, return_type);
14339 if (instr_is_comptime(casted_elem_index)) {14423 if (instr_is_comptime(casted_elem_index)) {
14340 uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);14424 uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);
14341 if (array_type->id == ZigTypeIdArray) {14425 if (array_type->id == ZigTypeIdArray) {
...@@ -14652,9 +14736,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -14652,9 +14736,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
14652 }14736 }
1465314737
14654 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,14738 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
14655 is_const, is_volatile,14739 is_const, is_volatile, PtrLenSingle, 0, 0, 0);
14656 PtrLenSingle,
14657 get_abi_alignment(ira->codegen, field_type), 0, 0);
1465814740
14659 IrInstruction *result = ir_get_const(ira, source_instr);14741 IrInstruction *result = ir_get_const(ira, source_instr);
14660 ConstExprValue *const_val = &result->value;14742 ConstExprValue *const_val = &result->value;
...@@ -14668,7 +14750,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -14668,7 +14750,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1466814750
14669 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);14751 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
14670 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,14752 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
14671 PtrLenSingle, get_abi_alignment(ira->codegen, field->type_entry), 0, 0);14753 PtrLenSingle, 0, 0, 0);
14672 return result;14754 return result;
14673 } else {14755 } else {
14674 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,14756 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
...@@ -15001,9 +15083,14 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi...@@ -15001,9 +15083,14 @@ static ZigType *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFi
15001 } else if (buf_eql_str(field_name, "alignment")) {15083 } else if (buf_eql_str(field_name, "alignment")) {
15002 bool ptr_is_const = true;15084 bool ptr_is_const = true;
15003 bool ptr_is_volatile = false;15085 bool ptr_is_volatile = false;
15086 if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type,
15087 ResolveStatusAlignmentKnown)))
15088 {
15089 return ira->codegen->builtin_types.entry_invalid;
15090 }
15004 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,15091 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
15005 create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,15092 create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int,
15006 child_type->data.pointer.alignment, false),15093 get_ptr_align(ira->codegen, child_type), false),
15007 ira->codegen->builtin_types.entry_num_lit_int,15094 ira->codegen->builtin_types.entry_num_lit_int,
15008 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);15095 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
15009 } else {15096 } else {
...@@ -15233,7 +15320,6 @@ static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeO...@@ -15233,7 +15320,6 @@ static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeO
15233 case ZigTypeIdUndefined:15320 case ZigTypeIdUndefined:
15234 case ZigTypeIdNull:15321 case ZigTypeIdNull:
15235 case ZigTypeIdNamespace:15322 case ZigTypeIdNamespace:
15236 case ZigTypeIdBlock:
15237 case ZigTypeIdBoundFn:15323 case ZigTypeIdBoundFn:
15238 case ZigTypeIdMetaType:15324 case ZigTypeIdMetaType:
15239 case ZigTypeIdVoid:15325 case ZigTypeIdVoid:
...@@ -15342,6 +15428,7 @@ static ZigType *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSet...@@ -15342,6 +15428,7 @@ static ZigType *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSet
15342 ir_build_const_from(ira, &instruction->base);15428 ir_build_const_from(ira, &instruction->base);
15343 return ira->codegen->builtin_types.entry_void;15429 return ira->codegen->builtin_types.entry_void;
15344}15430}
15431
15345static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,15432static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
15346 IrInstructionSetRuntimeSafety *set_runtime_safety_instruction)15433 IrInstructionSetRuntimeSafety *set_runtime_safety_instruction)
15347{15434{
...@@ -15402,14 +15489,6 @@ static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,...@@ -15402,14 +15489,6 @@ static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
15402static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,15489static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
15403 IrInstructionSetFloatMode *instruction)15490 IrInstructionSetFloatMode *instruction)
15404{15491{
15405 IrInstruction *target_instruction = instruction->scope_value->other;
15406 ZigType *target_type = target_instruction->value.type;
15407 if (type_is_invalid(target_type))
15408 return ira->codegen->builtin_types.entry_invalid;
15409 ConstExprValue *target_val = ir_resolve_const(ira, target_instruction, UndefBad);
15410 if (!target_val)
15411 return ira->codegen->builtin_types.entry_invalid;
15412
15413 if (ira->new_irb.exec->is_inline) {15492 if (ira->new_irb.exec->is_inline) {
15414 // ignore setFloatMode when running functions at compile time15493 // ignore setFloatMode when running functions at compile time
15415 ir_build_const_from(ira, &instruction->base);15494 ir_build_const_from(ira, &instruction->base);
...@@ -15418,40 +15497,34 @@ static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,...@@ -15418,40 +15497,34 @@ static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
1541815497
15419 bool *fast_math_on_ptr;15498 bool *fast_math_on_ptr;
15420 AstNode **fast_math_set_node_ptr;15499 AstNode **fast_math_set_node_ptr;
15421 if (target_type->id == ZigTypeIdBlock) {15500
15422 ScopeBlock *block_scope = (ScopeBlock *)target_val->data.x_block;15501 Scope *scope = instruction->base.scope;
15423 fast_math_on_ptr = &block_scope->fast_math_on;15502 while (scope != nullptr) {
15424 fast_math_set_node_ptr = &block_scope->fast_math_set_node;15503 if (scope->id == ScopeIdBlock) {
15425 } else if (target_type->id == ZigTypeIdFn) {15504 ScopeBlock *block_scope = (ScopeBlock *)scope;
15426 assert(target_val->data.x_ptr.special == ConstPtrSpecialFunction);15505 fast_math_on_ptr = &block_scope->fast_math_on;
15427 ZigFn *target_fn = target_val->data.x_ptr.data.fn.fn_entry;15506 fast_math_set_node_ptr = &block_scope->fast_math_set_node;
15428 assert(target_fn->def_scope);15507 break;
15429 fast_math_on_ptr = &target_fn->def_scope->fast_math_on;15508 } else if (scope->id == ScopeIdFnDef) {
15430 fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node;15509 ScopeFnDef *def_scope = (ScopeFnDef *)scope;
15431 } else if (target_type->id == ZigTypeIdMetaType) {15510 ZigFn *target_fn = def_scope->fn_entry;
15432 ScopeDecls *decls_scope;15511 assert(target_fn->def_scope != nullptr);
15433 ZigType *type_arg = target_val->data.x_type;15512 fast_math_on_ptr = &target_fn->def_scope->fast_math_on;
15434 if (type_arg->id == ZigTypeIdStruct) {15513 fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node;
15435 decls_scope = type_arg->data.structure.decls_scope;15514 break;
15436 } else if (type_arg->id == ZigTypeIdEnum) {15515 } else if (scope->id == ScopeIdDecls) {
15437 decls_scope = type_arg->data.enumeration.decls_scope;15516 ScopeDecls *decls_scope = (ScopeDecls *)scope;
15438 } else if (type_arg->id == ZigTypeIdUnion) {15517 fast_math_on_ptr = &decls_scope->fast_math_on;
15439 decls_scope = type_arg->data.unionation.decls_scope;15518 fast_math_set_node_ptr = &decls_scope->fast_math_set_node;
15519 break;
15440 } else {15520 } else {
15441 ir_add_error_node(ira, target_instruction->source_node,15521 scope = scope->parent;
15442 buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name)));15522 continue;
15443 return ira->codegen->builtin_types.entry_invalid;
15444 }15523 }
15445 fast_math_on_ptr = &decls_scope->fast_math_on;
15446 fast_math_set_node_ptr = &decls_scope->fast_math_set_node;
15447 } else {
15448 ir_add_error_node(ira, target_instruction->source_node,
15449 buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&target_type->name)));
15450 return ira->codegen->builtin_types.entry_invalid;
15451 }15524 }
15525 assert(scope != nullptr);
1545215526
15453 IrInstruction *float_mode_value = instruction->mode_value->other;15527 IrInstruction *float_mode_value = instruction->mode_value->other;
15454
15455 FloatMode float_mode_scalar;15528 FloatMode float_mode_scalar;
15456 if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))15529 if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))
15457 return ira->codegen->builtin_types.entry_invalid;15530 return ira->codegen->builtin_types.entry_invalid;
...@@ -15474,7 +15547,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15474,7 +15547,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15474 IrInstructionSliceType *slice_type_instruction)15547 IrInstructionSliceType *slice_type_instruction)
15475{15548{
15476 Error err;15549 Error err;
15477 uint32_t align_bytes;15550 uint32_t align_bytes = 0;
15478 if (slice_type_instruction->align_value != nullptr) {15551 if (slice_type_instruction->align_value != nullptr) {
15479 if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes))15552 if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes))
15480 return ira->codegen->builtin_types.entry_invalid;15553 return ira->codegen->builtin_types.entry_invalid;
...@@ -15484,12 +15557,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15484,12 +15557,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15484 if (type_is_invalid(child_type))15557 if (type_is_invalid(child_type))
15485 return ira->codegen->builtin_types.entry_invalid;15558 return ira->codegen->builtin_types.entry_invalid;
1548615559
15487 if (slice_type_instruction->align_value == nullptr) {
15488 if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
15489 return ira->codegen->builtin_types.entry_invalid;
15490 align_bytes = get_abi_alignment(ira->codegen, child_type);
15491 }
15492
15493 bool is_const = slice_type_instruction->is_const;15560 bool is_const = slice_type_instruction->is_const;
15494 bool is_volatile = slice_type_instruction->is_volatile;15561 bool is_volatile = slice_type_instruction->is_volatile;
1549515562
...@@ -15499,7 +15566,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15499,7 +15566,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15499 case ZigTypeIdUnreachable:15566 case ZigTypeIdUnreachable:
15500 case ZigTypeIdUndefined:15567 case ZigTypeIdUndefined:
15501 case ZigTypeIdNull:15568 case ZigTypeIdNull:
15502 case ZigTypeIdBlock:
15503 case ZigTypeIdArgTuple:15569 case ZigTypeIdArgTuple:
15504 case ZigTypeIdOpaque:15570 case ZigTypeIdOpaque:
15505 ir_add_error_node(ira, slice_type_instruction->base.source_node,15571 ir_add_error_node(ira, slice_type_instruction->base.source_node,
...@@ -15525,7 +15591,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15525,7 +15591,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15525 case ZigTypeIdBoundFn:15591 case ZigTypeIdBoundFn:
15526 case ZigTypeIdPromise:15592 case ZigTypeIdPromise:
15527 {15593 {
15528 if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))15594 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
15529 return ira->codegen->builtin_types.entry_invalid;15595 return ira->codegen->builtin_types.entry_invalid;
15530 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,15596 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
15531 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);15597 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);
...@@ -15610,7 +15676,6 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -15610,7 +15676,6 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,
15610 case ZigTypeIdUnreachable:15676 case ZigTypeIdUnreachable:
15611 case ZigTypeIdUndefined:15677 case ZigTypeIdUndefined:
15612 case ZigTypeIdNull:15678 case ZigTypeIdNull:
15613 case ZigTypeIdBlock:
15614 case ZigTypeIdArgTuple:15679 case ZigTypeIdArgTuple:
15615 case ZigTypeIdOpaque:15680 case ZigTypeIdOpaque:
15616 ir_add_error_node(ira, array_type_instruction->base.source_node,15681 ir_add_error_node(ira, array_type_instruction->base.source_node,
...@@ -15681,7 +15746,6 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15681,7 +15746,6 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,
15681 case ZigTypeIdUnreachable:15746 case ZigTypeIdUnreachable:
15682 case ZigTypeIdUndefined:15747 case ZigTypeIdUndefined:
15683 case ZigTypeIdNull:15748 case ZigTypeIdNull:
15684 case ZigTypeIdBlock:
15685 case ZigTypeIdComptimeFloat:15749 case ZigTypeIdComptimeFloat:
15686 case ZigTypeIdComptimeInt:15750 case ZigTypeIdComptimeInt:
15687 case ZigTypeIdBoundFn:15751 case ZigTypeIdBoundFn:
...@@ -15767,9 +15831,7 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -15767,9 +15831,7 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15767 }15831 }
15768 ZigType *child_type = type_entry->data.maybe.child_type;15832 ZigType *child_type = type_entry->data.maybe.child_type;
15769 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,15833 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
15770 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,15834 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
15771 PtrLenSingle,
15772 get_abi_alignment(ira->codegen, child_type), 0, 0);
1577315835
15774 if (instr_is_comptime(value)) {15836 if (instr_is_comptime(value)) {
15775 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);15837 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
...@@ -16139,7 +16201,7 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16139,7 +16201,7 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16139 return tag_type;16201 return tag_type;
16140 }16202 }
16141 case ZigTypeIdEnum: {16203 case ZigTypeIdEnum: {
16142 if ((err = type_ensure_zero_bits_known(ira->codegen, target_type)))16204 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
16143 return ira->codegen->builtin_types.entry_invalid;16205 return ira->codegen->builtin_types.entry_invalid;
16144 if (target_type->data.enumeration.src_field_count < 2) {16206 if (target_type->data.enumeration.src_field_count < 2) {
16145 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];16207 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
...@@ -16167,7 +16229,6 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16167,7 +16229,6 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16167 case ZigTypeIdUndefined:16229 case ZigTypeIdUndefined:
16168 case ZigTypeIdNull:16230 case ZigTypeIdNull:
16169 case ZigTypeIdOptional:16231 case ZigTypeIdOptional:
16170 case ZigTypeIdBlock:
16171 case ZigTypeIdBoundFn:16232 case ZigTypeIdBoundFn:
16172 case ZigTypeIdArgTuple:16233 case ZigTypeIdArgTuple:
16173 case ZigTypeIdOpaque:16234 case ZigTypeIdOpaque:
...@@ -16231,6 +16292,8 @@ static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUn...@@ -16231,6 +16292,8 @@ static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUn
16231}16292}
1623216293
16233static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {16294static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {
16295 Error err;
16296
16234 IrInstruction *name_value = import_instruction->name->other;16297 IrInstruction *name_value = import_instruction->name->other;
16235 Buf *import_target_str = ir_resolve_str(ira, name_value);16298 Buf *import_target_str = ir_resolve_str(ira, name_value);
16236 if (!import_target_str)16299 if (!import_target_str)
...@@ -16274,8 +16337,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor...@@ -16274,8 +16337,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
16274 return ira->codegen->builtin_types.entry_namespace;16337 return ira->codegen->builtin_types.entry_namespace;
16275 }16338 }
1627616339
16277 int err;16340 if ((err = file_fetch(ira->codegen, resolved_path, import_code))) {
16278 if ((err = os_fetch_file_path(resolved_path, import_code, true))) {
16279 if (err == ErrorFileNotFound) {16341 if (err == ErrorFileNotFound) {
16280 ir_add_error_node(ira, source_node,16342 ir_add_error_node(ira, source_node,
16281 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));16343 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
...@@ -16286,6 +16348,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor...@@ -16286,6 +16348,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
16286 return ira->codegen->builtin_types.entry_invalid;16348 return ira->codegen->builtin_types.entry_invalid;
16287 }16349 }
16288 }16350 }
16351
16289 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code);16352 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code);
1629016353
16291 scan_import(ira->codegen, target_import);16354 scan_import(ira->codegen, target_import);
...@@ -16367,7 +16430,7 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc...@@ -16367,7 +16430,7 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc
16367 if (casted_field_value == ira->codegen->invalid_instruction)16430 if (casted_field_value == ira->codegen->invalid_instruction)
16368 return ira->codegen->builtin_types.entry_invalid;16431 return ira->codegen->builtin_types.entry_invalid;
1636916432
16370 if ((err = type_ensure_zero_bits_known(ira->codegen, casted_field_value->value.type)))16433 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
16371 return ira->codegen->builtin_types.entry_invalid;16434 return ira->codegen->builtin_types.entry_invalid;
1637216435
16373 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);16436 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);
...@@ -16686,7 +16749,6 @@ static ZigType *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruc...@@ -16686,7 +16749,6 @@ static ZigType *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_instruc
16686 case ZigTypeIdUnion:16749 case ZigTypeIdUnion:
16687 case ZigTypeIdFn:16750 case ZigTypeIdFn:
16688 case ZigTypeIdNamespace:16751 case ZigTypeIdNamespace:
16689 case ZigTypeIdBlock:
16690 case ZigTypeIdBoundFn:16752 case ZigTypeIdBoundFn:
16691 case ZigTypeIdArgTuple:16753 case ZigTypeIdArgTuple:
16692 case ZigTypeIdOpaque:16754 case ZigTypeIdOpaque:
...@@ -16768,7 +16830,7 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr...@@ -16768,7 +16830,7 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr
16768 return ira->codegen->builtin_types.entry_invalid;16830 return ira->codegen->builtin_types.entry_invalid;
1676916831
16770 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,16832 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
16771 true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);16833 true, false, PtrLenUnknown, 0, 0, 0);
16772 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);16834 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
16773 if (casted_value->value.special == ConstValSpecialStatic) {16835 if (casted_value->value.special == ConstValSpecialStatic) {
16774 ErrorTableEntry *err = casted_value->value.data.x_err_set;16836 ErrorTableEntry *err = casted_value->value.data.x_err_set;
...@@ -16795,7 +16857,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi...@@ -16795,7 +16857,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi
16795 assert(target->value.type->id == ZigTypeIdEnum);16857 assert(target->value.type->id == ZigTypeIdEnum);
1679616858
16797 if (instr_is_comptime(target)) {16859 if (instr_is_comptime(target)) {
16798 if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type)))16860 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
16799 return ira->codegen->builtin_types.entry_invalid;16861 return ira->codegen->builtin_types.entry_invalid;
16800 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);16862 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
16801 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);16863 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
...@@ -16810,8 +16872,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi...@@ -16810,8 +16872,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi
16810 ZigType *u8_ptr_type = get_pointer_to_type_extra(16872 ZigType *u8_ptr_type = get_pointer_to_type_extra(
16811 ira->codegen, ira->codegen->builtin_types.entry_u8,16873 ira->codegen, ira->codegen->builtin_types.entry_u8,
16812 true, false, PtrLenUnknown,16874 true, false, PtrLenUnknown,
16813 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),16875 0, 0, 0);
16814 0, 0);
16815 result->value.type = get_slice_type(ira->codegen, u8_ptr_type);16876 result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
16816 return result->value.type;16877 return result->value.type;
16817}16878}
...@@ -17174,8 +17235,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17174,8 +17235,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17174 ZigType *u8_ptr = get_pointer_to_type_extra(17235 ZigType *u8_ptr = get_pointer_to_type_extra(
17175 ira->codegen, ira->codegen->builtin_types.entry_u8,17236 ira->codegen, ira->codegen->builtin_types.entry_u8,
17176 true, false, PtrLenUnknown,17237 true, false, PtrLenUnknown,
17177 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),17238 0, 0, 0);
17178 0, 0);
17179 fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));17239 fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
17180 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {17240 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
17181 fn_def_fields[6].data.x_optional = create_const_vals(1);17241 fn_def_fields[6].data.x_optional = create_const_vals(1);
...@@ -17295,7 +17355,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -17295,7 +17355,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
17295 ensure_field_index(result->type, "alignment", 3);17355 ensure_field_index(result->type, "alignment", 3);
17296 fields[3].special = ConstValSpecialStatic;17356 fields[3].special = ConstValSpecialStatic;
17297 fields[3].type = get_int_type(ira->codegen, false, 29);17357 fields[3].type = get_int_type(ira->codegen, false, 29);
17298 bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment);17358 bigint_init_unsigned(&fields[3].data.x_bigint, get_ptr_align(ira->codegen, attrs_type));
17299 // child: type17359 // child: type
17300 ensure_field_index(result->type, "child", 4);17360 ensure_field_index(result->type, "child", 4);
17301 fields[4].special = ConstValSpecialStatic;17361 fields[4].special = ConstValSpecialStatic;
...@@ -17349,7 +17409,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17349,7 +17409,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17349 case ZigTypeIdUndefined:17409 case ZigTypeIdUndefined:
17350 case ZigTypeIdNull:17410 case ZigTypeIdNull:
17351 case ZigTypeIdNamespace:17411 case ZigTypeIdNamespace:
17352 case ZigTypeIdBlock:
17353 case ZigTypeIdArgTuple:17412 case ZigTypeIdArgTuple:
17354 case ZigTypeIdOpaque:17413 case ZigTypeIdOpaque:
17355 *out = nullptr;17414 *out = nullptr;
...@@ -17959,6 +18018,12 @@ static ZigType *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTy...@@ -17959,6 +18018,12 @@ static ZigType *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTy
17959}18018}
1796018019
17961static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {18020static ZigType *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
18021 if (ira->codegen->enable_cache) {
18022 ir_add_error(ira, &instruction->base,
18023 buf_sprintf("TODO @cImport is incompatible with --cache on. The cache system currently is unable to detect subsequent changes in .h files."));
18024 return ira->codegen->builtin_types.entry_invalid;
18025 }
18026
17962 AstNode *node = instruction->base.source_node;18027 AstNode *node = instruction->base.source_node;
17963 assert(node->type == NodeTypeFnCallExpr);18028 assert(node->type == NodeTypeFnCallExpr);
17964 AstNode *block_node = node->data.fn_call_expr.params.at(0);18029 AstNode *block_node = node->data.fn_call_expr.params.at(0);
...@@ -18105,7 +18170,7 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE...@@ -18105,7 +18170,7 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
18105 // load from file system into const expr18170 // load from file system into const expr
18106 Buf *file_contents = buf_alloc();18171 Buf *file_contents = buf_alloc();
18107 int err;18172 int err;
18108 if ((err = os_fetch_file_path(&file_path, file_contents, false))) {18173 if ((err = file_fetch(ira->codegen, &file_path, file_contents))) {
18109 if (err == ErrorFileNotFound) {18174 if (err == ErrorFileNotFound) {
18110 ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));18175 ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
18111 return ira->codegen->builtin_types.entry_invalid;18176 return ira->codegen->builtin_types.entry_invalid;
...@@ -18115,9 +18180,6 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE...@@ -18115,9 +18180,6 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
18115 }18180 }
18116 }18181 }
1811718182
18118 // TODO add dependency on the file we embedded so that we know if it changes
18119 // we'll have to invalidate the cache
18120
18121 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);18183 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
18122 init_const_str_lit(ira->codegen, out_val, file_contents);18184 init_const_str_lit(ira->codegen, out_val, file_contents);
1812318185
...@@ -18383,7 +18445,21 @@ static ZigType *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructio...@@ -18383,7 +18445,21 @@ static ZigType *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructio
18383 return dest_type;18445 return dest_type;
18384}18446}
1838518447
18448static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18449 Error err;
18450
18451 if (ty->id == ZigTypeIdPointer) {
18452 if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18453 return err;
18454 }
18455
18456 *result_align = get_ptr_align(ira->codegen, ty);
18457 return ErrorNone;
18458}
18459
18386static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {18460static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
18461 Error err;
18462
18387 ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);18463 ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
18388 if (type_is_invalid(dest_child_type))18464 if (type_is_invalid(dest_child_type))
18389 return ira->codegen->builtin_types.entry_invalid;18465 return ira->codegen->builtin_types.entry_invalid;
...@@ -18398,15 +18474,23 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF...@@ -18398,15 +18474,23 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
18398 if (target->value.type->id == ZigTypeIdPointer) {18474 if (target->value.type->id == ZigTypeIdPointer) {
18399 src_ptr_const = target->value.type->data.pointer.is_const;18475 src_ptr_const = target->value.type->data.pointer.is_const;
18400 src_ptr_volatile = target->value.type->data.pointer.is_volatile;18476 src_ptr_volatile = target->value.type->data.pointer.is_volatile;
18401 src_ptr_align = target->value.type->data.pointer.alignment;18477
18478 if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align)))
18479 return ira->codegen->builtin_types.entry_invalid;
18402 } else if (is_slice(target->value.type)) {18480 } else if (is_slice(target->value.type)) {
18403 ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;18481 ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
18404 src_ptr_const = src_ptr_type->data.pointer.is_const;18482 src_ptr_const = src_ptr_type->data.pointer.is_const;
18405 src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;18483 src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
18406 src_ptr_align = src_ptr_type->data.pointer.alignment;18484
18485 if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align)))
18486 return ira->codegen->builtin_types.entry_invalid;
18407 } else {18487 } else {
18408 src_ptr_const = true;18488 src_ptr_const = true;
18409 src_ptr_volatile = false;18489 src_ptr_volatile = false;
18490
18491 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusAlignmentKnown)))
18492 return ira->codegen->builtin_types.entry_invalid;
18493
18410 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);18494 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
18411 }18495 }
1841218496
...@@ -18464,6 +18548,8 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF...@@ -18464,6 +18548,8 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
18464}18548}
1846518549
18466static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {18550static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
18551 Error err;
18552
18467 IrInstruction *target = instruction->target->other;18553 IrInstruction *target = instruction->target->other;
18468 if (type_is_invalid(target->value.type))18554 if (type_is_invalid(target->value.type))
18469 return ira->codegen->builtin_types.entry_invalid;18555 return ira->codegen->builtin_types.entry_invalid;
...@@ -18476,9 +18562,13 @@ static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToB...@@ -18476,9 +18562,13 @@ static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToB
1847618562
18477 ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;18563 ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
1847818564
18565 uint32_t alignment;
18566 if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment)))
18567 return ira->codegen->builtin_types.entry_invalid;
18568
18479 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,18569 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
18480 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,18570 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
18481 src_ptr_type->data.pointer.alignment, 0, 0);18571 alignment, 0, 0);
18482 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);18572 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
1848318573
18484 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);18574 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
...@@ -18636,6 +18726,8 @@ static ZigType *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoo...@@ -18636,6 +18726,8 @@ static ZigType *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoo
18636}18726}
1863718727
18638static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {18728static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {
18729 Error err;
18730
18639 IrInstruction *dest_ptr = instruction->dest_ptr->other;18731 IrInstruction *dest_ptr = instruction->dest_ptr->other;
18640 if (type_is_invalid(dest_ptr->value.type))18732 if (type_is_invalid(dest_ptr->value.type))
18641 return ira->codegen->builtin_types.entry_invalid;18733 return ira->codegen->builtin_types.entry_invalid;
...@@ -18654,8 +18746,13 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse...@@ -18654,8 +18746,13 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
1865418746
18655 ZigType *usize = ira->codegen->builtin_types.entry_usize;18747 ZigType *usize = ira->codegen->builtin_types.entry_usize;
18656 ZigType *u8 = ira->codegen->builtin_types.entry_u8;18748 ZigType *u8 = ira->codegen->builtin_types.entry_u8;
18657 uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?18749 uint32_t dest_align;
18658 dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);18750 if (dest_uncasted_type->id == ZigTypeIdPointer) {
18751 if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
18752 return ira->codegen->builtin_types.entry_invalid;
18753 } else {
18754 dest_align = get_abi_alignment(ira->codegen, u8);
18755 }
18659 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,18756 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
18660 PtrLenUnknown, dest_align, 0, 0);18757 PtrLenUnknown, dest_align, 0, 0);
1866118758
...@@ -18728,6 +18825,8 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse...@@ -18728,6 +18825,8 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
18728}18825}
1872918826
18730static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {18827static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {
18828 Error err;
18829
18731 IrInstruction *dest_ptr = instruction->dest_ptr->other;18830 IrInstruction *dest_ptr = instruction->dest_ptr->other;
18732 if (type_is_invalid(dest_ptr->value.type))18831 if (type_is_invalid(dest_ptr->value.type))
18733 return ira->codegen->builtin_types.entry_invalid;18832 return ira->codegen->builtin_types.entry_invalid;
...@@ -18747,10 +18846,22 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp...@@ -18747,10 +18846,22 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
18747 dest_uncasted_type->data.pointer.is_volatile;18846 dest_uncasted_type->data.pointer.is_volatile;
18748 bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) &&18847 bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) &&
18749 src_uncasted_type->data.pointer.is_volatile;18848 src_uncasted_type->data.pointer.is_volatile;
18750 uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?18849
18751 dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);18850 uint32_t dest_align;
18752 uint32_t src_align = (src_uncasted_type->id == ZigTypeIdPointer) ?18851 if (dest_uncasted_type->id == ZigTypeIdPointer) {
18753 src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);18852 if ((err = resolve_ptr_align(ira, dest_uncasted_type, &dest_align)))
18853 return ira->codegen->builtin_types.entry_invalid;
18854 } else {
18855 dest_align = get_abi_alignment(ira->codegen, u8);
18856 }
18857
18858 uint32_t src_align;
18859 if (src_uncasted_type->id == ZigTypeIdPointer) {
18860 if ((err = resolve_ptr_align(ira, src_uncasted_type, &src_align)))
18861 return ira->codegen->builtin_types.entry_invalid;
18862 } else {
18863 src_align = get_abi_alignment(ira->codegen, u8);
18864 }
1875418865
18755 ZigType *usize = ira->codegen->builtin_types.entry_usize;18866 ZigType *usize = ira->codegen->builtin_types.entry_usize;
18756 ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,18867 ZigType *u8_ptr_mut = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
...@@ -18895,17 +19006,13 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice...@@ -18895,17 +19006,13 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
18895 ZigType *return_type;19006 ZigType *return_type;
1889619007
18897 if (array_type->id == ZigTypeIdArray) {19008 if (array_type->id == ZigTypeIdArray) {
18898 uint32_t byte_alignment = ptr_type->data.pointer.alignment;
18899 if (array_type->data.array.len == 0 && byte_alignment == 0) {
18900 byte_alignment = get_abi_alignment(ira->codegen, array_type->data.array.child_type);
18901 }
18902 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&19009 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
18903 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;19010 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
18904 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,19011 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
18905 ptr_type->data.pointer.is_const || is_comptime_const,19012 ptr_type->data.pointer.is_const || is_comptime_const,
18906 ptr_type->data.pointer.is_volatile,19013 ptr_type->data.pointer.is_volatile,
18907 PtrLenUnknown,19014 PtrLenUnknown,
18908 byte_alignment, 0, 0);19015 ptr_type->data.pointer.explicit_alignment, 0, 0);
18909 return_type = get_slice_type(ira->codegen, slice_ptr_type);19016 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18910 } else if (array_type->id == ZigTypeIdPointer) {19017 } else if (array_type->id == ZigTypeIdPointer) {
18911 if (array_type->data.pointer.ptr_len == PtrLenSingle) {19018 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -18915,7 +19022,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice...@@ -18915,7 +19022,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
18915 main_type->data.pointer.child_type,19022 main_type->data.pointer.child_type,
18916 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,19023 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
18917 PtrLenUnknown,19024 PtrLenUnknown,
18918 array_type->data.pointer.alignment, 0, 0);19025 array_type->data.pointer.explicit_alignment, 0, 0);
18919 return_type = get_slice_type(ira->codegen, slice_ptr_type);19026 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18920 } else {19027 } else {
18921 ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));19028 ir_add_error(ira, &instruction->base, buf_sprintf("slice of single-item pointer"));
...@@ -18925,7 +19032,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice...@@ -18925,7 +19032,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
18925 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,19032 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
18926 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,19033 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
18927 PtrLenUnknown,19034 PtrLenUnknown,
18928 array_type->data.pointer.alignment, 0, 0);19035 array_type->data.pointer.explicit_alignment, 0, 0);
18929 return_type = get_slice_type(ira->codegen, slice_ptr_type);19036 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18930 if (!end) {19037 if (!end) {
18931 ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));19038 ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value"));
...@@ -19306,7 +19413,7 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli...@@ -19306,7 +19413,7 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
19306 return ira->codegen->builtin_types.entry_invalid;19413 return ira->codegen->builtin_types.entry_invalid;
19307 ZigType *type_entry = ir_resolve_type(ira, type_value);19414 ZigType *type_entry = ir_resolve_type(ira, type_value);
1930819415
19309 if ((err = type_ensure_zero_bits_known(ira->codegen, type_entry)))19416 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown)))
19310 return ira->codegen->builtin_types.entry_invalid;19417 return ira->codegen->builtin_types.entry_invalid;
1931119418
19312 switch (type_entry->id) {19419 switch (type_entry->id) {
...@@ -19319,7 +19426,6 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli...@@ -19319,7 +19426,6 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
19319 case ZigTypeIdUndefined:19426 case ZigTypeIdUndefined:
19320 case ZigTypeIdNull:19427 case ZigTypeIdNull:
19321 case ZigTypeIdNamespace:19428 case ZigTypeIdNamespace:
19322 case ZigTypeIdBlock:
19323 case ZigTypeIdBoundFn:19429 case ZigTypeIdBoundFn:
19324 case ZigTypeIdArgTuple:19430 case ZigTypeIdArgTuple:
19325 case ZigTypeIdVoid:19431 case ZigTypeIdVoid:
...@@ -19351,6 +19457,8 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli...@@ -19351,6 +19457,8 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
19351}19457}
1935219458
19353static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {19459static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
19460 Error err;
19461
19354 IrInstruction *type_value = instruction->type_value->other;19462 IrInstruction *type_value = instruction->type_value->other;
19355 if (type_is_invalid(type_value->value.type))19463 if (type_is_invalid(type_value->value.type))
19356 return ira->codegen->builtin_types.entry_invalid;19464 return ira->codegen->builtin_types.entry_invalid;
...@@ -19394,10 +19502,13 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction...@@ -19394,10 +19502,13 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
1939419502
19395 ZigType *expected_ptr_type;19503 ZigType *expected_ptr_type;
19396 if (result_ptr->value.type->id == ZigTypeIdPointer) {19504 if (result_ptr->value.type->id == ZigTypeIdPointer) {
19505 uint32_t alignment;
19506 if ((err = resolve_ptr_align(ira, result_ptr->value.type, &alignment)))
19507 return ira->codegen->builtin_types.entry_invalid;
19397 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,19508 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
19398 false, result_ptr->value.type->data.pointer.is_volatile,19509 false, result_ptr->value.type->data.pointer.is_volatile,
19399 PtrLenSingle,19510 PtrLenSingle,
19400 result_ptr->value.type->data.pointer.alignment, 0, 0);19511 alignment, 0, 0);
19401 } else {19512 } else {
19402 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);19513 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
19403 }19514 }
...@@ -19559,8 +19670,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -19559,8 +19670,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
19559 }19670 }
19560 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,19671 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19561 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,19672 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19562 PtrLenSingle,19673 PtrLenSingle, 0, 0, 0);
19563 get_abi_alignment(ira->codegen, payload_type), 0, 0);
19564 if (instr_is_comptime(value)) {19674 if (instr_is_comptime(value)) {
19565 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);19675 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19566 if (!ptr_val)19676 if (!ptr_val)
...@@ -19639,7 +19749,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP...@@ -19639,7 +19749,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
19639 ZigType *param_type = ir_resolve_type(ira, param_type_value);19749 ZigType *param_type = ir_resolve_type(ira, param_type_value);
19640 if (type_is_invalid(param_type))19750 if (type_is_invalid(param_type))
19641 return ira->codegen->builtin_types.entry_invalid;19751 return ira->codegen->builtin_types.entry_invalid;
19642 if ((err = type_ensure_zero_bits_known(ira->codegen, param_type)))19752 if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown)))
19643 return ira->codegen->builtin_types.entry_invalid;19753 return ira->codegen->builtin_types.entry_invalid;
19644 if (type_requires_comptime(param_type)) {19754 if (type_requires_comptime(param_type)) {
19645 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {19755 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
...@@ -19914,7 +20024,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic...@@ -19914,7 +20024,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
19914 }20024 }
1991520025
19916 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,20026 ZigType *u8_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
19917 true, false, PtrLenUnknown, get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);20027 true, false, PtrLenUnknown, 0, 0, 0);
19918 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);20028 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
19919 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);20029 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
19920 if (type_is_invalid(casted_msg->value.type))20030 if (type_is_invalid(casted_msg->value.type))
...@@ -19927,6 +20037,8 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic...@@ -19927,6 +20037,8 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
19927}20037}
1992820038
19929static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) {20039static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) {
20040 Error err;
20041
19930 ZigType *target_type = target->value.type;20042 ZigType *target_type = target->value.type;
19931 assert(!type_is_invalid(target_type));20043 assert(!type_is_invalid(target_type));
1993220044
...@@ -19935,7 +20047,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19935,7 +20047,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1993520047
19936 if (target_type->id == ZigTypeIdPointer) {20048 if (target_type->id == ZigTypeIdPointer) {
19937 result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes);20049 result_type = adjust_ptr_align(ira->codegen, target_type, align_bytes);
19938 old_align_bytes = target_type->data.pointer.alignment;20050 if ((err = resolve_ptr_align(ira, target_type, &old_align_bytes)))
20051 return ira->codegen->invalid_instruction;
19939 } else if (target_type->id == ZigTypeIdFn) {20052 } else if (target_type->id == ZigTypeIdFn) {
19940 FnTypeId fn_type_id = target_type->data.fn.fn_type_id;20053 FnTypeId fn_type_id = target_type->data.fn.fn_type_id;
19941 old_align_bytes = fn_type_id.alignment;20054 old_align_bytes = fn_type_id.alignment;
...@@ -19945,7 +20058,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19945,7 +20058,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19945 target_type->data.maybe.child_type->id == ZigTypeIdPointer)20058 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
19946 {20059 {
19947 ZigType *ptr_type = target_type->data.maybe.child_type;20060 ZigType *ptr_type = target_type->data.maybe.child_type;
19948 old_align_bytes = ptr_type->data.pointer.alignment;20061 if ((err = resolve_ptr_align(ira, ptr_type, &old_align_bytes)))
20062 return ira->codegen->invalid_instruction;
19949 ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);20063 ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);
1995020064
19951 result_type = get_optional_type(ira->codegen, better_ptr_type);20065 result_type = get_optional_type(ira->codegen, better_ptr_type);
...@@ -19959,7 +20073,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19959,7 +20073,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19959 result_type = get_optional_type(ira->codegen, fn_type);20073 result_type = get_optional_type(ira->codegen, fn_type);
19960 } else if (is_slice(target_type)) {20074 } else if (is_slice(target_type)) {
19961 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;20075 ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
19962 old_align_bytes = slice_ptr_type->data.pointer.alignment;20076 if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes)))
20077 return ira->codegen->invalid_instruction;
19963 ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);20078 ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);
19964 result_type = get_slice_type(ira->codegen, result_ptr_type);20079 result_type = get_slice_type(ira->codegen, result_ptr_type);
19965 } else {20080 } else {
...@@ -20038,8 +20153,13 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr...@@ -20038,8 +20153,13 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
20038 return dest_type;20153 return dest_type;
20039 }20154 }
2004020155
20041 uint32_t src_align_bytes = get_ptr_align(src_type);20156 uint32_t src_align_bytes;
20042 uint32_t dest_align_bytes = get_ptr_align(dest_type);20157 if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
20158 return ira->codegen->builtin_types.entry_invalid;
20159
20160 uint32_t dest_align_bytes;
20161 if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
20162 return ira->codegen->builtin_types.entry_invalid;
2004320163
20044 if (dest_align_bytes > src_align_bytes) {20164 if (dest_align_bytes > src_align_bytes) {
20045 ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));20165 ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
...@@ -20056,7 +20176,7 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr...@@ -20056,7 +20176,7 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
2005620176
20057 // Keep the bigger alignment, it can only help-20177 // Keep the bigger alignment, it can only help-
20058 // unless the target is zero bits.20178 // unless the target is zero bits.
20059 if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))20179 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
20060 return ira->codegen->builtin_types.entry_invalid;20180 return ira->codegen->builtin_types.entry_invalid;
2006120181
20062 IrInstruction *result;20182 IrInstruction *result;
...@@ -20080,7 +20200,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20080,7 +20200,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20080 case ZigTypeIdBoundFn:20200 case ZigTypeIdBoundFn:
20081 case ZigTypeIdArgTuple:20201 case ZigTypeIdArgTuple:
20082 case ZigTypeIdNamespace:20202 case ZigTypeIdNamespace:
20083 case ZigTypeIdBlock:
20084 case ZigTypeIdUnreachable:20203 case ZigTypeIdUnreachable:
20085 case ZigTypeIdComptimeFloat:20204 case ZigTypeIdComptimeFloat:
20086 case ZigTypeIdComptimeInt:20205 case ZigTypeIdComptimeInt:
...@@ -20147,7 +20266,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20147,7 +20266,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20147 case ZigTypeIdBoundFn:20266 case ZigTypeIdBoundFn:
20148 case ZigTypeIdArgTuple:20267 case ZigTypeIdArgTuple:
20149 case ZigTypeIdNamespace:20268 case ZigTypeIdNamespace:
20150 case ZigTypeIdBlock:
20151 case ZigTypeIdUnreachable:20269 case ZigTypeIdUnreachable:
20152 case ZigTypeIdComptimeFloat:20270 case ZigTypeIdComptimeFloat:
20153 case ZigTypeIdComptimeInt:20271 case ZigTypeIdComptimeInt:
...@@ -20227,7 +20345,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit...@@ -20227,7 +20345,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
20227 case ZigTypeIdBoundFn:20345 case ZigTypeIdBoundFn:
20228 case ZigTypeIdArgTuple:20346 case ZigTypeIdArgTuple:
20229 case ZigTypeIdNamespace:20347 case ZigTypeIdNamespace:
20230 case ZigTypeIdBlock:
20231 case ZigTypeIdUnreachable:20348 case ZigTypeIdUnreachable:
20232 case ZigTypeIdComptimeFloat:20349 case ZigTypeIdComptimeFloat:
20233 case ZigTypeIdComptimeInt:20350 case ZigTypeIdComptimeInt:
...@@ -20253,7 +20370,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit...@@ -20253,7 +20370,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
20253 case ZigTypeIdBoundFn:20370 case ZigTypeIdBoundFn:
20254 case ZigTypeIdArgTuple:20371 case ZigTypeIdArgTuple:
20255 case ZigTypeIdNamespace:20372 case ZigTypeIdNamespace:
20256 case ZigTypeIdBlock:
20257 case ZigTypeIdUnreachable:20373 case ZigTypeIdUnreachable:
20258 case ZigTypeIdComptimeFloat:20374 case ZigTypeIdComptimeFloat:
20259 case ZigTypeIdComptimeInt:20375 case ZigTypeIdComptimeInt:
...@@ -20308,7 +20424,7 @@ static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionI...@@ -20308,7 +20424,7 @@ static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionI
20308 return ira->codegen->builtin_types.entry_invalid;20424 return ira->codegen->builtin_types.entry_invalid;
20309 }20425 }
2031020426
20311 if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))20427 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
20312 return ira->codegen->builtin_types.entry_invalid;20428 return ira->codegen->builtin_types.entry_invalid;
20313 if (!type_has_bits(dest_type)) {20429 if (!type_has_bits(dest_type)) {
20314 ir_add_error(ira, dest_type_value,20430 ir_add_error(ira, dest_type_value,
...@@ -20459,12 +20575,15 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr...@@ -20459,12 +20575,15 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr
20459 if (instruction->align_value != nullptr) {20575 if (instruction->align_value != nullptr) {
20460 if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))20576 if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))
20461 return ira->codegen->builtin_types.entry_invalid;20577 return ira->codegen->builtin_types.entry_invalid;
20578 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
20579 return ira->codegen->builtin_types.entry_invalid;
20462 } else {20580 } else {
20463 if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))20581 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
20464 return ira->codegen->builtin_types.entry_invalid;20582 return ira->codegen->builtin_types.entry_invalid;
20465 align_bytes = get_abi_alignment(ira->codegen, child_type);20583 align_bytes = 0;
20466 }20584 }
2046720585
20586
20468 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);20587 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
20469 out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,20588 out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
20470 instruction->is_const, instruction->is_volatile,20589 instruction->is_const, instruction->is_volatile,
...@@ -21108,7 +21227,7 @@ static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstruction...@@ -21108,7 +21227,7 @@ static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstruction
21108 return ira->codegen->builtin_types.entry_invalid;21227 return ira->codegen->builtin_types.entry_invalid;
21109 }21228 }
2111021229
21111 if ((err = type_ensure_zero_bits_known(ira->codegen, target->value.type)))21230 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
21112 return ira->codegen->builtin_types.entry_invalid;21231 return ira->codegen->builtin_types.entry_invalid;
2111321232
21114 ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;21233 ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;
...@@ -21131,7 +21250,7 @@ static ZigType *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstruction...@@ -21131,7 +21250,7 @@ static ZigType *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstruction
21131 return ira->codegen->builtin_types.entry_invalid;21250 return ira->codegen->builtin_types.entry_invalid;
21132 }21251 }
2113321252
21134 if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))21253 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
21135 return ira->codegen->builtin_types.entry_invalid;21254 return ira->codegen->builtin_types.entry_invalid;
2113621255
21137 ZigType *tag_type = dest_type->data.enumeration.tag_int_type;21256 ZigType *tag_type = dest_type->data.enumeration.tag_int_type;
src/link.cpp+18-61
...@@ -5,7 +5,6 @@...@@ -5,7 +5,6 @@
5 * See http://opensource.org/licenses/MIT5 * See http://opensource.org/licenses/MIT
6 */6 */
77
8#include "link.hpp"
9#include "os.hpp"8#include "os.hpp"
10#include "config.h"9#include "config.h"
11#include "codegen.hpp"10#include "codegen.hpp"
...@@ -13,7 +12,6 @@...@@ -13,7 +12,6 @@
1312
14struct LinkJob {13struct LinkJob {
15 CodeGen *codegen;14 CodeGen *codegen;
16 Buf out_file;
17 ZigList<const char *> args;15 ZigList<const char *> args;
18 bool link_in_crt;16 bool link_in_crt;
19 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;17 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
...@@ -44,8 +42,6 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)...@@ -44,8 +42,6 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
44 child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir;42 child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir;
45 child_gen->verbose_cimport = parent_gen->verbose_cimport;43 child_gen->verbose_cimport = parent_gen->verbose_cimport;
4644
47 codegen_set_cache_dir(child_gen, parent_gen->cache_dir);
48
49 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);45 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
50 codegen_set_is_static(child_gen, parent_gen->is_static);46 codegen_set_is_static(child_gen, parent_gen->is_static);
5147
...@@ -62,16 +58,9 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)...@@ -62,16 +58,9 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
62 new_link_lib->provided_explicitly = link_lib->provided_explicitly;58 new_link_lib->provided_explicitly = link_lib->provided_explicitly;
63 }59 }
6460
65 codegen_build(child_gen);61 child_gen->enable_cache = true;
66 const char *o_ext = target_o_file_ext(&child_gen->zig_target);62 codegen_build_and_link(child_gen);
67 Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);63 return &child_gen->output_file_path;
68 Buf *output_path = buf_alloc();
69 os_path_join(&parent_gen->cache_dir, o_out_name, output_path);
70 codegen_link(child_gen, buf_ptr(output_path));
71
72 codegen_destroy(child_gen);
73
74 return output_path;
75}64}
7665
77static Buf *build_o(CodeGen *parent_gen, const char *oname) {66static Buf *build_o(CodeGen *parent_gen, const char *oname) {
...@@ -239,15 +228,15 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -239,15 +228,15 @@ static void construct_linker_job_elf(LinkJob *lj) {
239 } else if (shared) {228 } else if (shared) {
240 lj->args.append("-shared");229 lj->args.append("-shared");
241230
242 if (buf_len(&lj->out_file) == 0) {231 if (buf_len(&g->output_file_path) == 0) {
243 buf_appendf(&lj->out_file, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",232 buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
244 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);233 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
245 }234 }
246 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);235 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
247 }236 }
248237
249 lj->args.append("-o");238 lj->args.append("-o");
250 lj->args.append(buf_ptr(&lj->out_file));239 lj->args.append(buf_ptr(&g->output_file_path));
251240
252 if (lj->link_in_crt) {241 if (lj->link_in_crt) {
253 const char *crt1o;242 const char *crt1o;
...@@ -399,7 +388,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {...@@ -399,7 +388,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
399388
400 lj->args.append("--relocatable"); // So lld doesn't look for _start.389 lj->args.append("--relocatable"); // So lld doesn't look for _start.
401 lj->args.append("-o");390 lj->args.append("-o");
402 lj->args.append(buf_ptr(&lj->out_file));391 lj->args.append(buf_ptr(&g->output_file_path));
403392
404 // .o files393 // .o files
405 for (size_t i = 0; i < g->link_objects.length; i += 1) {394 for (size_t i = 0; i < g->link_objects.length; i += 1) {
...@@ -480,7 +469,7 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -480,7 +469,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
480 // }469 // }
481 //}470 //}
482471
483 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file))));472 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
484473
485 if (g->libc_link_lib != nullptr) {474 if (g->libc_link_lib != nullptr) {
486 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));475 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
...@@ -587,11 +576,11 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -587,11 +576,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
587 buf_appendf(def_contents, "\n");576 buf_appendf(def_contents, "\n");
588577
589 Buf *def_path = buf_alloc();578 Buf *def_path = buf_alloc();
590 os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);579 os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
591 os_write_file(def_path, def_contents);580 os_write_file(def_path, def_contents);
592581
593 Buf *generated_lib_path = buf_alloc();582 Buf *generated_lib_path = buf_alloc();
594 os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);583 os_path_join(&g->artifact_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
595584
596 gen_lib_args.resize(0);585 gen_lib_args.resize(0);
597 gen_lib_args.append("link");586 gen_lib_args.append("link");
...@@ -799,8 +788,8 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -799,8 +788,8 @@ static void construct_linker_job_macho(LinkJob *lj) {
799 //lj->args.append("-install_name");788 //lj->args.append("-install_name");
800 //lj->args.append(buf_ptr(dylib_install_name));789 //lj->args.append(buf_ptr(dylib_install_name));
801790
802 if (buf_len(&lj->out_file) == 0) {791 if (buf_len(&g->output_file_path) == 0) {
803 buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",792 buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
804 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);793 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
805 }794 }
806 }795 }
...@@ -834,13 +823,13 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -834,13 +823,13 @@ static void construct_linker_job_macho(LinkJob *lj) {
834 }823 }
835824
836 lj->args.append("-o");825 lj->args.append("-o");
837 lj->args.append(buf_ptr(&lj->out_file));826 lj->args.append(buf_ptr(&g->output_file_path));
838827
839 for (size_t i = 0; i < g->rpath_list.length; i += 1) {828 for (size_t i = 0; i < g->rpath_list.length; i += 1) {
840 Buf *rpath = g->rpath_list.at(i);829 Buf *rpath = g->rpath_list.at(i);
841 add_rpath(lj, rpath);830 add_rpath(lj, rpath);
842 }831 }
843 add_rpath(lj, &lj->out_file);832 add_rpath(lj, &g->output_file_path);
844833
845 if (shared) {834 if (shared) {
846 lj->args.append("-headerpad_max_install_names");835 lj->args.append("-headerpad_max_install_names");
...@@ -944,7 +933,8 @@ static void construct_linker_job(LinkJob *lj) {...@@ -944,7 +933,8 @@ static void construct_linker_job(LinkJob *lj) {
944 }933 }
945}934}
946935
947void codegen_link(CodeGen *g, const char *out_file) {936void codegen_link(CodeGen *g) {
937 assert(g->out_type != OutTypeObj);
948 codegen_add_time_event(g, "Build Dependencies");938 codegen_add_time_event(g, "Build Dependencies");
949939
950 LinkJob lj = {0};940 LinkJob lj = {0};
...@@ -955,11 +945,6 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -955,11 +945,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
955945
956 lj.rpath_table.init(4);946 lj.rpath_table.init(4);
957 lj.codegen = g;947 lj.codegen = g;
958 if (out_file) {
959 buf_init_from_str(&lj.out_file, out_file);
960 } else {
961 buf_resize(&lj.out_file, 0);
962 }
963948
964 if (g->verbose_llvm_ir) {949 if (g->verbose_llvm_ir) {
965 fprintf(stderr, "\nOptimization:\n");950 fprintf(stderr, "\nOptimization:\n");
...@@ -968,35 +953,9 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -968,35 +953,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
968 LLVMDumpModule(g->module);953 LLVMDumpModule(g->module);
969 }954 }
970955
971 bool override_out_file = (buf_len(&lj.out_file) != 0);
972 if (!override_out_file) {
973 assert(g->root_out_name);
974
975 buf_init_from_buf(&lj.out_file, g->root_out_name);
976 if (g->out_type == OutTypeExe) {
977 buf_append_str(&lj.out_file, target_exe_file_ext(&g->zig_target));
978 }
979 }
980
981 if (g->out_type == OutTypeObj) {
982 if (override_out_file) {
983 assert(g->link_objects.length == 1);
984 Buf *o_file_path = g->link_objects.at(0);
985 int err;
986 if ((err = os_rename(o_file_path, &lj.out_file))) {
987 zig_panic("unable to rename object file %s into final output %s: %s", buf_ptr(o_file_path), buf_ptr(&lj.out_file), err_str(err));
988 }
989 }
990 return;
991 }
992
993 if (g->out_type == OutTypeLib && g->is_static) {956 if (g->out_type == OutTypeLib && g->is_static) {
994 // invoke `ar`957 fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");
995 // example:958 exit(1);
996 // # static link into libfoo.a
997 // ar rcs libfoo.a foo1.o foo2.o
998 zig_panic("TODO invoke ar");
999 return;
1000 }959 }
1001960
1002 lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);961 lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
...@@ -1019,6 +978,4 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -1019,6 +978,4 @@ void codegen_link(CodeGen *g, const char *out_file) {
1019 fprintf(stderr, "%s\n", buf_ptr(&diag));978 fprintf(stderr, "%s\n", buf_ptr(&diag));
1020 exit(1);979 exit(1);
1021 }980 }
1022
1023 codegen_add_time_event(g, "Done");
1024}981}
src/link.hpp deleted-17
...@@ -1,17 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_LINK_HPP
9#define ZIG_LINK_HPP
10
11#include "all_types.hpp"
12
13void codegen_link(CodeGen *g, const char *out_file);
14
15
16#endif
17
src/main.cpp+93-52
...@@ -8,9 +8,9 @@...@@ -8,9 +8,9 @@
8#include "ast_render.hpp"8#include "ast_render.hpp"
9#include "buffer.hpp"9#include "buffer.hpp"
10#include "codegen.hpp"10#include "codegen.hpp"
11#include "compiler.hpp"
11#include "config.h"12#include "config.h"
12#include "error.hpp"13#include "error.hpp"
13#include "link.hpp"
14#include "os.hpp"14#include "os.hpp"
15#include "target.hpp"15#include "target.hpp"
1616
...@@ -24,6 +24,7 @@ static int usage(const char *arg0) {...@@ -24,6 +24,7 @@ static int usage(const char *arg0) {
24 " build-lib [source] create library from source or object files\n"24 " build-lib [source] create library from source or object files\n"
25 " build-obj [source] create object from source or assembly\n"25 " build-obj [source] create object from source or assembly\n"
26 " builtin show the source code of that @import(\"builtin\")\n"26 " builtin show the source code of that @import(\"builtin\")\n"
27 " id print the base64-encoded compiler id\n"
27 " run [source] create executable and run immediately\n"28 " run [source] create executable and run immediately\n"
28 " translate-c [source] convert c code to zig code\n"29 " translate-c [source] convert c code to zig code\n"
29 " targets list available compilation targets\n"30 " targets list available compilation targets\n"
...@@ -33,9 +34,10 @@ static int usage(const char *arg0) {...@@ -33,9 +34,10 @@ static int usage(const char *arg0) {
33 "Compile Options:\n"34 "Compile Options:\n"
34 " --assembly [source] add assembly file to build\n"35 " --assembly [source] add assembly file to build\n"
35 " --cache-dir [path] override the cache directory\n"36 " --cache-dir [path] override the cache directory\n"
37 " --cache [auto|off|on] build to the global cache and print output path to stdout\n"
36 " --color [auto|off|on] enable or disable colored error messages\n"38 " --color [auto|off|on] enable or disable colored error messages\n"
37 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"39 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
38 " --enable-timing-info print timing diagnostics\n"40 " -ftime-report print timing diagnostics\n"
39 " --libc-include-dir [path] directory where libc stdlib.h resides\n"41 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
40 " --name [name] override output name\n"42 " --name [name] override output name\n"
41 " --output [file] override destination path\n"43 " --output [file] override destination path\n"
...@@ -256,6 +258,24 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) {...@@ -256,6 +258,24 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) {
256 }258 }
257}259}
258260
261enum CacheOpt {
262 CacheOptAuto,
263 CacheOptOn,
264 CacheOptOff,
265};
266
267static bool get_cache_opt(CacheOpt opt, bool default_value) {
268 switch (opt) {
269 case CacheOptAuto:
270 return default_value;
271 case CacheOptOn:
272 return true;
273 case CacheOptOff:
274 return false;
275 }
276 zig_unreachable();
277}
278
259int main(int argc, char **argv) {279int main(int argc, char **argv) {
260 if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {280 if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
261 printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",281 printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
...@@ -270,6 +290,17 @@ int main(int argc, char **argv) {...@@ -270,6 +290,17 @@ int main(int argc, char **argv) {
270 return 0;290 return 0;
271 }291 }
272292
293 if (argc == 2 && strcmp(argv[1], "id") == 0) {
294 Error err;
295 Buf *compiler_id;
296 if ((err = get_compiler_id(&compiler_id))) {
297 fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
298 return EXIT_FAILURE;
299 }
300 printf("%s\n", buf_ptr(compiler_id));
301 return EXIT_SUCCESS;
302 }
303
273 os_init();304 os_init();
274305
275 char *arg0 = argv[0];306 char *arg0 = argv[0];
...@@ -289,6 +320,7 @@ int main(int argc, char **argv) {...@@ -289,6 +320,7 @@ int main(int argc, char **argv) {
289 bool verbose_llvm_ir = false;320 bool verbose_llvm_ir = false;
290 bool verbose_cimport = false;321 bool verbose_cimport = false;
291 ErrColor color = ErrColorAuto;322 ErrColor color = ErrColorAuto;
323 CacheOpt enable_cache = CacheOptAuto;
292 const char *libc_lib_dir = nullptr;324 const char *libc_lib_dir = nullptr;
293 const char *libc_static_lib_dir = nullptr;325 const char *libc_static_lib_dir = nullptr;
294 const char *libc_include_dir = nullptr;326 const char *libc_include_dir = nullptr;
...@@ -325,8 +357,7 @@ int main(int argc, char **argv) {...@@ -325,8 +357,7 @@ int main(int argc, char **argv) {
325 CliPkg *cur_pkg = allocate<CliPkg>(1);357 CliPkg *cur_pkg = allocate<CliPkg>(1);
326 BuildMode build_mode = BuildModeDebug;358 BuildMode build_mode = BuildModeDebug;
327 ZigList<const char *> test_exec_args = {0};359 ZigList<const char *> test_exec_args = {0};
328 int comptime_args_end = 0;360 int runtime_args_start = -1;
329 int runtime_args_start = argc;
330 bool no_rosegment_workaround = false;361 bool no_rosegment_workaround = false;
331362
332 if (argc >= 2 && strcmp(argv[1], "build") == 0) {363 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
...@@ -370,8 +401,9 @@ int main(int argc, char **argv) {...@@ -370,8 +401,9 @@ int main(int argc, char **argv) {
370 Buf *build_runner_path = buf_alloc();401 Buf *build_runner_path = buf_alloc();
371 os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);402 os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);
372403
373
374 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);404 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
405 g->enable_time_report = timing_info;
406 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
375 codegen_set_out_name(g, buf_create_from_str("build"));407 codegen_set_out_name(g, buf_create_from_str("build"));
376408
377 Buf *build_file_buf = buf_create_from_str(build_file);409 Buf *build_file_buf = buf_create_from_str(build_file);
...@@ -380,6 +412,7 @@ int main(int argc, char **argv) {...@@ -380,6 +412,7 @@ int main(int argc, char **argv) {
380 Buf build_file_dirname = BUF_INIT;412 Buf build_file_dirname = BUF_INIT;
381 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);413 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
382414
415
383 Buf full_cache_dir = BUF_INIT;416 Buf full_cache_dir = BUF_INIT;
384 if (cache_dir == nullptr) {417 if (cache_dir == nullptr) {
385 os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);418 os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
...@@ -388,10 +421,6 @@ int main(int argc, char **argv) {...@@ -388,10 +421,6 @@ int main(int argc, char **argv) {
388 full_cache_dir = os_path_resolve(&cache_dir_buf, 1);421 full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
389 }422 }
390423
391 Buf *path_to_build_exe = buf_alloc();
392 os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
393 codegen_set_cache_dir(g, full_cache_dir);
394
395 args.items[1] = buf_ptr(&build_file_dirname);424 args.items[1] = buf_ptr(&build_file_dirname);
396 args.items[2] = buf_ptr(&full_cache_dir);425 args.items[2] = buf_ptr(&full_cache_dir);
397426
...@@ -459,15 +488,14 @@ int main(int argc, char **argv) {...@@ -459,15 +488,14 @@ int main(int argc, char **argv) {
459 PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),488 PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
460 buf_ptr(&build_file_basename));489 buf_ptr(&build_file_basename));
461 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);490 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
462 codegen_build(g);491 g->enable_cache = get_cache_opt(enable_cache, true);
463 codegen_link(g, buf_ptr(path_to_build_exe));492 codegen_build_and_link(g);
464 codegen_destroy(g);
465493
466 Termination term;494 Termination term;
467 os_spawn_process(buf_ptr(path_to_build_exe), args, &term);495 os_spawn_process(buf_ptr(&g->output_file_path), args, &term);
468 if (term.how != TerminationIdClean || term.code != 0) {496 if (term.how != TerminationIdClean || term.code != 0) {
469 fprintf(stderr, "\nBuild failed. The following command failed:\n");497 fprintf(stderr, "\nBuild failed. The following command failed:\n");
470 fprintf(stderr, "%s", buf_ptr(path_to_build_exe));498 fprintf(stderr, "%s", buf_ptr(&g->output_file_path));
471 for (size_t i = 0; i < args.length; i += 1) {499 for (size_t i = 0; i < args.length; i += 1) {
472 fprintf(stderr, " %s", args.at(i));500 fprintf(stderr, " %s", args.at(i));
473 }501 }
...@@ -476,15 +504,11 @@ int main(int argc, char **argv) {...@@ -476,15 +504,11 @@ int main(int argc, char **argv) {
476 return (term.how == TerminationIdClean) ? term.code : -1;504 return (term.how == TerminationIdClean) ? term.code : -1;
477 }505 }
478506
479 for (int i = 1; i < argc; i += 1, comptime_args_end += 1) {507 for (int i = 1; i < argc; i += 1) {
480 char *arg = argv[i];508 char *arg = argv[i];
481509
482 if (arg[0] == '-') {510 if (arg[0] == '-') {
483 if (strcmp(arg, "--") == 0) {511 if (strcmp(arg, "--release-fast") == 0) {
484 // ignore -- from both compile and runtime arg sets
485 runtime_args_start = i + 1;
486 break;
487 } else if (strcmp(arg, "--release-fast") == 0) {
488 build_mode = BuildModeFastRelease;512 build_mode = BuildModeFastRelease;
489 } else if (strcmp(arg, "--release-safe") == 0) {513 } else if (strcmp(arg, "--release-safe") == 0) {
490 build_mode = BuildModeSafeRelease;514 build_mode = BuildModeSafeRelease;
...@@ -516,7 +540,7 @@ int main(int argc, char **argv) {...@@ -516,7 +540,7 @@ int main(int argc, char **argv) {
516 no_rosegment_workaround = true;540 no_rosegment_workaround = true;
517 } else if (strcmp(arg, "--each-lib-rpath") == 0) {541 } else if (strcmp(arg, "--each-lib-rpath") == 0) {
518 each_lib_rpath = true;542 each_lib_rpath = true;
519 } else if (strcmp(arg, "--enable-timing-info") == 0) {543 } else if (strcmp(arg, "-ftime-report") == 0) {
520 timing_info = true;544 timing_info = true;
521 } else if (strcmp(arg, "--test-cmd-bin") == 0) {545 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
522 test_exec_args.append(nullptr);546 test_exec_args.append(nullptr);
...@@ -562,6 +586,17 @@ int main(int argc, char **argv) {...@@ -562,6 +586,17 @@ int main(int argc, char **argv) {
562 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");586 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
563 return usage(arg0);587 return usage(arg0);
564 }588 }
589 } else if (strcmp(arg, "--cache") == 0) {
590 if (strcmp(argv[i], "auto") == 0) {
591 enable_cache = CacheOptAuto;
592 } else if (strcmp(argv[i], "on") == 0) {
593 enable_cache = CacheOptOn;
594 } else if (strcmp(argv[i], "off") == 0) {
595 enable_cache = CacheOptOff;
596 } else {
597 fprintf(stderr, "--cache options are 'auto', 'on', or 'off'\n");
598 return usage(arg0);
599 }
565 } else if (strcmp(arg, "--emit") == 0) {600 } else if (strcmp(arg, "--emit") == 0) {
566 if (strcmp(argv[i], "asm") == 0) {601 if (strcmp(argv[i], "asm") == 0) {
567 emit_file_type = EmitFileTypeAssembly;602 emit_file_type = EmitFileTypeAssembly;
...@@ -681,6 +716,10 @@ int main(int argc, char **argv) {...@@ -681,6 +716,10 @@ int main(int argc, char **argv) {
681 case CmdTest:716 case CmdTest:
682 if (!in_file) {717 if (!in_file) {
683 in_file = arg;718 in_file = arg;
719 if (cmd == CmdRun) {
720 runtime_args_start = i + 1;
721 break; // rest of the args are for the program
722 }
684 } else {723 } else {
685 fprintf(stderr, "Unexpected extra parameter: %s\n", arg);724 fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
686 return usage(arg0);725 return usage(arg0);
...@@ -790,32 +829,18 @@ int main(int argc, char **argv) {...@@ -790,32 +829,18 @@ int main(int argc, char **argv) {
790829
791 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;830 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
792831
793 Buf full_cache_dir = BUF_INIT;832 if (cmd == CmdRun && buf_out_name == nullptr) {
794 Buf *run_exec_path = buf_alloc();833 buf_out_name = buf_create_from_str("run");
795 if (cmd == CmdRun) {
796 if (buf_out_name == nullptr) {
797 buf_out_name = buf_create_from_str("run");
798 }
799
800 Buf *global_cache_dir = buf_alloc();
801 os_get_global_cache_directory(global_cache_dir);
802 os_path_join(global_cache_dir, buf_out_name, run_exec_path);
803 full_cache_dir = os_path_resolve(&global_cache_dir, 1);
804
805 out_file = buf_ptr(run_exec_path);
806 } else {
807 Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir);
808 full_cache_dir = os_path_resolve(&resolve_paths, 1);
809 }834 }
810
811 Buf *zig_lib_dir_buf = resolve_zig_lib_dir();835 Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
812836
813 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf);837 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf);
838 g->enable_time_report = timing_info;
839 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
814 codegen_set_out_name(g, buf_out_name);840 codegen_set_out_name(g, buf_out_name);
815 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);841 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
816 codegen_set_is_test(g, cmd == CmdTest);842 codegen_set_is_test(g, cmd == CmdTest);
817 codegen_set_linker_script(g, linker_script);843 codegen_set_linker_script(g, linker_script);
818 codegen_set_cache_dir(g, full_cache_dir);
819 if (each_lib_rpath)844 if (each_lib_rpath)
820 codegen_set_each_lib_rpath(g, each_lib_rpath);845 codegen_set_each_lib_rpath(g, each_lib_rpath);
821846
...@@ -885,6 +910,8 @@ int main(int argc, char **argv) {...@@ -885,6 +910,8 @@ int main(int argc, char **argv) {
885 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));910 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
886 }911 }
887912
913 if (out_file)
914 codegen_set_output_path(g, buf_create_from_str(out_file));
888 if (out_file_h)915 if (out_file_h)
889 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));916 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
890917
...@@ -904,8 +931,8 @@ int main(int argc, char **argv) {...@@ -904,8 +931,8 @@ int main(int argc, char **argv) {
904 if (cmd == CmdBuild || cmd == CmdRun) {931 if (cmd == CmdBuild || cmd == CmdRun) {
905 codegen_set_emit_file_type(g, emit_file_type);932 codegen_set_emit_file_type(g, emit_file_type);
906933
907 codegen_build(g);934 g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
908 codegen_link(g, out_file);935 codegen_build_and_link(g);
909 if (timing_info)936 if (timing_info)
910 codegen_print_timing_report(g, stdout);937 codegen_print_timing_report(g, stdout);
911938
...@@ -915,12 +942,26 @@ int main(int argc, char **argv) {...@@ -915,12 +942,26 @@ int main(int argc, char **argv) {
915 args.append(argv[i]);942 args.append(argv[i]);
916 }943 }
917944
945 const char *exec_path = buf_ptr(&g->output_file_path);
946 args.append(nullptr);
947
948 os_execv(exec_path, args.items);
949
950 args.pop();
918 Termination term;951 Termination term;
919 os_spawn_process(buf_ptr(run_exec_path), args, &term);952 os_spawn_process(exec_path, args, &term);
920 return term.code;953 return term.code;
954 } else if (cmd == CmdBuild) {
955 if (g->enable_cache) {
956 printf("%s\n", buf_ptr(&g->output_file_path));
957 if (g->out_h_path != nullptr) {
958 printf("%s\n", buf_ptr(g->out_h_path));
959 }
960 }
961 return EXIT_SUCCESS;
962 } else {
963 zig_unreachable();
921 }964 }
922
923 return EXIT_SUCCESS;
924 } else if (cmd == CmdTranslateC) {965 } else if (cmd == CmdTranslateC) {
925 codegen_translate_c(g, in_file_buf);966 codegen_translate_c(g, in_file_buf);
926 ast_render(g, stdout, g->root_import->root, 4);967 ast_render(g, stdout, g->root_import->root, 4);
...@@ -933,11 +974,16 @@ int main(int argc, char **argv) {...@@ -933,11 +974,16 @@ int main(int argc, char **argv) {
933 ZigTarget native;974 ZigTarget native;
934 get_native_target(&native);975 get_native_target(&native);
935976
936 ZigTarget *non_null_target = target ? target : &native;977 g->enable_cache = get_cache_opt(enable_cache, false);
978 codegen_build_and_link(g);
937979
938 Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));980 if (timing_info) {
981 codegen_print_timing_report(g, stdout);
982 }
983
984 Buf *test_exe_path_unresolved = &g->output_file_path;
939 Buf *test_exe_path = buf_alloc();985 Buf *test_exe_path = buf_alloc();
940 os_path_join(&full_cache_dir, test_exe_name, test_exe_path);986 *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
941987
942 for (size_t i = 0; i < test_exec_args.length; i += 1) {988 for (size_t i = 0; i < test_exec_args.length; i += 1) {
943 if (test_exec_args.items[i] == nullptr) {989 if (test_exec_args.items[i] == nullptr) {
...@@ -945,9 +991,6 @@ int main(int argc, char **argv) {...@@ -945,9 +991,6 @@ int main(int argc, char **argv) {
945 }991 }
946 }992 }
947993
948 codegen_build(g);
949 codegen_link(g, buf_ptr(test_exe_path));
950
951 if (!target_can_exec(&native, target)) {994 if (!target_can_exec(&native, target)) {
952 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",995 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
953 buf_ptr(test_exe_path));996 buf_ptr(test_exe_path));
...@@ -969,8 +1012,6 @@ int main(int argc, char **argv) {...@@ -969,8 +1012,6 @@ int main(int argc, char **argv) {
969 if (term.how != TerminationIdClean || term.code != 0) {1012 if (term.how != TerminationIdClean || term.code != 0) {
970 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");1013 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
971 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));1014 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
972 } else if (timing_info) {
973 codegen_print_timing_report(g, stdout);
974 }1015 }
975 return (term.how == TerminationIdClean) ? term.code : -1;1016 return (term.how == TerminationIdClean) ? term.code : -1;
976 } else {1017 } else {
src/os.cpp+479-120
...@@ -24,6 +24,7 @@...@@ -24,6 +24,7 @@
24#endif24#endif
2525
26#include <windows.h>26#include <windows.h>
27#include <shlobj.h>
27#include <io.h>28#include <io.h>
28#include <fcntl.h>29#include <fcntl.h>
2930
...@@ -40,6 +41,10 @@ typedef SSIZE_T ssize_t;...@@ -40,6 +41,10 @@ typedef SSIZE_T ssize_t;
4041
41#endif42#endif
4243
44#if defined(ZIG_OS_LINUX)
45#include <link.h>
46#endif
47
4348
44#if defined(__MACH__)49#if defined(__MACH__)
45#include <mach/clock.h>50#include <mach/clock.h>
...@@ -57,54 +62,6 @@ static clock_serv_t cclock;...@@ -57,54 +62,6 @@ static clock_serv_t cclock;
57#include <errno.h>62#include <errno.h>
58#include <time.h>63#include <time.h>
5964
60// Ported from std/mem.zig.
61// Coordinate struct fields with memSplit function
62struct SplitIterator {
63 size_t index;
64 Slice<uint8_t> buffer;
65 Slice<uint8_t> split_bytes;
66};
67
68// Ported from std/mem.zig.
69static bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
70 for (size_t i = 0; i < self->split_bytes.len; i += 1) {
71 if (byte == self->split_bytes.ptr[i]) {
72 return true;
73 }
74 }
75 return false;
76}
77
78// Ported from std/mem.zig.
79static Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
80 // move to beginning of token
81 while (self->index < self->buffer.len &&
82 SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
83 {
84 self->index += 1;
85 }
86 size_t start = self->index;
87 if (start == self->buffer.len) {
88 return {};
89 }
90
91 // move to end of token
92 while (self->index < self->buffer.len &&
93 !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
94 {
95 self->index += 1;
96 }
97 size_t end = self->index;
98
99 return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
100}
101
102// Ported from std/mem.zig
103static SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
104 return SplitIterator{0, buffer, split_bytes};
105}
106
107
108#if defined(ZIG_OS_POSIX)65#if defined(ZIG_OS_POSIX)
109static void populate_termination(Termination *term, int status) {66static void populate_termination(Termination *term, int status) {
110 if (WIFEXITED(status)) {67 if (WIFEXITED(status)) {
...@@ -765,7 +722,7 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {...@@ -765,7 +722,7 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
765#endif722#endif
766}723}
767724
768int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {725Error os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
769 static const ssize_t buf_size = 0x2000;726 static const ssize_t buf_size = 0x2000;
770 buf_resize(out_buf, buf_size);727 buf_resize(out_buf, buf_size);
771 ssize_t actual_buf_len = 0;728 ssize_t actual_buf_len = 0;
...@@ -801,7 +758,7 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {...@@ -801,7 +758,7 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
801 if (amt_read != buf_size) {758 if (amt_read != buf_size) {
802 if (feof(f)) {759 if (feof(f)) {
803 buf_resize(out_buf, actual_buf_len);760 buf_resize(out_buf, actual_buf_len);
804 return 0;761 return ErrorNone;
805 } else {762 } else {
806 return ErrorFileSystem;763 return ErrorFileSystem;
807 }764 }
...@@ -813,13 +770,13 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {...@@ -813,13 +770,13 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
813 zig_unreachable();770 zig_unreachable();
814}771}
815772
816int os_file_exists(Buf *full_path, bool *result) {773Error os_file_exists(Buf *full_path, bool *result) {
817#if defined(ZIG_OS_WINDOWS)774#if defined(ZIG_OS_WINDOWS)
818 *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;775 *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;
819 return 0;776 return ErrorNone;
820#else777#else
821 *result = access(buf_ptr(full_path), F_OK) != -1;778 *result = access(buf_ptr(full_path), F_OK) != -1;
822 return 0;779 return ErrorNone;
823#endif780#endif
824}781}
825782
...@@ -878,13 +835,15 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,...@@ -878,13 +835,15 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
878835
879 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");836 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
880 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");837 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
881 os_fetch_file(stdout_f, out_stdout, false);838 Error err1 = os_fetch_file(stdout_f, out_stdout, false);
882 os_fetch_file(stderr_f, out_stderr, false);839 Error err2 = os_fetch_file(stderr_f, out_stderr, false);
883840
884 fclose(stdout_f);841 fclose(stdout_f);
885 fclose(stderr_f);842 fclose(stderr_f);
886843
887 return 0;844 if (err1) return err1;
845 if (err2) return err2;
846 return ErrorNone;
888 }847 }
889}848}
890#endif849#endif
...@@ -1016,6 +975,22 @@ static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,...@@ -1016,6 +975,22 @@ static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
1016}975}
1017#endif976#endif
1018977
978Error os_execv(const char *exe, const char **argv) {
979#if defined(ZIG_OS_WINDOWS)
980 return ErrorUnsupportedOperatingSystem;
981#else
982 execv(exe, (char *const *)argv);
983 switch (errno) {
984 case ENOMEM:
985 return ErrorSystemResources;
986 case EIO:
987 return ErrorFileSystem;
988 default:
989 return ErrorUnexpected;
990 }
991#endif
992}
993
1019int os_exec_process(const char *exe, ZigList<const char *> &args,994int os_exec_process(const char *exe, ZigList<const char *> &args,
1020 Termination *term, Buf *out_stderr, Buf *out_stdout)995 Termination *term, Buf *out_stderr, Buf *out_stdout)
1021{996{
...@@ -1092,7 +1067,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) {...@@ -1092,7 +1067,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) {
1092 }1067 }
1093}1068}
10941069
1095int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {1070Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
1096 FILE *f = fopen(buf_ptr(full_path), "rb");1071 FILE *f = fopen(buf_ptr(full_path), "rb");
1097 if (!f) {1072 if (!f) {
1098 switch (errno) {1073 switch (errno) {
...@@ -1111,7 +1086,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {...@@ -1111,7 +1086,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
1111 return ErrorFileSystem;1086 return ErrorFileSystem;
1112 }1087 }
1113 }1088 }
1114 int result = os_fetch_file(f, out_contents, skip_shebang);1089 Error result = os_fetch_file(f, out_contents, skip_shebang);
1115 fclose(f);1090 fclose(f);
1116 return result;1091 return result;
1117}1092}
...@@ -1282,44 +1257,6 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {...@@ -1282,44 +1257,6 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
1282#endif1257#endif
1283}1258}
12841259
1285#if defined(ZIG_OS_POSIX)
1286int os_get_global_cache_directory(Buf *out_tmp_path) {
1287 const char *tmp_dir = getenv("TMPDIR");
1288 if (!tmp_dir) {
1289 tmp_dir = P_tmpdir;
1290 }
1291
1292 Buf *tmp_dir_buf = buf_create_from_str(tmp_dir);
1293 Buf *cache_dirname_buf = buf_create_from_str("zig-cache");
1294
1295 buf_resize(out_tmp_path, 0);
1296 os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path);
1297
1298 buf_deinit(tmp_dir_buf);
1299 buf_deinit(cache_dirname_buf);
1300 return 0;
1301}
1302#endif
1303
1304#if defined(ZIG_OS_WINDOWS)
1305int os_get_global_cache_directory(Buf *out_tmp_path) {
1306 char tmp_dir[MAX_PATH + 1];
1307 if (GetTempPath(MAX_PATH, tmp_dir) == 0) {
1308 zig_panic("GetTempPath failed");
1309 }
1310
1311 Buf *tmp_dir_buf = buf_create_from_str(tmp_dir);
1312 Buf *cache_dirname_buf = buf_create_from_str("zig-cache");
1313
1314 buf_resize(out_tmp_path, 0);
1315 os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path);
1316
1317 buf_deinit(tmp_dir_buf);
1318 buf_deinit(cache_dirname_buf);
1319 return 0;
1320}
1321#endif
1322
1323int os_delete_file(Buf *path) {1260int os_delete_file(Buf *path) {
1324 if (remove(buf_ptr(path))) {1261 if (remove(buf_ptr(path))) {
1325 return ErrorFileSystem;1262 return ErrorFileSystem;
...@@ -1368,16 +1305,16 @@ double os_get_time(void) {...@@ -1368,16 +1305,16 @@ double os_get_time(void) {
1368#endif1305#endif
1369}1306}
13701307
1371int os_make_path(Buf *path) {1308Error os_make_path(Buf *path) {
1372 Buf resolved_path = os_path_resolve(&path, 1);1309 Buf resolved_path = os_path_resolve(&path, 1);
13731310
1374 size_t end_index = buf_len(&resolved_path);1311 size_t end_index = buf_len(&resolved_path);
1375 int err;1312 Error err;
1376 while (true) {1313 while (true) {
1377 if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {1314 if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
1378 if (err == ErrorPathAlreadyExists) {1315 if (err == ErrorPathAlreadyExists) {
1379 if (end_index == buf_len(&resolved_path))1316 if (end_index == buf_len(&resolved_path))
1380 return 0;1317 return ErrorNone;
1381 } else if (err == ErrorFileNotFound) {1318 } else if (err == ErrorFileNotFound) {
1382 // march end_index backward until next path component1319 // march end_index backward until next path component
1383 while (true) {1320 while (true) {
...@@ -1391,7 +1328,7 @@ int os_make_path(Buf *path) {...@@ -1391,7 +1328,7 @@ int os_make_path(Buf *path) {
1391 }1328 }
1392 }1329 }
1393 if (end_index == buf_len(&resolved_path))1330 if (end_index == buf_len(&resolved_path))
1394 return 0;1331 return ErrorNone;
1395 // march end_index forward until next path component1332 // march end_index forward until next path component
1396 while (true) {1333 while (true) {
1397 end_index += 1;1334 end_index += 1;
...@@ -1399,10 +1336,10 @@ int os_make_path(Buf *path) {...@@ -1399,10 +1336,10 @@ int os_make_path(Buf *path) {
1399 break;1336 break;
1400 }1337 }
1401 }1338 }
1402 return 0;1339 return ErrorNone;
1403}1340}
14041341
1405int os_make_dir(Buf *path) {1342Error os_make_dir(Buf *path) {
1406#if defined(ZIG_OS_WINDOWS)1343#if defined(ZIG_OS_WINDOWS)
1407 if (!CreateDirectory(buf_ptr(path), NULL)) {1344 if (!CreateDirectory(buf_ptr(path), NULL)) {
1408 if (GetLastError() == ERROR_ALREADY_EXISTS)1345 if (GetLastError() == ERROR_ALREADY_EXISTS)
...@@ -1413,7 +1350,7 @@ int os_make_dir(Buf *path) {...@@ -1413,7 +1350,7 @@ int os_make_dir(Buf *path) {
1413 return ErrorAccess;1350 return ErrorAccess;
1414 return ErrorUnexpected;1351 return ErrorUnexpected;
1415 }1352 }
1416 return 0;1353 return ErrorNone;
1417#else1354#else
1418 if (mkdir(buf_ptr(path), 0755) == -1) {1355 if (mkdir(buf_ptr(path), 0755) == -1) {
1419 if (errno == EEXIST)1356 if (errno == EEXIST)
...@@ -1424,7 +1361,7 @@ int os_make_dir(Buf *path) {...@@ -1424,7 +1361,7 @@ int os_make_dir(Buf *path) {
1424 return ErrorAccess;1361 return ErrorAccess;
1425 return ErrorUnexpected;1362 return ErrorUnexpected;
1426 }1363 }
1427 return 0;1364 return ErrorNone;
1428#endif1365#endif
1429}1366}
14301367
...@@ -1447,7 +1384,7 @@ int os_init(void) {...@@ -1447,7 +1384,7 @@ int os_init(void) {
1447 return 0;1384 return 0;
1448}1385}
14491386
1450int os_self_exe_path(Buf *out_path) {1387Error os_self_exe_path(Buf *out_path) {
1451#if defined(ZIG_OS_WINDOWS)1388#if defined(ZIG_OS_WINDOWS)
1452 buf_resize(out_path, 256);1389 buf_resize(out_path, 256);
1453 for (;;) {1390 for (;;) {
...@@ -1457,7 +1394,7 @@ int os_self_exe_path(Buf *out_path) {...@@ -1457,7 +1394,7 @@ int os_self_exe_path(Buf *out_path) {
1457 }1394 }
1458 if (copied_amt < buf_len(out_path)) {1395 if (copied_amt < buf_len(out_path)) {
1459 buf_resize(out_path, copied_amt);1396 buf_resize(out_path, copied_amt);
1460 return 0;1397 return ErrorNone;
1461 }1398 }
1462 buf_resize(out_path, buf_len(out_path) * 2);1399 buf_resize(out_path, buf_len(out_path) * 2);
1463 }1400 }
...@@ -1480,27 +1417,21 @@ int os_self_exe_path(Buf *out_path) {...@@ -1480,27 +1417,21 @@ int os_self_exe_path(Buf *out_path) {
1480 char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));1417 char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
1481 if (!real_path) {1418 if (!real_path) {
1482 buf_init_from_buf(out_path, tmp);1419 buf_init_from_buf(out_path, tmp);
1483 return 0;1420 return ErrorNone;
1484 }1421 }
14851422
1486 // Resize out_path for the correct length.1423 // Resize out_path for the correct length.
1487 buf_resize(out_path, strlen(buf_ptr(out_path)));1424 buf_resize(out_path, strlen(buf_ptr(out_path)));
14881425
1489 return 0;1426 return ErrorNone;
1490#elif defined(ZIG_OS_LINUX)1427#elif defined(ZIG_OS_LINUX)
1491 buf_resize(out_path, 256);1428 buf_resize(out_path, PATH_MAX);
1492 for (;;) {1429 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
1493 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));1430 if (amt == -1) {
1494 if (amt == -1) {1431 return ErrorUnexpected;
1495 return ErrorUnexpected;
1496 }
1497 if (amt == (ssize_t)buf_len(out_path)) {
1498 buf_resize(out_path, buf_len(out_path) * 2);
1499 continue;
1500 }
1501 buf_resize(out_path, amt);
1502 return 0;
1503 }1432 }
1433 buf_resize(out_path, amt);
1434 return ErrorNone;
1504#endif1435#endif
1505 return ErrorFileNotFound;1436 return ErrorFileNotFound;
1506}1437}
...@@ -1685,3 +1616,431 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy...@@ -1685,3 +1616,431 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
1685 return ErrorFileNotFound;1616 return ErrorFileNotFound;
1686#endif1617#endif
1687}1618}
1619
1620#if defined(ZIG_OS_WINDOWS)
1621// Ported from std/unicode.zig
1622struct Utf16LeIterator {
1623 uint8_t *bytes;
1624 size_t i;
1625};
1626
1627// Ported from std/unicode.zig
1628static Utf16LeIterator Utf16LeIterator_init(WCHAR *ptr) {
1629 return {(uint8_t*)ptr, 0};
1630}
1631
1632// Ported from std/unicode.zig
1633static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
1634 if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
1635 return {};
1636 uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1637 if (c0 & ~((uint32_t)0x03ff) == 0xd800) {
1638 // surrogate pair
1639 it->i += 2;
1640 assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
1641 uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1642 assert(c1 & ~((uint32_t)0x03ff) == 0xdc00);
1643 it->i += 2;
1644 return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
1645 } else {
1646 assert(c0 & ~((uint32_t)0x03ff) != 0xdc00);
1647 it->i += 2;
1648 return Optional<uint32_t>::some(c0);
1649 }
1650}
1651
1652// Ported from std/unicode.zig
1653static uint8_t utf8CodepointSequenceLength(uint32_t c) {
1654 if (c < 0x80) return 1;
1655 if (c < 0x800) return 2;
1656 if (c < 0x10000) return 3;
1657 if (c < 0x110000) return 4;
1658 zig_unreachable();
1659}
1660
1661// Ported from std/unicode.zig
1662static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
1663 size_t length = utf8CodepointSequenceLength(c);
1664 assert(out.len >= length);
1665 switch (length) {
1666 // The pattern for each is the same
1667 // - Increasing the initial shift by 6 each time
1668 // - Each time after the first shorten the shifted
1669 // value to a max of 0b111111 (63)
1670 case 1:
1671 out.ptr[0] = c; // Can just do 0 + codepoint for initial range
1672 break;
1673 case 2:
1674 out.ptr[0] = 0b11000000 | (c >> 6);
1675 out.ptr[1] = 0b10000000 | (c & 0b111111);
1676 break;
1677 case 3:
1678 assert(!(0xd800 <= c && c <= 0xdfff));
1679 out.ptr[0] = 0b11100000 | (c >> 12);
1680 out.ptr[1] = 0b10000000 | ((c >> 6) & 0b111111);
1681 out.ptr[2] = 0b10000000 | (c & 0b111111);
1682 break;
1683 case 4:
1684 out.ptr[0] = 0b11110000 | (c >> 18);
1685 out.ptr[1] = 0b10000000 | ((c >> 12) & 0b111111);
1686 out.ptr[2] = 0b10000000 | ((c >> 6) & 0b111111);
1687 out.ptr[3] = 0b10000000 | (c & 0b111111);
1688 break;
1689 default:
1690 zig_unreachable();
1691 }
1692 return length;
1693}
1694
1695// Ported from std.unicode.utf16leToUtf8Alloc
1696static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
1697 // optimistically guess that it will all be ascii.
1698 buf_resize(out, 0);
1699 size_t out_index = 0;
1700 Utf16LeIterator it = Utf16LeIterator_init(utf16le);
1701 for (;;) {
1702 Optional<uint32_t> opt_codepoint = Utf16LeIterator_nextCodepoint(&it);
1703 if (!opt_codepoint.is_some) break;
1704 uint32_t codepoint = opt_codepoint.value;
1705
1706 size_t utf8_len = utf8CodepointSequenceLength(codepoint);
1707 buf_resize(out, buf_len(out) + utf8_len);
1708 utf8Encode(codepoint, {(uint8_t*)buf_ptr(out)+out_index, buf_len(out)-out_index});
1709 out_index += utf8_len;
1710 }
1711}
1712#endif
1713
1714// Ported from std.os.getAppDataDir
1715Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1716#if defined(ZIG_OS_WINDOWS)
1717 Error err;
1718 WCHAR *dir_path_ptr;
1719 switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
1720 case S_OK:
1721 // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
1722 utf16le_ptr_to_utf8(out_path, dir_path_ptr);
1723 CoTaskMemFree(dir_path_ptr);
1724 buf_appendf(out_path, "\\%s", appname);
1725 return ErrorNone;
1726 case E_OUTOFMEMORY:
1727 return ErrorNoMem;
1728 default:
1729 return ErrorUnexpected;
1730 }
1731 zig_unreachable();
1732#elif defined(ZIG_OS_DARWIN)
1733 const char *home_dir = getenv("HOME");
1734 if (home_dir == nullptr) {
1735 // TODO use /etc/passwd
1736 return ErrorFileNotFound;
1737 }
1738 buf_resize(out_path, 0);
1739 buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
1740 return ErrorNone;
1741#elif defined(ZIG_OS_LINUX)
1742 const char *home_dir = getenv("HOME");
1743 if (home_dir == nullptr) {
1744 // TODO use /etc/passwd
1745 return ErrorFileNotFound;
1746 }
1747 buf_resize(out_path, 0);
1748 buf_appendf(out_path, "%s/.local/share/%s", home_dir, appname);
1749 return ErrorNone;
1750#endif
1751}
1752
1753
1754#if defined(ZIG_OS_LINUX)
1755static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
1756 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
1757 if (info->dlpi_name[0] == '/') {
1758 libs->append(buf_create_from_str(info->dlpi_name));
1759 }
1760 return 0;
1761}
1762#endif
1763
1764Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
1765#if defined(ZIG_OS_LINUX)
1766 paths.resize(0);
1767 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
1768 return ErrorNone;
1769#elif defined(ZIG_OS_DARWIN)
1770 paths.resize(0);
1771 uint32_t img_count = _dyld_image_count();
1772 for (uint32_t i = 0; i != img_count; i += 1) {
1773 const char *name = _dyld_get_image_name(i);
1774 paths.append(buf_create_from_str(name));
1775 }
1776 return ErrorNone;
1777#elif defined(ZIG_OS_WINDOWS)
1778 // zig is built statically on windows, so we can return an empty list
1779 paths.resize(0);
1780 return ErrorNone;
1781#else
1782#error unimplemented
1783#endif
1784}
1785
1786Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1787#if defined(ZIG_OS_WINDOWS)
1788 // TODO use CreateFileW
1789 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
1790
1791 if (result == INVALID_HANDLE_VALUE) {
1792 DWORD err = GetLastError();
1793 switch (err) {
1794 case ERROR_SHARING_VIOLATION:
1795 return ErrorSharingViolation;
1796 case ERROR_ALREADY_EXISTS:
1797 return ErrorPathAlreadyExists;
1798 case ERROR_FILE_EXISTS:
1799 return ErrorPathAlreadyExists;
1800 case ERROR_FILE_NOT_FOUND:
1801 return ErrorFileNotFound;
1802 case ERROR_PATH_NOT_FOUND:
1803 return ErrorFileNotFound;
1804 case ERROR_ACCESS_DENIED:
1805 return ErrorAccess;
1806 case ERROR_PIPE_BUSY:
1807 return ErrorPipeBusy;
1808 default:
1809 return ErrorUnexpected;
1810 }
1811 }
1812
1813 *out_file = result;
1814 return ErrorNone;
1815#else
1816 for (;;) {
1817 int fd = open(buf_ptr(full_path), O_RDONLY|O_CLOEXEC);
1818 if (fd == -1) {
1819 switch (errno) {
1820 case EINTR:
1821 continue;
1822 case EINVAL:
1823 zig_unreachable();
1824 case EFAULT:
1825 zig_unreachable();
1826 case EACCES:
1827 return ErrorAccess;
1828 case EISDIR:
1829 return ErrorIsDir;
1830 case ENOENT:
1831 return ErrorFileNotFound;
1832 default:
1833 return ErrorFileSystem;
1834 }
1835 }
1836 *out_file = fd;
1837 return ErrorNone;
1838 }
1839#endif
1840}
1841
1842Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
1843#if defined(ZIG_OS_WINDOWS)
1844 for (;;) {
1845 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ | GENERIC_WRITE,
1846 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
1847
1848 if (result == INVALID_HANDLE_VALUE) {
1849 DWORD err = GetLastError();
1850 switch (err) {
1851 case ERROR_SHARING_VIOLATION:
1852 // TODO wait for the lock instead of sleeping
1853 Sleep(10);
1854 continue;
1855 case ERROR_ALREADY_EXISTS:
1856 return ErrorPathAlreadyExists;
1857 case ERROR_FILE_EXISTS:
1858 return ErrorPathAlreadyExists;
1859 case ERROR_FILE_NOT_FOUND:
1860 return ErrorFileNotFound;
1861 case ERROR_PATH_NOT_FOUND:
1862 return ErrorFileNotFound;
1863 case ERROR_ACCESS_DENIED:
1864 return ErrorAccess;
1865 case ERROR_PIPE_BUSY:
1866 return ErrorPipeBusy;
1867 default:
1868 return ErrorUnexpected;
1869 }
1870 }
1871 *out_file = result;
1872 return ErrorNone;
1873 }
1874#else
1875 int fd;
1876 for (;;) {
1877 fd = open(buf_ptr(full_path), O_RDWR|O_CLOEXEC|O_CREAT, 0666);
1878 if (fd == -1) {
1879 switch (errno) {
1880 case EINTR:
1881 continue;
1882 case EINVAL:
1883 zig_unreachable();
1884 case EFAULT:
1885 zig_unreachable();
1886 case EACCES:
1887 return ErrorAccess;
1888 case EISDIR:
1889 return ErrorIsDir;
1890 case ENOENT:
1891 return ErrorFileNotFound;
1892 default:
1893 return ErrorFileSystem;
1894 }
1895 }
1896 break;
1897 }
1898 for (;;) {
1899 struct flock lock;
1900 lock.l_type = F_WRLCK;
1901 lock.l_whence = SEEK_SET;
1902 lock.l_start = 0;
1903 lock.l_len = 0;
1904 if (fcntl(fd, F_SETLKW, &lock) == -1) {
1905 switch (errno) {
1906 case EINTR:
1907 continue;
1908 case EBADF:
1909 zig_unreachable();
1910 case EFAULT:
1911 zig_unreachable();
1912 case EINVAL:
1913 zig_unreachable();
1914 default:
1915 close(fd);
1916 return ErrorFileSystem;
1917 }
1918 }
1919 break;
1920 }
1921 *out_file = fd;
1922 return ErrorNone;
1923#endif
1924}
1925
1926Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1927#if defined(ZIG_OS_WINDOWS)
1928 FILETIME last_write_time;
1929 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
1930 return ErrorUnexpected;
1931 mtime->sec = last_write_time.dwLowDateTime | (last_write_time.dwHighDateTime << 32);
1932 mtime->nsec = 0;
1933 return ErrorNone;
1934#elif defined(ZIG_OS_LINUX)
1935 struct stat statbuf;
1936 if (fstat(file, &statbuf) == -1)
1937 return ErrorFileSystem;
1938
1939 mtime->sec = statbuf.st_mtim.tv_sec;
1940 mtime->nsec = statbuf.st_mtim.tv_nsec;
1941 return ErrorNone;
1942#elif defined(ZIG_OS_DARWIN)
1943 struct stat statbuf;
1944 if (fstat(file, &statbuf) == -1)
1945 return ErrorFileSystem;
1946
1947 mtime->sec = statbuf.st_mtimespec.tv_sec;
1948 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1949 return ErrorNone;
1950#else
1951#error unimplemented
1952#endif
1953}
1954
1955Error os_file_read(OsFile file, void *ptr, size_t *len) {
1956#if defined(ZIG_OS_WINDOWS)
1957 DWORD amt_read;
1958 if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0)
1959 return ErrorUnexpected;
1960 *len = amt_read;
1961 return ErrorNone;
1962#else
1963 for (;;) {
1964 ssize_t rc = read(file, ptr, *len);
1965 if (rc == -1) {
1966 switch (errno) {
1967 case EINTR:
1968 continue;
1969 case EBADF:
1970 zig_unreachable();
1971 case EFAULT:
1972 zig_unreachable();
1973 case EISDIR:
1974 zig_unreachable();
1975 default:
1976 return ErrorFileSystem;
1977 }
1978 }
1979 *len = rc;
1980 return ErrorNone;
1981 }
1982#endif
1983}
1984
1985Error os_file_read_all(OsFile file, Buf *contents) {
1986 Error err;
1987 size_t index = 0;
1988 for (;;) {
1989 size_t amt = buf_len(contents) - index;
1990
1991 if (amt < 4096) {
1992 buf_resize(contents, buf_len(contents) + (4096 - amt));
1993 amt = buf_len(contents) - index;
1994 }
1995
1996 if ((err = os_file_read(file, buf_ptr(contents) + index, &amt)))
1997 return err;
1998
1999 if (amt == 0) {
2000 buf_resize(contents, index);
2001 return ErrorNone;
2002 }
2003
2004 index += amt;
2005 }
2006}
2007
2008Error os_file_overwrite(OsFile file, Buf *contents) {
2009#if defined(ZIG_OS_WINDOWS)
2010 if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
2011 return ErrorFileSystem;
2012 if (!SetEndOfFile(file))
2013 return ErrorFileSystem;
2014 if (!WriteFile(file, buf_ptr(contents), buf_len(contents), nullptr, nullptr))
2015 return ErrorFileSystem;
2016 return ErrorNone;
2017#else
2018 if (lseek(file, 0, SEEK_SET) == -1)
2019 return ErrorFileSystem;
2020 if (ftruncate(file, 0) == -1)
2021 return ErrorFileSystem;
2022 for (;;) {
2023 if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {
2024 switch (errno) {
2025 case EINTR:
2026 continue;
2027 case EINVAL:
2028 zig_unreachable();
2029 case EBADF:
2030 zig_unreachable();
2031 default:
2032 return ErrorFileSystem;
2033 }
2034 }
2035 return ErrorNone;
2036 }
2037#endif
2038}
2039
2040void os_file_close(OsFile file) {
2041#if defined(ZIG_OS_WINDOWS)
2042 CloseHandle(file);
2043#else
2044 close(file);
2045#endif
2046}
src/os.hpp+61-38
...@@ -13,10 +13,43 @@...@@ -13,10 +13,43 @@
13#include "error.hpp"13#include "error.hpp"
14#include "zig_llvm.h"14#include "zig_llvm.h"
15#include "windows_sdk.h"15#include "windows_sdk.h"
16#include "result.hpp"
1617
17#include <stdio.h>18#include <stdio.h>
18#include <inttypes.h>19#include <inttypes.h>
1920
21#if defined(__APPLE__)
22#define ZIG_OS_DARWIN
23#elif defined(_WIN32)
24#define ZIG_OS_WINDOWS
25#elif defined(__linux__)
26#define ZIG_OS_LINUX
27#else
28#define ZIG_OS_UNKNOWN
29#endif
30
31#if defined(__x86_64__)
32#define ZIG_ARCH_X86_64
33#else
34#define ZIG_ARCH_UNKNOWN
35#endif
36
37#if defined(ZIG_OS_WINDOWS)
38#define ZIG_PRI_usize "I64u"
39#define ZIG_PRI_u64 "I64u"
40#define ZIG_PRI_llu "I64u"
41#define ZIG_PRI_x64 "I64x"
42#define OS_SEP "\\"
43#define ZIG_OS_SEP_CHAR '\\'
44#else
45#define ZIG_PRI_usize "zu"
46#define ZIG_PRI_u64 PRIu64
47#define ZIG_PRI_llu "llu"
48#define ZIG_PRI_x64 PRIx64
49#define OS_SEP "/"
50#define ZIG_OS_SEP_CHAR '/'
51#endif
52
20enum TermColor {53enum TermColor {
21 TermColorRed,54 TermColorRed,
22 TermColorGreen,55 TermColorGreen,
...@@ -38,11 +71,23 @@ struct Termination {...@@ -38,11 +71,23 @@ struct Termination {
38 int code;71 int code;
39};72};
4073
74#if defined(ZIG_OS_WINDOWS)
75#define OsFile void *
76#else
77#define OsFile int
78#endif
79
80struct OsTimeStamp {
81 uint64_t sec;
82 uint64_t nsec;
83};
84
41int os_init(void);85int os_init(void);
4286
43void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);87void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
44int os_exec_process(const char *exe, ZigList<const char *> &args,88int os_exec_process(const char *exe, ZigList<const char *> &args,
45 Termination *term, Buf *out_stderr, Buf *out_stdout);89 Termination *term, Buf *out_stderr, Buf *out_stdout);
90Error os_execv(const char *exe, const char **argv);
4691
47void os_path_dirname(Buf *full_path, Buf *out_dirname);92void os_path_dirname(Buf *full_path, Buf *out_dirname);
48void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);93void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
...@@ -52,16 +97,22 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path);...@@ -52,16 +97,22 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path);
52Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);97Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
53bool os_path_is_absolute(Buf *path);98bool os_path_is_absolute(Buf *path);
5499
55int os_get_global_cache_directory(Buf *out_tmp_path);100Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
101Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
56102
57int os_make_path(Buf *path);103Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);
58int os_make_dir(Buf *path);104Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
105Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime);
106Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
107Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
108Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
109void os_file_close(OsFile file);
59110
60void os_write_file(Buf *full_path, Buf *contents);111void os_write_file(Buf *full_path, Buf *contents);
61int os_copy_file(Buf *src_path, Buf *dest_path);112int os_copy_file(Buf *src_path, Buf *dest_path);
62113
63int os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);114Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
64int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);115Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
65116
66int os_get_cwd(Buf *out_cwd);117int os_get_cwd(Buf *out_cwd);
67118
...@@ -71,49 +122,21 @@ void os_stderr_set_color(TermColor color);...@@ -71,49 +122,21 @@ void os_stderr_set_color(TermColor color);
71int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);122int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
72int os_delete_file(Buf *path);123int os_delete_file(Buf *path);
73124
74int os_file_exists(Buf *full_path, bool *result);125Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
75126
76int os_rename(Buf *src_path, Buf *dest_path);127int os_rename(Buf *src_path, Buf *dest_path);
77double os_get_time(void);128double os_get_time(void);
78129
79bool os_is_sep(uint8_t c);130bool os_is_sep(uint8_t c);
80131
81int os_self_exe_path(Buf *out_path);132Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
133
134Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
82135
83int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);136int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
84int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);137int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
85int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);138int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
86139
87#if defined(__APPLE__)140Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
88#define ZIG_OS_DARWIN
89#elif defined(_WIN32)
90#define ZIG_OS_WINDOWS
91#elif defined(__linux__)
92#define ZIG_OS_LINUX
93#else
94#define ZIG_OS_UNKNOWN
95#endif
96
97#if defined(__x86_64__)
98#define ZIG_ARCH_X86_64
99#else
100#define ZIG_ARCH_UNKNOWN
101#endif
102
103#if defined(ZIG_OS_WINDOWS)
104#define ZIG_PRI_usize "I64u"
105#define ZIG_PRI_u64 "I64u"
106#define ZIG_PRI_llu "I64u"
107#define ZIG_PRI_x64 "I64x"
108#define OS_SEP "\\"
109#define ZIG_OS_SEP_CHAR '\\'
110#else
111#define ZIG_PRI_usize "zu"
112#define ZIG_PRI_u64 PRIu64
113#define ZIG_PRI_llu "llu"
114#define ZIG_PRI_x64 PRIx64
115#define OS_SEP "/"
116#define ZIG_OS_SEP_CHAR '/'
117#endif
118141
119#endif142#endif
src/parser.cpp+1-8
...@@ -700,7 +700,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b...@@ -700,7 +700,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
700700
701/*701/*
702PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType702PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
703KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"703KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend"
704ErrorSetDecl = "error" "{" list(Symbol, ",") "}"704ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
705*/705*/
706static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {706static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
...@@ -756,10 +756,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo...@@ -756,10 +756,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
756 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);756 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);
757 *token_index += 1;757 *token_index += 1;
758 return node;758 return node;
759 } else if (token->id == TokenIdKeywordThis) {
760 AstNode *node = ast_create_node(pc, NodeTypeThisLiteral, token);
761 *token_index += 1;
762 return node;
763 } else if (token->id == TokenIdKeywordUnreachable) {759 } else if (token->id == TokenIdKeywordUnreachable) {
764 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);760 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
765 *token_index += 1;761 *token_index += 1;
...@@ -3021,9 +3017,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3021,9 +3017,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3021 case NodeTypeUndefinedLiteral:3017 case NodeTypeUndefinedLiteral:
3022 // none3018 // none
3023 break;3019 break;
3024 case NodeTypeThisLiteral:
3025 // none
3026 break;
3027 case NodeTypeIfBoolExpr:3020 case NodeTypeIfBoolExpr:
3028 visit_field(&node->data.if_bool_expr.condition, visit, context);3021 visit_field(&node->data.if_bool_expr.condition, visit, context);
3029 visit_field(&node->data.if_bool_expr.then_block, visit, context);3022 visit_field(&node->data.if_bool_expr.then_block, visit, context);
src/target.cpp+16
...@@ -812,6 +812,22 @@ const char *target_exe_file_ext(ZigTarget *target) {...@@ -812,6 +812,22 @@ const char *target_exe_file_ext(ZigTarget *target) {
812 }812 }
813}813}
814814
815const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {
816 if (target->os == OsWindows) {
817 if (is_static) {
818 return ".lib";
819 } else {
820 return ".dll";
821 }
822 } else {
823 if (is_static) {
824 return ".a";
825 } else {
826 return buf_ptr(buf_sprintf(".so.%zu", version_major));
827 }
828 }
829}
830
815enum FloatAbi {831enum FloatAbi {
816 FloatAbiHard,832 FloatAbiHard,
817 FloatAbiSoft,833 FloatAbiSoft,
src/target.hpp+1
...@@ -114,6 +114,7 @@ const char *target_o_file_ext(ZigTarget *target);...@@ -114,6 +114,7 @@ const char *target_o_file_ext(ZigTarget *target);
114const char *target_asm_file_ext(ZigTarget *target);114const char *target_asm_file_ext(ZigTarget *target);
115const char *target_llvm_ir_file_ext(ZigTarget *target);115const char *target_llvm_ir_file_ext(ZigTarget *target);
116const char *target_exe_file_ext(ZigTarget *target);116const char *target_exe_file_ext(ZigTarget *target);
117const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch);
117118
118Buf *target_dynamic_linker(ZigTarget *target);119Buf *target_dynamic_linker(ZigTarget *target);
119120
src/tokenizer.cpp-2
...@@ -146,7 +146,6 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -146,7 +146,6 @@ static const struct ZigKeyword zig_keywords[] = {
146 {"suspend", TokenIdKeywordSuspend},146 {"suspend", TokenIdKeywordSuspend},
147 {"switch", TokenIdKeywordSwitch},147 {"switch", TokenIdKeywordSwitch},
148 {"test", TokenIdKeywordTest},148 {"test", TokenIdKeywordTest},
149 {"this", TokenIdKeywordThis},
150 {"true", TokenIdKeywordTrue},149 {"true", TokenIdKeywordTrue},
151 {"try", TokenIdKeywordTry},150 {"try", TokenIdKeywordTry},
152 {"undefined", TokenIdKeywordUndefined},151 {"undefined", TokenIdKeywordUndefined},
...@@ -1588,7 +1587,6 @@ const char * token_name(TokenId id) {...@@ -1588,7 +1587,6 @@ const char * token_name(TokenId id) {
1588 case TokenIdKeywordStruct: return "struct";1587 case TokenIdKeywordStruct: return "struct";
1589 case TokenIdKeywordSwitch: return "switch";1588 case TokenIdKeywordSwitch: return "switch";
1590 case TokenIdKeywordTest: return "test";1589 case TokenIdKeywordTest: return "test";
1591 case TokenIdKeywordThis: return "this";
1592 case TokenIdKeywordTrue: return "true";1590 case TokenIdKeywordTrue: return "true";
1593 case TokenIdKeywordTry: return "try";1591 case TokenIdKeywordTry: return "try";
1594 case TokenIdKeywordUndefined: return "undefined";1592 case TokenIdKeywordUndefined: return "undefined";
src/tokenizer.hpp-1
...@@ -87,7 +87,6 @@ enum TokenId {...@@ -87,7 +87,6 @@ enum TokenId {
87 TokenIdKeywordSuspend,87 TokenIdKeywordSuspend,
88 TokenIdKeywordSwitch,88 TokenIdKeywordSwitch,
89 TokenIdKeywordTest,89 TokenIdKeywordTest,
90 TokenIdKeywordThis,
91 TokenIdKeywordTrue,90 TokenIdKeywordTrue,
92 TokenIdKeywordTry,91 TokenIdKeywordTry,
93 TokenIdKeywordUndefined,92 TokenIdKeywordUndefined,
src/util.cpp+49
...@@ -43,3 +43,52 @@ uint32_t ptr_hash(const void *ptr) {...@@ -43,3 +43,52 @@ uint32_t ptr_hash(const void *ptr) {
43bool ptr_eq(const void *a, const void *b) {43bool ptr_eq(const void *a, const void *b) {
44 return a == b;44 return a == b;
45}45}
46
47// Ported from std/mem.zig.
48bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
49 for (size_t i = 0; i < self->split_bytes.len; i += 1) {
50 if (byte == self->split_bytes.ptr[i]) {
51 return true;
52 }
53 }
54 return false;
55}
56
57// Ported from std/mem.zig.
58Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
59 // move to beginning of token
60 while (self->index < self->buffer.len &&
61 SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
62 {
63 self->index += 1;
64 }
65 size_t start = self->index;
66 if (start == self->buffer.len) {
67 return {};
68 }
69
70 // move to end of token
71 while (self->index < self->buffer.len &&
72 !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
73 {
74 self->index += 1;
75 }
76 size_t end = self->index;
77
78 return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
79}
80
81// Ported from std/mem.zig
82Slice<uint8_t> SplitIterator_rest(SplitIterator *self) {
83 // move to beginning of token
84 size_t index = self->index;
85 while (index < self->buffer.len && SplitIterator_isSplitByte(self, self->buffer.ptr[index])) {
86 index += 1;
87 }
88 return self->buffer.sliceFrom(index);
89}
90
91// Ported from std/mem.zig
92SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
93 return SplitIterator{0, buffer, split_bytes};
94}
src/util.hpp+13
...@@ -254,4 +254,17 @@ static inline void memCopy(Slice<T> dest, Slice<T> src) {...@@ -254,4 +254,17 @@ static inline void memCopy(Slice<T> dest, Slice<T> src) {
254 memcpy(dest.ptr, src.ptr, src.len * sizeof(T));254 memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
255}255}
256256
257// Ported from std/mem.zig.
258// Coordinate struct fields with memSplit function
259struct SplitIterator {
260 size_t index;
261 Slice<uint8_t> buffer;
262 Slice<uint8_t> split_bytes;
263};
264
265bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte);
266Optional< Slice<uint8_t> > SplitIterator_next(SplitIterator *self);
267Slice<uint8_t> SplitIterator_rest(SplitIterator *self);
268SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes);
269
257#endif270#endif
src/zig_llvm.cpp+8-1
...@@ -30,6 +30,7 @@...@@ -30,6 +30,7 @@
30#include <llvm/PassRegistry.h>30#include <llvm/PassRegistry.h>
31#include <llvm/Support/FileSystem.h>31#include <llvm/Support/FileSystem.h>
32#include <llvm/Support/TargetParser.h>32#include <llvm/Support/TargetParser.h>
33#include <llvm/Support/Timer.h>
33#include <llvm/Support/raw_ostream.h>34#include <llvm/Support/raw_ostream.h>
34#include <llvm/Target/TargetMachine.h>35#include <llvm/Target/TargetMachine.h>
35#include <llvm/Transforms/Coroutines.h>36#include <llvm/Transforms/Coroutines.h>
...@@ -82,8 +83,11 @@ static const bool assertions_on = false;...@@ -82,8 +83,11 @@ static const bool assertions_on = false;
82#endif83#endif
8384
84bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,85bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
85 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, bool is_small)86 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
87 bool is_small, bool time_report)
86{88{
89 TimePassesIsEnabled = time_report;
90
87 std::error_code EC;91 std::error_code EC;
88 raw_fd_ostream dest(filename, EC, sys::fs::F_None);92 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
89 if (EC) {93 if (EC) {
...@@ -183,6 +187,9 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -183,6 +187,9 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
183 }187 }
184 }188 }
185189
190 if (time_report) {
191 TimerGroup::printAll(errs());
192 }
186 return false;193 return false;
187}194}
188195
src/zig_llvm.h+2-1
...@@ -55,7 +55,8 @@ enum ZigLLVM_EmitOutputType {...@@ -55,7 +55,8 @@ enum ZigLLVM_EmitOutputType {
55};55};
5656
57ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,57ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
58 const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, bool is_small);58 const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
59 bool is_small, bool time_report);
5960
60ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);61ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6162
std/array_list.zig+1-1
...@@ -11,7 +11,7 @@ pub fn ArrayList(comptime T: type) type {...@@ -11,7 +11,7 @@ pub fn ArrayList(comptime T: type) type {
1111
12pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {12pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
13 return struct {13 return struct {
14 const Self = this;14 const Self = @This();
1515
16 /// Use toSlice instead of slicing this directly, because if you don't16 /// Use toSlice instead of slicing this directly, because if you don't
17 /// specify the end position of the slice, this will potentially give17 /// specify the end position of the slice, this will potentially give
std/atomic/int.zig+1-1
...@@ -6,7 +6,7 @@ pub fn Int(comptime T: type) type {...@@ -6,7 +6,7 @@ pub fn Int(comptime T: type) type {
6 return struct {6 return struct {
7 unprotected_value: T,7 unprotected_value: T,
88
9 pub const Self = this;9 pub const Self = @This();
1010
11 pub fn init(init_val: T) Self {11 pub fn init(init_val: T) Self {
12 return Self{ .unprotected_value = init_val };12 return Self{ .unprotected_value = init_val };
std/atomic/queue.zig+2-2
...@@ -12,7 +12,7 @@ pub fn Queue(comptime T: type) type {...@@ -12,7 +12,7 @@ pub fn Queue(comptime T: type) type {
12 tail: ?*Node,12 tail: ?*Node,
13 mutex: std.Mutex,13 mutex: std.Mutex,
1414
15 pub const Self = this;15 pub const Self = @This();
16 pub const Node = std.LinkedList(T).Node;16 pub const Node = std.LinkedList(T).Node;
1717
18 pub fn init() Self {18 pub fn init() Self {
...@@ -114,7 +114,7 @@ pub fn Queue(comptime T: type) type {...@@ -114,7 +114,7 @@ pub fn Queue(comptime T: type) type {
114114
115 fn dumpRecursive(optional_node: ?*Node, indent: usize) void {115 fn dumpRecursive(optional_node: ?*Node, indent: usize) void {
116 var stderr_file = std.io.getStdErr() catch return;116 var stderr_file = std.io.getStdErr() catch return;
117 const stderr = &std.io.FileOutStream.init(&stderr_file).stream;117 const stderr = &std.io.FileOutStream.init(stderr_file).stream;
118 stderr.writeByteNTimes(' ', indent) catch return;118 stderr.writeByteNTimes(' ', indent) catch return;
119 if (optional_node) |node| {119 if (optional_node) |node| {
120 std.debug.warn("0x{x}={}\n", @ptrToInt(node), node.data);120 std.debug.warn("0x{x}={}\n", @ptrToInt(node), node.data);
std/atomic/stack.zig+1-1
...@@ -9,7 +9,7 @@ pub fn Stack(comptime T: type) type {...@@ -9,7 +9,7 @@ pub fn Stack(comptime T: type) type {
9 root: ?*Node,9 root: ?*Node,
10 lock: u8,10 lock: u8,
1111
12 pub const Self = this;12 pub const Self = @This();
1313
14 pub const Node = struct {14 pub const Node = struct {
15 next: ?*Node,15 next: ?*Node,
std/build.zig+27-1
...@@ -232,6 +232,8 @@ pub const Builder = struct {...@@ -232,6 +232,8 @@ pub const Builder = struct {
232 }232 }
233233
234 pub fn make(self: *Builder, step_names: []const []const u8) !void {234 pub fn make(self: *Builder, step_names: []const []const u8) !void {
235 try self.makePath(self.cache_root);
236
235 var wanted_steps = ArrayList(*Step).init(self.allocator);237 var wanted_steps = ArrayList(*Step).init(self.allocator);
236 defer wanted_steps.deinit();238 defer wanted_steps.deinit();
237239
...@@ -1641,6 +1643,7 @@ pub const TestStep = struct {...@@ -1641,6 +1643,7 @@ pub const TestStep = struct {
1641 lib_paths: ArrayList([]const u8),1643 lib_paths: ArrayList([]const u8),
1642 object_files: ArrayList([]const u8),1644 object_files: ArrayList([]const u8),
1643 no_rosegment: bool,1645 no_rosegment: bool,
1646 output_path: ?[]const u8,
16441647
1645 pub fn init(builder: *Builder, root_src: []const u8) TestStep {1648 pub fn init(builder: *Builder, root_src: []const u8) TestStep {
1646 const step_name = builder.fmt("test {}", root_src);1649 const step_name = builder.fmt("test {}", root_src);
...@@ -1659,6 +1662,7 @@ pub const TestStep = struct {...@@ -1659,6 +1662,7 @@ pub const TestStep = struct {
1659 .lib_paths = ArrayList([]const u8).init(builder.allocator),1662 .lib_paths = ArrayList([]const u8).init(builder.allocator),
1660 .object_files = ArrayList([]const u8).init(builder.allocator),1663 .object_files = ArrayList([]const u8).init(builder.allocator),
1661 .no_rosegment = false,1664 .no_rosegment = false,
1665 .output_path = null,
1662 };1666 };
1663 }1667 }
16641668
...@@ -1682,6 +1686,24 @@ pub const TestStep = struct {...@@ -1682,6 +1686,24 @@ pub const TestStep = struct {
1682 self.build_mode = mode;1686 self.build_mode = mode;
1683 }1687 }
16841688
1689 pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {
1690 self.output_path = file_path;
1691
1692 // catch a common mistake
1693 if (mem.eql(u8, self.builder.pathFromRoot(file_path), self.builder.pathFromRoot("."))) {
1694 debug.panic("setOutputPath wants a file path, not a directory\n");
1695 }
1696 }
1697
1698 pub fn getOutputPath(self: *TestStep) []const u8 {
1699 if (self.output_path) |output_path| {
1700 return output_path;
1701 } else {
1702 const basename = self.builder.fmt("test{}", self.target.exeFileExt());
1703 return os.path.join(self.builder.allocator, self.builder.cache_root, basename) catch unreachable;
1704 }
1705 }
1706
1685 pub fn linkSystemLibrary(self: *TestStep, name: []const u8) void {1707 pub fn linkSystemLibrary(self: *TestStep, name: []const u8) void {
1686 self.link_libs.put(name) catch unreachable;1708 self.link_libs.put(name) catch unreachable;
1687 }1709 }
...@@ -1746,6 +1768,10 @@ pub const TestStep = struct {...@@ -1746,6 +1768,10 @@ pub const TestStep = struct {
1746 builtin.Mode.ReleaseSmall => try zig_args.append("--release-small"),1768 builtin.Mode.ReleaseSmall => try zig_args.append("--release-small"),
1747 }1769 }
17481770
1771 const output_path = builder.pathFromRoot(self.getOutputPath());
1772 try zig_args.append("--output");
1773 try zig_args.append(output_path);
1774
1749 switch (self.target) {1775 switch (self.target) {
1750 Target.Native => {},1776 Target.Native => {},
1751 Target.Cross => |cross_target| {1777 Target.Cross => |cross_target| {
...@@ -1864,7 +1890,7 @@ const InstallArtifactStep = struct {...@@ -1864,7 +1890,7 @@ const InstallArtifactStep = struct {
1864 artifact: *LibExeObjStep,1890 artifact: *LibExeObjStep,
1865 dest_file: []const u8,1891 dest_file: []const u8,
18661892
1867 const Self = this;1893 const Self = @This();
18681894
1869 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {1895 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
1870 const dest_dir = switch (artifact.kind) {1896 const dest_dir = switch (artifact.kind) {
std/coff.zig+23-29
...@@ -8,9 +8,9 @@ const ArrayList = std.ArrayList;...@@ -8,9 +8,9 @@ const ArrayList = std.ArrayList;
88
9// CoffHeader.machine values9// CoffHeader.machine values
10// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx10// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
11const IMAGE_FILE_MACHINE_I386 = 0x014c;11const IMAGE_FILE_MACHINE_I386 = 0x014c;
12const IMAGE_FILE_MACHINE_IA64 = 0x0200;12const IMAGE_FILE_MACHINE_IA64 = 0x0200;
13const IMAGE_FILE_MACHINE_AMD64 = 0x8664;13const IMAGE_FILE_MACHINE_AMD64 = 0x8664;
1414
15// OptionalHeader.magic values15// OptionalHeader.magic values
16// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx16// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx
...@@ -20,7 +20,7 @@ const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;...@@ -20,7 +20,7 @@ const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
20const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;20const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
21const DEBUG_DIRECTORY = 6;21const DEBUG_DIRECTORY = 6;
2222
23pub const CoffError = error {23pub const CoffError = error{
24 InvalidPEMagic,24 InvalidPEMagic,
25 InvalidPEHeader,25 InvalidPEHeader,
26 InvalidMachine,26 InvalidMachine,
...@@ -56,24 +56,21 @@ pub const Coff = struct {...@@ -56,24 +56,21 @@ pub const Coff = struct {
5656
57 var pe_header_magic: [4]u8 = undefined;57 var pe_header_magic: [4]u8 = undefined;
58 try in.readNoEof(pe_header_magic[0..]);58 try in.readNoEof(pe_header_magic[0..]);
59 if (!mem.eql(u8, pe_header_magic, []u8{'P', 'E', 0, 0}))59 if (!mem.eql(u8, pe_header_magic, []u8{ 'P', 'E', 0, 0 }))
60 return error.InvalidPEHeader;60 return error.InvalidPEHeader;
6161
62 self.coff_header = CoffHeader {62 self.coff_header = CoffHeader{
63 .machine = try in.readIntLe(u16),63 .machine = try in.readIntLe(u16),
64 .number_of_sections = try in.readIntLe(u16), 64 .number_of_sections = try in.readIntLe(u16),
65 .timedate_stamp = try in.readIntLe(u32), 65 .timedate_stamp = try in.readIntLe(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32), 66 .pointer_to_symbol_table = try in.readIntLe(u32),
67 .number_of_symbols = try in.readIntLe(u32), 67 .number_of_symbols = try in.readIntLe(u32),
68 .size_of_optional_header = try in.readIntLe(u16), 68 .size_of_optional_header = try in.readIntLe(u16),
69 .characteristics = try in.readIntLe(u16), 69 .characteristics = try in.readIntLe(u16),
70 };70 };
7171
72 switch (self.coff_header.machine) {72 switch (self.coff_header.machine) {
73 IMAGE_FILE_MACHINE_I386,73 IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_IA64 => {},
74 IMAGE_FILE_MACHINE_AMD64,
75 IMAGE_FILE_MACHINE_IA64
76 => {},
77 else => return error.InvalidMachine,74 else => return error.InvalidMachine,
78 }75 }
7976
...@@ -89,11 +86,9 @@ pub const Coff = struct {...@@ -89,11 +86,9 @@ pub const Coff = struct {
89 var skip_size: u16 = undefined;86 var skip_size: u16 = undefined;
90 if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {87 if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
91 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 18 * @sizeOf(u32);88 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 18 * @sizeOf(u32);
92 }89 } else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
93 else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
94 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 12 * @sizeOf(u32) + 5 * @sizeOf(u64);90 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 12 * @sizeOf(u32) + 5 * @sizeOf(u64);
95 }91 } else
96 else
97 return error.InvalidPEMagic;92 return error.InvalidPEMagic;
9893
99 try self.in_file.seekForward(skip_size);94 try self.in_file.seekForward(skip_size);
...@@ -103,7 +98,7 @@ pub const Coff = struct {...@@ -103,7 +98,7 @@ pub const Coff = struct {
103 return error.InvalidPEHeader;98 return error.InvalidPEHeader;
10499
105 for (self.pe_header.data_directory) |*data_dir| {100 for (self.pe_header.data_directory) |*data_dir| {
106 data_dir.* = OptionalHeader.DataDirectory {101 data_dir.* = OptionalHeader.DataDirectory{
107 .virtual_address = try in.readIntLe(u32),102 .virtual_address = try in.readIntLe(u32),
108 .size = try in.readIntLe(u32),103 .size = try in.readIntLe(u32),
109 };104 };
...@@ -114,7 +109,7 @@ pub const Coff = struct {...@@ -114,7 +109,7 @@ pub const Coff = struct {
114 try self.loadSections();109 try self.loadSections();
115 const header = (self.getSection(".rdata") orelse return error.MissingCoffSection).header;110 const header = (self.getSection(".rdata") orelse return error.MissingCoffSection).header;
116111
117 // The linker puts a chunk that contains the .pdb path right after the 112 // The linker puts a chunk that contains the .pdb path right after the
118 // debug_directory.113 // debug_directory.
119 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];114 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];
120 const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;115 const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
...@@ -159,10 +154,10 @@ pub const Coff = struct {...@@ -159,10 +154,10 @@ pub const Coff = struct {
159 var i: u16 = 0;154 var i: u16 = 0;
160 while (i < self.coff_header.number_of_sections) : (i += 1) {155 while (i < self.coff_header.number_of_sections) : (i += 1) {
161 try in.readNoEof(name[0..]);156 try in.readNoEof(name[0..]);
162 try self.sections.append(Section {157 try self.sections.append(Section{
163 .header = SectionHeader {158 .header = SectionHeader{
164 .name = name,159 .name = name,
165 .misc = SectionHeader.Misc { .physical_address = try in.readIntLe(u32) },160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
166 .virtual_address = try in.readIntLe(u32),161 .virtual_address = try in.readIntLe(u32),
167 .size_of_raw_data = try in.readIntLe(u32),162 .size_of_raw_data = try in.readIntLe(u32),
168 .pointer_to_raw_data = try in.readIntLe(u32),163 .pointer_to_raw_data = try in.readIntLe(u32),
...@@ -184,7 +179,6 @@ pub const Coff = struct {...@@ -184,7 +179,6 @@ pub const Coff = struct {
184 }179 }
185 return null;180 return null;
186 }181 }
187
188};182};
189183
190const CoffHeader = struct {184const CoffHeader = struct {
...@@ -194,13 +188,13 @@ const CoffHeader = struct {...@@ -194,13 +188,13 @@ const CoffHeader = struct {
194 pointer_to_symbol_table: u32,188 pointer_to_symbol_table: u32,
195 number_of_symbols: u32,189 number_of_symbols: u32,
196 size_of_optional_header: u16,190 size_of_optional_header: u16,
197 characteristics: u16191 characteristics: u16,
198};192};
199193
200const OptionalHeader = struct {194const OptionalHeader = struct {
201 const DataDirectory = struct {195 const DataDirectory = struct {
202 virtual_address: u32,196 virtual_address: u32,
203 size: u32197 size: u32,
204 };198 };
205199
206 magic: u16,200 magic: u16,
...@@ -214,7 +208,7 @@ pub const Section = struct {...@@ -214,7 +208,7 @@ pub const Section = struct {
214const SectionHeader = struct {208const SectionHeader = struct {
215 const Misc = union {209 const Misc = union {
216 physical_address: u32,210 physical_address: u32,
217 virtual_size: u32211 virtual_size: u32,
218 };212 };
219213
220 name: [8]u8,214 name: [8]u8,
std/crypto/blake2.zig+2-2
...@@ -33,7 +33,7 @@ pub const Blake2s256 = Blake2s(256);...@@ -33,7 +33,7 @@ pub const Blake2s256 = Blake2s(256);
3333
34fn Blake2s(comptime out_len: usize) type {34fn Blake2s(comptime out_len: usize) type {
35 return struct {35 return struct {
36 const Self = this;36 const Self = @This();
37 const block_length = 64;37 const block_length = 64;
38 const digest_length = out_len / 8;38 const digest_length = out_len / 8;
3939
...@@ -266,7 +266,7 @@ pub const Blake2b512 = Blake2b(512);...@@ -266,7 +266,7 @@ pub const Blake2b512 = Blake2b(512);
266266
267fn Blake2b(comptime out_len: usize) type {267fn Blake2b(comptime out_len: usize) type {
268 return struct {268 return struct {
269 const Self = this;269 const Self = @This();
270 const block_length = 128;270 const block_length = 128;
271 const digest_length = out_len / 8;271 const digest_length = out_len / 8;
272272
std/crypto/hmac.zig+1-1
...@@ -9,7 +9,7 @@ pub const HmacSha256 = Hmac(crypto.Sha256);...@@ -9,7 +9,7 @@ pub const HmacSha256 = Hmac(crypto.Sha256);
99
10pub fn Hmac(comptime Hash: type) type {10pub fn Hmac(comptime Hash: type) type {
11 return struct {11 return struct {
12 const Self = this;12 const Self = @This();
13 pub const mac_length = Hash.digest_length;13 pub const mac_length = Hash.digest_length;
14 pub const minimum_key_length = 0;14 pub const minimum_key_length = 0;
1515
std/crypto/md5.zig+1-1
...@@ -28,7 +28,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar...@@ -28,7 +28,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundPar
28}28}
2929
30pub const Md5 = struct {30pub const Md5 = struct {
31 const Self = this;31 const Self = @This();
32 const block_length = 64;32 const block_length = 64;
33 const digest_length = 16;33 const digest_length = 16;
3434
std/crypto/poly1305.zig+1-1
...@@ -10,7 +10,7 @@ const readInt = std.mem.readInt;...@@ -10,7 +10,7 @@ const readInt = std.mem.readInt;
10const writeInt = std.mem.writeInt;10const writeInt = std.mem.writeInt;
1111
12pub const Poly1305 = struct {12pub const Poly1305 = struct {
13 const Self = this;13 const Self = @This();
1414
15 pub const mac_length = 16;15 pub const mac_length = 16;
16 pub const minimum_key_length = 32;16 pub const minimum_key_length = 32;
std/crypto/sha1.zig+1-1
...@@ -25,7 +25,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {...@@ -25,7 +25,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {
25}25}
2626
27pub const Sha1 = struct {27pub const Sha1 = struct {
28 const Self = this;28 const Self = @This();
29 const block_length = 64;29 const block_length = 64;
30 const digest_length = 20;30 const digest_length = 20;
3131
std/crypto/sha2.zig+2-2
...@@ -77,7 +77,7 @@ pub const Sha256 = Sha2_32(Sha256Params);...@@ -77,7 +77,7 @@ pub const Sha256 = Sha2_32(Sha256Params);
7777
78fn Sha2_32(comptime params: Sha2Params32) type {78fn Sha2_32(comptime params: Sha2Params32) type {
79 return struct {79 return struct {
80 const Self = this;80 const Self = @This();
81 const block_length = 64;81 const block_length = 64;
82 const digest_length = params.out_len / 8;82 const digest_length = params.out_len / 8;
8383
...@@ -418,7 +418,7 @@ pub const Sha512 = Sha2_64(Sha512Params);...@@ -418,7 +418,7 @@ pub const Sha512 = Sha2_64(Sha512Params);
418418
419fn Sha2_64(comptime params: Sha2Params64) type {419fn Sha2_64(comptime params: Sha2Params64) type {
420 return struct {420 return struct {
421 const Self = this;421 const Self = @This();
422 const block_length = 128;422 const block_length = 128;
423 const digest_length = params.out_len / 8;423 const digest_length = params.out_len / 8;
424424
std/crypto/sha3.zig+1-1
...@@ -12,7 +12,7 @@ pub const Sha3_512 = Keccak(512, 0x06);...@@ -12,7 +12,7 @@ pub const Sha3_512 = Keccak(512, 0x06);
1212
13fn Keccak(comptime bits: usize, comptime delim: u8) type {13fn Keccak(comptime bits: usize, comptime delim: u8) type {
14 return struct {14 return struct {
15 const Self = this;15 const Self = @This();
16 const block_length = 200;16 const block_length = 200;
17 const digest_length = bits / 8;17 const digest_length = bits / 8;
1818
std/crypto/x25519.zig+1-1
...@@ -115,7 +115,7 @@ pub const X25519 = struct {...@@ -115,7 +115,7 @@ pub const X25519 = struct {
115 return !zerocmp(u8, out);115 return !zerocmp(u8, out);
116 }116 }
117117
118 pub fn createPublicKey(public_key: [] u8, private_key: []const u8) bool {118 pub fn createPublicKey(public_key: []u8, private_key: []const u8) bool {
119 var base_point = []u8{9} ++ []u8{0} ** 31;119 var base_point = []u8{9} ++ []u8{0} ** 31;
120 return create(public_key, private_key, base_point);120 return create(public_key, private_key, base_point);
121 }121 }
std/debug/index.zig+15-14
...@@ -242,9 +242,12 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color...@@ -242,9 +242,12 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
242 }242 }
243}243}
244244
245pub fn writeCurrentStackTraceWindows(out_stream: var, debug_info: *DebugInfo,245pub fn writeCurrentStackTraceWindows(
246 tty_color: bool, start_addr: ?usize) !void246 out_stream: var,
247{247 debug_info: *DebugInfo,
248 tty_color: bool,
249 start_addr: ?usize,
250) !void {
248 var addr_buf: [1024]usize = undefined;251 var addr_buf: [1024]usize = undefined;
249 const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast252 const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast
250 const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null);253 const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null);
...@@ -391,7 +394,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -391,7 +394,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
391 break :subsections null;394 break :subsections null;
392 }395 }
393 };396 };
394 397
395 if (tty_color) {398 if (tty_color) {
396 setTtyColor(TtyColor.White);399 setTtyColor(TtyColor.White);
397 if (opt_line_info) |li| {400 if (opt_line_info) |li| {
...@@ -438,7 +441,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -438,7 +441,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
438 }441 }
439}442}
440443
441const TtyColor = enum{444const TtyColor = enum {
442 Red,445 Red,
443 Green,446 Green,
444 Cyan,447 Cyan,
...@@ -465,18 +468,16 @@ fn setTtyColor(tty_color: TtyColor) void {...@@ -465,18 +468,16 @@ fn setTtyColor(tty_color: TtyColor) void {
465 // TODO handle errors468 // TODO handle errors
466 switch (tty_color) {469 switch (tty_color) {
467 TtyColor.Red => {470 TtyColor.Red => {
468 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED|windows.FOREGROUND_INTENSITY);471 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY);
469 },472 },
470 TtyColor.Green => {473 TtyColor.Green => {
471 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN|windows.FOREGROUND_INTENSITY);474 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY);
472 },475 },
473 TtyColor.Cyan => {476 TtyColor.Cyan => {
474 _ = windows.SetConsoleTextAttribute(stderr_file.handle,477 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY);
475 windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE|windows.FOREGROUND_INTENSITY);
476 },478 },
477 TtyColor.White, TtyColor.Bold => {479 TtyColor.White, TtyColor.Bold => {
478 _ = windows.SetConsoleTextAttribute(stderr_file.handle,480 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY);
479 windows.FOREGROUND_RED|windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE|windows.FOREGROUND_INTENSITY);
480 },481 },
481 TtyColor.Dim => {482 TtyColor.Dim => {
482 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY);483 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY);
...@@ -915,7 +916,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -915,7 +916,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
915 } else {916 } else {
916 return error.MissingDebugInfo;917 return error.MissingDebugInfo;
917 };918 };
918 const syms = @ptrCast([*]macho.nlist_64, hdr_base + symtab.symoff)[0..symtab.nsyms];919 const syms = @ptrCast([*]macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), hdr_base + symtab.symoff))[0..symtab.nsyms];
919 const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize];920 const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize];
920921
921 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);922 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
...@@ -1496,14 +1497,14 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1496,14 +1497,14 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1496 const segcmd = while (ncmd != 0) : (ncmd -= 1) {1497 const segcmd = while (ncmd != 0) : (ncmd -= 1) {
1497 const lc = @ptrCast(*const std.macho.load_command, ptr);1498 const lc = @ptrCast(*const std.macho.load_command, ptr);
1498 switch (lc.cmd) {1499 switch (lc.cmd) {
1499 std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, ptr),1500 std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)),
1500 else => {},1501 else => {},
1501 }1502 }
1502 ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/14031503 ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403
1503 } else {1504 } else {
1504 return error.MissingDebugInfo;1505 return error.MissingDebugInfo;
1505 };1506 };
1506 const sections = @alignCast(@alignOf(macho.section_64), @ptrCast([*]const macho.section_64, ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects];1507 const sections = @ptrCast([*]const macho.section_64, @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects];
1507 for (sections) |*sect| {1508 for (sections) |*sect| {
1508 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and1509 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
1509 (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)1510 (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
std/event/channel.zig+1-1
...@@ -25,7 +25,7 @@ pub fn Channel(comptime T: type) type {...@@ -25,7 +25,7 @@ pub fn Channel(comptime T: type) type {
25 buffer_index: usize,25 buffer_index: usize,
26 buffer_len: usize,26 buffer_len: usize,
2727
28 const SelfChannel = this;28 const SelfChannel = @This();
29 const GetNode = struct {29 const GetNode = struct {
30 tick_node: *Loop.NextTickNode,30 tick_node: *Loop.NextTickNode,
31 data: Data,31 data: Data,
std/event/fs.zig+42-46
...@@ -109,30 +109,28 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off...@@ -109,30 +109,28 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off
109 .base = Loop.ResumeNode{109 .base = Loop.ResumeNode{
110 .id = Loop.ResumeNode.Id.Basic,110 .id = Loop.ResumeNode.Id.Basic,
111 .handle = @handle(),111 .handle = @handle(),
112 .overlapped = windows.OVERLAPPED{
113 .Internal = 0,
114 .InternalHigh = 0,
115 .Offset = @truncate(u32, offset),
116 .OffsetHigh = @truncate(u32, offset >> 32),
117 .hEvent = null,
118 },
112 },119 },
113 };120 };
114 const completion_key = @ptrToInt(&resume_node.base);121 // TODO only call create io completion port once per fd
115 // TODO support concurrent async ops on the file handle122 _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined);
116 // we can do this by ignoring completion key and using @fieldParentPtr with the *Overlapped
117 _ = try os.windowsCreateIoCompletionPort(fd, loop.os_data.io_port, completion_key, undefined);
118 var overlapped = windows.OVERLAPPED{
119 .Internal = 0,
120 .InternalHigh = 0,
121 .Offset = @truncate(u32, offset),
122 .OffsetHigh = @truncate(u32, offset >> 32),
123 .hEvent = null,
124 };
125 loop.beginOneEvent();123 loop.beginOneEvent();
126 errdefer loop.finishOneEvent();124 errdefer loop.finishOneEvent();
127125
128 errdefer {126 errdefer {
129 _ = windows.CancelIoEx(fd, &overlapped);127 _ = windows.CancelIoEx(fd, &resume_node.base.overlapped);
130 }128 }
131 suspend {129 suspend {
132 _ = windows.WriteFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &overlapped);130 _ = windows.WriteFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped);
133 }131 }
134 var bytes_transferred: windows.DWORD = undefined;132 var bytes_transferred: windows.DWORD = undefined;
135 if (windows.GetOverlappedResult(fd, &overlapped, &bytes_transferred, windows.FALSE) == 0) {133 if (windows.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) {
136 const err = windows.GetLastError();134 const err = windows.GetLastError();
137 return switch (err) {135 return switch (err) {
138 windows.ERROR.IO_PENDING => unreachable,136 windows.ERROR.IO_PENDING => unreachable,
...@@ -243,37 +241,36 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6...@@ -243,37 +241,36 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
243 .base = Loop.ResumeNode{241 .base = Loop.ResumeNode{
244 .id = Loop.ResumeNode.Id.Basic,242 .id = Loop.ResumeNode.Id.Basic,
245 .handle = @handle(),243 .handle = @handle(),
244 .overlapped = windows.OVERLAPPED{
245 .Internal = 0,
246 .InternalHigh = 0,
247 .Offset = @truncate(u32, offset),
248 .OffsetHigh = @truncate(u32, offset >> 32),
249 .hEvent = null,
250 },
246 },251 },
247 };252 };
248 const completion_key = @ptrToInt(&resume_node.base);253 // TODO only call create io completion port once per fd
249 // TODO support concurrent async ops on the file handle254 _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined);
250 // we can do this by ignoring completion key and using @fieldParentPtr with the *Overlapped
251 _ = try os.windowsCreateIoCompletionPort(fd, loop.os_data.io_port, completion_key, undefined);
252 var overlapped = windows.OVERLAPPED{
253 .Internal = 0,
254 .InternalHigh = 0,
255 .Offset = @truncate(u32, offset),
256 .OffsetHigh = @truncate(u32, offset >> 32),
257 .hEvent = null,
258 };
259 loop.beginOneEvent();255 loop.beginOneEvent();
260 errdefer loop.finishOneEvent();256 errdefer loop.finishOneEvent();
261257
262 errdefer {258 errdefer {
263 _ = windows.CancelIoEx(fd, &overlapped);259 _ = windows.CancelIoEx(fd, &resume_node.base.overlapped);
264 }260 }
265 suspend {261 suspend {
266 _ = windows.ReadFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &overlapped);262 _ = windows.ReadFile(fd, data.ptr, @intCast(windows.DWORD, data.len), null, &resume_node.base.overlapped);
267 }263 }
268 var bytes_transferred: windows.DWORD = undefined;264 var bytes_transferred: windows.DWORD = undefined;
269 if (windows.GetOverlappedResult(fd, &overlapped, &bytes_transferred, windows.FALSE) == 0) {265 if (windows.GetOverlappedResult(fd, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) {
270 const err = windows.GetLastError();266 const err = windows.GetLastError();
271 return switch (err) {267 switch (err) {
272 windows.ERROR.IO_PENDING => unreachable,268 windows.ERROR.IO_PENDING => unreachable,
273 windows.ERROR.OPERATION_ABORTED => error.OperationAborted,269 windows.ERROR.OPERATION_ABORTED => return error.OperationAborted,
274 windows.ERROR.BROKEN_PIPE => error.BrokenPipe,270 windows.ERROR.BROKEN_PIPE => return error.BrokenPipe,
275 else => os.unexpectedErrorWindows(err),271 windows.ERROR.HANDLE_EOF => return usize(bytes_transferred),
276 };272 else => return os.unexpectedErrorWindows(err),
273 }
277 }274 }
278 return usize(bytes_transferred);275 return usize(bytes_transferred);
279}276}
...@@ -727,7 +724,7 @@ pub fn Watch(comptime V: type) type {...@@ -727,7 +724,7 @@ pub fn Watch(comptime V: type) type {
727724
728 const FileToHandle = std.AutoHashMap([]const u8, promise);725 const FileToHandle = std.AutoHashMap([]const u8, promise);
729726
730 const Self = this;727 const Self = @This();
731728
732 pub const Event = struct {729 pub const Event = struct {
733 id: Id,730 id: Id,
...@@ -1074,23 +1071,22 @@ pub fn Watch(comptime V: type) type {...@@ -1074,23 +1071,22 @@ pub fn Watch(comptime V: type) type {
1074 .base = Loop.ResumeNode{1071 .base = Loop.ResumeNode{
1075 .id = Loop.ResumeNode.Id.Basic,1072 .id = Loop.ResumeNode.Id.Basic,
1076 .handle = @handle(),1073 .handle = @handle(),
1074 .overlapped = windows.OVERLAPPED{
1075 .Internal = 0,
1076 .InternalHigh = 0,
1077 .Offset = 0,
1078 .OffsetHigh = 0,
1079 .hEvent = null,
1080 },
1077 },1081 },
1078 };1082 };
1079 const completion_key = @ptrToInt(&resume_node.base);
1080 var overlapped = windows.OVERLAPPED{
1081 .Internal = 0,
1082 .InternalHigh = 0,
1083 .Offset = 0,
1084 .OffsetHigh = 0,
1085 .hEvent = null,
1086 };
1087 var event_buf: [4096]u8 align(@alignOf(windows.FILE_NOTIFY_INFORMATION)) = undefined;1083 var event_buf: [4096]u8 align(@alignOf(windows.FILE_NOTIFY_INFORMATION)) = undefined;
10881084
1089 // TODO handle this error not in the channel but in the setup1085 // TODO handle this error not in the channel but in the setup
1090 _ = os.windowsCreateIoCompletionPort(1086 _ = os.windowsCreateIoCompletionPort(
1091 dir_handle,1087 dir_handle,
1092 self.channel.loop.os_data.io_port,1088 self.channel.loop.os_data.io_port,
1093 completion_key,1089 undefined,
1094 undefined,1090 undefined,
1095 ) catch |err| {1091 ) catch |err| {
1096 await (async self.channel.put(err) catch unreachable);1092 await (async self.channel.put(err) catch unreachable);
...@@ -1103,7 +1099,7 @@ pub fn Watch(comptime V: type) type {...@@ -1103,7 +1099,7 @@ pub fn Watch(comptime V: type) type {
1103 self.channel.loop.beginOneEvent();1099 self.channel.loop.beginOneEvent();
1104 errdefer self.channel.loop.finishOneEvent();1100 errdefer self.channel.loop.finishOneEvent();
1105 errdefer {1101 errdefer {
1106 _ = windows.CancelIoEx(dir_handle, &overlapped);1102 _ = windows.CancelIoEx(dir_handle, &resume_node.base.overlapped);
1107 }1103 }
1108 suspend {1104 suspend {
1109 _ = windows.ReadDirectoryChangesW(1105 _ = windows.ReadDirectoryChangesW(
...@@ -1116,13 +1112,13 @@ pub fn Watch(comptime V: type) type {...@@ -1116,13 +1112,13 @@ pub fn Watch(comptime V: type) type {
1116 windows.FILE_NOTIFY_CHANGE_LAST_WRITE | windows.FILE_NOTIFY_CHANGE_LAST_ACCESS |1112 windows.FILE_NOTIFY_CHANGE_LAST_WRITE | windows.FILE_NOTIFY_CHANGE_LAST_ACCESS |
1117 windows.FILE_NOTIFY_CHANGE_CREATION | windows.FILE_NOTIFY_CHANGE_SECURITY,1113 windows.FILE_NOTIFY_CHANGE_CREATION | windows.FILE_NOTIFY_CHANGE_SECURITY,
1118 null, // number of bytes transferred (unused for async)1114 null, // number of bytes transferred (unused for async)
1119 &overlapped,1115 &resume_node.base.overlapped,
1120 null, // completion routine - unused because we use IOCP1116 null, // completion routine - unused because we use IOCP
1121 );1117 );
1122 }1118 }
1123 }1119 }
1124 var bytes_transferred: windows.DWORD = undefined;1120 var bytes_transferred: windows.DWORD = undefined;
1125 if (windows.GetOverlappedResult(dir_handle, &overlapped, &bytes_transferred, windows.FALSE) == 0) {1121 if (windows.GetOverlappedResult(dir_handle, &resume_node.base.overlapped, &bytes_transferred, windows.FALSE) == 0) {
1126 const errno = windows.GetLastError();1122 const errno = windows.GetLastError();
1127 const err = switch (errno) {1123 const err = switch (errno) {
1128 else => os.unexpectedErrorWindows(errno),1124 else => os.unexpectedErrorWindows(errno),
std/event/future.zig+1-1
...@@ -21,7 +21,7 @@ pub fn Future(comptime T: type) type {...@@ -21,7 +21,7 @@ pub fn Future(comptime T: type) type {
21 /// 2 - finished21 /// 2 - finished
22 available: u8,22 available: u8,
2323
24 const Self = this;24 const Self = @This();
25 const Queue = std.atomic.Queue(promise);25 const Queue = std.atomic.Queue(promise);
2626
27 pub fn init(loop: *Loop) Self {27 pub fn init(loop: *Loop) Self {
std/event/group.zig+1-1
...@@ -13,7 +13,7 @@ pub fn Group(comptime ReturnType: type) type {...@@ -13,7 +13,7 @@ pub fn Group(comptime ReturnType: type) type {
13 alloc_stack: Stack,13 alloc_stack: Stack,
14 lock: Lock,14 lock: Lock,
1515
16 const Self = this;16 const Self = @This();
1717
18 const Error = switch (@typeInfo(ReturnType)) {18 const Error = switch (@typeInfo(ReturnType)) {
19 builtin.TypeId.ErrorUnion => |payload| payload.error_set,19 builtin.TypeId.ErrorUnion => |payload| payload.error_set,
std/event/locked.zig+1-1
...@@ -10,7 +10,7 @@ pub fn Locked(comptime T: type) type {...@@ -10,7 +10,7 @@ pub fn Locked(comptime T: type) type {
10 lock: Lock,10 lock: Lock,
11 private_data: T,11 private_data: T,
1212
13 const Self = this;13 const Self = @This();
1414
15 pub const HeldLock = struct {15 pub const HeldLock = struct {
16 value: *T,16 value: *T,
std/event/loop.zig+30-14
...@@ -27,6 +27,19 @@ pub const Loop = struct {...@@ -27,6 +27,19 @@ pub const Loop = struct {
27 pub const ResumeNode = struct {27 pub const ResumeNode = struct {
28 id: Id,28 id: Id,
29 handle: promise,29 handle: promise,
30 overlapped: Overlapped,
31
32 pub const overlapped_init = switch (builtin.os) {
33 builtin.Os.windows => windows.OVERLAPPED{
34 .Internal = 0,
35 .InternalHigh = 0,
36 .Offset = 0,
37 .OffsetHigh = 0,
38 .hEvent = null,
39 },
40 else => {},
41 };
42 pub const Overlapped = @typeOf(overlapped_init);
3043
31 pub const Id = enum {44 pub const Id = enum {
32 Basic,45 Basic,
...@@ -101,6 +114,7 @@ pub const Loop = struct {...@@ -101,6 +114,7 @@ pub const Loop = struct {
101 .final_resume_node = ResumeNode{114 .final_resume_node = ResumeNode{
102 .id = ResumeNode.Id.Stop,115 .id = ResumeNode.Id.Stop,
103 .handle = undefined,116 .handle = undefined,
117 .overlapped = ResumeNode.overlapped_init,
104 },118 },
105 };119 };
106 const extra_thread_count = thread_count - 1;120 const extra_thread_count = thread_count - 1;
...@@ -153,6 +167,7 @@ pub const Loop = struct {...@@ -153,6 +167,7 @@ pub const Loop = struct {
153 .base = ResumeNode{167 .base = ResumeNode{
154 .id = ResumeNode.Id.EventFd,168 .id = ResumeNode.Id.EventFd,
155 .handle = undefined,169 .handle = undefined,
170 .overlapped = ResumeNode.overlapped_init,
156 },171 },
157 .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),172 .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),
158 .epoll_op = posix.EPOLL_CTL_ADD,173 .epoll_op = posix.EPOLL_CTL_ADD,
...@@ -225,6 +240,7 @@ pub const Loop = struct {...@@ -225,6 +240,7 @@ pub const Loop = struct {
225 .base = ResumeNode{240 .base = ResumeNode{
226 .id = ResumeNode.Id.EventFd,241 .id = ResumeNode.Id.EventFd,
227 .handle = undefined,242 .handle = undefined,
243 .overlapped = ResumeNode.overlapped_init,
228 },244 },
229 // this one is for sending events245 // this one is for sending events
230 .kevent = posix.Kevent{246 .kevent = posix.Kevent{
...@@ -311,6 +327,7 @@ pub const Loop = struct {...@@ -311,6 +327,7 @@ pub const Loop = struct {
311 .base = ResumeNode{327 .base = ResumeNode{
312 .id = ResumeNode.Id.EventFd,328 .id = ResumeNode.Id.EventFd,
313 .handle = undefined,329 .handle = undefined,
330 .overlapped = ResumeNode.overlapped_init,
314 },331 },
315 // this one is for sending events332 // this one is for sending events
316 .completion_key = @ptrToInt(&eventfd_node.data.base),333 .completion_key = @ptrToInt(&eventfd_node.data.base),
...@@ -325,8 +342,8 @@ pub const Loop = struct {...@@ -325,8 +342,8 @@ pub const Loop = struct {
325 var i: usize = 0;342 var i: usize = 0;
326 while (i < extra_thread_index) : (i += 1) {343 while (i < extra_thread_index) : (i += 1) {
327 while (true) {344 while (true) {
328 const overlapped = @intToPtr(?*windows.OVERLAPPED, 0x1);345 const overlapped = &self.final_resume_node.overlapped;
329 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, @ptrToInt(&self.final_resume_node), overlapped) catch continue;346 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
330 break;347 break;
331 }348 }
332 }349 }
...@@ -398,6 +415,7 @@ pub const Loop = struct {...@@ -398,6 +415,7 @@ pub const Loop = struct {
398 .base = ResumeNode{415 .base = ResumeNode{
399 .id = ResumeNode.Id.Basic,416 .id = ResumeNode.Id.Basic,
400 .handle = @handle(),417 .handle = @handle(),
418 .overlapped = ResumeNode.overlapped_init,
401 },419 },
402 };420 };
403 try self.linuxAddFd(fd, &resume_node.base, flags);421 try self.linuxAddFd(fd, &resume_node.base, flags);
...@@ -413,6 +431,7 @@ pub const Loop = struct {...@@ -413,6 +431,7 @@ pub const Loop = struct {
413 .base = ResumeNode{431 .base = ResumeNode{
414 .id = ResumeNode.Id.Basic,432 .id = ResumeNode.Id.Basic,
415 .handle = @handle(),433 .handle = @handle(),
434 .overlapped = ResumeNode.overlapped_init,
416 },435 },
417 .kev = undefined,436 .kev = undefined,
418 };437 };
...@@ -489,15 +508,11 @@ pub const Loop = struct {...@@ -489,15 +508,11 @@ pub const Loop = struct {
489 };508 };
490 },509 },
491 builtin.Os.windows => {510 builtin.Os.windows => {
492 // this value is never dereferenced but we need it to be non-null so that
493 // the consumer code can decide whether to read the completion key.
494 // it has to do this for normal I/O, so we match that behavior here.
495 const overlapped = @intToPtr(?*windows.OVERLAPPED, 0x1);
496 os.windowsPostQueuedCompletionStatus(511 os.windowsPostQueuedCompletionStatus(
497 self.os_data.io_port,512 self.os_data.io_port,
498 undefined,513 undefined,
499 eventfd_node.completion_key,514 undefined,
500 overlapped,515 &eventfd_node.base.overlapped,
501 ) catch {516 ) catch {
502 self.next_tick_queue.unget(next_tick_node);517 self.next_tick_queue.unget(next_tick_node);
503 self.available_eventfd_resume_nodes.push(resume_stack_node);518 self.available_eventfd_resume_nodes.push(resume_stack_node);
...@@ -606,8 +621,8 @@ pub const Loop = struct {...@@ -606,8 +621,8 @@ pub const Loop = struct {
606 var i: usize = 0;621 var i: usize = 0;
607 while (i < self.extra_threads.len + 1) : (i += 1) {622 while (i < self.extra_threads.len + 1) : (i += 1) {
608 while (true) {623 while (true) {
609 const overlapped = @intToPtr(?*windows.OVERLAPPED, 0x1);624 const overlapped = &self.final_resume_node.overlapped;
610 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, @ptrToInt(&self.final_resume_node), overlapped) catch continue;625 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
611 break;626 break;
612 }627 }
613 }628 }
...@@ -680,17 +695,18 @@ pub const Loop = struct {...@@ -680,17 +695,18 @@ pub const Loop = struct {
680 },695 },
681 builtin.Os.windows => {696 builtin.Os.windows => {
682 var completion_key: usize = undefined;697 var completion_key: usize = undefined;
683 while (true) {698 const overlapped = while (true) {
684 var nbytes: windows.DWORD = undefined;699 var nbytes: windows.DWORD = undefined;
685 var overlapped: ?*windows.OVERLAPPED = undefined;700 var overlapped: ?*windows.OVERLAPPED = undefined;
686 switch (os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {701 switch (os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {
687 os.WindowsWaitResult.Aborted => return,702 os.WindowsWaitResult.Aborted => return,
688 os.WindowsWaitResult.Normal => {},703 os.WindowsWaitResult.Normal => {},
704 os.WindowsWaitResult.EOF => {},
689 os.WindowsWaitResult.Cancelled => continue,705 os.WindowsWaitResult.Cancelled => continue,
690 }706 }
691 if (overlapped != null) break;707 if (overlapped) |o| break o;
692 }708 } else unreachable; // TODO else unreachable should not be necessary
693 const resume_node = @intToPtr(*ResumeNode, completion_key);709 const resume_node = @fieldParentPtr(ResumeNode, "overlapped", overlapped);
694 const handle = resume_node.handle;710 const handle = resume_node.handle;
695 const resume_node_id = resume_node.id;711 const resume_node_id = resume_node.id;
696 switch (resume_node_id) {712 switch (resume_node_id) {
std/event/rwlocked.zig+1-1
...@@ -10,7 +10,7 @@ pub fn RwLocked(comptime T: type) type {...@@ -10,7 +10,7 @@ pub fn RwLocked(comptime T: type) type {
10 lock: RwLock,10 lock: RwLock,
11 locked_data: T,11 locked_data: T,
1212
13 const Self = this;13 const Self = @This();
1414
15 pub const HeldReadLock = struct {15 pub const HeldReadLock = struct {
16 value: *const T,16 value: *const T,
std/event/tcp.zig+2-1
...@@ -32,6 +32,7 @@ pub const Server = struct {...@@ -32,6 +32,7 @@ pub const Server = struct {
32 .listen_resume_node = event.Loop.ResumeNode{32 .listen_resume_node = event.Loop.ResumeNode{
33 .id = event.Loop.ResumeNode.Id.Basic,33 .id = event.Loop.ResumeNode.Id.Basic,
34 .handle = undefined,34 .handle = undefined,
35 .overlapped = event.Loop.ResumeNode.overlapped_init,
35 },36 },
36 };37 };
37 }38 }
...@@ -131,7 +132,7 @@ test "listen on a port, send bytes, receive bytes" {...@@ -131,7 +132,7 @@ test "listen on a port, send bytes, receive bytes" {
131 const MyServer = struct {132 const MyServer = struct {
132 tcp_server: Server,133 tcp_server: Server,
133134
134 const Self = this;135 const Self = @This();
135 async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const std.os.File) void {136 async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const std.os.File) void {
136 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);137 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
137 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733138 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
std/fmt/index.zig+1-1
...@@ -1183,7 +1183,7 @@ test "fmt.format" {...@@ -1183,7 +1183,7 @@ test "fmt.format" {
1183 //custom type format1183 //custom type format
1184 {1184 {
1185 const Vec2 = struct {1185 const Vec2 = struct {
1186 const SelfType = this;1186 const SelfType = @This();
1187 x: f32,1187 x: f32,
1188 y: f32,1188 y: f32,
11891189
std/hash/crc.zig+2-2
...@@ -20,7 +20,7 @@ pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);...@@ -20,7 +20,7 @@ pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
20// slicing-by-8 crc32 implementation.20// slicing-by-8 crc32 implementation.
21pub fn Crc32WithPoly(comptime poly: u32) type {21pub fn Crc32WithPoly(comptime poly: u32) type {
22 return struct {22 return struct {
23 const Self = this;23 const Self = @This();
24 const lookup_tables = comptime block: {24 const lookup_tables = comptime block: {
25 @setEvalBranchQuota(20000);25 @setEvalBranchQuota(20000);
26 var tables: [8][256]u32 = undefined;26 var tables: [8][256]u32 = undefined;
...@@ -117,7 +117,7 @@ test "crc32 castagnoli" {...@@ -117,7 +117,7 @@ test "crc32 castagnoli" {
117// half-byte lookup table implementation.117// half-byte lookup table implementation.
118pub fn Crc32SmallWithPoly(comptime poly: u32) type {118pub fn Crc32SmallWithPoly(comptime poly: u32) type {
119 return struct {119 return struct {
120 const Self = this;120 const Self = @This();
121 const lookup_table = comptime block: {121 const lookup_table = comptime block: {
122 var table: [16]u32 = undefined;122 var table: [16]u32 = undefined;
123123
std/hash/fnv.zig+1-1
...@@ -13,7 +13,7 @@ pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb01426...@@ -13,7 +13,7 @@ pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb01426
1313
14fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {14fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
15 return struct {15 return struct {
16 const Self = this;16 const Self = @This();
1717
18 value: T,18 value: T,
1919
std/hash/siphash.zig+1-1
...@@ -25,7 +25,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -25,7 +25,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
25 debug.assert(c_rounds > 0 and d_rounds > 0);25 debug.assert(c_rounds > 0 and d_rounds > 0);
2626
27 return struct {27 return struct {
28 const Self = this;28 const Self = @This();
29 const digest_size = 64;29 const digest_size = 64;
30 const block_size = 64;30 const block_size = 64;
3131
std/hash_map.zig+1-3
...@@ -22,7 +22,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -22,7 +22,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
22 // this is used to detect bugs where a hashtable is edited while an iterator is running.22 // this is used to detect bugs where a hashtable is edited while an iterator is running.
23 modification_count: debug_u32,23 modification_count: debug_u32,
2424
25 const Self = this;25 const Self = @This();
2626
27 pub const KV = struct {27 pub const KV = struct {
28 key: K,28 key: K,
...@@ -472,7 +472,6 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -472,7 +472,6 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
472 builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng),472 builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng),
473473
474 builtin.TypeId.Namespace,474 builtin.TypeId.Namespace,
475 builtin.TypeId.Block,
476 builtin.TypeId.BoundFn,475 builtin.TypeId.BoundFn,
477 builtin.TypeId.ComptimeFloat,476 builtin.TypeId.ComptimeFloat,
478 builtin.TypeId.ComptimeInt,477 builtin.TypeId.ComptimeInt,
...@@ -517,7 +516,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -517,7 +516,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
517 builtin.TypeId.ComptimeFloat,516 builtin.TypeId.ComptimeFloat,
518 builtin.TypeId.ComptimeInt,517 builtin.TypeId.ComptimeInt,
519 builtin.TypeId.Namespace,518 builtin.TypeId.Namespace,
520 builtin.TypeId.Block,
521 builtin.TypeId.Promise,519 builtin.TypeId.Promise,
522 builtin.TypeId.Enum,520 builtin.TypeId.Enum,
523 builtin.TypeId.BoundFn,521 builtin.TypeId.BoundFn,
std/heap.zig+1-1
...@@ -385,7 +385,7 @@ pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) Stack...@@ -385,7 +385,7 @@ pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) Stack
385385
386pub fn StackFallbackAllocator(comptime size: usize) type {386pub fn StackFallbackAllocator(comptime size: usize) type {
387 return struct {387 return struct {
388 const Self = this;388 const Self = @This();
389389
390 buffer: [size]u8,390 buffer: [size]u8,
391 allocator: Allocator,391 allocator: Allocator,
std/io.zig+6-6
...@@ -76,7 +76,7 @@ pub const FileOutStream = struct {...@@ -76,7 +76,7 @@ pub const FileOutStream = struct {
7676
77pub fn InStream(comptime ReadError: type) type {77pub fn InStream(comptime ReadError: type) type {
78 return struct {78 return struct {
79 const Self = this;79 const Self = @This();
80 pub const Error = ReadError;80 pub const Error = ReadError;
8181
82 /// Return the number of bytes read. If the number read is smaller than buf.len, it82 /// Return the number of bytes read. If the number read is smaller than buf.len, it
...@@ -218,7 +218,7 @@ pub fn InStream(comptime ReadError: type) type {...@@ -218,7 +218,7 @@ pub fn InStream(comptime ReadError: type) type {
218218
219pub fn OutStream(comptime WriteError: type) type {219pub fn OutStream(comptime WriteError: type) type {
220 return struct {220 return struct {
221 const Self = this;221 const Self = @This();
222 pub const Error = WriteError;222 pub const Error = WriteError;
223223
224 writeFn: fn (self: *Self, bytes: []const u8) Error!void,224 writeFn: fn (self: *Self, bytes: []const u8) Error!void,
...@@ -291,7 +291,7 @@ pub fn BufferedInStream(comptime Error: type) type {...@@ -291,7 +291,7 @@ pub fn BufferedInStream(comptime Error: type) type {
291291
292pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type {292pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type {
293 return struct {293 return struct {
294 const Self = this;294 const Self = @This();
295 const Stream = InStream(Error);295 const Stream = InStream(Error);
296296
297 pub stream: Stream,297 pub stream: Stream,
...@@ -361,7 +361,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)...@@ -361,7 +361,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
361/// This makes look-ahead style parsing much easier.361/// This makes look-ahead style parsing much easier.
362pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {362pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
363 return struct {363 return struct {
364 const Self = this;364 const Self = @This();
365 pub const Error = InStreamError;365 pub const Error = InStreamError;
366 pub const Stream = InStream(Error);366 pub const Stream = InStream(Error);
367367
...@@ -424,7 +424,7 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ...@@ -424,7 +424,7 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ
424}424}
425425
426pub const SliceInStream = struct {426pub const SliceInStream = struct {
427 const Self = this;427 const Self = @This();
428 pub const Error = error{};428 pub const Error = error{};
429 pub const Stream = InStream(Error);429 pub const Stream = InStream(Error);
430430
...@@ -505,7 +505,7 @@ pub fn BufferedOutStream(comptime Error: type) type {...@@ -505,7 +505,7 @@ pub fn BufferedOutStream(comptime Error: type) type {
505505
506pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamError: type) type {506pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamError: type) type {
507 return struct {507 return struct {
508 const Self = this;508 const Self = @This();
509 pub const Stream = OutStream(Error);509 pub const Stream = OutStream(Error);
510 pub const Error = OutStreamError;510 pub const Error = OutStreamError;
511511
std/lazy_init.zig+1-1
...@@ -18,7 +18,7 @@ fn LazyInit(comptime T: type) type {...@@ -18,7 +18,7 @@ fn LazyInit(comptime T: type) type {
18 state: u8, // TODO make this an enum18 state: u8, // TODO make this an enum
19 data: Data,19 data: Data,
2020
21 const Self = this;21 const Self = @This();
2222
23 // TODO this isn't working for void, investigate and then remove this special case23 // TODO this isn't working for void, investigate and then remove this special case
24 const Data = if (@sizeOf(T) == 0) u8 else T;24 const Data = if (@sizeOf(T) == 0) u8 else T;
std/linked_list.zig+1-1
...@@ -7,7 +7,7 @@ const Allocator = mem.Allocator;...@@ -7,7 +7,7 @@ const Allocator = mem.Allocator;
7/// Generic doubly linked list.7/// Generic doubly linked list.
8pub fn LinkedList(comptime T: type) type {8pub fn LinkedList(comptime T: type) type {
9 return struct {9 return struct {
10 const Self = this;10 const Self = @This();
1111
12 /// Node inside the linked list wrapping the actual data.12 /// Node inside the linked list wrapping the actual data.
13 pub const Node = struct {13 pub const Node = struct {
std/math/complex/cosh.zig+2-2
...@@ -44,7 +44,7 @@ fn cosh32(z: *const Complex(f32)) Complex(f32) {...@@ -44,7 +44,7 @@ fn cosh32(z: *const Complex(f32)) Complex(f32) {
44 else if (ix < 0x4340b1e7) {44 else if (ix < 0x4340b1e7) {
45 const v = Complex(f32).new(math.fabs(x), y);45 const v = Complex(f32).new(math.fabs(x), y);
46 const r = ldexp_cexp(v, -1);46 const r = ldexp_cexp(v, -1);
47 return Complex(f32).new(x, y * math.copysign(f32, 1, x));47 return Complex(f32).new(r.re, r.im * math.copysign(f32, 1, x));
48 }48 }
49 // x >= 192.7: result always overflows49 // x >= 192.7: result always overflows
50 else {50 else {
...@@ -112,7 +112,7 @@ fn cosh64(z: *const Complex(f64)) Complex(f64) {...@@ -112,7 +112,7 @@ fn cosh64(z: *const Complex(f64)) Complex(f64) {
112 else if (ix < 0x4096bbaa) {112 else if (ix < 0x4096bbaa) {
113 const v = Complex(f64).new(math.fabs(x), y);113 const v = Complex(f64).new(math.fabs(x), y);
114 const r = ldexp_cexp(v, -1);114 const r = ldexp_cexp(v, -1);
115 return Complex(f64).new(x, y * math.copysign(f64, 1, x));115 return Complex(f64).new(r.re, r.im * math.copysign(f64, 1, x));
116 }116 }
117 // x >= 1455: result always overflows117 // x >= 1455: result always overflows
118 else {118 else {
std/math/complex/exp.zig+4-5
...@@ -69,7 +69,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {...@@ -69,7 +69,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
69 const y = z.im;69 const y = z.im;
7070
71 const fy = @bitCast(u64, y);71 const fy = @bitCast(u64, y);
72 const hy = u32(fy >> 32) & 0x7fffffff;72 const hy = @intCast(u32, (fy >> 32) & 0x7fffffff);
73 const ly = @truncate(u32, fy);73 const ly = @truncate(u32, fy);
7474
75 // cexp(x + i0) = exp(x) + i075 // cexp(x + i0) = exp(x) + i0
...@@ -78,7 +78,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {...@@ -78,7 +78,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
78 }78 }
7979
80 const fx = @bitCast(u64, x);80 const fx = @bitCast(u64, x);
81 const hx = u32(fx >> 32);81 const hx = @intCast(u32, fx >> 32);
82 const lx = @truncate(u32, fx);82 const lx = @truncate(u32, fx);
8383
84 // cexp(0 + iy) = cos(y) + isin(y)84 // cexp(0 + iy) = cos(y) + isin(y)
...@@ -101,8 +101,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {...@@ -101,8 +101,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
101101
102 // 709.7 <= x <= 1454.3 so must scale102 // 709.7 <= x <= 1454.3 so must scale
103 if (hx >= exp_overflow and hx <= cexp_overflow) {103 if (hx >= exp_overflow and hx <= cexp_overflow) {
104 const r = ldexp_cexp(z, 0);104 return ldexp_cexp(z, 0);
105 return r.*;
106 } // - x < exp_overflow => exp(x) won't overflow (common)105 } // - x < exp_overflow => exp(x) won't overflow (common)
107 // - x > cexp_overflow, so exp(x) * s overflows for s > 0106 // - x > cexp_overflow, so exp(x) * s overflows for s > 0
108 // - x = +-inf107 // - x = +-inf
...@@ -124,7 +123,7 @@ test "complex.cexp32" {...@@ -124,7 +123,7 @@ test "complex.cexp32" {
124}123}
125124
126test "complex.cexp64" {125test "complex.cexp64" {
127 const a = Complex(f32).new(5, 3);126 const a = Complex(f64).new(5, 3);
128 const c = exp(a);127 const c = exp(a);
129128
130 debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon));129 debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon));
std/math/complex/index.zig+1-1
...@@ -25,7 +25,7 @@ pub const tan = @import("tan.zig").tan;...@@ -25,7 +25,7 @@ pub const tan = @import("tan.zig").tan;
2525
26pub fn Complex(comptime T: type) type {26pub fn Complex(comptime T: type) type {
27 return struct {27 return struct {
28 const Self = this;28 const Self = @This();
2929
30 re: T,30 re: T,
31 im: T,31 im: T,
std/math/complex/sinh.zig+2-2
...@@ -44,7 +44,7 @@ fn sinh32(z: Complex(f32)) Complex(f32) {...@@ -44,7 +44,7 @@ fn sinh32(z: Complex(f32)) Complex(f32) {
44 else if (ix < 0x4340b1e7) {44 else if (ix < 0x4340b1e7) {
45 const v = Complex(f32).new(math.fabs(x), y);45 const v = Complex(f32).new(math.fabs(x), y);
46 const r = ldexp_cexp(v, -1);46 const r = ldexp_cexp(v, -1);
47 return Complex(f32).new(x * math.copysign(f32, 1, x), y);47 return Complex(f32).new(r.re * math.copysign(f32, 1, x), r.im);
48 }48 }
49 // x >= 192.7: result always overflows49 // x >= 192.7: result always overflows
50 else {50 else {
...@@ -111,7 +111,7 @@ fn sinh64(z: Complex(f64)) Complex(f64) {...@@ -111,7 +111,7 @@ fn sinh64(z: Complex(f64)) Complex(f64) {
111 else if (ix < 0x4096bbaa) {111 else if (ix < 0x4096bbaa) {
112 const v = Complex(f64).new(math.fabs(x), y);112 const v = Complex(f64).new(math.fabs(x), y);
113 const r = ldexp_cexp(v, -1);113 const r = ldexp_cexp(v, -1);
114 return Complex(f64).new(x * math.copysign(f64, 1, x), y);114 return Complex(f64).new(r.re * math.copysign(f64, 1, x), r.im);
115 }115 }
116 // x >= 1455: result always overflows116 // x >= 1455: result always overflows
117 else {117 else {
std/mem.zig+1-1
...@@ -3,7 +3,7 @@ const debug = std.debug;...@@ -3,7 +3,7 @@ const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const math = std.math;4const math = std.math;
5const builtin = @import("builtin");5const builtin = @import("builtin");
6const mem = this;6const mem = @This();
77
8pub const Allocator = struct {8pub const Allocator = struct {
9 pub const Error = error{OutOfMemory};9 pub const Error = error{OutOfMemory};
std/net.zig+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const net = this;4const net = @This();
5const posix = std.os.posix;5const posix = std.os.posix;
6const mem = std.mem;6const mem = std.mem;
77
std/os/child_process.zig+10-2
...@@ -658,8 +658,16 @@ fn windowsCreateProcess(app_name: [*]u16, cmd_line: [*]u16, envp_ptr: ?[*]u16, c...@@ -658,8 +658,16 @@ fn windowsCreateProcess(app_name: [*]u16, cmd_line: [*]u16, envp_ptr: ?[*]u16, c
658 // environment variables to programs that were not, which seems unlikely.658 // environment variables to programs that were not, which seems unlikely.
659 // More investigation is needed.659 // More investigation is needed.
660 if (windows.CreateProcessW(660 if (windows.CreateProcessW(
661 app_name, cmd_line, null, null, windows.TRUE, windows.CREATE_UNICODE_ENVIRONMENT,661 app_name,
662 @ptrCast(?*c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation,662 cmd_line,
663 null,
664 null,
665 windows.TRUE,
666 windows.CREATE_UNICODE_ENVIRONMENT,
667 @ptrCast(?*c_void, envp_ptr),
668 cwd_ptr,
669 lpStartupInfo,
670 lpProcessInformation,
663 ) == 0) {671 ) == 0) {
664 const err = windows.GetLastError();672 const err = windows.GetLastError();
665 switch (err) {673 switch (err) {
std/os/index.zig+20-18
...@@ -6,7 +6,7 @@ const is_posix = switch (builtin.os) {...@@ -6,7 +6,7 @@ const is_posix = switch (builtin.os) {
6 builtin.Os.linux, builtin.Os.macosx => true,6 builtin.Os.linux, builtin.Os.macosx => true,
7 else => false,7 else => false,
8};8};
9const os = this;9const os = @This();
1010
11test "std.os" {11test "std.os" {
12 _ = @import("child_process.zig");12 _ = @import("child_process.zig");
...@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {...@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
345 const write_err = posix.getErrno(rc);345 const write_err = posix.getErrno(rc);
346 if (write_err > 0) {346 switch (write_err) {
347 return switch (write_err) {347 0 => {
348 posix.EINTR => continue,348 index += rc;
349 posix.EINVAL, posix.EFAULT => unreachable,349 continue;
350 posix.EAGAIN => PosixWriteError.WouldBlock,350 },
351 posix.EBADF => PosixWriteError.FileClosed,351 posix.EINTR => continue,
352 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,352 posix.EINVAL => unreachable,
353 posix.EDQUOT => PosixWriteError.DiskQuota,353 posix.EFAULT => unreachable,
354 posix.EFBIG => PosixWriteError.FileTooBig,354 posix.EAGAIN => return PosixWriteError.WouldBlock,
355 posix.EIO => PosixWriteError.InputOutput,355 posix.EBADF => return PosixWriteError.FileClosed,
356 posix.ENOSPC => PosixWriteError.NoSpaceLeft,356 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
357 posix.EPERM => PosixWriteError.AccessDenied,357 posix.EDQUOT => return PosixWriteError.DiskQuota,
358 posix.EPIPE => PosixWriteError.BrokenPipe,358 posix.EFBIG => return PosixWriteError.FileTooBig,
359 else => unexpectedErrorPosix(write_err),359 posix.EIO => return PosixWriteError.InputOutput,
360 };360 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
361 posix.EPERM => return PosixWriteError.AccessDenied,
362 posix.EPIPE => return PosixWriteError.BrokenPipe,
363 else => return unexpectedErrorPosix(write_err),
361 }364 }
362 index += rc;
363 }365 }
364}366}
365367
...@@ -1614,7 +1616,7 @@ pub const Dir = struct {...@@ -1614,7 +1616,7 @@ pub const Dir = struct {
1614 return null;1616 return null;
1615 }1617 }
1616 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);1618 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
1617 if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{'.', '.'}))1619 if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{ '.', '.' }))
1618 continue;1620 continue;
1619 // Trust that Windows gives us valid UTF-16LE1621 // Trust that Windows gives us valid UTF-16LE
1620 const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;1622 const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;
std/os/windows/kernel32.zig-1
...@@ -206,7 +206,6 @@ pub const FILE_NOTIFY_CHANGE_DIR_NAME = 2;...@@ -206,7 +206,6 @@ pub const FILE_NOTIFY_CHANGE_DIR_NAME = 2;
206pub const FILE_NOTIFY_CHANGE_FILE_NAME = 1;206pub const FILE_NOTIFY_CHANGE_FILE_NAME = 1;
207pub const FILE_NOTIFY_CHANGE_ATTRIBUTES = 4;207pub const FILE_NOTIFY_CHANGE_ATTRIBUTES = 4;
208208
209
210pub const CONSOLE_SCREEN_BUFFER_INFO = extern struct {209pub const CONSOLE_SCREEN_BUFFER_INFO = extern struct {
211 dwSize: COORD,210 dwSize: COORD,
212 dwCursorPosition: COORD,211 dwCursorPosition: COORD,
std/os/windows/util.zig+5-2
...@@ -52,7 +52,8 @@ pub const WriteError = error{...@@ -52,7 +52,8 @@ pub const WriteError = error{
52};52};
5353
54pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) WriteError!void {54pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) WriteError!void {
55 if (windows.WriteFile(handle, bytes.ptr, @intCast(u32, bytes.len), null, null) == 0) {55 var bytes_written: windows.DWORD = undefined;
56 if (windows.WriteFile(handle, bytes.ptr, @intCast(u32, bytes.len), &bytes_written, null) == 0) {
56 const err = windows.GetLastError();57 const err = windows.GetLastError();
57 return switch (err) {58 return switch (err) {
58 windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources,59 windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources,
...@@ -222,7 +223,7 @@ pub fn windowsFindFirstFile(...@@ -222,7 +223,7 @@ pub fn windowsFindFirstFile(
222 dir_path: []const u8,223 dir_path: []const u8,
223 find_file_data: *windows.WIN32_FIND_DATAW,224 find_file_data: *windows.WIN32_FIND_DATAW,
224) !windows.HANDLE {225) !windows.HANDLE {
225 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, []u16{'\\', '*', 0});226 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, []u16{ '\\', '*', 0 });
226 const handle = windows.FindFirstFileW(&dir_path_w, find_file_data);227 const handle = windows.FindFirstFileW(&dir_path_w, find_file_data);
227228
228 if (handle == windows.INVALID_HANDLE_VALUE) {229 if (handle == windows.INVALID_HANDLE_VALUE) {
...@@ -277,6 +278,7 @@ pub const WindowsWaitResult = enum {...@@ -277,6 +278,7 @@ pub const WindowsWaitResult = enum {
277 Normal,278 Normal,
278 Aborted,279 Aborted,
279 Cancelled,280 Cancelled,
281 EOF,
280};282};
281283
282pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_transferred_count: *windows.DWORD, lpCompletionKey: *usize, lpOverlapped: *?*windows.OVERLAPPED, dwMilliseconds: windows.DWORD) WindowsWaitResult {284pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_transferred_count: *windows.DWORD, lpCompletionKey: *usize, lpOverlapped: *?*windows.OVERLAPPED, dwMilliseconds: windows.DWORD) WindowsWaitResult {
...@@ -285,6 +287,7 @@ pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_t...@@ -285,6 +287,7 @@ pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_t
285 switch (err) {287 switch (err) {
286 windows.ERROR.ABANDONED_WAIT_0 => return WindowsWaitResult.Aborted,288 windows.ERROR.ABANDONED_WAIT_0 => return WindowsWaitResult.Aborted,
287 windows.ERROR.OPERATION_ABORTED => return WindowsWaitResult.Cancelled,289 windows.ERROR.OPERATION_ABORTED => return WindowsWaitResult.Cancelled,
290 windows.ERROR.HANDLE_EOF => return WindowsWaitResult.EOF,
288 else => {291 else => {
289 if (std.debug.runtime_safety) {292 if (std.debug.runtime_safety) {
290 std.debug.panic("unexpected error: {}\n", err);293 std.debug.panic("unexpected error: {}\n", err);
std/pdb.zig+98-63
...@@ -64,19 +64,35 @@ pub const ModInfo = packed struct {...@@ -64,19 +64,35 @@ pub const ModInfo = packed struct {
64};64};
6565
66pub const SectionMapHeader = packed struct {66pub const SectionMapHeader = packed struct {
67 Count: u16, /// Number of segment descriptors67 /// Number of segment descriptors
68 LogCount: u16, /// Number of logical segment descriptors68 Count: u16,
69
70 /// Number of logical segment descriptors
71 LogCount: u16,
69};72};
7073
71pub const SectionMapEntry = packed struct {74pub const SectionMapEntry = packed struct {
72 Flags: u16 , /// See the SectionMapEntryFlags enum below.75 /// See the SectionMapEntryFlags enum below.
73 Ovl: u16 , /// Logical overlay number76 Flags: u16,
74 Group: u16 , /// Group index into descriptor array.77
75 Frame: u16 ,78 /// Logical overlay number
76 SectionName: u16 , /// Byte index of segment / group name in string table, or 0xFFFF.79 Ovl: u16,
77 ClassName: u16 , /// Byte index of class in string table, or 0xFFFF.80
78 Offset: u32 , /// Byte offset of the logical segment within physical segment. If group is set in flags, this is the offset of the group.81 /// Group index into descriptor array.
79 SectionLength: u32 , /// Byte count of the segment or group.82 Group: u16,
83 Frame: u16,
84
85 /// Byte index of segment / group name in string table, or 0xFFFF.
86 SectionName: u16,
87
88 /// Byte index of class in string table, or 0xFFFF.
89 ClassName: u16,
90
91 /// Byte offset of the logical segment within physical segment. If group is set in flags, this is the offset of the group.
92 Offset: u32,
93
94 /// Byte count of the segment or group.
95 SectionLength: u32,
80};96};
8197
82pub const StreamType = enum(u16) {98pub const StreamType = enum(u16) {
...@@ -290,13 +306,13 @@ pub const SymbolKind = packed enum(u16) {...@@ -290,13 +306,13 @@ pub const SymbolKind = packed enum(u16) {
290pub const TypeIndex = u32;306pub const TypeIndex = u32;
291307
292pub const ProcSym = packed struct {308pub const ProcSym = packed struct {
293 Parent: u32 ,309 Parent: u32,
294 End: u32 ,310 End: u32,
295 Next: u32 ,311 Next: u32,
296 CodeSize: u32 ,312 CodeSize: u32,
297 DbgStart: u32 ,313 DbgStart: u32,
298 DbgEnd: u32 ,314 DbgEnd: u32,
299 FunctionType: TypeIndex ,315 FunctionType: TypeIndex,
300 CodeOffset: u32,316 CodeOffset: u32,
301 Segment: u16,317 Segment: u16,
302 Flags: ProcSymFlags,318 Flags: ProcSymFlags,
...@@ -315,25 +331,34 @@ pub const ProcSymFlags = packed struct {...@@ -315,25 +331,34 @@ pub const ProcSymFlags = packed struct {
315 HasOptimizedDebugInfo: bool,331 HasOptimizedDebugInfo: bool,
316};332};
317333
318pub const SectionContrSubstreamVersion = enum(u32) {334pub const SectionContrSubstreamVersion = enum(u32) {
319 Ver60 = 0xeffe0000 + 19970605,335 Ver60 = 0xeffe0000 + 19970605,
320 V2 = 0xeffe0000 + 20140516336 V2 = 0xeffe0000 + 20140516,
321};337};
322338
323pub const RecordPrefix = packed struct {339pub const RecordPrefix = packed struct {
324 RecordLen: u16, /// Record length, starting from &RecordKind.340 /// Record length, starting from &RecordKind.
325 RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind)341 RecordLen: u16,
342
343 /// Record kind enum (SymRecordKind or TypeRecordKind)
344 RecordKind: SymbolKind,
326};345};
327346
328pub const LineFragmentHeader = packed struct {347pub const LineFragmentHeader = packed struct {
329 RelocOffset: u32, /// Code offset of line contribution.348 /// Code offset of line contribution.
330 RelocSegment: u16, /// Code segment of line contribution.349 RelocOffset: u32,
350
351 /// Code segment of line contribution.
352 RelocSegment: u16,
331 Flags: LineFlags,353 Flags: LineFlags,
332 CodeSize: u32, /// Code size of this line contribution.354
355 /// Code size of this line contribution.
356 CodeSize: u32,
333};357};
334358
335pub const LineFlags = packed struct {359pub const LineFlags = packed struct {
336 LF_HaveColumns: bool, /// CV_LINES_HAVE_COLUMNS360 /// CV_LINES_HAVE_COLUMNS
361 LF_HaveColumns: bool,
337 unused: u15,362 unused: u15,
338};363};
339364
...@@ -348,12 +373,14 @@ pub const LineBlockFragmentHeader = packed struct {...@@ -348,12 +373,14 @@ pub const LineBlockFragmentHeader = packed struct {
348 /// table of the actual name.373 /// table of the actual name.
349 NameIndex: u32,374 NameIndex: u32,
350 NumLines: u32,375 NumLines: u32,
351 BlockSize: u32, /// code size of block, in bytes
352};
353376
377 /// code size of block, in bytes
378 BlockSize: u32,
379};
354380
355pub const LineNumberEntry = packed struct {381pub const LineNumberEntry = packed struct {
356 Offset: u32, /// Offset to start of code bytes for line number382 /// Offset to start of code bytes for line number
383 Offset: u32,
357 Flags: u32,384 Flags: u32,
358385
359 /// TODO runtime crash when I make the actual type of Flags this386 /// TODO runtime crash when I make the actual type of Flags this
...@@ -371,42 +398,53 @@ pub const ColumnNumberEntry = packed struct {...@@ -371,42 +398,53 @@ pub const ColumnNumberEntry = packed struct {
371398
372/// Checksum bytes follow.399/// Checksum bytes follow.
373pub const FileChecksumEntryHeader = packed struct {400pub const FileChecksumEntryHeader = packed struct {
374 FileNameOffset: u32, /// Byte offset of filename in global string table.401 /// Byte offset of filename in global string table.
375 ChecksumSize: u8, /// Number of bytes of checksum.402 FileNameOffset: u32,
376 ChecksumKind: u8, /// FileChecksumKind403
404 /// Number of bytes of checksum.
405 ChecksumSize: u8,
406
407 /// FileChecksumKind
408 ChecksumKind: u8,
377};409};
378410
379pub const DebugSubsectionKind = packed enum(u32) {411pub const DebugSubsectionKind = packed enum(u32) {
380 None = 0,412 None = 0,
381 Symbols = 0xf1,413 Symbols = 0xf1,
382 Lines = 0xf2,414 Lines = 0xf2,
383 StringTable = 0xf3,415 StringTable = 0xf3,
384 FileChecksums = 0xf4,416 FileChecksums = 0xf4,
385 FrameData = 0xf5,417 FrameData = 0xf5,
386 InlineeLines = 0xf6,418 InlineeLines = 0xf6,
387 CrossScopeImports = 0xf7,419 CrossScopeImports = 0xf7,
388 CrossScopeExports = 0xf8,420 CrossScopeExports = 0xf8,
389421
390 // These appear to relate to .Net assembly info.422 // These appear to relate to .Net assembly info.
391 ILLines = 0xf9,423 ILLines = 0xf9,
392 FuncMDTokenMap = 0xfa,424 FuncMDTokenMap = 0xfa,
393 TypeMDTokenMap = 0xfb,425 TypeMDTokenMap = 0xfb,
394 MergedAssemblyInput = 0xfc,426 MergedAssemblyInput = 0xfc,
395427
396 CoffSymbolRVA = 0xfd,428 CoffSymbolRVA = 0xfd,
397};429};
398430
399
400pub const DebugSubsectionHeader = packed struct {431pub const DebugSubsectionHeader = packed struct {
401 Kind: DebugSubsectionKind, /// codeview::DebugSubsectionKind enum432 /// codeview::DebugSubsectionKind enum
402 Length: u32, /// number of bytes occupied by this record.433 Kind: DebugSubsectionKind,
403};
404434
435 /// number of bytes occupied by this record.
436 Length: u32,
437};
405438
406pub const PDBStringTableHeader = packed struct {439pub const PDBStringTableHeader = packed struct {
407 Signature: u32, /// PDBStringTableSignature440 /// PDBStringTableSignature
408 HashVersion: u32, /// 1 or 2441 Signature: u32,
409 ByteSize: u32, /// Number of bytes of names buffer.442
443 /// 1 or 2
444 HashVersion: u32,
445
446 /// Number of bytes of names buffer.
447 ByteSize: u32,
410};448};
411449
412pub const Pdb = struct {450pub const Pdb = struct {
...@@ -456,7 +494,7 @@ const Msf = struct {...@@ -456,7 +494,7 @@ const Msf = struct {
456 switch (superblock.BlockSize) {494 switch (superblock.BlockSize) {
457 // llvm only supports 4096 but we can handle any of these values495 // llvm only supports 4096 but we can handle any of these values
458 512, 1024, 2048, 4096 => {},496 512, 1024, 2048, 4096 => {},
459 else => return error.InvalidDebugInfo497 else => return error.InvalidDebugInfo,
460 }498 }
461499
462 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())500 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())
...@@ -536,7 +574,6 @@ const SuperBlock = packed struct {...@@ -536,7 +574,6 @@ const SuperBlock = packed struct {
536 /// The number of ulittle32_t’s in this array is given by574 /// The number of ulittle32_t’s in this array is given by
537 /// ceil(NumDirectoryBytes / BlockSize).575 /// ceil(NumDirectoryBytes / BlockSize).
538 BlockMapAddr: u32,576 BlockMapAddr: u32,
539
540};577};
541578
542const MsfStream = struct {579const MsfStream = struct {
...@@ -552,14 +589,12 @@ const MsfStream = struct {...@@ -552,14 +589,12 @@ const MsfStream = struct {
552 pub const Stream = io.InStream(Error);589 pub const Stream = io.InStream(Error);
553590
554 fn init(block_size: u32, block_count: u32, pos: usize, file: os.File, allocator: *mem.Allocator) !MsfStream {591 fn init(block_size: u32, block_count: u32, pos: usize, file: os.File, allocator: *mem.Allocator) !MsfStream {
555 var stream = MsfStream {592 var stream = MsfStream{
556 .in_file = file,593 .in_file = file,
557 .pos = 0,594 .pos = 0,
558 .blocks = try allocator.alloc(u32, block_count),595 .blocks = try allocator.alloc(u32, block_count),
559 .block_size = block_size,596 .block_size = block_size,
560 .stream = Stream {597 .stream = Stream{ .readFn = readFn },
561 .readFn = readFn,
562 },
563 };598 };
564599
565 var file_stream = io.FileInStream.init(file);600 var file_stream = io.FileInStream.init(file);
...@@ -597,7 +632,7 @@ const MsfStream = struct {...@@ -597,7 +632,7 @@ const MsfStream = struct {
597632
598 var size: usize = 0;633 var size: usize = 0;
599 for (buffer) |*byte| {634 for (buffer) |*byte| {
600 byte.* = try in.readByte(); 635 byte.* = try in.readByte();
601636
602 offset += 1;637 offset += 1;
603 size += 1;638 size += 1;
std/segmented_list.zig+1-1
...@@ -75,7 +75,7 @@ const Allocator = std.mem.Allocator;...@@ -75,7 +75,7 @@ const Allocator = std.mem.Allocator;
75/// size is small. `prealloc_item_count` must be 0, or a power of 2.75/// size is small. `prealloc_item_count` must be 0, or a power of 2.
76pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {76pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {
77 return struct {77 return struct {
78 const Self = this;78 const Self = @This();
79 const prealloc_exp = blk: {79 const prealloc_exp = blk: {
80 // we don't use the prealloc_exp constant when prealloc_item_count is 0.80 // we don't use the prealloc_exp constant when prealloc_item_count is 0.
81 assert(prealloc_item_count != 0);81 assert(prealloc_item_count != 0);
std/zig/ast.zig+2-2
...@@ -231,7 +231,7 @@ pub const Error = union(enum) {...@@ -231,7 +231,7 @@ pub const Error = union(enum) {
231231
232 fn SingleTokenError(comptime msg: []const u8) type {232 fn SingleTokenError(comptime msg: []const u8) type {
233 return struct {233 return struct {
234 const ThisError = this;234 const ThisError = @This();
235235
236 token: TokenIndex,236 token: TokenIndex,
237237
...@@ -244,7 +244,7 @@ pub const Error = union(enum) {...@@ -244,7 +244,7 @@ pub const Error = union(enum) {
244244
245 fn SimpleError(comptime msg: []const u8) type {245 fn SimpleError(comptime msg: []const u8) type {
246 return struct {246 return struct {
247 const ThisError = this;247 const ThisError = @This();
248248
249 token: TokenIndex,249 token: TokenIndex,
250250
std/zig/bench.zig+1-1
...@@ -24,7 +24,7 @@ pub fn main() !void {...@@ -24,7 +24,7 @@ pub fn main() !void {
24 const mb_per_sec = bytes_per_sec / (1024 * 1024);24 const mb_per_sec = bytes_per_sec / (1024 * 1024);
2525
26 var stdout_file = try std.io.getStdOut();26 var stdout_file = try std.io.getStdOut();
27 const stdout = &std.io.FileOutStream.init(&stdout_file).stream;27 const stdout = &std.io.FileOutStream.init(stdout_file).stream;
28 try stdout.print("{.3} MiB/s, {} KiB used \n", mb_per_sec, memory_used / 1024);28 try stdout.print("{.3} MiB/s, {} KiB used \n", mb_per_sec, memory_used / 1024);
29}29}
3030
std/zig/parser_test.zig+1-1
...@@ -1354,7 +1354,7 @@ test "zig fmt: indexing" {...@@ -1354,7 +1354,7 @@ test "zig fmt: indexing" {
1354test "zig fmt: struct declaration" {1354test "zig fmt: struct declaration" {
1355 try testCanonical(1355 try testCanonical(
1356 \\const S = struct {1356 \\const S = struct {
1357 \\ const Self = this;1357 \\ const Self = @This();
1358 \\ f1: u8,1358 \\ f1: u8,
1359 \\ pub f3: u8,1359 \\ pub f3: u8,
1360 \\1360 \\
std/zig/render.zig+1-1
...@@ -20,7 +20,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@typeOf(...@@ -20,7 +20,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@typeOf(
2020
21 // make a passthrough stream that checks whether something changed21 // make a passthrough stream that checks whether something changed
22 const MyStream = struct {22 const MyStream = struct {
23 const MyStream = this;23 const MyStream = @This();
24 const StreamError = @typeOf(stream).Child.Error;24 const StreamError = @typeOf(stream).Child.Error;
25 const Stream = std.io.OutStream(StreamError);25 const Stream = std.io.OutStream(StreamError);
2626
test/behavior.zig+3
...@@ -10,7 +10,10 @@ comptime {...@@ -10,7 +10,10 @@ comptime {
10 _ = @import("cases/bool.zig");10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bugs/1111.zig");11 _ = @import("cases/bugs/1111.zig");
12 _ = @import("cases/bugs/1277.zig");12 _ = @import("cases/bugs/1277.zig");
13 _ = @import("cases/bugs/1322.zig");
14 _ = @import("cases/bugs/1381.zig");
13 _ = @import("cases/bugs/1421.zig");15 _ = @import("cases/bugs/1421.zig");
16 _ = @import("cases/bugs/1442.zig");
14 _ = @import("cases/bugs/394.zig");17 _ = @import("cases/bugs/394.zig");
15 _ = @import("cases/bugs/655.zig");18 _ = @import("cases/bugs/655.zig");
16 _ = @import("cases/bugs/656.zig");19 _ = @import("cases/bugs/656.zig");
test/cases/align.zig+7
...@@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 {...@@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);212 @setAlignStack(256);
213 return 1234;213 return 1234;
214}214}
215
216test "alignment of structs" {
217 assert(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
test/cases/bugs/1322.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
19}
test/cases/bugs/1381.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/cases/bugs/1442.zig created+11
...@@ -0,0 +1,11 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: error!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/cases/cast.zig+13-2
...@@ -64,7 +64,7 @@ test "implicitly cast a container to a const pointer of it" {...@@ -64,7 +64,7 @@ test "implicitly cast a container to a const pointer of it" {
6464
65fn Struct(comptime T: type) type {65fn Struct(comptime T: type) type {
66 return struct {66 return struct {
67 const Self = this;67 const Self = @This();
68 x: T,68 x: T,
6969
70 fn pointer(self: *const Self) Self {70 fn pointer(self: *const Self) Self {
...@@ -106,7 +106,7 @@ const Enum = enum {...@@ -106,7 +106,7 @@ const Enum = enum {
106106
107test "implicitly cast indirect pointer to maybe-indirect pointer" {107test "implicitly cast indirect pointer to maybe-indirect pointer" {
108 const S = struct {108 const S = struct {
109 const Self = this;109 const Self = @This();
110 x: u8,110 x: u8,
111 fn constConst(p: *const *const Self) u8 {111 fn constConst(p: *const *const Self) u8 {
112 return p.*.x;112 return p.*.x;
...@@ -526,3 +526,14 @@ test "*usize to *void" {...@@ -526,3 +526,14 @@ test "*usize to *void" {
526 var v = @ptrCast(*void, &i);526 var v = @ptrCast(*void, &i);
527 v.* = {};527 v.* = {};
528}528}
529
530test "compile time int to ptr of function" {
531 foobar(FUNCTION_CONSTANT);
532}
533
534pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, @maxValue(usize));
535pub const PFN_void = extern fn (*c_void) void;
536
537fn foobar(func: PFN_void) void {
538 std.debug.assert(@ptrToInt(func) == @maxValue(usize));
539}
test/cases/eval.zig+2-2
...@@ -275,7 +275,7 @@ test "eval @setFloatMode at compile-time" {...@@ -275,7 +275,7 @@ test "eval @setFloatMode at compile-time" {
275}275}
276276
277fn fnWithFloatMode() f32 {277fn fnWithFloatMode() f32 {
278 @setFloatMode(this, builtin.FloatMode.Strict);278 @setFloatMode(builtin.FloatMode.Strict);
279 return 1234.0;279 return 1234.0;
280}280}
281281
...@@ -628,7 +628,7 @@ test "call method with comptime pass-by-non-copying-value self parameter" {...@@ -628,7 +628,7 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
628 const S = struct {628 const S = struct {
629 a: u8,629 a: u8,
630630
631 fn b(comptime s: this) u8 {631 fn b(comptime s: @This()) u8 {
632 return s.a;632 return s.a;
633 }633 }
634 };634 };
test/cases/misc.zig-3
...@@ -510,9 +510,6 @@ test "@typeId" {...@@ -510,9 +510,6 @@ test "@typeId" {
510 assert(@typeId(AUnion) == Tid.Union);510 assert(@typeId(AUnion) == Tid.Union);
511 assert(@typeId(fn () void) == Tid.Fn);511 assert(@typeId(fn () void) == Tid.Fn);
512 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);512 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
513 assert(@typeId(@typeOf(x: {
514 break :x this;
515 })) == Tid.Block);
516 // TODO bound fn513 // TODO bound fn
517 // TODO arg tuple514 // TODO arg tuple
518 // TODO opaque515 // TODO opaque
test/cases/reflection.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;2const mem = @import("std").mem;
3const reflection = this;3const reflection = @This();
44
5test "reflection: array, pointer, optional, error union type child" {5test "reflection: array, pointer, optional, error union type child" {
6 comptime {6 comptime {
test/cases/struct.zig+2-2
...@@ -423,10 +423,10 @@ fn alloc(comptime T: type) []T {...@@ -423,10 +423,10 @@ fn alloc(comptime T: type) []T {
423423
424test "call method with mutable reference to struct with no fields" {424test "call method with mutable reference to struct with no fields" {
425 const S = struct {425 const S = struct {
426 fn doC(s: *const this) bool {426 fn doC(s: *const @This()) bool {
427 return true;427 return true;
428 }428 }
429 fn do(s: *this) bool {429 fn do(s: *@This()) bool {
430 return true;430 return true;
431 }431 }
432 };432 };
test/cases/this.zig+2-11
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
22
3const module = this;3const module = @This();
44
5fn Point(comptime T: type) type {5fn Point(comptime T: type) type {
6 return struct {6 return struct {
7 const Self = this;7 const Self = @This();
8 x: T,8 x: T,
9 y: T,9 y: T,
1010
...@@ -19,11 +19,6 @@ fn add(x: i32, y: i32) i32 {...@@ -19,11 +19,6 @@ fn add(x: i32, y: i32) i32 {
19 return x + y;19 return x + y;
20}20}
2121
22fn factorial(x: i32) i32 {
23 const selfFn = this;
24 return if (x == 0) 1 else x * selfFn(x - 1);
25}
26
27test "this refer to module call private fn" {22test "this refer to module call private fn" {
28 assert(module.add(1, 2) == 3);23 assert(module.add(1, 2) == 3);
29}24}
...@@ -37,7 +32,3 @@ test "this refer to container" {...@@ -37,7 +32,3 @@ test "this refer to container" {
37 assert(pt.x == 13);32 assert(pt.x == 13);
38 assert(pt.y == 35);33 assert(pt.y == 35);
39}34}
40
41test "this refer to fn" {
42 assert(factorial(5) == 120);
43}
test/cases/type_info.zig+2-2
...@@ -166,7 +166,7 @@ fn testUnion() void {...@@ -166,7 +166,7 @@ fn testUnion() void {
166 assert(TypeId(typeinfo_info) == TypeId.Union);166 assert(TypeId(typeinfo_info) == TypeId.Union);
167 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);167 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
168 assert(typeinfo_info.Union.tag_type.? == TypeId);168 assert(typeinfo_info.Union.tag_type.? == TypeId);
169 assert(typeinfo_info.Union.fields.len == 25);169 assert(typeinfo_info.Union.fields.len == 24);
170 assert(typeinfo_info.Union.fields[4].enum_field != null);170 assert(typeinfo_info.Union.fields[4].enum_field != null);
171 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);171 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
172 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));172 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
...@@ -217,7 +217,7 @@ fn testStruct() void {...@@ -217,7 +217,7 @@ fn testStruct() void {
217}217}
218218
219const TestStruct = packed struct {219const TestStruct = packed struct {
220 const Self = this;220 const Self = @This();
221221
222 fieldA: usize,222 fieldA: usize,
223 fieldB: void,223 fieldB: void,
test/cases/union.zig+39
...@@ -324,3 +324,42 @@ test "tagged union with no payloads" {...@@ -324,3 +324,42 @@ test "tagged union with no payloads" {
324 @TagType(UnionEnumNoPayloads).B => {},324 @TagType(UnionEnumNoPayloads).B => {},
325 }325 }
326}326}
327
328test "union with only 1 field casted to its enum type" {
329 const Literal = union(enum) {
330 Number: f64,
331 Bool: bool,
332 };
333
334 const Expr = union(enum) {
335 Literal: Literal,
336 };
337
338 var e = Expr{ .Literal = Literal{ .Bool = true } };
339 const Tag = @TagType(Expr);
340 comptime assert(@TagType(Tag) == comptime_int);
341 var t = Tag(e);
342 assert(t == Expr.Literal);
343}
344
345test "union with only 1 field casted to its enum type which has enum value specified" {
346 const Literal = union(enum) {
347 Number: f64,
348 Bool: bool,
349 };
350
351 const Tag = enum {
352 Literal = 33,
353 };
354
355 const Expr = union(Tag) {
356 Literal: Literal,
357 };
358
359 var e = Expr{ .Literal = Literal{ .Bool = true } };
360 comptime assert(@TagType(Tag) == comptime_int);
361 var t = Tag(e);
362 assert(t == Expr.Literal);
363 assert(@enumToInt(t) == 33);
364 comptime assert(@enumToInt(t) == 33);
365}
test/compile_errors.zig+29-18
...@@ -1,6 +1,19 @@...@@ -1,6 +1,19 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "non error sets used in merge error sets operator",
6 \\export fn foo() void {
7 \\ const Errors = u8 || u16;
8 \\}
9 \\export fn bar() void {
10 \\ const Errors = error{} || u16;
11 \\}
12 ,
13 ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",
14 ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",
15 );
16
4 cases.add(17 cases.add(
5 "variable initialization compile error then referenced",18 "variable initialization compile error then referenced",
6 \\fn Undeclared() type {19 \\fn Undeclared() type {
...@@ -3431,7 +3444,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3431,7 +3444,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3431 \\3444 \\
3432 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }3445 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
3433 ,3446 ,
3434 ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(1:3:6) const u3'",3447 ".tmp_source.zig:8:26: error: expected type '*const u3', found '*align(:3:6) const u3'",
3435 );3448 );
34363449
3437 cases.add(3450 cases.add(
...@@ -3800,11 +3813,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3800,11 +3813,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3800 \\ return struct {3813 \\ return struct {
3801 \\ b: B(),3814 \\ b: B(),
3802 \\3815 \\
3803 \\ const Self = this;3816 \\ const Self = @This();
3804 \\3817 \\
3805 \\ fn B() type {3818 \\ fn B() type {
3806 \\ return struct {3819 \\ return struct {
3807 \\ const Self = this;3820 \\ const Self = @This();
3808 \\ };3821 \\ };
3809 \\ }3822 \\ }
3810 \\ };3823 \\ };
...@@ -3983,8 +3996,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3983,8 +3996,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3983 cases.add(3996 cases.add(
3984 "@setFloatMode twice for same scope",3997 "@setFloatMode twice for same scope",
3985 \\export fn foo() void {3998 \\export fn foo() void {
3986 \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized);3999 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);
3987 \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized);4000 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);
3988 \\}4001 \\}
3989 ,4002 ,
3990 ".tmp_source.zig:3:5: error: float mode set twice for same scope",4003 ".tmp_source.zig:3:5: error: float mode set twice for same scope",
...@@ -4301,12 +4314,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4301,12 +4314,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4301 \\ var a = undefined;4314 \\ var a = undefined;
4302 \\ var b = 1;4315 \\ var b = 1;
4303 \\ var c = 1.0;4316 \\ var c = 1.0;
4304 \\ var d = this;4317 \\ var d = null;
4305 \\ var e = null;4318 \\ var e = opaque.*;
4306 \\ var f = opaque.*;4319 \\ var f = i32;
4307 \\ var g = i32;4320 \\ var g = @import("std",);
4308 \\ var h = @import("std",);4321 \\ var h = (Foo {}).bar;
4309 \\ var i = (Foo {}).bar;
4310 \\4322 \\
4311 \\ var z: noreturn = return;4323 \\ var z: noreturn = return;
4312 \\}4324 \\}
...@@ -4319,13 +4331,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4319,13 +4331,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4319 ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",4331 ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
4320 ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",4332 ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
4321 ".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",4333 ".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",
4322 ".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime",4334 ".tmp_source.zig:10:4: error: variable of type '(null)' must be const or comptime",
4323 ".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",4335 ".tmp_source.zig:11:4: error: variable of type 'Opaque' not allowed",
4324 ".tmp_source.zig:12:4: error: variable of type 'Opaque' not allowed",4336 ".tmp_source.zig:12:4: error: variable of type 'type' must be const or comptime",
4325 ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime",4337 ".tmp_source.zig:13:4: error: variable of type '(namespace)' must be const or comptime",
4326 ".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime",4338 ".tmp_source.zig:14:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
4327 ".tmp_source.zig:15:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",4339 ".tmp_source.zig:16:4: error: unreachable code",
4328 ".tmp_source.zig:17:4: error: unreachable code",
4329 );4340 );
43304341
4331 cases.add(4342 cases.add(
test/standalone/brace_expansion/main.zig+1-1
...@@ -191,7 +191,7 @@ pub fn main() !void {...@@ -191,7 +191,7 @@ pub fn main() !void {
191 var stdin_buf = try Buffer.initSize(global_allocator, 0);191 var stdin_buf = try Buffer.initSize(global_allocator, 0);
192 defer stdin_buf.deinit();192 defer stdin_buf.deinit();
193193
194 var stdin_adapter = io.FileInStream.init(&stdin_file);194 var stdin_adapter = io.FileInStream.init(stdin_file);
195 try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));195 try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));
196196
197 var result_buf = try Buffer.initSize(global_allocator, 0);197 var result_buf = try Buffer.initSize(global_allocator, 0);