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)
393393 )
394394else()
395395 set_target_properties(embedded_softfloat PROPERTIES
396 COMPILE_FLAGS "-std=c99"
396 COMPILE_FLAGS "-std=c99 -O3"
397397 )
398398endif()
399399target_include_directories(embedded_softfloat PUBLIC
......@@ -412,7 +412,9 @@ set(ZIG_SOURCES
412412 "${CMAKE_SOURCE_DIR}/src/bigint.cpp"
413413 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
414414 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
415 "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
415416 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
417 "${CMAKE_SOURCE_DIR}/src/compiler.cpp"
416418 "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
417419 "${CMAKE_SOURCE_DIR}/src/error.cpp"
418420 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
......@@ -427,6 +429,9 @@ set(ZIG_SOURCES
427429 "${CMAKE_SOURCE_DIR}/src/util.cpp"
428430 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
429431)
432set(BLAKE_SOURCES
433 "${CMAKE_SOURCE_DIR}/src/blake2b.c"
434)
430435set(ZIG_CPP_SOURCES
431436 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
432437 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
......@@ -793,6 +798,7 @@ else()
793798 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")
794799endif()
795800
801set(BLAKE_CFLAGS "-std=c99")
796802
797803set(EXE_LDFLAGS " ")
798804if(MINGW)
......@@ -814,6 +820,11 @@ set_target_properties(zig_cpp PROPERTIES
814820 COMPILE_FLAGS ${EXE_CFLAGS}
815821)
816822
823add_library(embedded_blake STATIC ${BLAKE_SOURCES})
824set_target_properties(embedded_blake PROPERTIES
825 COMPILE_FLAGS "${BLAKE_CFLAGS} -O3"
826)
827
817828add_executable(zig ${ZIG_SOURCES})
818829set_target_properties(zig PROPERTIES
819830 COMPILE_FLAGS ${EXE_CFLAGS}
......@@ -822,6 +833,7 @@ set_target_properties(zig PROPERTIES
822833
823834target_link_libraries(zig LINK_PUBLIC
824835 zig_cpp
836 embedded_blake
825837 ${SOFTFLOAT_LIBRARIES}
826838 ${CLANG_LIBRARIES}
827839 ${LLD_LIBRARIES}
build.zig+27-9
......@@ -16,11 +16,12 @@ pub fn build(b: *Builder) !void {
1616 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
1818 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;
1920 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
2021 docgen_exe.getOutputPath(),
2122 rel_zig_exe,
2223 "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,
2425 });
2526 docgen_cmd.step.dependOn(&docgen_exe.step);
2627
......@@ -61,6 +62,9 @@ pub fn build(b: *Builder) !void {
6162 b.default_step.dependOn(&exe.step);
6263
6364 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;
6468 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
6569 if (!skip_self_hosted) {
6670 test_step.dependOn(&exe.step);
......@@ -76,15 +80,29 @@ pub fn build(b: *Builder) !void {
7680
7781 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
7882 test_stage2_step.dependOn(&test_stage2.step);
79 test_step.dependOn(test_stage2_step);
8083
81 const all_modes = []builtin.Mode{
82 builtin.Mode.Debug,
83 builtin.Mode.ReleaseSafe,
84 builtin.Mode.ReleaseFast,
85 builtin.Mode.ReleaseSmall,
86 };
87 const modes = if (skip_release) []builtin.Mode{builtin.Mode.Debug} else all_modes;
84 // TODO see https://github.com/ziglang/zig/issues/1364
85 if (false) {
86 test_step.dependOn(test_stage2_step);
87 }
88
89 var chosen_modes: [4]builtin.Mode = undefined;
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
89107 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%
2323cmake.exe .. -Thost=x64 -G"Visual Studio 14 2015 Win64" "-DCMAKE_INSTALL_PREFIX=%ZIGBUILDDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release || exit /b
2424msbuild /p:Configuration=Release INSTALL.vcxproj || exit /b
2525
26bin\zig.exe build --build-file ..\build.zig test || exit /b
26bin\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
88echo $PATH
99mkdir build
1010cd build
11cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd)
11cmake .. -DCMAKE_BUILD_TYPE=Release
1212make -j2 install
13./zig build --build-file ../build.zig test
13./zig build --build-file ../build.zig test -Dskip-release-small
1414
1515if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then
1616 mkdir $TRAVIS_BUILD_DIR/artifacts
ci/travis_osx_script+2-2
......@@ -5,8 +5,8 @@ set -e
55
66mkdir build
77cd 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
99make VERBOSE=1
1010make install
1111
12./zig build --build-file ../build.zig test
12./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;
1111const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
1212const obj_ext = std.build.Target(std.build.Target.Native).oFileExt();
1313const tmp_dir_name = "docgen_tmp";
14const test_out_path = tmp_dir_name ++ os.path.sep_str ++ "test" ++ exe_ext;
1415
1516pub fn main() !void {
1617 var direct_allocator = std.heap.DirectAllocator.init();
......@@ -299,6 +300,7 @@ const Node = union(enum) {
299300 SeeAlso: []const SeeAlsoItem,
300301 Code: Code,
301302 Link: Link,
303 Syntax: Token,
302304};
303305
304306const Toc = struct {
......@@ -529,6 +531,17 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
529531 },
530532 });
531533 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 });
532545 } else {
533546 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
534547 }
......@@ -570,6 +583,11 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
570583
571584 var buf_adapter = io.BufferOutStream.init(&buf);
572585 var out = &buf_adapter.stream;
586 try writeEscaped(out, input);
587 return buf.toOwnedSlice();
588}
589
590fn writeEscaped(out: var, input: []const u8) !void {
573591 for (input) |c| {
574592 try switch (c) {
575593 '&' => out.write("&amp;"),
......@@ -579,7 +597,6 @@ fn escapeHtml(allocator: *mem.Allocator, input: []const u8) ![]u8 {
579597 else => out.writeByte(c),
580598 };
581599 }
582 return buf.toOwnedSlice();
583600}
584601
585602//#define VT_RED "\x1b[31;1m"
......@@ -686,6 +703,230 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
686703 return buf.toOwnedSlice();
687704}
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
689930fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void {
690931 var code_progress_index: usize = 0;
691932
......@@ -725,17 +966,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
725966 }
726967 try out.write("</ul>\n");
727968 },
969 Node.Syntax => |content_tok| {
970 try tokenizeAndPrint(allocator, tokenizer, out, content_tok);
971 },
728972 Node.Code => |code| {
729973 code_progress_index += 1;
730974 warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count);
731975
732976 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
733977 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
734 const escaped_source = try escapeHtml(allocator, trimmed_raw_source);
735978 if (!code.is_inline) {
736979 try out.print("<p class=\"file\">{}.zig</p>", code.name);
737980 }
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>");
739984 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
740985 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
741986 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
8211066 zig_exe,
8221067 "test",
8231068 tmp_source_file_name,
1069 "--output",
1070 test_out_path,
8241071 });
8251072 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
8261073 switch (code.mode) {
......@@ -863,6 +1110,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
8631110 "--color",
8641111 "on",
8651112 tmp_source_file_name,
1113 "--output",
1114 test_out_path,
8661115 });
8671116 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
8681117 switch (code.mode) {
......@@ -918,6 +1167,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
9181167 zig_exe,
9191168 "test",
9201169 tmp_source_file_name,
1170 "--output",
1171 test_out_path,
9211172 });
9221173 switch (code.mode) {
9231174 builtin.Mode.Debug => {},
doc/langref.html.in+742-809
......@@ -5,9 +5,6 @@
55 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
66 <title>Documentation - The Zig Programming Language</title>
77 <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">
118 table, th, td {
129 border-collapse: collapse;
1310 border: 1px solid grey;
......@@ -39,11 +36,46 @@
3936 pre > code {
4037 display: block;
4138 overflow: auto;
39
40 overflow-x: auto;
41 padding: 0.5em;
42 color: #333;
43 background: #f8f8f8;
4244 }
4345 .table-wrapper {
4446 width: 100%;
4547 overflow-y: auto;
4648 }
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
4779 /* Desktop */
4880 @media screen and (min-width: 56.25em) {
4981 #nav {
......@@ -129,8 +161,8 @@ pub fn main() void {
129161}
130162 {#code_end#}
131163 <p>
132 Note that we also left off the <code class="zig">!</code> from the return type.
133 In Zig, if your main function cannot fail, you must use the <code class="zig">void</code> return type.
164 Note that we also left off the {#syntax#}!{#endsyntax#} from the return type.
165 In Zig, if your main function cannot fail, you must use the {#syntax#}void{#endsyntax#} return type.
134166 </p>
135167 {#see_also|Values|@import|Errors|Root Source File#}
136168 {#header_close#}
......@@ -149,14 +181,14 @@ test "comments" {
149181}
150182 {#code_end#}
151183 <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>
153185 comments in C). This helps allow Zig to have the property that each line
154186 of code can be tokenized out of context.
155187 </p>
156188 {#header_open|Doc comments#}
157189 <p>
158190 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#});
160192 multiple doc comments in a row are merged together to form a multiline
161193 doc comment. The doc comment documents whatever immediately follows it.
162194 </p>
......@@ -248,169 +280,169 @@ pub fn main() void {
248280 </th>
249281 </tr>
250282 <tr>
251 <td><code>i8</code></td>
252 <td><code>int8_t</code></td>
283 <td>{#syntax#}i8{#endsyntax#}</td>
284 <td><code class="c">int8_t</code></td>
253285 <td>signed 8-bit integer</td>
254286 </tr>
255287 <tr>
256 <td><code>u8</code></td>
257 <td><code>uint8_t</code></td>
288 <td>{#syntax#}u8{#endsyntax#}</td>
289 <td><code class="c">uint8_t</code></td>
258290 <td>unsigned 8-bit integer</td>
259291 </tr>
260292 <tr>
261 <td><code>i16</code></td>
262 <td><code>int16_t</code></td>
293 <td>{#syntax#}i16{#endsyntax#}</td>
294 <td><code class="c">int16_t</code></td>
263295 <td>signed 16-bit integer</td>
264296 </tr>
265297 <tr>
266 <td><code>u16</code></td>
267 <td><code>uint16_t</code></td>
298 <td>{#syntax#}u16{#endsyntax#}</td>
299 <td><code class="c">uint16_t</code></td>
268300 <td>unsigned 16-bit integer</td>
269301 </tr>
270302 <tr>
271 <td><code>i32</code></td>
272 <td><code>int32_t</code></td>
303 <td>{#syntax#}i32{#endsyntax#}</td>
304 <td><code class="c">int32_t</code></td>
273305 <td>signed 32-bit integer</td>
274306 </tr>
275307 <tr>
276 <td><code>u32</code></td>
277 <td><code>uint32_t</code></td>
308 <td>{#syntax#}u32{#endsyntax#}</td>
309 <td><code class="c">uint32_t</code></td>
278310 <td>unsigned 32-bit integer</td>
279311 </tr>
280312 <tr>
281 <td><code>i64</code></td>
282 <td><code>int64_t</code></td>
313 <td>{#syntax#}i64{#endsyntax#}</td>
314 <td><code class="c">int64_t</code></td>
283315 <td>signed 64-bit integer</td>
284316 </tr>
285317 <tr>
286 <td><code>u64</code></td>
287 <td><code>uint64_t</code></td>
318 <td>{#syntax#}u64{#endsyntax#}</td>
319 <td><code class="c">uint64_t</code></td>
288320 <td>unsigned 64-bit integer</td>
289321 </tr>
290322 <tr>
291 <td><code>i128</code></td>
292 <td><code>__int128</code></td>
323 <td>{#syntax#}i128{#endsyntax#}</td>
324 <td><code class="c">__int128</code></td>
293325 <td>signed 128-bit integer</td>
294326 </tr>
295327 <tr>
296 <td><code>u128</code></td>
297 <td><code>unsigned __int128</code></td>
328 <td>{#syntax#}u128{#endsyntax#}</td>
329 <td><code class="c">unsigned __int128</code></td>
298330 <td>unsigned 128-bit integer</td>
299331 </tr>
300332 <tr>
301 <td><code>isize</code></td>
302 <td><code>intptr_t</code></td>
333 <td>{#syntax#}isize{#endsyntax#}</td>
334 <td><code class="c">intptr_t</code></td>
303335 <td>signed pointer sized integer</td>
304336 </tr>
305337 <tr>
306 <td><code>usize</code></td>
307 <td><code>uintptr_t</code></td>
338 <td>{#syntax#}usize{#endsyntax#}</td>
339 <td><code class="c">uintptr_t</code></td>
308340 <td>unsigned pointer sized integer</td>
309341 </tr>
310342
311343 <tr>
312 <td><code>c_short</code></td>
313 <td><code>short</code></td>
344 <td>{#syntax#}c_short{#endsyntax#}</td>
345 <td><code class="c">short</code></td>
314346 <td>for ABI compatibility with C</td>
315347 </tr>
316348 <tr>
317 <td><code>c_ushort</code></td>
318 <td><code>unsigned short</code></td>
349 <td>{#syntax#}c_ushort{#endsyntax#}</td>
350 <td><code class="c">unsigned short</code></td>
319351 <td>for ABI compatibility with C</td>
320352 </tr>
321353 <tr>
322 <td><code>c_int</code></td>
323 <td><code>int</code></td>
354 <td>{#syntax#}c_int{#endsyntax#}</td>
355 <td><code class="c">int</code></td>
324356 <td>for ABI compatibility with C</td>
325357 </tr>
326358 <tr>
327 <td><code>c_uint</code></td>
328 <td><code>unsigned int</code></td>
359 <td>{#syntax#}c_uint{#endsyntax#}</td>
360 <td><code class="c">unsigned int</code></td>
329361 <td>for ABI compatibility with C</td>
330362 </tr>
331363 <tr>
332 <td><code>c_long</code></td>
333 <td><code>long</code></td>
364 <td>{#syntax#}c_long{#endsyntax#}</td>
365 <td><code class="c">long</code></td>
334366 <td>for ABI compatibility with C</td>
335367 </tr>
336368 <tr>
337 <td><code>c_ulong</code></td>
338 <td><code>unsigned long</code></td>
369 <td>{#syntax#}c_ulong{#endsyntax#}</td>
370 <td><code class="c">unsigned long</code></td>
339371 <td>for ABI compatibility with C</td>
340372 </tr>
341373 <tr>
342 <td><code>c_longlong</code></td>
343 <td><code>long long</code></td>
374 <td>{#syntax#}c_longlong{#endsyntax#}</td>
375 <td><code class="c">long long</code></td>
344376 <td>for ABI compatibility with C</td>
345377 </tr>
346378 <tr>
347 <td><code>c_ulonglong</code></td>
348 <td><code>unsigned long long</code></td>
379 <td>{#syntax#}c_ulonglong{#endsyntax#}</td>
380 <td><code class="c">unsigned long long</code></td>
349381 <td>for ABI compatibility with C</td>
350382 </tr>
351383 <tr>
352 <td><code>c_longdouble</code></td>
353 <td><code>long double</code></td>
384 <td>{#syntax#}c_longdouble{#endsyntax#}</td>
385 <td><code class="c">long double</code></td>
354386 <td>for ABI compatibility with C</td>
355387 </tr>
356388 <tr>
357 <td><code>c_void</code></td>
358 <td><code>void</code></td>
389 <td>{#syntax#}c_void{#endsyntax#}</td>
390 <td><code class="c">void</code></td>
359391 <td>for ABI compatibility with C</td>
360392 </tr>
361393
362394 <tr>
363 <td><code>f16</code></td>
364 <td><code>float</code></td>
395 <td>{#syntax#}f16{#endsyntax#}</td>
396 <td><code class="c">float</code></td>
365397 <td>16-bit floating point (10-bit mantissa) IEEE-754-2008 binary16</td>
366398 </tr>
367399 <tr>
368 <td><code>f32</code></td>
369 <td><code>float</code></td>
400 <td>{#syntax#}f32{#endsyntax#}</td>
401 <td><code class="c">float</code></td>
370402 <td>32-bit floating point (23-bit mantissa) IEEE-754-2008 binary32</td>
371403 </tr>
372404 <tr>
373 <td><code>f64</code></td>
374 <td><code>double</code></td>
405 <td>{#syntax#}f64{#endsyntax#}</td>
406 <td><code class="c">double</code></td>
375407 <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td>
376408 </tr>
377409 <tr>
378 <td><code>f128</code></td>
410 <td>{#syntax#}f128{#endsyntax#}</td>
379411 <td>(none)</td>
380412 <td>128-bit floating point (112-bit mantissa) IEEE-754-2008 binary128</td>
381413 </tr>
382414 <tr>
383 <td><code>bool</code></td>
384 <td><code>bool</code></td>
385 <td><code>true</code> or <code>false</code></td>
415 <td>{#syntax#}bool{#endsyntax#}</td>
416 <td><code class="c">bool</code></td>
417 <td>{#syntax#}true{#endsyntax#} or {#syntax#}false{#endsyntax#}</td>
386418 </tr>
387419 <tr>
388 <td><code>void</code></td>
420 <td>{#syntax#}void{#endsyntax#}</td>
389421 <td>(none)</td>
390422 <td>0 bit type</td>
391423 </tr>
392424 <tr>
393 <td><code>noreturn</code></td>
425 <td>{#syntax#}noreturn{#endsyntax#}</td>
394426 <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>
396428 </tr>
397429 <tr>
398 <td><code>type</code></td>
430 <td>{#syntax#}type{#endsyntax#}</td>
399431 <td>(none)</td>
400432 <td>the type of types</td>
401433 </tr>
402434 <tr>
403 <td><code>error</code></td>
435 <td>{#syntax#}error{#endsyntax#}</td>
404436 <td>(none)</td>
405437 <td>an error code</td>
406438 </tr>
407439 <tr>
408 <td><code>comptime_int</code></td>
440 <td>{#syntax#}comptime_int{#endsyntax#}</td>
409441 <td>(none)</td>
410442 <td>Only allowed for {#link|comptime#}-known values. The type of integer literals.</td>
411443 </tr>
412444 <tr>
413 <td><code>comptime_float</code></td>
445 <td>{#syntax#}comptime_float{#endsyntax#}</td>
414446 <td>(none)</td>
415447 <td>Only allowed for {#link|comptime#}-known values. The type of float literals.</td>
416448 </tr>
......@@ -419,7 +451,7 @@ pub fn main() void {
419451 <p>
420452 In addition to the integer types above, arbitrary bit-width integers can be referenced by using
421453 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.
423455 </p>
424456 {#see_also|Integers|Floats|void|Errors#}
425457 {#header_close#}
......@@ -435,24 +467,20 @@ pub fn main() void {
435467 </th>
436468 </tr>
437469 <tr>
438 <td><code>true</code> and <code>false</code></td>
439 <td><code>bool</code> values</td>
470 <td>{#syntax#}true{#endsyntax#} and {#syntax#}false{#endsyntax#}</td>
471 <td>{#syntax#}bool{#endsyntax#} values</td>
440472 </tr>
441473 <tr>
442 <td><code>null</code></td>
443 <td>used to set an optional type to <code>null</code></td>
474 <td>{#syntax#}null{#endsyntax#}</td>
475 <td>used to set an optional type to {#syntax#}null{#endsyntax#}</td>
444476 </tr>
445477 <tr>
446 <td><code>undefined</code></td>
478 <td>{#syntax#}undefined{#endsyntax#}</td>
447479 <td>used to leave a value unspecified</td>
448480 </tr>
449 <tr>
450 <td><code>this</code></td>
451 <td>refers to the thing in immediate scope</td>
452 </tr>
453481 </table>
454482 </div>
455 {#see_also|Optionals|this#}
483 {#see_also|Optionals#}
456484 {#header_close#}
457485 {#header_open|String Literals#}
458486 {#code_begin|test#}
......@@ -487,52 +515,52 @@ test "string literals" {
487515 </th>
488516 </tr>
489517 <tr>
490 <td><code>\n</code></td>
518 <td><code>\n</code></td>
491519 <td>Newline</td>
492520 </tr>
493521 <tr>
494 <td><code>\r</code></td>
522 <td><code>\r</code></td>
495523 <td>Carriage Return</td>
496524 </tr>
497525 <tr>
498 <td><code>\t</code></td>
526 <td><code>\t</code></td>
499527 <td>Tab</td>
500528 </tr>
501529 <tr>
502 <td><code>\\</code></td>
530 <td><code>\\</code></td>
503531 <td>Backslash</td>
504532 </tr>
505533 <tr>
506 <td><code>\'</code></td>
534 <td><code>\'</code></td>
507535 <td>Single Quote</td>
508536 </tr>
509537 <tr>
510 <td><code>\"</code></td>
538 <td><code>\"</code></td>
511539 <td>Double Quote</td>
512540 </tr>
513541 <tr>
514 <td><code>\xNN</code></td>
542 <td><code>\xNN</code></td>
515543 <td>hexadecimal 8-bit character code (2 digits)</td>
516544 </tr>
517545 <tr>
518 <td><code>\uNNNN</code></td>
546 <td><code>\uNNNN</code></td>
519547 <td>hexadecimal 16-bit Unicode character code UTF-8 encoded (4 digits)</td>
520548 </tr>
521549 <tr>
522 <td><code>\UNNNNNN</code></td>
550 <td><code>\UNNNNNN</code></td>
523551 <td>hexadecimal 24-bit Unicode character code UTF-8 encoded (6 digits)</td>
524552 </tr>
525553 </table>
526554 </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>
528556 {#header_close#}
529557 {#header_open|Multiline String Literals#}
530558 <p>
531559 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,
533561 the string literal goes until the end of the line. The end of the line is
534562 not included in the string literal.
535 However, if the next line begins with <code>\\</code> then a newline is appended and
563 However, if the next line begins with {#syntax#}\\{#endsyntax#} then a newline is appended and
536564 the string literal continues.
537565 </p>
538566 {#code_begin|syntax#}
......@@ -546,7 +574,7 @@ const hello_world_in_c =
546574;
547575 {#code_end#}
548576 <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#}:
550578 </p>
551579 {#code_begin|syntax#}
552580const c_string_literal =
......@@ -559,14 +587,14 @@ const c_string_literal =
559587;
560588 {#code_end#}
561589 <p>
562 In this example the variable <code>c_string_literal</code> has type <code>[*]const char</code> and
590 In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const char{#endsyntax#} and
563591 has a terminating null byte.
564592 </p>
565593 {#see_also|@embedFile#}
566594 {#header_close#}
567595 {#header_close#}
568596 {#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>
570598 {#code_begin|test_err|cannot assign to constant#}
571599const x = 1234;
572600
......@@ -582,8 +610,8 @@ test "assignment" {
582610 foo();
583611}
584612 {#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>
586 <p>If you need a variable that you can modify, use the <code>var</code> keyword:</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>
614 <p>If you need a variable that you can modify, use the {#syntax#}var{#endsyntax#} keyword:</p>
587615 {#code_begin|test#}
588616const assert = @import("std").debug.assert;
589617
......@@ -604,7 +632,7 @@ test "initialization" {
604632}
605633 {#code_end#}
606634 {#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>
608636 {#code_begin|test#}
609637const assert = @import("std").debug.assert;
610638
......@@ -615,14 +643,14 @@ test "init with undefined" {
615643}
616644 {#code_end#}
617645 <p>
618 <code>undefined</code> 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>.
620 <code>undefined</code> 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 meaningful
646 {#syntax#}undefined{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to any type.
647 Once this happens, it is no longer possible to detect that the value is {#syntax#}undefined{#endsyntax#}.
648 {#syntax#}undefined{#endsyntax#} means the value could be anything, even something that is nonsense
649 according to the type. Translated into English, {#syntax#}undefined{#endsyntax#} means "Not a meaningful
622650 value. Using this value would be a bug. The value will be unused, or overwritten before being used."
623651 </p>
624652 <p>
625 In {#link|Debug#} mode, Zig writes <code>0xaa</code> bytes to undefined memory. This is to catch
653 In {#link|Debug#} mode, Zig writes {#syntax#}0xaa{#endsyntax#} bytes to undefined memory. This is to catch
626654 bugs early, and to help detect use of undefined memory in a debugger.
627655 </p>
628656 {#header_close#}
......@@ -653,14 +681,14 @@ fn divide(a: i32, b: i32) i32 {
653681}
654682 {#code_end#}
655683 <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,
657685 and thus this division operation is vulnerable to both integer overflow and
658686 division by zero.
659687 </p>
660688 <p>
661 Operators such as <code>+</code> and <code>-</code> cause undefined behavior on
662 integer overflow. Also available are operations such as <code>+%</code> and
663 <code>-%</code> which are defined to have wrapping arithmetic on all targets.
689 Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
690 integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
691 {#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
664692 </p>
665693 {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#}
666694 {#header_close#}
......@@ -668,15 +696,15 @@ fn divide(a: i32, b: i32) i32 {
668696 {#header_open|Floats#}
669697 <p>Zig has the following floating point types:</p>
670698 <ul>
671 <li><code>f16</code> - IEEE-754-2008 binary16</li>
672 <li><code>f32</code> - IEEE-754-2008 binary32</li>
673 <li><code>f64</code> - IEEE-754-2008 binary64</li>
674 <li><code>f128</code> - IEEE-754-2008 binary128</li>
675 <li><code>c_longdouble</code> - matches <code>long double</code> for the target C ABI</li>
699 <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li>
700 <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li>
701 <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li>
702 <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li>
703 <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li>
676704 </ul>
677705 {#header_open|Float Literals#}
678706 <p>
679 Float literals have type <code>comptime_float</code> which is guaranteed to hold at least all possible values
707 Float literals have type {#syntax#}comptime_float{#endsyntax#} which is guaranteed to hold at least all possible values
680708 that the largest other floating point type can hold. Float literals {#link|implicitly cast|Implicit Casts#} to any other type.
681709 </p>
682710 {#code_begin|syntax#}
......@@ -690,8 +718,8 @@ const yet_another_hex_float = 0x103.70P-5;
690718 {#code_end#}
691719 {#header_close#}
692720 {#header_open|Floating Point Operations#}
693 <p>By default floating point operations use <code>Strict</code> mode,
694 but you can switch to <code>Optimized</code> mode on a per-block basis:</p>
721 <p>By default floating point operations use {#syntax#}Strict{#endsyntax#} mode,
722 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>
695723 {#code_begin|obj|foo#}
696724 {#code_release_fast#}
697725const builtin = @import("builtin");
......@@ -702,7 +730,7 @@ export fn foo_strict(x: f64) f64 {
702730}
703731
704732export fn foo_optimized(x: f64) f64 {
705 @setFloatMode(this, builtin.FloatMode.Optimized);
733 @setFloatMode(builtin.FloatMode.Optimized);
706734 return x + big - big;
707735}
708736 {#code_end#}
......@@ -744,8 +772,8 @@ pub fn main() void {
744772 </th>
745773 </tr>
746774 <tr>
747 <td><pre><code class="zig">a + b
748a += b</code></pre></td>
775 <td><pre>{#syntax#}a + b
776a += b{#endsyntax#}</pre></td>
749777 <td>
750778 <ul>
751779 <li>{#link|Integers#}</li>
......@@ -760,12 +788,12 @@ a += b</code></pre></td>
760788 </ul>
761789 </td>
762790 <td>
763 <pre><code class="zig">2 + 5 == 7</code></pre>
791 <pre>{#syntax#}2 + 5 == 7{#endsyntax#}</pre>
764792 </td>
765793 </tr>
766794 <tr>
767 <td><pre><code class="zig">a +% b
768a +%= b</code></pre></td>
795 <td><pre>{#syntax#}a +% b
796a +%= b{#endsyntax#}</pre></td>
769797 <td>
770798 <ul>
771799 <li>{#link|Integers#}</li>
......@@ -779,12 +807,12 @@ a +%= b</code></pre></td>
779807 </ul>
780808 </td>
781809 <td>
782 <pre><code class="zig">u32(@maxValue(u32)) +% 1 == 0</code></pre>
810 <pre>{#syntax#}u32(@maxValue(u32)) +% 1 == 0{#endsyntax#}</pre>
783811 </td>
784812 </tr>
785813 <tr>
786 <td><pre><code class="zig">a - b
787a -= b</code></pre></td>
814 <td><pre>{#syntax#}a - b
815a -= b{#endsyntax#}</pre></td>
788816 <td>
789817 <ul>
790818 <li>{#link|Integers#}</li>
......@@ -799,12 +827,12 @@ a -= b</code></pre></td>
799827 </ul>
800828 </td>
801829 <td>
802 <pre><code class="zig">2 - 5 == -3</code></pre>
830 <pre>{#syntax#}2 - 5 == -3{#endsyntax#}</pre>
803831 </td>
804832 </tr>
805833 <tr>
806 <td><pre><code class="zig">a -% b
807a -%= b</code></pre></td>
834 <td><pre>{#syntax#}a -% b
835a -%= b{#endsyntax#}</pre></td>
808836 <td>
809837 <ul>
810838 <li>{#link|Integers#}</li>
......@@ -818,11 +846,11 @@ a -%= b</code></pre></td>
818846 </ul>
819847 </td>
820848 <td>
821 <pre><code class="zig">u32(0) -% 1 == @maxValue(u32)</code></pre>
849 <pre>{#syntax#}u32(0) -% 1 == @maxValue(u32){#endsyntax#}</pre>
822850 </td>
823851 </tr>
824852 <tr>
825 <td><pre><code class="zig">-a<code></pre></td>
853 <td><pre>{#syntax#}-a{#endsyntax#}</pre></td>
826854 <td>
827855 <ul>
828856 <li>{#link|Integers#}</li>
......@@ -836,11 +864,11 @@ a -%= b</code></pre></td>
836864 </ul>
837865 </td>
838866 <td>
839 <pre><code class="zig">-1 == 0 - 1</code></pre>
867 <pre>{#syntax#}-1 == 0 - 1{#endsyntax#}</pre>
840868 </td>
841869 </tr>
842870 <tr>
843 <td><pre><code class="zig">-%a<code></pre></td>
871 <td><pre>{#syntax#}-%a{#endsyntax#}</pre></td>
844872 <td>
845873 <ul>
846874 <li>{#link|Integers#}</li>
......@@ -853,12 +881,12 @@ a -%= b</code></pre></td>
853881 </ul>
854882 </td>
855883 <td>
856 <pre><code class="zig">-%i32(@minValue(i32)) == @minValue(i32)</code></pre>
884 <pre>{#syntax#}-%i32(@minValue(i32)) == @minValue(i32){#endsyntax#}</pre>
857885 </td>
858886 </tr>
859887 <tr>
860 <td><pre><code class="zig">a * b
861a *= b</code></pre></td>
888 <td><pre>{#syntax#}a * b
889a *= b{#endsyntax#}</pre></td>
862890 <td>
863891 <ul>
864892 <li>{#link|Integers#}</li>
......@@ -873,12 +901,12 @@ a *= b</code></pre></td>
873901 </ul>
874902 </td>
875903 <td>
876 <pre><code class="zig">2 * 5 == 10</code></pre>
904 <pre>{#syntax#}2 * 5 == 10{#endsyntax#}</pre>
877905 </td>
878906 </tr>
879907 <tr>
880 <td><pre><code class="zig">a *% b
881a *%= b</code></pre></td>
908 <td><pre>{#syntax#}a *% b
909a *%= b{#endsyntax#}</pre></td>
882910 <td>
883911 <ul>
884912 <li>{#link|Integers#}</li>
......@@ -892,12 +920,12 @@ a *%= b</code></pre></td>
892920 </ul>
893921 </td>
894922 <td>
895 <pre><code class="zig">u8(200) *% 2 == 144</code></pre>
923 <pre>{#syntax#}u8(200) *% 2 == 144{#endsyntax#}</pre>
896924 </td>
897925 </tr>
898926 <tr>
899 <td><pre><code class="zig">a / b
900a /= b</code></pre></td>
927 <td><pre>{#syntax#}a / b
928a /= b{#endsyntax#}</pre></td>
901929 <td>
902930 <ul>
903931 <li>{#link|Integers#}</li>
......@@ -912,18 +940,18 @@ a /= b</code></pre></td>
912940 <li>For non-compile-time-known signed integers, must use
913941 {#link|@divTrunc#},
914942 {#link|@divFloor#}, or
915 {#link|@divExact#} instead of <code>/</code>.
943 {#link|@divExact#} instead of {#syntax#}/{#endsyntax#}.
916944 </li>
917945 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
918946 </ul>
919947 </td>
920948 <td>
921 <pre><code class="zig">10 / 5 == 2</code></pre>
949 <pre>{#syntax#}10 / 5 == 2{#endsyntax#}</pre>
922950 </td>
923951 </tr>
924952 <tr>
925 <td><pre><code class="zig">a % b
926a %= b</code></pre></td>
953 <td><pre>{#syntax#}a % b
954a %= b{#endsyntax#}</pre></td>
927955 <td>
928956 <ul>
929957 <li>{#link|Integers#}</li>
......@@ -936,18 +964,18 @@ a %= b</code></pre></td>
936964 <li>Can cause {#link|Division by Zero#} for floats in {#link|FloatMode.Optimized Mode|Floating Point Operations#}.</li>
937965 <li>For non-compile-time-known signed integers, must use
938966 {#link|@rem#} or
939 {#link|@mod#} instead of <code>%</code>.
967 {#link|@mod#} instead of {#syntax#}%{#endsyntax#}.
940968 </li>
941969 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
942970 </ul>
943971 </td>
944972 <td>
945 <pre><code class="zig">10 % 3 == 1</code></pre>
973 <pre>{#syntax#}10 % 3 == 1{#endsyntax#}</pre>
946974 </td>
947975 </tr>
948976 <tr>
949 <td><pre><code class="zig">a &lt;&lt; b
950a &lt;&lt;= b</code></pre></td>
977 <td><pre>{#syntax#}a << b
978a <<= b{#endsyntax#}</pre></td>
951979 <td>
952980 <ul>
953981 <li>{#link|Integers#}</li>
......@@ -955,18 +983,18 @@ a &lt;&lt;= b</code></pre></td>
955983 </td>
956984 <td>Bit Shift Left.
957985 <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>
959987 <li>See also {#link|@shlExact#}.</li>
960988 <li>See also {#link|@shlWithOverflow#}.</li>
961989 </ul>
962990 </td>
963991 <td>
964 <pre><code class="zig">1 &lt;&lt; 8 == 256</code></pre>
992 <pre>{#syntax#}1 << 8 == 256{#endsyntax#}</pre>
965993 </td>
966994 </tr>
967995 <tr>
968 <td><pre><code class="zig">a &gt;&gt; b
969a &gt;&gt;= b</code></pre></td>
996 <td><pre>{#syntax#}a >> b
997a >>= b{#endsyntax#}</pre></td>
970998 <td>
971999 <ul>
9721000 <li>{#link|Integers#}</li>
......@@ -974,17 +1002,17 @@ a &gt;&gt;= b</code></pre></td>
9741002 </td>
9751003 <td>Bit Shift Right.
9761004 <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>
9781006 <li>See also {#link|@shrExact#}.</li>
9791007 </ul>
9801008 </td>
9811009 <td>
982 <pre><code class="zig">10 &gt;&gt; 1 == 5</code></pre>
1010 <pre>{#syntax#}10 >> 1 == 5{#endsyntax#}</pre>
9831011 </td>
9841012 </tr>
9851013 <tr>
986 <td><pre><code class="zig">a &amp; b
987a &amp;= b</code></pre></td>
1014 <td><pre>{#syntax#}a & b
1015a &= b{#endsyntax#}</pre></td>
9881016 <td>
9891017 <ul>
9901018 <li>{#link|Integers#}</li>
......@@ -996,12 +1024,12 @@ a &amp;= b</code></pre></td>
9961024 </ul>
9971025 </td>
9981026 <td>
999 <pre><code class="zig">0b011 &amp; 0b101 == 0b001</code></pre>
1027 <pre>{#syntax#}0b011 &amp; 0b101 == 0b001{#endsyntax#}</pre>
10001028 </td>
10011029 </tr>
10021030 <tr>
1003 <td><pre><code class="zig">a | b
1004a |= b</code></pre></td>
1031 <td><pre>{#syntax#}a | b
1032a |= b{#endsyntax#}</pre></td>
10051033 <td>
10061034 <ul>
10071035 <li>{#link|Integers#}</li>
......@@ -1013,12 +1041,12 @@ a |= b</code></pre></td>
10131041 </ul>
10141042 </td>
10151043 <td>
1016 <pre><code class="zig">0b010 | 0b100 == 0b110</code></pre>
1044 <pre>{#syntax#}0b010 | 0b100 == 0b110{#endsyntax#}</pre>
10171045 </td>
10181046 </tr>
10191047 <tr>
1020 <td><pre><code class="zig">a ^ b
1021a ^= b</code></pre></td>
1048 <td><pre>{#syntax#}a ^ b
1049a ^= b{#endsyntax#}</pre></td>
10221050 <td>
10231051 <ul>
10241052 <li>{#link|Integers#}</li>
......@@ -1030,11 +1058,11 @@ a ^= b</code></pre></td>
10301058 </ul>
10311059 </td>
10321060 <td>
1033 <pre><code class="zig">0b011 ^ 0b101 == 0b110</code></pre>
1061 <pre>{#syntax#}0b011 ^ 0b101 == 0b110{#endsyntax#}</pre>
10341062 </td>
10351063 </tr>
10361064 <tr>
1037 <td><pre><code class="zig">~a<code></pre></td>
1065 <td><pre>{#syntax#}~a{#endsyntax#}</pre></td>
10381066 <td>
10391067 <ul>
10401068 <li>{#link|Integers#}</li>
......@@ -1044,29 +1072,29 @@ a ^= b</code></pre></td>
10441072 Bitwise NOT.
10451073 </td>
10461074 <td>
1047 <pre><code class="zig">~u8(0b0101111) == 0b1010000</code></pre>
1075 <pre>{#syntax#}~u8(0b0101111) == 0b1010000{#endsyntax#}</pre>
10481076 </td>
10491077 </tr>
10501078 <tr>
1051 <td><pre><code class="zig">a orelse b</code></pre></td>
1079 <td><pre>{#syntax#}a orelse b{#endsyntax#}</pre></td>
10521080 <td>
10531081 <ul>
10541082 <li>{#link|Optionals#}</li>
10551083 </ul>
10561084 </td>
1057 <td>If <code>a</code> is <code>null</code>,
1058 returns <code>b</code> ("default value"),
1059 otherwise returns the unwrapped value of <code>a</code>.
1060 Note that <code>b</code> may be a value of type {#link|noreturn#}.
1085 <td>If {#syntax#}a{#endsyntax#} is {#syntax#}null{#endsyntax#},
1086 returns {#syntax#}b{#endsyntax#} ("default value"),
1087 otherwise returns the unwrapped value of {#syntax#}a{#endsyntax#}.
1088 Note that {#syntax#}b{#endsyntax#} may be a value of type {#link|noreturn#}.
10611089 </td>
10621090 <td>
1063 <pre><code class="zig">const value: ?u32 = null;
1091 <pre>{#syntax#}const value: ?u32 = null;
10641092const unwrapped = value orelse 1234;
1065unwrapped == 1234</code></pre>
1093unwrapped == 1234{#endsyntax#}</pre>
10661094 </td>
10671095 </tr>
10681096 <tr>
1069 <td><pre><code class="zig">a.?</code></pre></td>
1097 <td><pre>{#syntax#}a.?{#endsyntax#}</pre></td>
10701098 <td>
10711099 <ul>
10721100 <li>{#link|Optionals#}</li>
......@@ -1074,65 +1102,65 @@ unwrapped == 1234</code></pre>
10741102 </td>
10751103 <td>
10761104 Equivalent to:
1077 <pre><code class="zig">a orelse unreachable</code></pre>
1105 <pre>{#syntax#}a orelse unreachable{#endsyntax#}</pre>
10781106 </td>
10791107 <td>
1080 <pre><code class="zig">const value: ?u32 = 5678;
1081value.? == 5678</code></pre>
1108 <pre>{#syntax#}const value: ?u32 = 5678;
1109value.? == 5678{#endsyntax#}</pre>
10821110 </td>
10831111 </tr>
10841112 <tr>
1085 <td><pre><code class="zig">a catch b
1086a catch |err| b</code></pre></td>
1113 <td><pre>{#syntax#}a catch b
1114a catch |err| b{#endsyntax#}</pre></td>
10871115 <td>
10881116 <ul>
10891117 <li>{#link|Error Unions|Errors#}</li>
10901118 </ul>
10911119 </td>
1092 <td>If <code>a</code> is an <code>error</code>,
1093 returns <code>b</code> ("default value"),
1094 otherwise returns the unwrapped value of <code>a</code>.
1095 Note that <code>b</code> 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>.
1120 <td>If {#syntax#}a{#endsyntax#} is an {#syntax#}error{#endsyntax#},
1121 returns {#syntax#}b{#endsyntax#} ("default value"),
1122 otherwise returns the unwrapped value of {#syntax#}a{#endsyntax#}.
1123 Note that {#syntax#}b{#endsyntax#} may be a value of type {#link|noreturn#}.
1124 {#syntax#}err{#endsyntax#} is the {#syntax#}error{#endsyntax#} and is in scope of the expression {#syntax#}b{#endsyntax#}.
10971125 </td>
10981126 <td>
1099 <pre><code class="zig">const value: error!u32 = error.Broken;
1127 <pre>{#syntax#}const value: error!u32 = error.Broken;
11001128const unwrapped = value catch 1234;
1101unwrapped == 1234</code></pre>
1129unwrapped == 1234{#endsyntax#}</pre>
11021130 </td>
11031131 </tr>
11041132 <tr>
1105 <td><pre><code class="zig">a and b<code></pre></td>
1133 <td><pre>{#syntax#}a and b{#endsyntax#}</pre></td>
11061134 <td>
11071135 <ul>
11081136 <li>{#link|bool|Primitive Types#}</li>
11091137 </ul>
11101138 </td>
11111139 <td>
1112 If <code>a</code> is <code>false</code>, returns <code>false</code>
1113 without evaluating <code>b</code>. Otherwise, returns <code>b</code>.
1140 If {#syntax#}a{#endsyntax#} is {#syntax#}false{#endsyntax#}, returns {#syntax#}false{#endsyntax#}
1141 without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}.
11141142 </td>
11151143 <td>
1116 <pre><code class="zig">false and true == false</code></pre>
1144 <pre>{#syntax#}false and true == false{#endsyntax#}</pre>
11171145 </td>
11181146 </tr>
11191147 <tr>
1120 <td><pre><code class="zig">a or b<code></pre></td>
1148 <td><pre>{#syntax#}a or b{#endsyntax#}</pre></td>
11211149 <td>
11221150 <ul>
11231151 <li>{#link|bool|Primitive Types#}</li>
11241152 </ul>
11251153 </td>
11261154 <td>
1127 If <code>a</code> is <code>true</code>, returns <code>true</code>
1128 without evaluating <code>b</code>. Otherwise, returns <code>b</code>.
1155 If {#syntax#}a{#endsyntax#} is {#syntax#}true{#endsyntax#}, returns {#syntax#}true{#endsyntax#}
1156 without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}.
11291157 </td>
11301158 <td>
1131 <pre><code class="zig">false or true == true</code></pre>
1159 <pre>{#syntax#}false or true == true{#endsyntax#}</pre>
11321160 </td>
11331161 </tr>
11341162 <tr>
1135 <td><pre><code class="zig">!a<code></pre></td>
1163 <td><pre>{#syntax#}!a{#endsyntax#}</pre></td>
11361164 <td>
11371165 <ul>
11381166 <li>{#link|bool|Primitive Types#}</li>
......@@ -1142,11 +1170,11 @@ unwrapped == 1234</code></pre>
11421170 Boolean NOT.
11431171 </td>
11441172 <td>
1145 <pre><code class="zig">!false == true</code></pre>
1173 <pre>{#syntax#}!false == true{#endsyntax#}</pre>
11461174 </td>
11471175 </tr>
11481176 <tr>
1149 <td><pre><code class="zig">a == b<code></pre></td>
1177 <td><pre>{#syntax#}a == b{#endsyntax#}</pre></td>
11501178 <td>
11511179 <ul>
11521180 <li>{#link|Integers#}</li>
......@@ -1156,30 +1184,30 @@ unwrapped == 1234</code></pre>
11561184 </ul>
11571185 </td>
11581186 <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#}.
11601188 Invokes {#link|Peer Type Resolution#} for the operands.
11611189 </td>
11621190 <td>
1163 <pre><code class="zig">(1 == 1) == true</code></pre>
1191 <pre>{#syntax#}(1 == 1) == true{#endsyntax#}</pre>
11641192 </td>
11651193 </tr>
11661194 <tr>
1167 <td><pre><code class="zig">a == null<code></pre></td>
1195 <td><pre>{#syntax#}a == null{#endsyntax#}</pre></td>
11681196 <td>
11691197 <ul>
11701198 <li>{#link|Optionals#}</li>
11711199 </ul>
11721200 </td>
11731201 <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#}.
11751203 </td>
11761204 <td>
1177 <pre><code class="zig">const value: ?u32 = null;
1178value == null</code></pre>
1205 <pre>{#syntax#}const value: ?u32 = null;
1206value == null{#endsyntax#}</pre>
11791207 </td>
11801208 </tr>
11811209 <tr>
1182 <td><pre><code class="zig">a != b<code></pre></td>
1210 <td><pre>{#syntax#}a != b{#endsyntax#}</pre></td>
11831211 <td>
11841212 <ul>
11851213 <li>{#link|Integers#}</li>
......@@ -1189,15 +1217,15 @@ value == null</code></pre>
11891217 </ul>
11901218 </td>
11911219 <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#}.
11931221 Invokes {#link|Peer Type Resolution#} for the operands.
11941222 </td>
11951223 <td>
1196 <pre><code class="zig">(1 != 1) == false</code></pre>
1224 <pre>{#syntax#}(1 != 1) == false{#endsyntax#}</pre>
11971225 </td>
11981226 </tr>
11991227 <tr>
1200 <td><pre><code class="zig">a &gt; b<code></pre></td>
1228 <td><pre>{#syntax#}a > b{#endsyntax#}</pre></td>
12011229 <td>
12021230 <ul>
12031231 <li>{#link|Integers#}</li>
......@@ -1205,15 +1233,15 @@ value == null</code></pre>
12051233 </ul>
12061234 </td>
12071235 <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#}.
12091237 Invokes {#link|Peer Type Resolution#} for the operands.
12101238 </td>
12111239 <td>
1212 <pre><code class="zig">(2 &gt; 1) == true</code></pre>
1240 <pre>{#syntax#}(2 > 1) == true{#endsyntax#}</pre>
12131241 </td>
12141242 </tr>
12151243 <tr>
1216 <td><pre><code class="zig">a &gt;= b<code></pre></td>
1244 <td><pre>{#syntax#}a >= b{#endsyntax#}</pre></td>
12171245 <td>
12181246 <ul>
12191247 <li>{#link|Integers#}</li>
......@@ -1221,15 +1249,15 @@ value == null</code></pre>
12211249 </ul>
12221250 </td>
12231251 <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#}.
12251253 Invokes {#link|Peer Type Resolution#} for the operands.
12261254 </td>
12271255 <td>
1228 <pre><code class="zig">(2 &gt;= 1) == true</code></pre>
1256 <pre>{#syntax#}(2 >= 1) == true{#endsyntax#}</pre>
12291257 </td>
12301258 </tr>
12311259 <tr>
1232 <td><pre><code class="zig">a &lt; b<code></pre></td>
1260 <td><pre>{#syntax#}a < b{#endsyntax#}</pre></td>
12331261 <td>
12341262 <ul>
12351263 <li>{#link|Integers#}</li>
......@@ -1237,15 +1265,15 @@ value == null</code></pre>
12371265 </ul>
12381266 </td>
12391267 <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#}.
12411269 Invokes {#link|Peer Type Resolution#} for the operands.
12421270 </td>
12431271 <td>
1244 <pre><code class="zig">(1 &lt; 2) == true</code></pre>
1272 <pre>{#syntax#}(1 < 2) == true{#endsyntax#}></pre>
12451273 </td>
12461274 </tr>
12471275 <tr>
1248 <td><pre><code class="zig">a &lt;= b<code></pre></td>
1276 <td><pre>{#syntax#}a <= b{#endsyntax#}</pre></td>
12491277 <td>
12501278 <ul>
12511279 <li>{#link|Integers#}</li>
......@@ -1253,15 +1281,15 @@ value == null</code></pre>
12531281 </ul>
12541282 </td>
12551283 <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#}.
12571285 Invokes {#link|Peer Type Resolution#} for the operands.
12581286 </td>
12591287 <td>
1260 <pre><code class="zig">(1 &lt;= 2) == true</code></pre>
1288 <pre>{#syntax#}(1 <= 2) == true{#endsyntax#}</pre>
12611289 </td>
12621290 </tr>
12631291 <tr>
1264 <td><pre><code class="zig">a ++ b<code></pre></td>
1292 <td><pre>{#syntax#}a ++ b{#endsyntax#}</pre></td>
12651293 <td>
12661294 <ul>
12671295 <li>{#link|Arrays#}</li>
......@@ -1270,19 +1298,19 @@ value == null</code></pre>
12701298 <td>
12711299 Array concatenation.
12721300 <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#}.
12741302 </ul>
12751303 </td>
12761304 <td>
1277 <pre><code class="zig">const mem = @import("std").mem;
1305 <pre>{#syntax#}const mem = @import("std").mem;
12781306const array1 = []u32{1,2};
12791307const array2 = []u32{3,4};
12801308const 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>
12821310 </td>
12831311 </tr>
12841312 <tr>
1285 <td><pre><code class="zig">a ** b<code></pre></td>
1313 <td><pre>{#syntax#}a ** b{#endsyntax#}</pre></td>
12861314 <td>
12871315 <ul>
12881316 <li>{#link|Arrays#}</li>
......@@ -1291,17 +1319,17 @@ mem.eql(u32, together, []u32{1,2,3,4})</code></pre>
12911319 <td>
12921320 Array multiplication.
12931321 <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#}.
12951323 </ul>
12961324 </td>
12971325 <td>
1298 <pre><code class="zig">const mem = @import("std").mem;
1326 <pre>{#syntax#}const mem = @import("std").mem;
12991327const pattern = "ab" ** 3;
1300mem.eql(u8, pattern, "ababab")</code></pre>
1328mem.eql(u8, pattern, "ababab"){#endsyntax#}</pre>
13011329 </td>
13021330 </tr>
13031331 <tr>
1304 <td><pre><code class="zig">a.*<code></pre></td>
1332 <td><pre>{#syntax#}a.*{#endsyntax#}</pre></td>
13051333 <td>
13061334 <ul>
13071335 <li>{#link|Pointers#}</li>
......@@ -1311,13 +1339,13 @@ mem.eql(u8, pattern, "ababab")</code></pre>
13111339 Pointer dereference.
13121340 </td>
13131341 <td>
1314 <pre><code class="zig">const x: u32 = 1234;
1315const ptr = &amp;x;
1316x.* == 1234</code></pre>
1342 <pre>{#syntax#}const x: u32 = 1234;
1343const ptr = &x;
1344x.* == 1234{#endsyntax#}</pre>
13171345 </td>
13181346 </tr>
13191347 <tr>
1320 <td><pre><code class="zig">&amp;a<code></pre></td>
1348 <td><pre>{#syntax#}&amp;a{#endsyntax#}</pre></td>
13211349 <td>
13221350 All types
13231351 </td>
......@@ -1325,13 +1353,13 @@ x.* == 1234</code></pre>
13251353 Address of.
13261354 </td>
13271355 <td>
1328 <pre><code class="zig">const x: u32 = 1234;
1329const ptr = &amp;x;
1330x.* == 1234</code></pre>
1356 <pre>{#syntax#}const x: u32 = 1234;
1357const ptr = &x;
1358x.* == 1234{#endsyntax#}</pre>
13311359 </td>
13321360 </tr>
13331361 <tr>
1334 <td><pre><code class="zig">a || b<code></pre></td>
1362 <td><pre>{#syntax#}a || b{#endsyntax#}</pre></td>
13351363 <td>
13361364 <ul>
13371365 <li>{#link|Error Set Type#}</li>
......@@ -1341,30 +1369,30 @@ x.* == 1234</code></pre>
13411369 {#link|Merging Error Sets#}
13421370 </td>
13431371 <td>
1344 <pre><code class="zig">const A = error{One};
1372 <pre>{#syntax#}const A = error{One};
13451373const B = error{Two};
1346(A || B) == error{One, Two}</code></pre>
1374(A || B) == error{One, Two}{#endsyntax#}</pre>
13471375 </td>
13481376 </tr>
13491377 </table>
13501378 </div>
13511379 {#header_close#}
13521380 {#header_open|Precedence#}
1353 <pre><code>x() x[] x.y
1381 <pre>{#syntax#}x() x[] x.y
13541382a!b
1355!x -x -%x ~x &amp;x ?x
1383!x -x -%x ~x &x ?x
13561384x{} x.* x.?
13571385! * / % ** *% ||
13581386+ - ++ +% -%
1359&lt;&lt; &gt;&gt;
1360&amp;
1387<< >>
1388&
13611389^
13621390|
1363== != &lt; &gt; &lt;= &gt;=
1391== != < > <= >=
13641392and
13651393or
13661394orelse catch
1367= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>
1395= *= /= %= += -= <<= >>= &= ^= |={#endsyntax#}</pre>
13681396 {#header_close#}
13691397 {#header_close#}
13701398 {#header_open|Arrays#}
......@@ -1613,7 +1641,7 @@ test "pointer child type" {
16131641 </p>
16141642 <p>
16151643 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#}.
16171645 </p>
16181646 <p>
16191647 In Zig, a pointer type has an alignment value. If the value is equal to the
......@@ -1633,8 +1661,8 @@ test "variable alignment" {
16331661 }
16341662}
16351663 {#code_end#}
1636 <p>In the same way that a <code>*i32</code> can be {#link|implicitly cast|Implicit Casts#} to a
1637 <code>*const i32</code>, a pointer with a larger alignment can be implicitly
1664 <p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to a
1665 {#syntax#}*const i32{#endsyntax#}, a pointer with a larger alignment can be implicitly
16381666 cast to a pointer with a smaller alignment, but not vice versa.
16391667 </p>
16401668 <p>
......@@ -1689,14 +1717,14 @@ fn foo(bytes: []u8) u32 {
16891717 {#header_open|Type Based Alias Analysis#}
16901718 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
16911719 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 to
1693 <code>u8</code> can alias any memory.
1720 not alias the same memory, with the exception of {#syntax#}u8{#endsyntax#}. Pointers to
1721 {#syntax#}u8{#endsyntax#} can alias any memory.
16941722 </p>
16951723 <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>
16971725 <p>Instead, use {#link|@bitCast#}:
1698 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
1699 <p>As an added benefit, the <code>@bitCast</code> version works at compile-time.</p>
1726 <pre>{#syntax#}@bitCast(u32, f32(12.34)){#endsyntax#}</pre>
1727 <p>As an added benefit, the {#syntax#}@bitCast{#endsyntax#} version works at compile-time.</p>
17001728 {#see_also|Slices|Memory#}
17011729 {#header_close#}
17021730 {#header_close#}
......@@ -1924,9 +1952,9 @@ test "linked list" {
19241952 <ul>
19251953 <li>If the struct is in the initialization expression of a variable, it gets named after
19261954 that variable.</li>
1927 <li>If the struct is in the <code>return</code> expression, it gets named after
1955 <li>If the struct is in the {#syntax#}return{#endsyntax#} expression, it gets named after
19281956 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>
19301958 </ul>
19311959 {#code_begin|exe|struct_name#}
19321960const std = @import("std");
......@@ -2058,7 +2086,7 @@ const Foo = enum { A, B, C };
20582086export fn entry(foo: Foo) void { }
20592087 {#code_end#}
20602088 <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#}:
20622090 </p>
20632091 {#code_begin|obj#}
20642092const Foo = extern enum { A, B, C };
......@@ -2067,7 +2095,7 @@ export fn entry(foo: Foo) void { }
20672095 {#header_close#}
20682096 {#header_open|packed enum#}
20692097 <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 type
2098 <p>{#syntax#}packed enum{#endsyntax#} causes the size of the enum to be the same as the size of the integer tag type
20712099 of the enum:</p>
20722100 {#code_begin|test#}
20732101const std = @import("std");
......@@ -2218,7 +2246,7 @@ test "access variable after block scope" {
22182246 x += 1;
22192247}
22202248 {#code_end#}
2221 <p>Blocks are expressions. When labeled, <code>break</code> can be used
2249 <p>Blocks are expressions. When labeled, {#syntax#}break{#endsyntax#} can be used
22222250 to return a value from the block:
22232251 </p>
22242252 {#code_begin|test#}
......@@ -2236,7 +2264,7 @@ test "labeled break from labeled block expression" {
22362264 assert(y == 124);
22372265}
22382266 {#code_end#}
2239 <p>Here, <code>blk</code> can be any name.</p>
2267 <p>Here, {#syntax#}blk{#endsyntax#} can be any name.</p>
22402268 {#see_also|Labeled while|Labeled for#}
22412269 {#header_close#}
22422270 {#header_open|switch#}
......@@ -2352,7 +2380,7 @@ test "while basic" {
23522380}
23532381 {#code_end#}
23542382 <p>
2355 Use <code>break</code> to exit a while loop early.
2383 Use {#syntax#}break{#endsyntax#} to exit a while loop early.
23562384 </p>
23572385 {#code_begin|test|while#}
23582386const assert = @import("std").debug.assert;
......@@ -2368,7 +2396,7 @@ test "while break" {
23682396}
23692397 {#code_end#}
23702398 <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.
23722400 </p>
23732401 {#code_begin|test|while#}
23742402const assert = @import("std").debug.assert;
......@@ -2386,7 +2414,7 @@ test "while continue" {
23862414 {#code_end#}
23872415 <p>
23882416 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.
23902418 </p>
23912419 {#code_begin|test|while#}
23922420const assert = @import("std").debug.assert;
......@@ -2408,13 +2436,13 @@ test "while loop continue expression, more complicated" {
24082436 {#code_end#}
24092437 <p>
24102438 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 when
2439 result of the {#syntax#}else{#endsyntax#} clause of a while loop, which is executed when
24122440 the condition of the while loop is tested as false.
24132441 </p>
24142442 <p>
2415 <code>break</code>, like <code>return</code>, accepts a value
2416 parameter. This is the result of the <code>while</code> expression.
2417 When you <code>break</code> from a while loop, the <code>else</code> branch is not
2443 {#syntax#}break{#endsyntax#}, like {#syntax#}return{#endsyntax#}, accepts a value
2444 parameter. This is the result of the {#syntax#}while{#endsyntax#} expression.
2445 When you {#syntax#}break{#endsyntax#} from a while loop, the {#syntax#}else{#endsyntax#} branch is not
24182446 evaluated.
24192447 </p>
24202448 {#code_begin|test|while#}
......@@ -2435,8 +2463,8 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
24352463}
24362464 {#code_end#}
24372465 {#header_open|Labeled while#}
2438 <p>When a <code>while</code> loop is labeled, it can be referenced from a <code>break</code>
2439 or <code>continue</code> from within a nested loop:</p>
2466 <p>When a {#syntax#}while{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
2467 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
24402468 {#code_begin|test#}
24412469test "nested break" {
24422470 outer: while (true) {
......@@ -2463,11 +2491,11 @@ test "nested continue" {
24632491 exits.
24642492 </p>
24652493 <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,
24672495 the while condition must have an {#link|Optional Type#}.
24682496 </p>
24692497 <p>
2470 The <code>else</code> branch is allowed on optional iteration. In this case, it will
2498 The {#syntax#}else{#endsyntax#} branch is allowed on optional iteration. In this case, it will
24712499 be executed on the first null value encountered.
24722500 </p>
24732501 {#code_begin|test|while#}
......@@ -2509,7 +2537,7 @@ fn eventuallyNullSequence() ?u32 {
25092537 the loop is finished.
25102538 </p>
25112539 <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,
25132541 the while condition must have an {#link|Error Union Type#}.
25142542 </p>
25152543 {#code_begin|test|while#}
......@@ -2565,7 +2593,7 @@ fn typeNameLength(comptime T: type) usize {
25652593}
25662594 {#code_end#}
25672595 <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:
25692597 </p>
25702598 <ul>
25712599 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>
......@@ -2643,8 +2671,8 @@ test "for else" {
26432671}
26442672 {#code_end#}
26452673 {#header_open|Labeled for#}
2646 <p>When a <code>for</code> loop is labeled, it can be referenced from a <code>break</code>
2647 or <code>continue</code> from within a nested loop:</p>
2674 <p>When a {#syntax#}for{#endsyntax#} loop is labeled, it can be referenced from a {#syntax#}break{#endsyntax#}
2675 or {#syntax#}continue{#endsyntax#} from within a nested loop:</p>
26482676 {#code_begin|test#}
26492677const std = @import("std");
26502678const assert = std.debug.assert;
......@@ -2704,7 +2732,7 @@ fn typeNameLength(comptime T: type) usize {
27042732}
27052733 {#code_end#}
27062734 <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:
27082736 </p>
27092737 <ul>
27102738 <li>You need the loop to execute at {#link|comptime#} for the semantics to work.</li>
......@@ -2904,13 +2932,13 @@ test "errdefer unwinding" {
29042932 {#header_close#}
29052933 {#header_open|unreachable#}
29062934 <p>
2907 In <code>Debug</code> and <code>ReleaseSafe</code> 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>.
2935 In {#syntax#}Debug{#endsyntax#} and {#syntax#}ReleaseSafe{#endsyntax#} mode, and when using <code>zig test</code>,
2936 {#syntax#}unreachable{#endsyntax#} emits a call to {#syntax#}panic{#endsyntax#} with the message <code>reached unreachable code</code>.
29092937 </p>
29102938 <p>
2911 In <code>ReleaseFast</code> mode, the optimizer uses the assumption that <code>unreachable</code> code
2912 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode
2913 still emits <code>unreachable</code> as calls to <code>panic</code>.
2939 In {#syntax#}ReleaseFast{#endsyntax#} mode, the optimizer uses the assumption that {#syntax#}unreachable{#endsyntax#} code
2940 will never be hit to perform optimizations. However, <code>zig test</code> even in {#syntax#}ReleaseFast{#endsyntax#} mode
2941 still emits {#syntax#}unreachable{#endsyntax#} as calls to {#syntax#}panic{#endsyntax#}.
29142942 </p>
29152943 {#header_open|Basics#}
29162944 {#code_begin|test#}
......@@ -2956,17 +2984,17 @@ test "type of unreachable" {
29562984 {#header_close#}
29572985 {#header_open|noreturn#}
29582986 <p>
2959 <code>noreturn</code> is the type of:
2987 {#syntax#}noreturn{#endsyntax#} is the type of:
29602988 </p>
29612989 <ul>
2962 <li><code>break</code></li>
2963 <li><code>continue</code></li>
2964 <li><code>return</code></li>
2965 <li><code>unreachable</code></li>
2966 <li><code>while (true) {}</code></li>
2990 <li>{#syntax#}break{#endsyntax#}</li>
2991 <li>{#syntax#}continue{#endsyntax#}</li>
2992 <li>{#syntax#}return{#endsyntax#}</li>
2993 <li>{#syntax#}unreachable{#endsyntax#}</li>
2994 <li>{#syntax#}while (true) {}{#endsyntax#}</li>
29672995 </ul>
2968 <p>When resolving types together, such as <code>if</code> clauses or <code>switch</code> prongs,
2969 the <code>noreturn</code> type is compatible with every other type. Consider:
2996 <p>When resolving types together, such as {#syntax#}if{#endsyntax#} clauses or {#syntax#}switch{#endsyntax#} prongs,
2997 the {#syntax#}noreturn{#endsyntax#} type is compatible with every other type. Consider:
29702998 </p>
29712999 {#code_begin|test#}
29723000fn foo(condition: bool, b: u32) void {
......@@ -2977,7 +3005,7 @@ test "noreturn" {
29773005 foo(false, 1);
29783006}
29793007 {#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>
29813009 {#code_begin|test#}
29823010 {#target_windows#}
29833011pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn;
......@@ -3106,7 +3134,7 @@ test "fn reflection" {
31063134 </p>
31073135 <p>
31083136 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>.
31103138 </p>
31113139 <p>
31123140 You can {#link|implicitly cast|Implicit Casts#} an error from a subset to its superset:
......@@ -3169,7 +3197,7 @@ const err = (error {FileNotFound}).FileNotFound;
31693197 This becomes useful when using {#link|Inferred Error Sets#}.
31703198 </p>
31713199 {#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.
31733201 This is the error set that contains all errors in the entire compilation unit.
31743202 It is a superset of all other error sets and a subset of none of them.
31753203 </p>
......@@ -3188,7 +3216,7 @@ const err = (error {FileNotFound}).FileNotFound;
31883216 {#header_close#}
31893217 {#header_open|Error Union Type#}
31903218 <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#}
31923220 binary operator to form an error union type. You are likely to use an
31933221 error union type more often than an error set type by itself.
31943222 </p>
......@@ -3235,14 +3263,14 @@ test "parse u64" {
32353263}
32363264 {#code_end#}
32373265 <p>
3238 Notice the return type is <code>!u64</code>. This means that the function
3266 Notice the return type is {#syntax#}!u64{#endsyntax#}. This means that the function
32393267 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.
32413269 </p>
32423270 <p>
32433271 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>.
3245 Both types {#link|implicitly cast|Implicit Casts#} to <code>error!u64</code>.
3272 an error, and at the bottom a return statement that returns a {#syntax#}u64{#endsyntax#}.
3273 Both types {#link|implicitly cast|Implicit Casts#} to {#syntax#}error!u64{#endsyntax#}.
32463274 </p>
32473275 <p>
32483276 What it looks like to use this function varies depending on what you're
......@@ -3255,7 +3283,7 @@ test "parse u64" {
32553283 <li>You want to take a different action for each possible error.</li>
32563284 </ul>
32573285 {#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>
32593287 {#code_begin|syntax#}
32603288fn doAThing(str: []u8) void {
32613289 const number = parseU64(str, 10) catch 13;
......@@ -3263,9 +3291,9 @@ fn doAThing(str: []u8) void {
32633291}
32643292 {#code_end#}
32653293 <p>
3266 In this code, <code>number</code> 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 must
3268 match the unwrapped error union type, or be of type <code>noreturn</code>.
3294 In this code, {#syntax#}number{#endsyntax#} will be equal to the successfully parsed string, or
3295 a default value of 13. The type of the right hand side of the binary {#syntax#}catch{#endsyntax#} operator must
3296 match the unwrapped error union type, or be of type {#syntax#}noreturn{#endsyntax#}.
32693297 </p>
32703298 {#header_close#}
32713299 {#header_open|try#}
......@@ -3278,7 +3306,7 @@ fn doAThing(str: []u8) !void {
32783306}
32793307 {#code_end#}
32803308 <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:
32823310 </p>
32833311 {#code_begin|syntax#}
32843312fn doAThing(str: []u8) !void {
......@@ -3287,7 +3315,7 @@ fn doAThing(str: []u8) !void {
32873315}
32883316 {#code_end#}
32893317 <p>
3290 <code>try</code> evaluates an error union expression. If it is an error, it returns
3318 {#syntax#}try{#endsyntax#} evaluates an error union expression. If it is an error, it returns
32913319 from the current function with the same error. Otherwise, the expression results in
32923320 the unwrapped value.
32933321 </p>
......@@ -3299,7 +3327,7 @@ fn doAThing(str: []u8) !void {
32993327 {#code_begin|syntax#}const number = parseU64("1234", 10) catch unreachable;{#code_end#}
33003328 <p>
33013329 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> generates
3330 {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates
33033331 a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
33043332 application, if there <em>was</em> a surprise error here, the application would crash
33053333 appropriately.
......@@ -3324,7 +3352,7 @@ fn doAThing(str: []u8) void {
33243352 {#header_open|errdefer#}
33253353 <p>
33263354 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#},
33283356 which evaluates the deferred expression on block exit path if and only if
33293357 the function returned with an error from the block.
33303358 </p>
......@@ -3362,7 +3390,7 @@ fn createFoo(param: i32) !Foo {
33623390 <ul>
33633391 <li>These primitives give enough expressiveness that it's completely practical
33643392 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> and
3393 to ignore the error, you can add {#syntax#}catch unreachable{#endsyntax#} and
33663394 get the added benefit of crashing in Debug and ReleaseSafe modes if your assumption was wrong.
33673395 </li>
33683396 <li>
......@@ -3373,7 +3401,7 @@ fn createFoo(param: i32) !Foo {
33733401 </ul>
33743402 {#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.
33773405 You can use compile-time reflection to access the child type of an error union:</p>
33783406 {#code_begin|test#}
33793407const assert = @import("std").debug.assert;
......@@ -3396,15 +3424,15 @@ test "error union" {
33963424 {#code_end#}
33973425 {#header_open|Merging Error Sets#}
33983426 <p>
3399 Use the <code>||</code> operator to merge two error sets together. The resulting
3427 Use the {#syntax#}||{#endsyntax#} operator to merge two error sets together. The resulting
34003428 error set contains the errors of both error sets. Doc comments from the left-hand
34013429 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>.
34033431 </p>
34043432 <p>
34053433 This is especially useful for functions which return different error sets depending
34063434 on {#link|comptime#} branches. For example, the Zig standard library uses
3407 <code>LinuxFileOpenError || WindowsFileOpenError</code> for the error set of opening
3435 {#syntax#}LinuxFileOpenError || WindowsFileOpenError{#endsyntax#} for the error set of opening
34083436 files.
34093437 </p>
34103438 {#code_begin|test#}
......@@ -3537,8 +3565,8 @@ fn bang2() !void {
35373565 Look closely at this example. This is no stack trace.
35383566 </p>
35393567 <p>
3540 You can see that the final error bubbled up was <code>PermissionDenied</code>,
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,
3568 You can see that the final error bubbled up was {#syntax#}PermissionDenied{#endsyntax#},
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,
35423570 and then returns another one, from the switch statement. Error Return Traces make this clear, whereas a stack trace would look like this:
35433571 </p>
35443572 {#code_begin|exe_err#}
......@@ -3584,7 +3612,7 @@ fn bang2() void {
35843612 {#code_end#}
35853613 <p>
35863614 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.
35883616 One would have to open a debugger or further instrument the application
35893617 in order to find out. The error return trace, on the other hand,
35903618 shows exactly how the error bubbled up.
......@@ -3603,8 +3631,8 @@ fn bang2() void {
36033631 </p>
36043632 <ul>
36053633 <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>
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>
3634 <li>An error makes its way to {#syntax#}catch unreachable{#endsyntax#} and you have not overridden the default panic handler</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>
36083636 </ul>
36093637 {#header_open|Implementation Details#}
36103638 <p>
......@@ -3615,7 +3643,7 @@ fn bang2() void {
36153643 <li>when returning errors</li>
36163644 </ul>
36173645 <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#}.
36193647 This is to initialize this struct in the stack memory:
36203648 </p>
36213649 {#code_begin|syntax#}
......@@ -3628,13 +3656,13 @@ pub const StackTrace = struct {
36283656 Here, N is the maximum function call depth as determined by call graph analysis. Recursion is ignored and counts for 2.
36293657 </p>
36303658 <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.
36323660 </p>
36333661 <p>
36343662 That's it for the path when no errors occur. It's practically free in terms of performance.
36353663 </p>
36363664 <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:
36383666 </p>
36393667 {#code_begin|syntax#}
36403668// marked as "no-inline" in LLVM IR
......@@ -3649,7 +3677,7 @@ fn __zig_return_error(stack_trace: *StackTrace) void {
36493677 <p>
36503678 As for code size cost, 1 function call before a return statement is no big deal. Even so,
36513679 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.
36533681 </p>
36543682 {#header_close#}
36553683 {#header_close#}
......@@ -3671,7 +3699,7 @@ const normal_int: i32 = 1234;
36713699const optional_int: ?i32 = 5678;
36723700 {#code_end#}
36733701 <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#}.
36753703 </p>
36763704 <p>
36773705 Instead of integers, let's talk about pointers. Null references are the source of many runtime
......@@ -3712,8 +3740,8 @@ fn doAThing() ?*Foo {
37123740 {#code_end#}
37133741 <p>
37143742 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> keyword
3716 unwrapped the optional type and therefore <code>ptr</code> is guaranteed to be non-null everywhere
3743 is {#syntax#}*u8{#endsyntax#} <em>not</em> {#syntax#}?*u8{#endsyntax#}. The {#syntax#}orelse{#endsyntax#} keyword
3744 unwrapped the optional type and therefore {#syntax#}ptr{#endsyntax#} is guaranteed to be non-null everywhere
37173745 it is used in the function.
37183746 </p>
37193747 <p>
......@@ -3744,7 +3772,7 @@ fn doAThing(optional_foo: ?*Foo) void {
37443772 {#code_end#}
37453773 <p>
37463774 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, which
3775 {#syntax#}foo{#endsyntax#} is no longer an optional pointer, it is a pointer, which
37483776 cannot be null.
37493777 </p>
37503778 <p>
......@@ -3755,7 +3783,7 @@ fn doAThing(optional_foo: ?*Foo) void {
37553783 cannot be null.
37563784 </p>
37573785 {#header_open|Optional Type#}
3758 <p>An optional is created by putting <code>?</code> in front of a type. You can use compile-time
3786 <p>An optional is created by putting {#syntax#}?{#endsyntax#} in front of a type. You can use compile-time
37593787 reflection to access the child type of an optional:</p>
37603788 {#code_begin|test#}
37613789const assert = @import("std").debug.assert;
......@@ -3774,7 +3802,7 @@ test "optional type" {
37743802 {#header_close#}
37753803 {#header_open|null#}
37763804 <p>
3777 Just like {#link|undefined#}, <code>null</code> has its own type, and the only way to use it is to
3805 Just like {#link|undefined#}, {#syntax#}null{#endsyntax#} has its own type, and the only way to use it is to
37783806 cast it to a different type:
37793807 </p>
37803808 {#code_begin|syntax#}
......@@ -3822,9 +3850,9 @@ test "implicit cast - invoke a type as a function" {
38223850 of the qualifiers, no matter how nested the qualifiers are:
38233851 </p>
38243852 <ul>
3825 <li><code>const</code> - non-const to const is allowed</li>
3826 <li><code>volatile</code> - non-volatile to volatile is allowed</li>
3827 <li><code>align</code> - bigger to smaller alignment is allowed </li>
3853 <li>{#syntax#}const{#endsyntax#} - non-const to const is allowed</li>
3854 <li>{#syntax#}volatile{#endsyntax#} - non-volatile to volatile is allowed</li>
3855 <li>{#syntax#}align{#endsyntax#} - bigger to smaller alignment is allowed </li>
38283856 <li>{#link|error sets|Error Set Type#} to supersets is allowed</li>
38293857 </ul>
38303858 <p>
......@@ -4072,7 +4100,7 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 {
40724100
40734101 {#header_open|void#}
40744102 <p>
4075 <code>void</code> represents a type that has no value. Code that makes use of void values is
4103 {#syntax#}void{#endsyntax#} represents a type that has no value. Code that makes use of void values is
40764104 not included in the final generated code:
40774105 </p>
40784106 {#code_begin|syntax#}
......@@ -4082,7 +4110,7 @@ export fn entry() void {
40824110 x = y;
40834111}
40844112 {#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#},
40864114 even in debug mode. For example, on x86_64:</p>
40874115 <pre><code>0000000000000010 &lt;entry&gt;:
40884116 10: 55 push %rbp
......@@ -4092,9 +4120,9 @@ export fn entry() void {
40924120 <p>These assembly instructions do not have any code associated with the void values -
40934121 they only perform the function call prologue and epilog.</p>
40944122 <p>
4095 <code>void</code> 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>
4097 type to make it into a <code>Set</code>:
4123 {#syntax#}void{#endsyntax#} can be useful for instantiating generic types. For example, given a
4124 {#syntax#}Map(Key, Value){#endsyntax#}, one can pass {#syntax#}void{#endsyntax#} for the {#syntax#}Value{#endsyntax#}
4125 type to make it into a {#syntax#}Set{#endsyntax#}:
40984126 </p>
40994127 {#code_begin|test#}
41004128const std = @import("std");
......@@ -4123,17 +4151,17 @@ fn eql_i32(a: i32, b: i32) bool {
41234151}
41244152 {#code_end#}
41254153 <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, and
4154 By using {#syntax#}void{#endsyntax#} as the type of the value, the hash map entry type has no value field, and
41274155 thus the hash map takes up less space. Further, all the code that deals with storing and loading the
41284156 value is deleted, as seen above.
41294157 </p>
41304158 <p>
4131 <code>void</code> is distinct from <code>c_void</code>, which is defined like this:
4132 <code>pub const c_void = @OpaqueType();</code>.
4133 <code>void</code> has a known size of 0 bytes, and <code>c_void</code> has an unknown, but non-zero, size.
4159 {#syntax#}void{#endsyntax#} is distinct from {#syntax#}c_void{#endsyntax#}, which is defined like this:
4160 {#syntax#}pub const c_void = @OpaqueType();{#endsyntax#}.
4161 {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}c_void{#endsyntax#} has an unknown, but non-zero, size.
41344162 </p>
41354163 <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:
41374165 </p>
41384166 {#code_begin|test_err|expression value is ignored#}
41394167test "ignoring expression value" {
......@@ -4144,7 +4172,7 @@ fn foo() i32 {
41444172 return 1234;
41454173}
41464174 {#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>
41484176 {#code_begin|test#}
41494177test "ignoring expression value" {
41504178 foo();
......@@ -4154,11 +4182,6 @@ fn foo() void {}
41544182 {#code_end#}
41554183 {#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#}
41624185 {#header_open|comptime#}
41634186 <p>
41644187 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 {
41844207 <p>
41854208 In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions,
41864209 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#}.
41884211 </p>
41894212 <p>
4190 A <code>comptime</code> parameter means that:
4213 A {#syntax#}comptime{#endsyntax#} parameter means that:
41914214 </p>
41924215 <ul>
41934216 <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" {
42324255}
42334256 {#code_end#}
42344257 <p>
4235 On the flip side, inside the function definition with the <code>comptime</code> parameter, the
4258 On the flip side, inside the function definition with the {#syntax#}comptime{#endsyntax#} parameter, the
42364259 value is known at compile-time. This means that we actually could make this work for the bool type
42374260 if we wanted to:
42384261 </p>
......@@ -4251,12 +4274,12 @@ test "try to compare bools" {
42514274}
42524275 {#code_end#}
42534276 <p>
4254 This works because Zig implicitly inlines <code>if</code> expressions when the condition
4277 This works because Zig implicitly inlines {#syntax#}if{#endsyntax#} expressions when the condition
42554278 is known at compile-time, and the compiler guarantees that it will skip analysis of
42564279 the branch not taken.
42574280 </p>
42584281 <p>
4259 This means that the actual function generated for <code>max</code> in this situation looks like
4282 This means that the actual function generated for {#syntax#}max{#endsyntax#} in this situation looks like
42604283 this:
42614284 </p>
42624285 {#code_begin|syntax#}
......@@ -4269,18 +4292,18 @@ fn max(a: bool, b: bool) bool {
42694292 the necessary run-time code to accomplish the task.
42704293 </p>
42714294 <p>
4272 This works the same way for <code>switch</code> expressions - they are implicitly inlined
4295 This works the same way for {#syntax#}switch{#endsyntax#} expressions - they are implicitly inlined
42734296 when the target expression is compile-time known.
42744297 </p>
42754298 {#header_close#}
42764299 {#header_open|Compile-Time Variables#}
42774300 <p>
4278 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler
4301 In Zig, the programmer can label variables as {#syntax#}comptime{#endsyntax#}. This guarantees to the compiler
42794302 that every load and store of the variable is performed at compile-time. Any violation of this results in a
42804303 compile error.
42814304 </p>
42824305 <p>
4283 This combined with the fact that we can <code>inline</code> loops allows us to write
4306 This combined with the fact that we can {#syntax#}inline{#endsyntax#} loops allows us to write
42844307 a function which is partially evaluated at compile-time and partially at run-time.
42854308 </p>
42864309 <p>
......@@ -4323,8 +4346,8 @@ test "perform fn" {
43234346 <p>
43244347 This example is a bit contrived, because the compile-time evaluation component is unnecessary;
43254348 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,
4327 for the different values of <code>prefix_char</code> provided:
4349 different code. In this example, the function {#syntax#}performFn{#endsyntax#} is generated three different times,
4350 for the different values of {#syntax#}prefix_char{#endsyntax#} provided:
43284351 </p>
43294352 {#code_begin|syntax#}
43304353// From the line:
......@@ -4365,7 +4388,7 @@ fn performFn(start_value: i32) i32 {
43654388 {#header_open|Compile-Time Expressions#}
43664389 <p>
43674390 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.
43694392 If this cannot be accomplished, the compiler will emit an error. For example:
43704393 </p>
43714394 {#code_begin|test_err|unable to evaluate constant expression#}
......@@ -4378,16 +4401,16 @@ test "foo" {
43784401}
43794402 {#code_end#}
43804403 <p>
4381 It doesn't make sense that a program could call <code>exit()</code> (or any other external function)
4382 at compile-time, so this is a compile error. However, a <code>comptime</code> expression does much
4404 It doesn't make sense that a program could call {#syntax#}exit(){#endsyntax#} (or any other external function)
4405 at compile-time, so this is a compile error. However, a {#syntax#}comptime{#endsyntax#} expression does much
43834406 more than sometimes cause a compile error.
43844407 </p>
43854408 <p>
4386 Within a <code>comptime</code> expression:
4409 Within a {#syntax#}comptime{#endsyntax#} expression:
43874410 </p>
43884411 <ul>
4389 <li>All variables are <code>comptime</code> variables.</li>
4390 <li>All <code>if</code>, <code>while</code>, <code>for</code>, and <code>switch</code>
4412 <li>All variables are {#syntax#}comptime{#endsyntax#} variables.</li>
4413 <li>All {#syntax#}if{#endsyntax#}, {#syntax#}while{#endsyntax#}, {#syntax#}for{#endsyntax#}, and {#syntax#}switch{#endsyntax#}
43914414 expressions are evaluated at compile-time, or emit a compile error if this is not possible.</li>
43924415 <li>All function calls cause the compiler to interpret the function at compile-time, emitting a
43934416 compile error if the function tries to do something that has global run-time side effects.</li>
......@@ -4464,7 +4487,7 @@ test "fibonacci" {
44644487 {#link|@setEvalBranchQuota#} to change the default number 1000 to something else.
44654488 </p>
44664489 <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?
44684491 </p>
44694492 {#code_begin|test_err|encountered @panic at compile-time#}
44704493const assert = @import("std").debug.assert;
......@@ -4481,16 +4504,16 @@ test "fibonacci" {
44814504}
44824505 {#code_end#}
44834506 <p>
4484 What happened is Zig started interpreting the <code>assert</code> function with the
4485 parameter <code>ok</code> set to <code>false</code>. When the interpreter hit
4486 <code>unreachable</code> it emitted a compile error, because reaching unreachable
4507 What happened is Zig started interpreting the {#syntax#}assert{#endsyntax#} function with the
4508 parameter {#syntax#}ok{#endsyntax#} set to {#syntax#}false{#endsyntax#}. When the interpreter hit
4509 {#syntax#}unreachable{#endsyntax#} it emitted a compile error, because reaching unreachable
44874510 code is undefined behavior, and undefined behavior causes a compile error if it is detected
44884511 at compile-time.
44894512 </p>
44904513
44914514 <p>
44924515 In the global scope (outside of any function), all expressions are implicitly
4493 <code>comptime</code> expressions. This means that we can use functions to
4516 {#syntax#}comptime{#endsyntax#} expressions. This means that we can use functions to
44944517 initialize complex static data. For example:
44954518 </p>
44964519 {#code_begin|test#}
......@@ -4538,7 +4561,7 @@ test "variable values" {
45384561@1 = internal unnamed_addr constant i32 1060</code></pre>
45394562 <p>
45404563 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 were
4564 we could call the {#syntax#}sum{#endsyntax#} function as is with a slice of numbers whose length and values were
45424565 only known at run-time.
45434566 </p>
45444567 {#header_close#}
......@@ -4550,8 +4573,8 @@ test "variable values" {
45504573 generic data structure.
45514574 </p>
45524575 <p>
4553 Here is an example of a generic <code>List</code> 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>.
4576 Here is an example of a generic {#syntax#}List{#endsyntax#} data structure, that we will instantiate with
4577 the type {#syntax#}i32{#endsyntax#}. In Zig we refer to the type as {#syntax#}List(i32){#endsyntax#}.
45554578 </p>
45564579 {#code_begin|syntax#}
45574580fn List(comptime T: type) type {
......@@ -4562,8 +4585,8 @@ fn List(comptime T: type) type {
45624585}
45634586 {#code_end#}
45644587 <p>
4565 That's it. It's a function that returns an anonymous <code>struct</code>. 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 creating
4588 That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. For the purposes of error messages
4589 and debugging, Zig infers the name {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating
45674590 the anonymous struct.
45684591 </p>
45694592 <p>
......@@ -4579,13 +4602,13 @@ const Node = struct {
45794602 <p>
45804603 This works because all top level declarations are order-independent, and as long as there isn't
45814604 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, so
4605 {#syntax#}Node{#endsyntax#} refers to itself as a pointer, which is not actually an infinite regression, so
45834606 it works fine.
45844607 </p>
45854608 {#header_close#}
45864609 {#header_open|Case Study: printf in Zig#}
45874610 <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.
45894612 </p>
45904613 {#code_begin|exe|printf#}
45914614const warn = @import("std").debug.warn;
......@@ -4686,7 +4709,7 @@ pub fn printf(self: *OutStream, arg0: i32, arg1: []const u8) !void {
46864709}
46874710 {#code_end#}
46884711 <p>
4689 <code>printValue</code> is a function that takes a parameter of any type, and does different things depending
4712 {#syntax#}printValue{#endsyntax#} is a function that takes a parameter of any type, and does different things depending
46904713 on the type:
46914714 </p>
46924715 {#code_begin|syntax#}
......@@ -4702,7 +4725,7 @@ pub fn printValue(self: *OutStream, value: var) !void {
47024725}
47034726 {#code_end#}
47044727 <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#}?
47064729 </p>
47074730 {#code_begin|test_err|Unused arguments#}
47084731const warn = @import("std").debug.warn;
......@@ -4720,7 +4743,7 @@ test "printf too many arguments" {
47204743 </p>
47214744 <p>
47224745 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#}:
47244747 </p>
47254748 {#code_begin|exe|printf#}
47264749const warn = @import("std").debug.warn;
......@@ -4774,16 +4797,16 @@ pub fn main() void {
47744797 </p>
47754798 {#header_open|Minimal Coroutine Example#}
47764799 <p>
4777 Declare a coroutine with the <code>async</code> keyword.
4800 Declare a coroutine with the {#syntax#}async{#endsyntax#} keyword.
47784801 The expression in angle brackets must evaluate to a struct
47794802 which has these fields:
47804803 </p>
47814804 <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>
4783 <li><code>freeFn: fn (self: *Allocator, old_mem: []u8) void</code></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>
4806 <li>{#syntax#}freeFn: fn (self: *Allocator, old_mem: []u8) void{#endsyntax#}</li>
47844807 </ul>
47854808 <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.
47874810 This makes it convenient to integrate with existing allocators. Note, however,
47884811 that the language feature does not depend on the standard library, and any struct which
47894812 has these fields is allowed.
......@@ -4793,13 +4816,13 @@ pub fn main() void {
47934816 the function generic. Zig will infer the allocator type when the async function is called.
47944817 </p>
47954818 <p>
4796 Call a coroutine with the <code>async</code> keyword. Here, the expression in angle brackets
4819 Call a coroutine with the {#syntax#}async{#endsyntax#} keyword. Here, the expression in angle brackets
47974820 is a pointer to the allocator struct that the coroutine expects.
47984821 </p>
47994822 <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#}
48014824 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#}:
48034826 </p>
48044827 <p>
48054828 Async functions start executing when created, so in the following example, the entire
......@@ -4888,18 +4911,18 @@ async fn testSuspendBlock() void {
48884911 {#code_end#}
48894912 <p>
48904913 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 in
4892 scope are run, as well as <code>errdefer</code> expressions.
4914 could be destroyed. If that happens, {#syntax#}defer{#endsyntax#} expressions that are in
4915 scope are run, as well as {#syntax#}errdefer{#endsyntax#} expressions.
48934916 </p>
48944917 <p>
48954918 {#link|Await#} counts as a suspend point.
48964919 </p>
48974920 {#header_open|Resuming from Suspend Blocks#}
48984921 <p>
4899 Upon entering a <code>suspend</code> block, the coroutine is already considered
4922 Upon entering a {#syntax#}suspend{#endsyntax#} block, the coroutine is already considered
49004923 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 the
4902 <code>suspend</code> block, the new thread would begin executing after the suspend
4924 and had that thread call {#syntax#}resume{#endsyntax#} on the promise handle provided by the
4925 {#syntax#}suspend{#endsyntax#} block, the new thread would begin executing after the suspend
49034926 block, while the old thread continued executing the suspend block.
49044927 </p>
49054928 <p>
......@@ -4934,26 +4957,26 @@ async fn testResumeFromSuspend(my_result: *i32) void {
49344957 {#header_close#}
49354958 {#header_open|Await#}
49364959 <p>
4937 The <code>await</code> keyword is used to coordinate with an async function's
4938 <code>return</code> statement.
4960 The {#syntax#}await{#endsyntax#} keyword is used to coordinate with an async function's
4961 {#syntax#}return{#endsyntax#} statement.
49394962 </p>
49404963 <p>
4941 <code>await</code> is valid only in an <code>async</code> function, and it takes
4964 {#syntax#}await{#endsyntax#} is valid only in an {#syntax#}async{#endsyntax#} function, and it takes
49424965 as an operand a promise handle.
49434966 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.
4945 Otherwise, <code>await</code> suspends the current async function, registering its
4967 then {#syntax#}await{#endsyntax#} destroys the target async function, and gives the return value.
4968 Otherwise, {#syntax#}await{#endsyntax#} suspends the current async function, registering its
49464969 promise handle with the target coroutine. It becomes the target coroutine's responsibility
49474970 to have ensured that it will be resumed or destroyed. When the target coroutine reaches
49484971 its return statement, it gives the return value to the awaiter, destroys itself, and then
49494972 resumes the awaiter.
49504973 </p>
49514974 <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#}.
49534976 </p>
49544977 <p>
4955 <code>await</code> counts as a suspend point, and therefore at every <code>await</code>,
4956 a coroutine can be potentially destroyed, which would run <code>defer</code> and <code>errdefer</code> expressions.
4978 {#syntax#}await{#endsyntax#} counts as a suspend point, and therefore at every {#syntax#}await{#endsyntax#},
4979 a coroutine can be potentially destroyed, which would run {#syntax#}defer{#endsyntax#} and {#syntax#}errdefer{#endsyntax#} expressions.
49574980 </p>
49584981 {#code_begin|test#}
49594982const std = @import("std");
......@@ -4997,9 +5020,9 @@ fn seq(c: u8) void {
49975020}
49985021 {#code_end#}
49995022 <p>
5000 In general, <code>suspend</code> is lower level than <code>await</code>. Most application
5001 code will use only <code>async</code> and <code>await</code>, but event loop
5002 implementations will make use of <code>suspend</code> internally.
5023 In general, {#syntax#}suspend{#endsyntax#} is lower level than {#syntax#}await{#endsyntax#}. Most application
5024 code will use only {#syntax#}async{#endsyntax#} and {#syntax#}await{#endsyntax#}, but event loop
5025 implementations will make use of {#syntax#}suspend{#endsyntax#} internally.
50035026 </p>
50045027 {#header_close#}
50055028 {#header_open|Open Issues#}
......@@ -5029,36 +5052,36 @@ fn seq(c: u8) void {
50295052 {#header_open|Builtin Functions#}
50305053 <p>
50315054 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 known
5055 The {#syntax#}comptime{#endsyntax#} keyword on a parameter means that the parameter must be known
50335056 at compile time.
50345057 </p>
50355058 {#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>
50375060 <p>
5038 Performs <code>result.* = a + b</code>. If overflow or underflow occurs,
5039 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
5040 If no overflow or underflow occurs, returns <code>false</code>.
5061 Performs {#syntax#}result.* = a + b{#endsyntax#}. If overflow or underflow occurs,
5062 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
5063 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
50415064 </p>
50425065 {#header_close#}
50435066 {#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>
50455068 <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#}.
50475070 </p>
50485071 <p>
5049 <code>T</code> must be a function type.
5072 {#syntax#}T{#endsyntax#} must be a function type.
50505073 </p>
50515074 <p>
50525075 Note: This function is deprecated. Use {#link|@typeInfo#} instead.
50535076 </p>
50545077 {#header_close#}
50555078 {#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>
50575080 <p>
50585081 This builtin function atomically dereferences a pointer and returns the value.
50595082 </p>
50605083 <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#},
50625085 or an integer whose bit count meets these requirements:
50635086 </p>
50645087 <ul>
......@@ -5072,12 +5095,12 @@ fn seq(c: u8) void {
50725095 </p>
50735096 {#header_close#}
50745097 {#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>
50765099 <p>
50775100 This builtin function atomically modifies memory and then returns the previous value.
50785101 </p>
50795102 <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#},
50815104 or an integer whose bit count meets these requirements:
50825105 </p>
50835106 <ul>
......@@ -5091,29 +5114,29 @@ fn seq(c: u8) void {
50915114 </p>
50925115 {#header_close#}
50935116 {#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>
50955118 <p>
50965119 Converts a value of one type to another type.
50975120 </p>
50985121 <p>
5099 Asserts that <code>@sizeOf(@typeOf(value)) == @sizeOf(DestType)</code>.
5122 Asserts that {#syntax#}@sizeOf(@typeOf(value)) == @sizeOf(DestType){#endsyntax#}.
51005123 </p>
51015124 <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.
51035126 </p>
51045127 <p>
51055128 Can be used for these things for example:
51065129 </p>
51075130 <ul>
5108 <li>Convert <code>f32</code> to <code>u32</code> bits</li>
5109 <li>Convert <code>i32</code> to <code>u32</code> preserving twos complement</li>
5131 <li>Convert {#syntax#}f32{#endsyntax#} to {#syntax#}u32{#endsyntax#} bits</li>
5132 <li>Convert {#syntax#}i32{#endsyntax#} to {#syntax#}u32{#endsyntax#} preserving twos complement</li>
51105133 </ul>
51115134 <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.
51135136 </p>
51145137 {#header_close#}
51155138 {#header_open|@breakpoint#}
5116 <pre><code class="zig">@breakpoint()</code></pre>
5139 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
51175140 <p>
51185141 This function inserts a platform-specific debug trap instruction which causes
51195142 debuggers to break there.
......@@ -5124,10 +5147,10 @@ fn seq(c: u8) void {
51245147
51255148 {#header_close#}
51265149 {#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>
51285151 <p>
5129 <code>ptr</code> can be <code>*T</code>, <code>fn()</code>, <code>?*T</code>,
5130 <code>?fn()</code>, or <code>[]T</code>. It returns the same type as <code>ptr</code>
5152 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5153 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
51315154 except with the alignment adjusted to the new value.
51325155 </p>
51335156 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
......@@ -5135,16 +5158,16 @@ fn seq(c: u8) void {
51355158
51365159 {#header_close#}
51375160 {#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>
51395162 <p>
51405163 This function returns the number of bytes that this type should be aligned to
51415164 for the current target to match the C ABI. When the child type of a pointer has
51425165 this alignment, the alignment can be omitted from the type.
51435166 </p>
5144 <pre><code class="zig">const assert = @import("std").debug.assert;
5167 <pre>{#syntax#}const assert = @import("std").debug.assert;
51455168comptime {
51465169 assert(*u32 == *align(@alignOf(u32)) u32);
5147}</code></pre>
5170}{#endsyntax#}</pre>
51485171 <p>
51495172 The result is a target-specific compile time constant. It is guaranteed to be
51505173 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
......@@ -5153,21 +5176,21 @@ comptime {
51535176 {#header_close#}
51545177
51555178 {#header_open|@boolToInt#}
5156 <pre><code class="zig">@boolToInt(value: bool) u1</code></pre>
5179 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
51575180 <p>
5158 Converts <code>true</code> to <code>u1(1)</code> and <code>false</code> to
5159 <code>u1(0)</code>.
5181 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5182 {#syntax#}u1(0){#endsyntax#}.
51605183 </p>
51615184 <p>
5162 If the value is known at compile-time, the return type is <code>comptime_int</code>
5163 instead of <code>u1</code>.
5185 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
5186 instead of {#syntax#}u1{#endsyntax#}.
51645187 </p>
51655188 {#header_close#}
51665189
51675190 {#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>
51695192 <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#}.
51715194 The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.
51725195 </p>
51735196 <p>
......@@ -5177,12 +5200,12 @@ comptime {
51775200 {#header_close#}
51785201
51795202 {#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>
51815204 <p>
5182 This function can only occur inside <code>@cImport</code>.
5205 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
51835206 </p>
51845207 <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#}
51865209 temporary buffer.
51875210 </p>
51885211 <p>
......@@ -5192,72 +5215,72 @@ comptime {
51925215 <p>
51935216 Use the void value, like this:
51945217 </p>
5195 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>
5218 <pre>{#syntax#}@cDefine("_GNU_SOURCE", {}){#endsyntax#}</pre>
51965219 {#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}
51975220 {#header_close#}
51985221 {#header_open|@cImport#}
5199 <pre><code class="zig">@cImport(expression) (namespace)</code></pre>
5222 <pre>{#syntax#}@cImport(expression) (namespace){#endsyntax#}</pre>
52005223 <p>
52015224 This function parses C code and imports the functions, types, variables, and
52025225 compatible macro definitions into the result namespace.
52035226 </p>
52045227 <p>
5205 <code>expression</code> is interpreted at compile time. The builtin functions
5206 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work
5228 {#syntax#}expression{#endsyntax#} is interpreted at compile time. The builtin functions
5229 {#syntax#}@cInclude{#endsyntax#}, {#syntax#}@cDefine{#endsyntax#}, and {#syntax#}@cUndef{#endsyntax#} work
52075230 within this expression, appending to a temporary buffer which is then parsed as C code.
52085231 </p>
52095232 <p>
5210 Usually you should only have one <code>@cImport</code> in your entire application, because it saves the compiler
5233 Usually you should only have one {#syntax#}@cImport{#endsyntax#} in your entire application, because it saves the compiler
52115234 from invoking clang multiple times, and prevents inline functions from being duplicated.
52125235 </p>
52135236 <p>
5214 Reasons for having multiple <code>@cImport</code> expressions would be:
5237 Reasons for having multiple {#syntax#}@cImport{#endsyntax#} expressions would be:
52155238 </p>
52165239 <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>
52185241 <li>To analyze the C code with different preprocessor defines</li>
52195242 </ul>
52205243 {#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
52215244 {#header_close#}
52225245 {#header_open|@cInclude#}
5223 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>
5246 <pre>{#syntax#}@cInclude(comptime path: []u8){#endsyntax#}</pre>
52245247 <p>
5225 This function can only occur inside <code>@cImport</code>.
5248 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
52265249 </p>
52275250 <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#}
52295252 temporary buffer.
52305253 </p>
52315254 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
52325255 {#header_close#}
52335256 {#header_open|@cUndef#}
5234 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>
5257 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
52355258 <p>
5236 This function can only occur inside <code>@cImport</code>.
5259 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
52375260 </p>
52385261 <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#}
52405263 temporary buffer.
52415264 </p>
52425265 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
52435266 {#header_close#}
52445267 {#header_open|@clz#}
5245 <pre><code class="zig">@clz(x: T) U</code></pre>
5268 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
52465269 <p>
5247 This function counts the number of leading zeroes in <code>x</code> which is an integer
5248 type <code>T</code>.
5270 This function counts the number of leading zeroes in {#syntax#}x{#endsyntax#} which is an integer
5271 type {#syntax#}T{#endsyntax#}.
52495272 </p>
52505273 <p>
5251 The return type <code>U</code> is an unsigned integer with the minimum number
5252 of bits that can represent the value <code>T.bit_count</code>.
5274 The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
5275 of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
52535276 </p>
52545277 <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#}.
52565279 </p>
52575280 {#see_also|@ctz|@popCount#}
52585281 {#header_close#}
52595282 {#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>
52615284 <p>
52625285 This function performs a strong atomic compare exchange operation. It's the equivalent of this code,
52635286 except atomic:
......@@ -5278,13 +5301,13 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
52785301 more efficiently in machine instructions.
52795302 </p>
52805303 <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#}.
52825305 </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>
52845307 {#see_also|Compile Variables|cmpxchgWeak#}
52855308 {#header_close#}
52865309 {#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>
52885311 <p>
52895312 This function performs a weak atomic compare exchange operation. It's the equivalent of this code,
52905313 except atomic:
......@@ -5301,30 +5324,30 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
53015324}
53025325 {#code_end#}
53035326 <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#}
53055328 is the better choice, because it can be implemented more efficiently in machine instructions.
53065329 However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
53075330 </p>
53085331 <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#}.
53105333 </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>
53125335 {#see_also|Compile Variables|cmpxchgStrong#}
53135336 {#header_close#}
53145337 {#header_open|@compileError#}
5315 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>
5338 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
53165339 <p>
53175340 This function, when semantically analyzed, causes a compile error with the
5318 message <code>msg</code>.
5341 message {#syntax#}msg{#endsyntax#}.
53195342 </p>
53205343 <p>
53215344 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,
5323 and <code>comptime</code> functions.
5345 using {#syntax#}if{#endsyntax#} or {#syntax#}switch{#endsyntax#} with compile time constants,
5346 and {#syntax#}comptime{#endsyntax#} functions.
53245347 </p>
53255348 {#header_close#}
53265349 {#header_open|@compileLog#}
5327 <pre><code class="zig">@compileLog(args: ...)</code></pre>
5350 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
53285351 <p>
53295352 This function prints the arguments passed to it at compile-time.
53305353 </p>
......@@ -5359,7 +5382,7 @@ test "main" {
53595382 will ouput:
53605383 </p>
53615384 <p>
5362 If all <code>@compileLog</code> calls are removed or
5385 If all {#syntax#}@compileLog{#endsyntax#} calls are removed or
53635386 not encountered by analysis, the
53645387 program compiles successfully and the generated executable prints:
53655388 </p>
......@@ -5378,84 +5401,88 @@ test "main" {
53785401 {#code_end#}
53795402 {#header_close#}
53805403 {#header_open|@ctz#}
5381 <pre><code class="zig">@ctz(x: T) U</code></pre>
5404 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
53825405 <p>
5383 This function counts the number of trailing zeroes in <code>x</code> which is an integer
5384 type <code>T</code>.
5406 This function counts the number of trailing zeroes in {#syntax#}x{#endsyntax#} which is an integer
5407 type {#syntax#}T{#endsyntax#}.
53855408 </p>
53865409 <p>
5387 The return type <code>U</code> is an unsigned integer with the minimum number
5388 of bits that can represent the value <code>T.bit_count</code>.
5410 The return type {#syntax#}U{#endsyntax#} is an unsigned integer with the minimum number
5411 of bits that can represent the value {#syntax#}T.bit_count{#endsyntax#}.
53895412 </p>
53905413 <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#}.
53925415 </p>
53935416 {#see_also|@clz|@popCount#}
53945417 {#header_close#}
53955418 {#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>
53975420 <p>
5398 Exact division. Caller guarantees <code>denominator != 0</code> and
5399 <code>@divTrunc(numerator, denominator) * denominator == numerator</code>.
5421 Exact division. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5422 {#syntax#}@divTrunc(numerator, denominator) * denominator == numerator{#endsyntax#}.
54005423 </p>
54015424 <ul>
5402 <li><code>@divExact(6, 3) == 2</code></li>
5403 <li><code>@divExact(a, b) * b == a</code></li>
5425 <li>{#syntax#}@divExact(6, 3) == 2{#endsyntax#}</li>
5426 <li>{#syntax#}@divExact(a, b) * b == a{#endsyntax#}</li>
54045427 </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>
54065429 {#see_also|@divTrunc|@divFloor#}
54075430 {#header_close#}
54085431 {#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>
54105433 <p>
54115434 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> and
5413 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.
5435 the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5436 {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1){#endsyntax#}.
54145437 </p>
54155438 <ul>
5416 <li><code>@divFloor(-5, 3) == -2</code></li>
5417 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
5439 <li>{#syntax#}@divFloor(-5, 3) == -2{#endsyntax#}</li>
5440 <li>{#syntax#}@divFloor(a, b) + @mod(a, b) == a{#endsyntax#}</li>
54185441 </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>
54205443 {#see_also|@divTrunc|@divExact#}
54215444 {#header_close#}
54225445 {#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>
54245447 <p>
54255448 Truncated division. Rounds toward zero. For unsigned integers it is
5426 the same as <code>numerator / denominator</code>. Caller guarantees <code>denominator != 0</code> and
5427 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.
5449 the same as {#syntax#}numerator / denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator != 0{#endsyntax#} and
5450 {#syntax#}!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1){#endsyntax#}.
54285451 </p>
54295452 <ul>
5430 <li><code>@divTrunc(-5, 3) == -1</code></li>
5431 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
5453 <li>{#syntax#}@divTrunc(-5, 3) == -1{#endsyntax#}</li>
5454 <li>{#syntax#}@divTrunc(a, b) + @rem(a, b) == a{#endsyntax#}</li>
54325455 </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>
54345457 {#see_also|@divFloor|@divExact#}
54355458 {#header_close#}
54365459 {#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>
54385461 <p>
54395462 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 array
5463 equal to the byte count of the file given by {#syntax#}path{#endsyntax#}. The contents of the array
54415464 are the contents of the file.
54425465 </p>
54435466 <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#}.
54455468 </p>
54465469 {#see_also|@import#}
54475470 {#header_close#}
54485471
54495472 {#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>
54515474 <p>
54525475 Converts an enumeration value into its integer tag type.
54535476 </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>
54545481 {#see_also|@intToEnum#}
54555482 {#header_close#}
54565483
54575484 {#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>
54595486 <p>
54605487 Converts an error value from one error set to another error set. Attempting to convert an error
54615488 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
......@@ -5463,24 +5490,24 @@ test "main" {
54635490 {#header_close#}
54645491
54655492 {#header_open|@errorName#}
5466 <pre><code class="zig">@errorName(err: error) []u8</code></pre>
5493 <pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre>
54675494 <p>
54685495 This function returns the string representation of an error. If an error
54695496 declaration is:
54705497 </p>
5471 <pre><code class="zig">error OutOfMem</code></pre>
5498 <pre>{#syntax#}error OutOfMem{#endsyntax#}</pre>
54725499 <p>
5473 Then the string representation is <code>"OutOfMem"</code>.
5500 Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}.
54745501 </p>
54755502 <p>
5476 If there are no calls to <code>@errorName</code> in an entire application,
5477 or all calls have a compile-time known value for <code>err</code>, then no
5503 If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,
5504 or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no
54785505 error name table will be generated.
54795506 </p>
54805507 {#header_close#}
54815508
54825509 {#header_open|@errorReturnTrace#}
5483 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>
5510 <pre>{#syntax#}@errorReturnTrace() ?*builtin.StackTrace{#endsyntax#}</pre>
54845511 <p>
54855512 If the binary is built with error return tracing, and this function is invoked in a
54865513 function that calls a function with an error or error union return type, returns a
......@@ -5489,13 +5516,13 @@ test "main" {
54895516 {#header_close#}
54905517
54915518 {#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>
54935520 <p>
54945521 Supports the following types:
54955522 </p>
54965523 <ul>
54975524 <li>error unions</li>
5498 <li><code>E!void</code></li>
5525 <li>{#syntax#}E!void{#endsyntax#}</li>
54995526 </ul>
55005527 <p>
55015528 Converts an error to the integer representation of an error.
......@@ -5508,38 +5535,41 @@ test "main" {
55085535 {#header_close#}
55095536
55105537 {#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>
55125539 <p>
55135540 Creates a symbol in the output object file.
55145541 </p>
55155542 {#header_close#}
55165543
55175544 {#header_open|@fence#}
5518 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
5545 <pre>{#syntax#}@fence(order: AtomicOrder){#endsyntax#}</pre>
55195546 <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.
55215548 </p>
55225549 <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#}.
55245551 </p>
55255552 {#see_also|Compile Variables#}
55265553 {#header_close#}
55275554
55285555 {#header_open|@field#}
5529 <pre><code class="zig">@field(lhs: var, comptime field_name: []const u8) (field)</code></pre>
5530 <p>Preforms field access equivalent to <code>lhs.-&gtfield_name-&lt</code>.</p>
5556 <pre>{#syntax#}@field(lhs: var, comptime field_name: []const u8) (field){#endsyntax#}</pre>
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>
55315561 {#header_close#}
55325562
55335563 {#header_open|@fieldParentPtr#}
5534 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
5535 field_ptr: *T) *ParentType</code></pre>
5564 <pre>{#syntax#}@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
5565 field_ptr: *T) *ParentType{#endsyntax#}</pre>
55365566 <p>
55375567 Given a pointer to a field, returns the base pointer of a struct.
55385568 </p>
55395569 {#header_close#}
55405570
55415571 {#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>
55435573 <p>
55445574 Convert from one float type to another. This cast is safe, but may cause the
55455575 numeric value to lose precision.
......@@ -5547,7 +5577,7 @@ test "main" {
55475577 {#header_close#}
55485578
55495579 {#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>
55515581 <p>
55525582 Converts the integer part of a floating point number to the destination type.
55535583 </p>
......@@ -5559,7 +5589,7 @@ test "main" {
55595589 {#header_close#}
55605590
55615591 {#header_open|@frameAddress#}
5562 <pre><code class="zig">@frameAddress()</code></pre>
5592 <pre>{#syntax#}@frameAddress(){#endsyntax#}</pre>
55635593 <p>
55645594 This function returns the base pointer of the current stack frame.
55655595 </p>
......@@ -5573,9 +5603,9 @@ test "main" {
55735603 </p>
55745604 {#header_close#}
55755605 {#header_open|@handle#}
5576 <pre><code class="zig">@handle()</code></pre>
5606 <pre>{#syntax#}@handle(){#endsyntax#}</pre>
55775607 <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#}
55795609 is the return type of the async function in scope.
55805610 </p>
55815611 <p>
......@@ -5583,27 +5613,27 @@ test "main" {
55835613 </p>
55845614 {#header_close#}
55855615 {#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>
55875617 <p>
5588 This function finds a zig file corresponding to <code>path</code> and imports all the
5618 This function finds a zig file corresponding to {#syntax#}path{#endsyntax#} and imports all the
55895619 public top level declarations into the resulting namespace.
55905620 </p>
55915621 <p>
5592 <code>path</code> 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>
5622 {#syntax#}path{#endsyntax#} can be a relative or absolute path, or it can be the name of a package.
5623 If it is a relative path, it is relative to the file that contains the {#syntax#}@import{#endsyntax#}
55945624 function call.
55955625 </p>
55965626 <p>
55975627 The following packages are always available:
55985628 </p>
55995629 <ul>
5600 <li><code>@import("std")</code> - Zig Standard Library</li>
5601 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>
5630 <li>{#syntax#}@import("std"){#endsyntax#} - Zig Standard Library</li>
5631 <li>{#syntax#}@import("builtin"){#endsyntax#} - Compiler-provided types and variables</li>
56025632 </ul>
56035633 {#see_also|Compile Variables|@embedFile#}
56045634 {#header_close#}
56055635 {#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>
56075637 <p>
56085638 This calls a function, in the same way that invoking an expression with parentheses does:
56095639 </p>
......@@ -5617,14 +5647,14 @@ test "inline function call" {
56175647fn add(a: i32, b: i32) i32 { return a + b; }
56185648 {#code_end#}
56195649 <p>
5620 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
5650 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
56215651 will be inlined. If the call cannot be inlined, a compile error is emitted.
56225652 </p>
56235653 {#see_also|@noInlineCall#}
56245654 {#header_close#}
56255655
56265656 {#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>
56285658 <p>
56295659 Converts an integer to another integer while keeping the same numerical value.
56305660 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; }
56335663 {#header_close#}
56345664
56355665 {#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>
56375667 <p>
56385668 Converts an integer into an {#link|enum#} value.
56395669 </p>
......@@ -5645,7 +5675,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
56455675 {#header_close#}
56465676
56475677 {#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>
56495679 <p>
56505680 Converts from the integer representation of an error into the global error set type.
56515681 </p>
......@@ -5661,36 +5691,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }
56615691 {#header_close#}
56625692
56635693 {#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>
56655695 <p>
56665696 Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.
56675697 </p>
56685698 {#header_close#}
56695699
56705700 {#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>
56725702 <p>
56735703 Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.
56745704 </p>
56755705 {#header_close#}
56765706
56775707 {#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>
56795709 <p>
56805710 This function returns an integer type with the given signness and bit count.
56815711 </p>
56825712 {#header_close#}
56835713 {#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>
56855715 <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#}.
56875717 </p>
56885718 <p>
56895719 The result is a compile time constant.
56905720 </p>
56915721 {#header_close#}
56925722 {#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>
56945724 <p>
56955725 This function returns the number of members in a struct, enum, or union type.
56965726 </p>
......@@ -5702,7 +5732,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
57025732 </p>
57035733 {#header_close#}
57045734 {#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>
57065736 <p>Returns the field name of a struct, union, or enum.</p>
57075737 <p>
57085738 The result is a compile time constant.
......@@ -5712,46 +5742,46 @@ fn add(a: i32, b: i32) i32 { return a + b; }
57125742 </p>
57135743 {#header_close#}
57145744 {#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>
57165746 <p>Returns the field type of a struct or union.</p>
57175747 {#header_close#}
57185748 {#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>
57205750 <p>
5721 This function copies bytes from one region of memory to another. <code>dest</code> and
5722 <code>source</code> are both pointers and must not overlap.
5751 This function copies bytes from one region of memory to another. {#syntax#}dest{#endsyntax#} and
5752 {#syntax#}source{#endsyntax#} are both pointers and must not overlap.
57235753 </p>
57245754 <p>
57255755 This function is a low level intrinsic with no safety mechanisms. Most code
57265756 should not use this function, instead using something like this:
57275757 </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>
57295759 <p>
57305760 The optimizer is intelligent enough to turn the above snippet into a memcpy.
57315761 </p>
57325762 <p>There is also a standard library function for this:</p>
5733 <pre><code class="zig">const mem = @import("std").mem;
5734mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
5763 <pre>{#syntax#}const mem = @import("std").mem;
5764mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
57355765 {#header_close#}
57365766 {#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>
57385768 <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.
57405770 </p>
57415771 <p>
57425772 This function is a low level intrinsic with no safety mechanisms. Most
57435773 code should not use this function, instead using something like this:
57445774 </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>
57465776 <p>
57475777 The optimizer is intelligent enough to turn the above snippet into a memset.
57485778 </p>
57495779 <p>There is also a standard library function for this:</p>
5750 <pre><code>const mem = @import("std").mem;
5751mem.set(u8, dest, c);</code></pre>
5780 <pre>{#syntax#}const mem = @import("std").mem;
5781mem.set(u8, dest, c);{#endsyntax#}</pre>
57525782 {#header_close#}
57535783 {#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>
57555785 <p>
57565786 This function returns the minimum value of the integer type T.
57575787 </p>
......@@ -5760,31 +5790,31 @@ mem.set(u8, dest, c);</code></pre>
57605790 </p>
57615791 {#header_close#}
57625792 {#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>
57645794 <p>
57655795 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#}.
57675797 </p>
57685798 <ul>
5769 <li><code>@mod(-5, 3) == 1</code></li>
5770 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
5799 <li>{#syntax#}@mod(-5, 3) == 1{#endsyntax#}</li>
5800 <li>{#syntax#}@divFloor(a, b) + @mod(a, b) == a{#endsyntax#}</li>
57715801 </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>
57735803 {#see_also|@rem#}
57745804 {#header_close#}
57755805 {#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>
57775807 <p>
5778 Performs <code>result.* = a * b</code>. If overflow or underflow occurs,
5779 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
5780 If no overflow or underflow occurs, returns <code>false</code>.
5808 Performs {#syntax#}result.* = a * b{#endsyntax#}. If overflow or underflow occurs,
5809 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
5810 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
57815811 </p>
57825812 {#header_close#}
57835813 {#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>
57855815 <p>
57865816 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#}
57885818 parameter.
57895819 </p>
57905820 {#code_begin|test#}
......@@ -5817,7 +5847,7 @@ fn targetFunction(x: i32) usize {
58175847 {#code_end#}
58185848 {#header_close#}
58195849 {#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>
58215851 <p>
58225852 This calls a function, in the same way that invoking an expression with parentheses does:
58235853 </p>
......@@ -5833,19 +5863,19 @@ fn add(a: i32, b: i32) i32 {
58335863}
58345864 {#code_end#}
58355865 <p>
5836 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call
5866 Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
58375867 will not be inlined. If the call must be inlined, a compile error is emitted.
58385868 </p>
58395869 {#see_also|@inlineCall#}
58405870 {#header_close#}
58415871 {#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>
58435873 <p>
58445874 This function returns the byte offset of a field relative to its containing struct.
58455875 </p>
58465876 {#header_close#}
58475877 {#header_open|@OpaqueType#}
5848 <pre><code class="zig">@OpaqueType() type</code></pre>
5878 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
58495879 <p>
58505880 Creates a new type with an unknown size and alignment.
58515881 </p>
......@@ -5868,14 +5898,14 @@ test "call foo" {
58685898 {#code_end#}
58695899 {#header_close#}
58705900 {#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>
58725902 <p>
58735903 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, or
5875 if there is not one specified, invokes the one provided in <code>std/special/panic.zig</code>.
5904 calls the public {#syntax#}panic{#endsyntax#} function exposed in the root source file, or
5905 if there is not one specified, invokes the one provided in {#syntax#}std/special/panic.zig{#endsyntax#}.
58765906 </p>
5877 <p>Generally it is better to use <code>@import("std").debug.panic</code>.
5878 However, <code>@panic</code> can be useful for 2 scenarios:
5907 <p>Generally it is better to use {#syntax#}@import("std").debug.panic{#endsyntax#}.
5908 However, {#syntax#}@panic{#endsyntax#} can be useful for 2 scenarios:
58795909 </p>
58805910 <ul>
58815911 <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" {
58845914 {#see_also|Root Source File#}
58855915 {#header_close#}
58865916 {#header_open|@popCount#}
5887 <pre><code class="zig">@popCount(integer: var) var</code></pre>
5917 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
58885918 <p>Counts the number of bits set in an integer.</p>
58895919 <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#}.
58915921 Otherwise, the return type is an unsigned integer with the minimum number
58925922 of bits that can represent the bit count of the integer type.
58935923 </p>
58945924 {#see_also|@ctz|@clz#}
58955925 {#header_close#}
58965926 {#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>
58985928 <p>
58995929 Converts a pointer of one type to a pointer of another type.
59005930 </p>
59015931 {#header_close#}
59025932 {#header_open|@ptrToInt#}
5903 <pre><code class="zig">@ptrToInt(value: var) usize</code></pre>
5933 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
59045934 <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:
59065936 </p>
59075937 <ul>
5908 <li><code>*T</code></li>
5909 <li><code>?*T</code></li>
5910 <li><code>fn()</code></li>
5911 <li><code>?fn()</code></li>
5938 <li>{#syntax#}*T{#endsyntax#}</li>
5939 <li>{#syntax#}?*T{#endsyntax#}</li>
5940 <li>{#syntax#}fn(){#endsyntax#}</li>
5941 <li>{#syntax#}?fn(){#endsyntax#}</li>
59125942 </ul>
59135943 <p>To convert the other way, use {#link|@intToPtr#}</p>
59145944
59155945 {#header_close#}
59165946 {#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>
59185948 <p>
59195949 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#}.
59215951 </p>
59225952 <ul>
5923 <li><code>@rem(-5, 3) == -2</code></li>
5924 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
5953 <li>{#syntax#}@rem(-5, 3) == -2{#endsyntax#}</li>
5954 <li>{#syntax#}@divTrunc(a, b) + @rem(a, b) == a{#endsyntax#}</li>
59255955 </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>
59275957 {#see_also|@mod#}
59285958 {#header_close#}
59295959 {#header_open|@returnAddress#}
5930 <pre><code class="zig">@returnAddress()</code></pre>
5960 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
59315961 <p>
59325962 This function returns a pointer to the return address of the current stack
59335963 frame.
......@@ -5941,32 +5971,32 @@ test "call foo" {
59415971 </p>
59425972 {#header_close#}
59435973 {#header_open|@setAlignStack#}
5944 <pre><code class="zig">@setAlignStack(comptime alignment: u29)</code></pre>
5974 <pre>{#syntax#}@setAlignStack(comptime alignment: u29){#endsyntax#}</pre>
59455975 <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.
59475977 </p>
59485978 {#header_close#}
59495979 {#header_open|@setCold#}
5950 <pre><code class="zig">@setCold(is_cold: bool)</code></pre>
5980 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
59515981 <p>
59525982 Tells the optimizer that a function is rarely called.
59535983 </p>
59545984 {#header_close#}
59555985 {#header_open|@setRuntimeSafety#}
5956 <pre><code class="zig">@setRuntimeSafety(safety_on: bool)</code></pre>
5986 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
59575987 <p>
59585988 Sets whether runtime safety checks are on for the scope that contains the function call.
59595989 </p>
59605990
59615991 {#header_close#}
59625992 {#header_open|@setEvalBranchQuota#}
5963 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>
5993 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
59645994 <p>
59655995 Changes the maximum number of backwards branches that compile-time code
59665996 execution can use before giving up and making a compile error.
59675997 </p>
59685998 <p>
5969 If the <code>new_quota</code> is smaller than the default quota (<code>1000</code>) or
5999 If the {#syntax#}new_quota{#endsyntax#} is smaller than the default quota ({#syntax#}1000{#endsyntax#}) or
59706000 a previously explicitly set quota, it is ignored.
59716001 </p>
59726002 <p>
......@@ -5980,7 +6010,7 @@ test "foo" {
59806010 }
59816011}
59826012 {#code_end#}
5983 <p>Now we use <code class="zig">@setEvalBranchQuota</code>:</p>
6013 <p>Now we use {#syntax#}@setEvalBranchQuota{#endsyntax#}:</p>
59846014 {#code_begin|test#}
59856015test "foo" {
59866016 comptime {
......@@ -5994,19 +6024,22 @@ test "foo" {
59946024 {#see_also|comptime#}
59956025 {#header_close#}
59966026 {#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>
59986028 <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:
60006030 </p>
60016031 {#code_begin|syntax#}
60026032pub const FloatMode = enum {
6003 Optimized,
60046033 Strict,
6034 Optimized,
60056035};
60066036 {#code_end#}
60076037 <ul>
60086038 <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:
60106043 <ul>
60116044 <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>
60126045 <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 {
60176050 </ul>
60186051 This is equivalent to <code>-ffast-math</code> in GCC.
60196052 </li>
6020 <li>
6021 <code>Strict</code> (default) - Floating point operations follow strict IEEE compliance.
6022 </li>
60236053 </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>
60246058 {#see_also|Floating Point Operations#}
60256059 {#header_close#}
60266060 {#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>
60286062 <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#}.
60306064 </p>
60316065 {#see_also|Compile Variables#}
60326066 {#header_close#}
60336067 {#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>
60356069 <p>
6036 Performs the left shift operation (<code>&lt;&lt;</code>). Caller guarantees
6070 Performs the left shift operation ({#syntax#}<<{#endsyntax#}). Caller guarantees
60376071 that the shift will not shift any 1 bits out.
60386072 </p>
60396073 <p>
6040 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
6041 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
6074 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6075 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
60426076 </p>
60436077 {#see_also|@shrExact|@shlWithOverflow#}
60446078 {#header_close#}
60456079 {#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>
60476081 <p>
6048 Performs <code>result.* = a &lt;&lt; b</code>. If overflow or underflow occurs,
6049 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
6050 If no overflow or underflow occurs, returns <code>false</code>.
6082 Performs {#syntax#}result.* = a << b{#endsyntax#}. If overflow or underflow occurs,
6083 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
6084 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
60516085 </p>
60526086 <p>
6053 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
6054 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
6087 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6088 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
60556089 </p>
60566090 {#see_also|@shlExact|@shrExact#}
60576091 {#header_close#}
60586092 {#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>
60606094 <p>
6061 Performs the right shift operation (<code>&gt;&gt;</code>). Caller guarantees
6095 Performs the right shift operation ({#syntax#}>>{#endsyntax#}). Caller guarantees
60626096 that the shift will not shift any 1 bits out.
60636097 </p>
60646098 <p>
6065 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
6066 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
6099 The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
6100 This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
60676101 </p>
60686102 {#see_also|@shlExact|@shlWithOverflow#}
60696103 {#header_close#}
60706104
60716105 {#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>
60736107 <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.
60756109 </p>
60766110 <p>
60776111 The result is a target-specific compile time constant.
......@@ -6079,39 +6113,39 @@ pub const FloatMode = enum {
60796113 {#header_close#}
60806114
60816115 {#header_open|@sliceToBytes#}
6082 <pre><code class="zig">@sliceToBytes(value: var) []u8</code></pre>
6116 <pre>{#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}</pre>
60836117 <p>
6084 Converts a slice or array to a slice of <code>u8</code>. The resulting slice has the same
6118 Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same
60856119 {#link|pointer|Pointers#} properties as the parameter.
60866120 </p>
60876121 {#header_close#}
60886122
60896123 {#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>
60916125 <p>
60926126 Performs the square root of a floating point number. Uses a dedicated hardware instruction
60936127 when available. Currently only supports f32 and f64 at runtime. f128 at runtime is TODO.
60946128 </p>
60956129 <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.
60976131 </p>
60986132 {#header_close#}
60996133 {#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>
61016135 <p>
6102 Performs <code>result.* = a - b</code>. If overflow or underflow occurs,
6103 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
6104 If no overflow or underflow occurs, returns <code>false</code>.
6136 Performs {#syntax#}result.* = a - b{#endsyntax#}. If overflow or underflow occurs,
6137 stores the overflowed bits in {#syntax#}result{#endsyntax#} and returns {#syntax#}true{#endsyntax#}.
6138 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
61056139 </p>
61066140 {#header_close#}
61076141 {#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>
61096143 <p>
61106144 Converts an enum value or union value to a slice of bytes representing the name.
61116145 </p>
61126146 {#header_close#}
61136147 {#header_open|@TagType#}
6114 <pre><code class="zig">@TagType(T: type) type</code></pre>
6148 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
61156149 <p>
61166150 For an enum, returns the integer type that is used to store the enumeration value.
61176151 </p>
......@@ -6119,8 +6153,43 @@ pub const FloatMode = enum {
61196153 For a union, returns the enum type that is used to store the tag value.
61206154 </p>
61216155 {#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#}
61226191 {#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>
61246193 <p>
61256194 This function truncates bits from an integer type, resulting in a smaller
61266195 integer type.
......@@ -6129,14 +6198,14 @@ pub const FloatMode = enum {
61296198 The following produces a crash in debug mode and undefined behavior in
61306199 release mode:
61316200 </p>
6132 <pre><code class="zig">const a: u16 = 0xabcd;
6133const b: u8 = u8(a);</code></pre>
6201 <pre>{#syntax#}const a: u16 = 0xabcd;
6202const b: u8 = u8(a);{#endsyntax#}</pre>
61346203 <p>
61356204 However this is well defined and working code:
61366205 </p>
6137 <pre><code class="zig">const a: u16 = 0xabcd;
6206 <pre>{#syntax#}const a: u16 = 0xabcd;
61386207const b: u8 = @truncate(u8, a);
6139// b is now 0xcd</code></pre>
6208// b is now 0xcd{#endsyntax#}</pre>
61406209 <p>
61416210 This function always truncates the significant bits of the integer, regardless
61426211 of endianness on the target platform.
......@@ -6144,7 +6213,7 @@ const b: u8 = @truncate(u8, a);
61446213
61456214 {#header_close#}
61466215 {#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>
61486217 <p>
61496218 Returns which kind of type something is. Possible values:
61506219 </p>
......@@ -6178,7 +6247,7 @@ pub const TypeId = enum {
61786247 {#code_end#}
61796248 {#header_close#}
61806249 {#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>
61826251 <p>
61836252 Returns information on the type. Returns a value of the following union:
61846253 </p>
......@@ -6361,14 +6430,14 @@ pub const TypeInfo = union(TypeId) {
63616430 {#code_end#}
63626431 {#header_close#}
63636432 {#header_open|@typeName#}
6364 <pre><code class="zig">@typeName(T: type) []u8</code></pre>
6433 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
63656434 <p>
63666435 This function returns the string representation of a type.
63676436 </p>
63686437
63696438 {#header_close#}
63706439 {#header_open|@typeOf#}
6371 <pre><code class="zig">@typeOf(expression) type</code></pre>
6440 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
63726441 <p>
63736442 This function returns a compile-time constant, which is the type of the
63746443 expression passed as an argument. The expression is evaluated.
......@@ -6545,11 +6614,11 @@ pub fn main() void {
65456614 {#header_open|Default Operations#}
65466615 <p>The following operators can cause integer overflow:</p>
65476616 <ul>
6548 <li><code>+</code> (addition)</li>
6549 <li><code>-</code> (subtraction)</li>
6550 <li><code>-</code> (negation)</li>
6551 <li><code>*</code> (multiplication)</li>
6552 <li><code>/</code> (division)</li>
6617 <li>{#syntax#}+{#endsyntax#} (addition)</li>
6618 <li>{#syntax#}-{#endsyntax#} (subtraction)</li>
6619 <li>{#syntax#}-{#endsyntax#} (negation)</li>
6620 <li>{#syntax#}*{#endsyntax#} (multiplication)</li>
6621 <li>{#syntax#}/{#endsyntax#} (division)</li>
65536622 <li>{#link|@divTrunc#} (division)</li>
65546623 <li>{#link|@divFloor#} (division)</li>
65556624 <li>{#link|@divExact#} (division)</li>
......@@ -6575,13 +6644,13 @@ pub fn main() void {
65756644 {#header_open|Standard Library Math Functions#}
65766645 <p>These functions provided by the standard library return possible errors.</p>
65776646 <ul>
6578 <li><code>@import("std").math.add</code></li>
6579 <li><code>@import("std").math.sub</code></li>
6580 <li><code>@import("std").math.mul</code></li>
6581 <li><code>@import("std").math.divTrunc</code></li>
6582 <li><code>@import("std").math.divFloor</code></li>
6583 <li><code>@import("std").math.divExact</code></li>
6584 <li><code>@import("std").math.shl</code></li>
6647 <li>{#syntax#}@import("std").math.add{#endsyntax#}</li>
6648 <li>{#syntax#}@import("std").math.sub{#endsyntax#}</li>
6649 <li>{#syntax#}@import("std").math.mul{#endsyntax#}</li>
6650 <li>{#syntax#}@import("std").math.divTrunc{#endsyntax#}</li>
6651 <li>{#syntax#}@import("std").math.divFloor{#endsyntax#}</li>
6652 <li>{#syntax#}@import("std").math.divExact{#endsyntax#}</li>
6653 <li>{#syntax#}@import("std").math.shl{#endsyntax#}</li>
65856654 </ul>
65866655 <p>Example of catching an overflow for addition:</p>
65876656 {#code_begin|exe_err#}
......@@ -6601,7 +6670,7 @@ pub fn main() !void {
66016670 {#header_close#}
66026671 {#header_open|Builtin Overflow Functions#}
66036672 <p>
6604 These builtins return a <code>bool</code> of whether or not overflow
6673 These builtins return a {#syntax#}bool{#endsyntax#} of whether or not overflow
66056674 occurred, as well as returning the overflowed bits:
66066675 </p>
66076676 <ul>
......@@ -6632,10 +6701,10 @@ pub fn main() void {
66326701 These operations have guaranteed wraparound semantics.
66336702 </p>
66346703 <ul>
6635 <li><code>+%</code> (wraparound addition)</li>
6636 <li><code>-%</code> (wraparound subtraction)</li>
6637 <li><code>-%</code> (wraparound negation)</li>
6638 <li><code>*%</code> (wraparound multiplication)</li>
6704 <li>{#syntax#}+%{#endsyntax#} (wraparound addition)</li>
6705 <li>{#syntax#}-%{#endsyntax#} (wraparound subtraction)</li>
6706 <li>{#syntax#}-%{#endsyntax#} (wraparound negation)</li>
6707 <li>{#syntax#}*%{#endsyntax#} (wraparound multiplication)</li>
66396708 </ul>
66406709 {#code_begin|test#}
66416710const assert = @import("std").debug.assert;
......@@ -6787,7 +6856,7 @@ pub fn main() void {
67876856}
67886857 {#code_end#}
67896858 <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>
67916860 {#code_begin|exe|test#}
67926861const warn = @import("std").debug.warn;
67936862pub fn main() void {
......@@ -6827,7 +6896,7 @@ fn getNumberOrFail() !i32 {
68276896}
68286897 {#code_end#}
68296898 <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>
68316900 {#code_begin|exe#}
68326901const warn = @import("std").debug.warn;
68336902
......@@ -6991,7 +7060,7 @@ fn bar(f: *Foo) void {
69917060}
69927061 {#code_end#}
69937062 <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.
69957064 </p>
69967065 <p>
69977066 To change the active field of a union, assign the entire union, like this:
......@@ -7056,7 +7125,7 @@ fn bar(f: *Foo) void {
70567125 {#header_close#}
70577126 {#header_open|Compile Variables#}
70587127 <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,
70607129 which the compiler makes available to every Zig source file. It contains
70617130 compile-time constants such as the current target, endianness, and release mode.
70627131 </p>
......@@ -7065,7 +7134,7 @@ const builtin = @import("builtin");
70657134const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';
70667135 {#code_end#}
70677136 <p>
7068 Example of what is imported with <code>@import("builtin")</code>:
7137 Example of what is imported with {#syntax#}@import("builtin"){#endsyntax#}:
70697138 </p>
70707139 {#builtin#}
70717140 {#see_also|Build Mode#}
......@@ -7104,16 +7173,16 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';
71047173 These have guaranteed C ABI compatibility and can be used like any other type.
71057174 </p>
71067175 <ul>
7107 <li><code>c_short</code></li>
7108 <li><code>c_ushort</code></li>
7109 <li><code>c_int</code></li>
7110 <li><code>c_uint</code></li>
7111 <li><code>c_long</code></li>
7112 <li><code>c_ulong</code></li>
7113 <li><code>c_longlong</code></li>
7114 <li><code>c_ulonglong</code></li>
7115 <li><code>c_longdouble</code></li>
7116 <li><code>c_void</code></li>
7176 <li>{#syntax#}c_short{#endsyntax#}</li>
7177 <li>{#syntax#}c_ushort{#endsyntax#}</li>
7178 <li>{#syntax#}c_int{#endsyntax#}</li>
7179 <li>{#syntax#}c_uint{#endsyntax#}</li>
7180 <li>{#syntax#}c_long{#endsyntax#}</li>
7181 <li>{#syntax#}c_ulong{#endsyntax#}</li>
7182 <li>{#syntax#}c_longlong{#endsyntax#}</li>
7183 <li>{#syntax#}c_ulonglong{#endsyntax#}</li>
7184 <li>{#syntax#}c_longdouble{#endsyntax#}</li>
7185 <li>{#syntax#}c_void{#endsyntax#}</li>
71177186 </ul>
71187187 {#see_also|Primitive Types#}
71197188 {#header_close#}
......@@ -7135,7 +7204,7 @@ pub fn main() void {
71357204 {#header_close#}
71367205 {#header_open|Import from C Header File#}
71377206 <p>
7138 The <code>@cImport</code> builtin function can be used
7207 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
71397208 to directly import symbols from .h files:
71407209 </p>
71417210 {#code_begin|exe#}
......@@ -7150,7 +7219,7 @@ pub fn main() void {
71507219}
71517220 {#code_end#}
71527221 <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.
71547223 This expression is evaluated at compile-time and is used to control
71557224 preprocessor directives and include multiple .h files:
71567225 </p>
......@@ -7174,7 +7243,7 @@ const c = @cImport({
71747243 {#header_open|Exporting a C Library#}
71757244 <p>
71767245 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 to
7246 to call into. The {#syntax#}export{#endsyntax#} keyword in front of functions, variables, and types causes them to
71787247 be part of the library API:
71797248 </p>
71807249 <p class="file">mathtest.zig</p>
......@@ -7423,7 +7492,7 @@ Environments:
74237492 coreclr
74247493 opencl</code></pre>
74257494 <p>
7426 The Zig Standard Library (<code>@import("std")</code>) has architecture, environment, and operating sytsem
7495 The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem
74277496 abstractions, and thus takes additional work to support more platforms.
74287497 Not all standard library code requires operating system abstractions, however,
74297498 so things such as generic data structures work an all above platforms.
......@@ -7460,25 +7529,25 @@ coding style.
74607529 {#header_close#}
74617530 {#header_open|Names#}
74627531 <p>
7463 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,
7464 <code>snake_case_variable_name</code>. More precisely:
7532 Roughly speaking: {#syntax#}camelCaseFunctionName{#endsyntax#}, {#syntax#}TitleCaseTypeName{#endsyntax#},
7533 {#syntax#}snake_case_variable_name{#endsyntax#}. More precisely:
74657534 </p>
74667535 <ul>
74677536 <li>
7468 If <code>x</code> is a <code>struct</code> (or an alias of a <code>struct</code>),
7469 then <code>x</code> should be <code>TitleCase</code>.
7537 If {#syntax#}x{#endsyntax#} is a {#syntax#}struct{#endsyntax#} (or an alias of a {#syntax#}struct{#endsyntax#}),
7538 then {#syntax#}x{#endsyntax#} should be {#syntax#}TitleCase{#endsyntax#}.
74707539 </li>
74717540 <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#}.
74737542 </li>
74747543 <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#}.
74767545 </li>
74777546 <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#}.
74797548 </li>
74807549 <li>
7481 Otherwise, <code>x</code> should be <code>snake_case</code>.
7550 Otherwise, {#syntax#}x{#endsyntax#} should be {#syntax#}snake_case{#endsyntax#}.
74827551 </li>
74837552 </ul>
74847553 <p>
......@@ -7490,7 +7559,7 @@ coding style.
74907559 <p>
74917560 These are general rules of thumb; if it makes sense to do something different,
74927561 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.
74947563 </p>
74957564 {#header_close#}
74967565 {#header_open|Examples#}
......@@ -7704,7 +7773,7 @@ ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":"
77047773
77057774GroupedExpression = "(" Expression ")"
77067775
7707KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
7776KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "unreachable" | "suspend"
77087777
77097778ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
77107779
......@@ -7728,141 +7797,5 @@ ContainerDecl = option("extern" | "packed")
77287797 </ul>
77297798 {#header_close#}
77307799 </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>
78677800 </body>
78687801</html>
src-self-hosted/main.zig+1-1
......@@ -737,7 +737,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8) FmtError!void {
737737 file_path,
738738 max_src_size,
739739 )) catch |err| switch (err) {
740 error.IsDir => {
740 error.IsDir, error.AccessDenied => {
741741 // TODO make event based (and dir.next())
742742 var dir = try std.os.Dir.open(fmt.loop.allocator, file_path);
743743 defer dir.close();
src-self-hosted/type.zig-12
......@@ -40,7 +40,6 @@ pub const Type = struct {
4040 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
4141 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
4242 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
43 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
4443 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
4544 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
4645 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
......@@ -74,7 +73,6 @@ pub const Type = struct {
7473 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
7574 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
7675 Id.Namespace => unreachable,
77 Id.Block => unreachable,
7876 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
7977 Id.ArgTuple => unreachable,
8078 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
......@@ -90,7 +88,6 @@ pub const Type = struct {
9088 Id.Undefined,
9189 Id.Null,
9290 Id.Namespace,
93 Id.Block,
9491 Id.BoundFn,
9592 Id.ArgTuple,
9693 Id.Opaque,
......@@ -124,7 +121,6 @@ pub const Type = struct {
124121 Id.Undefined,
125122 Id.Null,
126123 Id.Namespace,
127 Id.Block,
128124 Id.BoundFn,
129125 Id.ArgTuple,
130126 Id.Opaque,
......@@ -1012,14 +1008,6 @@ pub const Type = struct {
10121008 }
10131009 };
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
10231011 pub const BoundFn = struct {
10241012 base: Type,
10251013
src/all_types.hpp+164-161
......@@ -10,6 +10,7 @@
1010
1111#include "list.hpp"
1212#include "buffer.hpp"
13#include "cache_hash.hpp"
1314#include "zig_llvm.h"
1415#include "hash_map.hpp"
1516#include "errmsg.hpp"
......@@ -282,7 +283,6 @@ struct ConstExprValue {
282283 ConstArrayValue x_array;
283284 ConstPtrValue x_ptr;
284285 ImportTableEntry *x_import;
285 Scope *x_block;
286286 ConstArgTuple x_arg_tuple;
287287
288288 // populated if special == ConstValSpecialRuntime
......@@ -412,7 +412,6 @@ enum NodeType {
412412 NodeTypeBoolLiteral,
413413 NodeTypeNullLiteral,
414414 NodeTypeUndefinedLiteral,
415 NodeTypeThisLiteral,
416415 NodeTypeUnreachable,
417416 NodeTypeIfBoolExpr,
418417 NodeTypeWhileExpr,
......@@ -1013,13 +1012,13 @@ enum PtrLen {
10131012
10141013struct ZigTypePointer {
10151014 ZigType *child_type;
1015 ZigType *slice_parent;
10161016 PtrLen ptr_len;
1017 bool is_const;
1018 bool is_volatile;
1019 uint32_t alignment;
1017 uint32_t explicit_alignment; // 0 means use ABI alignment
10201018 uint32_t bit_offset;
10211019 uint32_t unaligned_bit_count;
1022 ZigType *slice_parent;
1020 bool is_const;
1021 bool is_volatile;
10231022};
10241023
10251024struct ZigTypeInt {
......@@ -1047,32 +1046,35 @@ struct TypeStructField {
10471046 size_t unaligned_bit_count;
10481047 AstNode *decl_node;
10491048};
1049
1050enum ResolveStatus {
1051 ResolveStatusUnstarted,
1052 ResolveStatusInvalid,
1053 ResolveStatusZeroBitsKnown,
1054 ResolveStatusAlignmentKnown,
1055 ResolveStatusSizeKnown,
1056};
1057
10501058struct ZigTypeStruct {
10511059 AstNode *decl_node;
1052 ContainerLayout layout;
1053 uint32_t src_field_count;
1054 uint32_t gen_field_count;
10551060 TypeStructField *fields;
1056 uint64_t size_bytes;
1057 bool is_invalid; // true if any fields are invalid
1058 bool is_slice;
10591061 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 loops
1062 bool embedded_in_current;
1063 bool reported_infinite_err;
1064 // whether we've finished resolving it
1065 bool complete;
1065 uint32_t src_field_count;
1066 uint32_t gen_field_count;
1067
1068 uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown
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;
10671075 // whether any of the fields require comptime
1068 // the value is not valid until zero_bits_known == true
1076 // known after ResolveStatusZeroBitsKnown
10691077 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;
10761078};
10771079
10781080struct ZigTypeOptional {
......@@ -1204,7 +1206,6 @@ enum ZigTypeId {
12041206 ZigTypeIdUnion,
12051207 ZigTypeIdFn,
12061208 ZigTypeIdNamespace,
1207 ZigTypeIdBlock,
12081209 ZigTypeIdBoundFn,
12091210 ZigTypeIdArgTuple,
12101211 ZigTypeIdOpaque,
......@@ -1412,6 +1413,7 @@ enum BuiltinFnId {
14121413 BuiltinFnIdSetEvalBranchQuota,
14131414 BuiltinFnIdAlignCast,
14141415 BuiltinFnIdOpaqueType,
1416 BuiltinFnIdThis,
14151417 BuiltinFnIdSetAlignStack,
14161418 BuiltinFnIdArgType,
14171419 BuiltinFnIdExport,
......@@ -1550,22 +1552,50 @@ struct LinkLib {
15501552 bool provided_explicitly;
15511553};
15521554
1555// When adding fields, check if they should be added to the hash computation in build_with_cache
15531556struct CodeGen {
1557 //////////////////////////// Runtime State
15541558 LLVMModuleRef module;
15551559 ZigList<ErrorMsg*> errors;
15561560 LLVMBuilderRef builder;
15571561 ZigLLVMDIBuilder *dbuilder;
15581562 ZigLLVMDICompileUnit *compile_unit;
15591563 ZigLLVMDIFile *compile_unit_file;
1560
1561 ZigList<LinkLib *> link_libs_list;
15621564 LinkLib *libc_link_lib;
1563
1564 // add -framework [name] args to linker
1565 ZigList<Buf *> darwin_frameworks;
1566 // add -rpath [name] args to linker
1567 ZigList<Buf *> rpath_list;
1568
1565 LLVMTargetDataRef target_data_ref;
1566 LLVMTargetMachineRef target_machine;
1567 ZigLLVMDIFile *dummy_di_file;
1568 LLVMValueRef cur_ret_ptr;
1569 LLVMValueRef cur_fn_val;
1570 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
15701600 // reminder: hash tables must be initialized before use
15711601 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
......@@ -1582,15 +1612,29 @@ struct CodeGen {
15821612 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
15831613 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
15841614
1585
15861615 ZigList<ImportTableEntry *> import_queue;
15871616 size_t import_queue_index;
15881617 ZigList<Tld *> resolve_queue;
15891618 size_t resolve_queue_index;
15901619 ZigList<AstNode *> use_queue;
15911620 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
15951639 struct {
15961640 ZigType *entry_bool;
......@@ -1626,163 +1670,122 @@ struct CodeGen {
16261670 ZigType *entry_arg_tuple;
16271671 ZigType *entry_promise;
16281672 } 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;
16561679 Buf triple_str;
1657 BuildMode build_mode;
1658 bool is_test_build;
1659 bool have_err_ret_tracing;
1660 uint32_t target_os_index;
1661 uint32_t target_arch_index;
1662 uint32_t target_environ_index;
1663 uint32_t target_oformat_index;
1664 LLVMTargetMachineRef target_machine;
1665 ZigLLVMDIFile *dummy_di_file;
1666 bool is_native_target;
1667 PackageTableEntry *root_package;
1668 PackageTableEntry *std_package;
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;
1680 Buf global_asm;
1681 Buf *out_h_path;
1682 Buf artifact_dir;
1683 Buf output_file_path;
1684 Buf o_file_output_path;
1685 Buf *wanted_output_file_path;
1686 Buf cache_dir;
1687
1688 IrInstruction *invalid_instruction;
1689
1690 ConstExprValue const_void_val;
1691 ConstExprValue panic_msg_vals[PanicMsgIdCount];
16801692
16811693 // The function definitions this module includes.
16821694 ZigList<ZigFn *> fn_defs;
16831695 size_t fn_defs_index;
16841696 ZigList<TldVar *> global_vars;
16851697
1686 OutType out_type;
16871698 ZigFn *cur_fn;
16881699 ZigFn *main_fn;
16891700 ZigFn *panic_fn;
1690 LLVMValueRef cur_ret_ptr;
1691 LLVMValueRef cur_fn_val;
1692 LLVMValueRef cur_err_ret_trace_val_arg;
1693 LLVMValueRef cur_err_ret_trace_val_stack;
1701 AstNode *root_export_decl;
1702
1703 CacheHash cache_hash;
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;
16941720 bool c_want_stdint;
16951721 bool c_want_stdbool;
1696 AstNode *root_export_decl;
1697 size_t version_major;
1698 size_t version_minor;
1699 size_t version_patch;
17001722 bool verbose_tokenize;
17011723 bool verbose_ast;
17021724 bool verbose_link;
17031725 bool verbose_ir;
17041726 bool verbose_llvm_ir;
17051727 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;
17311728 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;
1734
1735 const char **clang_argv;
1736 size_t clang_argv_len;
1733 //////////////////////////// Participates in Input Parameter Cache Hash
1734 ZigList<LinkLib *> link_libs_list;
1735 // add -framework [name] args to linker
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;
17371742 ZigList<const char *> lib_dirs;
17381743
1739 const char **llvm_argv;
1740 size_t llvm_argv_len;
1741
1742 ZigList<ZigFn *> test_fns;
1743 ZigType *test_fn_type;
1744 size_t version_major;
1745 size_t version_minor;
1746 size_t version_patch;
1747 const char *linker_script;
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;
17451761 bool each_lib_rpath;
17461762
1747 ZigType *err_tag_type;
1748 ZigList<ZigLLVMDIEnumerator *> err_enumerators;
1749 ZigList<ErrorTableEntry *> errors_by_index;
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
1763 Buf *mmacosx_version_min;
1764 Buf *mios_version_min;
1765 Buf *root_out_name;
17661766 Buf *test_filter;
17671767 Buf *test_name_prefix;
1768 PackageTableEntry *root_package;
17681769
1769 ZigList<TimeEvent> timing_events;
1770
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;
1770 const char **llvm_argv;
1771 size_t llvm_argv_len;
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;
17861789};
17871790
17881791enum VarLinkage {
......@@ -3285,8 +3288,8 @@ static const size_t stack_trace_ptr_count = 30;
32853288
32863289
32873290enum FloatMode {
3288 FloatModeOptimized,
32893291 FloatModeStrict,
3292 FloatModeOptimized,
32903293};
32913294
32923295enum FnWalkId {
src/analyze.cpp+265-243
......@@ -23,6 +23,7 @@ static Error resolve_enum_type(CodeGen *g, ZigType *enum_type);
2323static Error resolve_struct_type(CodeGen *g, ZigType *struct_type);
2424
2525static 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);
2627static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type);
2728static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
2829static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
......@@ -246,7 +247,6 @@ AstNode *type_decl_node(ZigType *type_entry) {
246247 case ZigTypeIdErrorSet:
247248 case ZigTypeIdFn:
248249 case ZigTypeIdNamespace:
249 case ZigTypeIdBlock:
250250 case ZigTypeIdBoundFn:
251251 case ZigTypeIdArgTuple:
252252 case ZigTypeIdPromise:
......@@ -255,18 +255,42 @@ AstNode *type_decl_node(ZigType *type_entry) {
255255 zig_unreachable();
256256}
257257
258bool type_is_complete(ZigType *type_entry) {
258bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
259259 switch (type_entry->id) {
260260 case ZigTypeIdInvalid:
261261 zig_unreachable();
262262 case ZigTypeIdStruct:
263 return type_entry->data.structure.complete;
263 return type_entry->data.structure.resolve_status >= status;
264264 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();
266278 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();
268292 case ZigTypeIdOpaque:
269 return false;
293 return status < ResolveStatusSizeKnown;
270294 case ZigTypeIdMetaType:
271295 case ZigTypeIdVoid:
272296 case ZigTypeIdBool:
......@@ -284,7 +308,6 @@ bool type_is_complete(ZigType *type_entry) {
284308 case ZigTypeIdErrorSet:
285309 case ZigTypeIdFn:
286310 case ZigTypeIdNamespace:
287 case ZigTypeIdBlock:
288311 case ZigTypeIdBoundFn:
289312 case ZigTypeIdArgTuple:
290313 case ZigTypeIdPromise:
......@@ -293,44 +316,10 @@ bool type_is_complete(ZigType *type_entry) {
293316 zig_unreachable();
294317}
295318
296bool type_has_zero_bits_known(ZigType *type_entry) {
297 switch (type_entry->id) {
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();
319bool type_is_complete(ZigType *type_entry) {
320 return type_is_resolved(type_entry, ResolveStatusSizeKnown);
331321}
332322
333
334323uint64_t type_size(CodeGen *g, ZigType *type_entry) {
335324 assert(type_is_complete(type_entry));
336325
......@@ -379,7 +368,7 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
379368
380369Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry) {
381370 Error err;
382 if ((err = type_ensure_zero_bits_known(g, type_entry)))
371 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
383372 return err;
384373
385374 if (!type_has_bits(type_entry))
......@@ -434,10 +423,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
434423 assert(!type_is_invalid(child_type));
435424 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
437432 TypeId type_id = {};
438433 ZigType **parent_pointer = nullptr;
439 uint32_t abi_alignment = get_abi_alignment(g, child_type);
440 if (unaligned_bit_count != 0 || is_volatile || byte_alignment != abi_alignment || ptr_len != PtrLenSingle) {
434 if (unaligned_bit_count != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
441435 type_id.id = ZigTypeIdPointer;
442436 type_id.data.pointer.child_type = child_type;
443437 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
454448 assert(bit_offset == 0);
455449 parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
456450 if (*parent_pointer) {
457 assert((*parent_pointer)->data.pointer.alignment == byte_alignment);
451 assert((*parent_pointer)->data.pointer.explicit_alignment == 0);
458452 return *parent_pointer;
459453 }
460454 }
461455
462 assertNoError(type_ensure_zero_bits_known(g, child_type));
456 assert(type_is_resolved(child_type, ResolveStatusZeroBitsKnown));
463457
464458 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
465459 entry->is_copyable = true;
......@@ -468,11 +462,14 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
468462 const char *const_str = is_const ? "const " : "";
469463 const char *volatile_str = is_volatile ? "volatile " : "";
470464 buf_resize(&entry->name, 0);
471 if (unaligned_bit_count == 0 && byte_alignment == abi_alignment) {
465 if (unaligned_bit_count == 0 && byte_alignment == 0) {
472466 buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
473467 } else if (unaligned_bit_count == 0) {
474468 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
475469 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));
476473 } else {
477474 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
478475 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
483480 entry->zero_bits = !type_has_bits(child_type);
484481
485482 if (!entry->zero_bits) {
486 assert(byte_alignment > 0);
487 if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != abi_alignment ||
483 if (is_const || is_volatile || unaligned_bit_count != 0 || byte_alignment != 0 ||
488484 ptr_len != PtrLenSingle)
489485 {
490486 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
508504 entry->data.pointer.child_type = child_type;
509505 entry->data.pointer.is_const = is_const;
510506 entry->data.pointer.is_volatile = is_volatile;
511 entry->data.pointer.alignment = byte_alignment;
507 entry->data.pointer.explicit_alignment = byte_alignment;
512508 entry->data.pointer.bit_offset = bit_offset;
513509 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
521517}
522518
523519ZigType *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,
525 get_abi_alignment(g, child_type), 0, 0);
520 return get_pointer_to_type_extra(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0);
526521}
527522
528523ZigType *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
803798 entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);
804799 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));
807 if (pointer_type->data.pointer.child_type->zero_bits) {
801 if (!type_has_bits(pointer_type->data.pointer.child_type)) {
808802 entry->data.structure.gen_field_count = 1;
809803 entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;
810804 entry->data.structure.fields[slice_len_index].gen_index = 0;
......@@ -829,20 +823,18 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
829823 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
830824
831825 ZigType *child_type = ptr_type->data.pointer.child_type;
832 uint32_t abi_alignment = get_abi_alignment(g, child_type);
833826 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)
835828 {
836829 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);
838831 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
839832
840833 slice_type_common_init(g, ptr_type, entry);
841834
842835 entry->type_ref = peer_slice_type->type_ref;
843836 entry->di_type = peer_slice_type->di_type;
844 entry->data.structure.complete = true;
845 entry->data.structure.zero_bits_known = true;
837 entry->data.structure.resolve_status = ResolveStatusSizeKnown;
846838 entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment;
847839
848840 *parent_pointer = entry;
......@@ -854,15 +846,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
854846 if (is_slice(child_type)) {
855847 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
856848 assert(child_ptr_type->id == ZigTypeIdPointer);
857 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
858849 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)
860851 {
852 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
861853 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);
863855 ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type);
864856 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);
866858 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
867859
868860 entry->type_ref = peer_slice_type->type_ref;
......@@ -964,8 +956,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
964956 }
965957
966958
967 entry->data.structure.complete = true;
968 entry->data.structure.zero_bits_known = true;
959 entry->data.structure.resolve_status = ResolveStatusSizeKnown;
969960
970961 *parent_pointer = entry;
971962 return entry;
......@@ -1370,7 +1361,7 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_
13701361
13711362static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) {
13721363 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);
13741365 ZigType *str_type = get_slice_type(g, ptr_type);
13751366 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
13761367 if (type_is_invalid(instr->value.type))
......@@ -1414,7 +1405,6 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
14141405 case ZigTypeIdErrorUnion:
14151406 case ZigTypeIdErrorSet:
14161407 case ZigTypeIdNamespace:
1417 case ZigTypeIdBlock:
14181408 case ZigTypeIdBoundFn:
14191409 case ZigTypeIdArgTuple:
14201410 case ZigTypeIdOpaque:
......@@ -1455,7 +1445,6 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14551445 case ZigTypeIdErrorUnion:
14561446 case ZigTypeIdErrorSet:
14571447 case ZigTypeIdNamespace:
1458 case ZigTypeIdBlock:
14591448 case ZigTypeIdBoundFn:
14601449 case ZigTypeIdArgTuple:
14611450 case ZigTypeIdPromise:
......@@ -1581,7 +1570,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
15811570 return g->builtin_types.entry_invalid;
15821571 }
15831572 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)))
15851574 return g->builtin_types.entry_invalid;
15861575 if (!type_has_bits(type_entry)) {
15871576 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
16131602 case ZigTypeIdComptimeFloat:
16141603 case ZigTypeIdComptimeInt:
16151604 case ZigTypeIdNamespace:
1616 case ZigTypeIdBlock:
16171605 case ZigTypeIdBoundFn:
16181606 case ZigTypeIdMetaType:
16191607 case ZigTypeIdVoid:
......@@ -1630,7 +1618,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
16301618 case ZigTypeIdUnion:
16311619 case ZigTypeIdFn:
16321620 case ZigTypeIdPromise:
1633 if ((err = type_ensure_zero_bits_known(g, type_entry)))
1621 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
16341622 return g->builtin_types.entry_invalid;
16351623 if (type_requires_comptime(type_entry)) {
16361624 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
17031691 case ZigTypeIdComptimeFloat:
17041692 case ZigTypeIdComptimeInt:
17051693 case ZigTypeIdNamespace:
1706 case ZigTypeIdBlock:
17071694 case ZigTypeIdBoundFn:
17081695 case ZigTypeIdMetaType:
17091696 case ZigTypeIdUnreachable:
......@@ -1721,7 +1708,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
17211708 case ZigTypeIdUnion:
17221709 case ZigTypeIdFn:
17231710 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)))
17251712 return g->builtin_types.entry_invalid;
17261713 if (type_requires_comptime(fn_type_id.return_type)) {
17271714 return get_generic_fn_type(g, &fn_type_id);
......@@ -1747,7 +1734,7 @@ bool type_is_invalid(ZigType *type_entry) {
17471734 case ZigTypeIdInvalid:
17481735 return true;
17491736 case ZigTypeIdStruct:
1750 return type_entry->data.structure.is_invalid;
1737 return type_entry->data.structure.resolve_status == ResolveStatusInvalid;
17511738 case ZigTypeIdEnum:
17521739 return type_entry->data.enumeration.is_invalid;
17531740 case ZigTypeIdUnion:
......@@ -1862,8 +1849,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
18621849
18631850 struct_type->data.structure.src_field_count = field_count;
18641851 struct_type->data.structure.gen_field_count = 0;
1865 struct_type->data.structure.zero_bits_known = true;
1866 struct_type->data.structure.complete = true;
1852 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
18671853 struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
18681854 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
19351921static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
19361922 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)
19391929 return ErrorNone;
19401930
1941 Error err;
1942 if ((err = resolve_struct_zero_bits(g, struct_type)))
1931 if ((err = resolve_struct_alignment(g, struct_type)))
19431932 return err;
19441933
19451934 AstNode *decl_node = struct_type->data.structure.decl_node;
19461935
1947 if (struct_type->data.structure.embedded_in_current) {
1948 struct_type->data.structure.is_invalid = true;
1949 if (!struct_type->data.structure.reported_infinite_err) {
1950 struct_type->data.structure.reported_infinite_err = true;
1936 if (struct_type->data.structure.resolve_loop_flag) {
1937 if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) {
1938 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
19511939 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)));
19531941 }
19541942 return ErrorSemanticAnalyzeFail;
19551943 }
19561944
1957 assert(!struct_type->data.structure.zero_bits_loop_flag);
1945 struct_type->data.structure.resolve_loop_flag = true;
1946
19581947 assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
19591948 assert(decl_node->type == NodeTypeContainerDecl);
19601949
......@@ -1963,9 +1952,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
19631952 size_t gen_field_count = struct_type->data.structure.gen_field_count;
19641953 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
19691955 Scope *scope = &struct_type->data.structure.decls_scope->base;
19701956
19711957 size_t gen_field_index = 0;
......@@ -1979,7 +1965,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
19791965 ZigType *field_type = type_struct_field->type_entry;
19801966
19811967 if ((err = ensure_complete_type(g, field_type))) {
1982 struct_type->data.structure.is_invalid = true;
1968 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
19831969 break;
19841970 }
19851971
......@@ -1989,7 +1975,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
19891975 add_node_error(g, field_source_node,
19901976 buf_sprintf("extern structs cannot contain fields of type '%s'",
19911977 buf_ptr(&field_type->name)));
1992 struct_type->data.structure.is_invalid = true;
1978 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
19931979 break;
19941980 }
19951981 }
......@@ -2005,7 +1991,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
20051991 add_node_error(g, field_source_node,
20061992 buf_sprintf("packed structs cannot contain fields of type '%s'",
20071993 buf_ptr(&field_type->name)));
2008 struct_type->data.structure.is_invalid = true;
1994 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
20091995 break;
20101996 }
20111997
......@@ -2056,12 +2042,13 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
20562042 gen_field_index += 1;
20572043 }
20582044
2059 struct_type->data.structure.embedded_in_current = false;
2060 struct_type->data.structure.complete = true;
2045 struct_type->data.structure.resolve_loop_flag = false;
20612046
2062 if (struct_type->data.structure.is_invalid)
2047 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
20632048 return ErrorSemanticAnalyzeFail;
20642049
2050 struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
2051
20652052 if (struct_type->zero_bits) {
20662053 struct_type->type_ref = LLVMVoidType();
20672054
......@@ -2123,7 +2110,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
21232110
21242111 assert(field_type->type_ref);
21252112 assert(struct_type->type_ref);
2126 assert(struct_type->data.structure.complete);
2113 assert(struct_type->data.structure.resolve_status == ResolveStatusSizeKnown);
21272114 uint64_t debug_size_in_bits;
21282115 uint64_t debug_align_in_bits;
21292116 uint64_t debug_offset_in_bits;
......@@ -2450,6 +2437,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
24502437 ZigType *tag_int_type;
24512438 if (enum_type->data.enumeration.layout == ContainerLayoutExtern) {
24522439 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;
24532442 } else {
24542443 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
24552444 }
......@@ -2513,7 +2502,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25132502 continue;
25142503 }
25152504 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);
25172507 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
25182508 if (entry == nullptr) {
25192509 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) {
25742564
25752565 Error err;
25762566
2577 if (struct_type->data.structure.is_invalid)
2567 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
25782568 return ErrorSemanticAnalyzeFail;
2579
2580 if (struct_type->data.structure.zero_bits_known)
2569 if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
25812570 return ErrorNone;
25822571
2583 if (struct_type->data.structure.zero_bits_loop_flag) {
2584 // If we get here it's due to recursion. This is a design flaw in the compiler,
2585 // we should be able to still figure out alignment, but here we give up and say that
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 }
2572 if (struct_type->data.structure.resolve_loop_flag) {
2573 struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown;
2574 struct_type->data.structure.resolve_loop_flag = false;
25972575 return ErrorNone;
25982576 }
25992577
2600 struct_type->data.structure.zero_bits_loop_flag = true;
2578 struct_type->data.structure.resolve_loop_flag = true;
26012579
26022580 AstNode *decl_node = struct_type->data.structure.decl_node;
26032581 assert(decl_node->type == NodeTypeContainerDecl);
......@@ -2620,7 +2598,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26202598
26212599 if (field_node->data.struct_field.type == nullptr) {
26222600 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;
26242602 continue;
26252603 }
26262604
......@@ -2629,7 +2607,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26292607 ErrorMsg *msg = add_node_error(g, field_node,
26302608 buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name)));
26312609 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;
26332611 continue;
26342612 }
26352613
......@@ -2643,8 +2621,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26432621 buf_sprintf("enums, not structs, support field assignment"));
26442622 }
26452623
2646 if ((err = type_ensure_zero_bits_known(g, field_type))) {
2647 struct_type->data.structure.is_invalid = true;
2624 if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) {
2625 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
26482626 continue;
26492627 }
26502628
......@@ -2655,36 +2633,87 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
26552633 if (!type_has_bits(field_type))
26562634 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
26752636 type_struct_field->gen_index = gen_field_index;
26762637 gen_field_index += 1;
26772638 }
26782639
2679 struct_type->data.structure.zero_bits_loop_flag = false;
2640 struct_type->data.structure.resolve_loop_flag = false;
26802641 struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index;
26812642 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) {
26852713 return ErrorSemanticAnalyzeFail;
26862714 }
26872715
2716 struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown;
26882717 return ErrorNone;
26892718}
26902719
......@@ -2776,6 +2805,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
27762805 union_type->data.unionation.is_invalid = true;
27772806 return ErrorSemanticAnalyzeFail;
27782807 }
2808 } else if (auto_layout && field_count == 1) {
2809 tag_int_type = g->builtin_types.entry_num_lit_int;
27792810 } else {
27802811 tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
27812812 }
......@@ -2809,6 +2840,10 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
28092840 buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name)));
28102841 return ErrorSemanticAnalyzeFail;
28112842 }
2843 if ((err = type_resolve(g, enum_type, ResolveStatusAlignmentKnown))) {
2844 assert(g->errors.length != 0);
2845 return err;
2846 }
28122847 tag_type = enum_type;
28132848 abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count
28142849 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) {
28462881 }
28472882 } else {
28482883 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))) {
28502885 union_type->data.unionation.is_invalid = true;
28512886 continue;
28522887 }
......@@ -3109,7 +3144,7 @@ static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
31093144 return wrong_panic_prototype(g, proto_node, fn_type);
31103145 }
31113146 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);
31133148 ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
31143149 if (fn_type_id->param_info[0].type != const_u8_slice) {
31153150 return wrong_panic_prototype(g, proto_node, fn_type);
......@@ -3428,7 +3463,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
34283463 case NodeTypeBoolLiteral:
34293464 case NodeTypeNullLiteral:
34303465 case NodeTypeUndefinedLiteral:
3431 case NodeTypeThisLiteral:
34323466 case NodeTypeSymbol:
34333467 case NodeTypePrefixOpExpr:
34343468 case NodeTypePointerType:
......@@ -3488,7 +3522,6 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
34883522 case ZigTypeIdUnreachable:
34893523 case ZigTypeIdUndefined:
34903524 case ZigTypeIdNull:
3491 case ZigTypeIdBlock:
34923525 case ZigTypeIdArgTuple:
34933526 case ZigTypeIdOpaque:
34943527 add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
......@@ -3789,34 +3822,6 @@ ZigFn *scope_fn_entry(Scope *scope) {
37893822 return nullptr;
37903823}
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
38203825TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
38213826 assert(enum_type->id == ZigTypeIdEnum);
38223827 if (enum_type->data.enumeration.src_field_count == 0)
......@@ -3829,7 +3834,7 @@ TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name) {
38293834
38303835TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) {
38313836 assert(type_entry->id == ZigTypeIdStruct);
3832 assert(type_entry->data.structure.complete);
3837 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
38333838 if (type_entry->data.structure.src_field_count == 0)
38343839 return nullptr;
38353840 auto entry = type_entry->data.structure.fields_by_name.maybe_get(name);
......@@ -3898,7 +3903,6 @@ static bool is_container(ZigType *type_entry) {
38983903 case ZigTypeIdErrorSet:
38993904 case ZigTypeIdFn:
39003905 case ZigTypeIdNamespace:
3901 case ZigTypeIdBlock:
39023906 case ZigTypeIdBoundFn:
39033907 case ZigTypeIdArgTuple:
39043908 case ZigTypeIdOpaque:
......@@ -3957,7 +3961,6 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
39573961 case ZigTypeIdErrorSet:
39583962 case ZigTypeIdFn:
39593963 case ZigTypeIdNamespace:
3960 case ZigTypeIdBlock:
39613964 case ZigTypeIdBoundFn:
39623965 case ZigTypeIdInvalid:
39633966 case ZigTypeIdArgTuple:
......@@ -3983,14 +3986,17 @@ bool type_is_codegen_pointer(ZigType *type) {
39833986 return get_codegen_ptr_type(type) == type;
39843987}
39853988
3986uint32_t get_ptr_align(ZigType *type) {
3989uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
39873990 ZigType *ptr_type = get_codegen_ptr_type(type);
39883991 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;
39903994 } 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;
39923998 } else if (ptr_type->id == ZigTypeIdPromise) {
3993 return 1;
3999 return get_coro_frame_align_bytes(g);
39944000 } else {
39954001 zig_unreachable();
39964002 }
......@@ -4060,6 +4066,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
40604066}
40614067
40624068bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) {
4069 assert(err_set_type->id == ZigTypeIdErrorSet);
40634070 ZigFn *infer_fn = err_set_type->data.error_set.infer_fn;
40644071 if (infer_fn != nullptr) {
40654072 if (infer_fn->anal_state == FnAnalStateInvalid) {
......@@ -4417,7 +4424,6 @@ bool handle_is_ptr(ZigType *type_entry) {
44174424 case ZigTypeIdUndefined:
44184425 case ZigTypeIdNull:
44194426 case ZigTypeIdNamespace:
4420 case ZigTypeIdBlock:
44214427 case ZigTypeIdBoundFn:
44224428 case ZigTypeIdArgTuple:
44234429 case ZigTypeIdOpaque:
......@@ -4832,8 +4838,6 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48324838 return const_val->data.x_err_set->value ^ 2630160122;
48334839 case ZigTypeIdNamespace:
48344840 return hash_ptr(const_val->data.x_import);
4835 case ZigTypeIdBlock:
4836 return hash_ptr(const_val->data.x_block);
48374841 case ZigTypeIdBoundFn:
48384842 case ZigTypeIdInvalid:
48394843 case ZigTypeIdUnreachable:
......@@ -4894,7 +4898,6 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
48944898 case ZigTypeIdNamespace:
48954899 case ZigTypeIdBoundFn:
48964900 case ZigTypeIdFn:
4897 case ZigTypeIdBlock:
48984901 case ZigTypeIdOpaque:
48994902 case ZigTypeIdPromise:
49004903 case ZigTypeIdErrorSet:
......@@ -4961,7 +4964,6 @@ static bool return_type_is_cacheable(ZigType *return_type) {
49614964 case ZigTypeIdNamespace:
49624965 case ZigTypeIdBoundFn:
49634966 case ZigTypeIdFn:
4964 case ZigTypeIdBlock:
49654967 case ZigTypeIdOpaque:
49664968 case ZigTypeIdPromise:
49674969 case ZigTypeIdErrorSet:
......@@ -5057,8 +5059,8 @@ bool fn_eval_eql(Scope *a, Scope *b) {
50575059
50585060bool type_has_bits(ZigType *type_entry) {
50595061 assert(type_entry);
5060 assert(type_entry->id != ZigTypeIdInvalid);
5061 assert(type_has_zero_bits_known(type_entry));
5062 assert(!type_is_invalid(type_entry));
5063 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
50625064 return !type_entry->zero_bits;
50635065}
50645066
......@@ -5073,17 +5075,16 @@ bool type_requires_comptime(ZigType *type_entry) {
50735075 case ZigTypeIdNull:
50745076 case ZigTypeIdMetaType:
50755077 case ZigTypeIdNamespace:
5076 case ZigTypeIdBlock:
50775078 case ZigTypeIdBoundFn:
50785079 case ZigTypeIdArgTuple:
50795080 return true;
50805081 case ZigTypeIdArray:
50815082 return type_requires_comptime(type_entry->data.array.child_type);
50825083 case ZigTypeIdStruct:
5083 assert(type_has_zero_bits_known(type_entry));
5084 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
50845085 return type_entry->data.structure.requires_comptime;
50855086 case ZigTypeIdUnion:
5086 assert(type_has_zero_bits_known(type_entry));
5087 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
50875088 return type_entry->data.unionation.requires_comptime;
50885089 case ZigTypeIdOptional:
50895090 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) {
51595160 const_val->special = ConstValSpecialStatic;
51605161 // TODO make this `[*]null u8` instead of `[*]u8`
51615162 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);
51635164 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
51645165 const_val->data.x_ptr.data.base_array.array_val = array_val;
51655166 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
53045305 assert(array_val->type->id == ZigTypeIdArray);
53055306
53065307 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 0, 0);
5308 is_const, false, PtrLenUnknown, 0, 0, 0);
53095309
53105310 const_val->special = ConstValSpecialStatic;
53115311 const_val->type = get_slice_type(g, ptr_type);
......@@ -5330,7 +5330,7 @@ void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue
53305330
53315331 const_val->special = ConstValSpecialStatic;
53325332 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);
53345334 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
53355335 const_val->data.x_ptr.data.base_array.array_val = array_val;
53365336 const_val->data.x_ptr.data.base_array.elem_index = elem_index;
......@@ -5429,32 +5429,46 @@ ConstExprValue *create_const_vals(size_t count) {
54295429}
54305430
54315431Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
5432 if (type_is_invalid(type_entry))
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;
5432 return type_resolve(g, type_entry, ResolveStatusSizeKnown);
54455433}
54465434
5447Error type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry) {
5448 if (type_is_invalid(type_entry))
5435Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
5436 if (type_is_invalid(ty))
54495437 return ErrorSemanticAnalyzeFail;
5450 if (type_entry->id == ZigTypeIdStruct) {
5451 return resolve_struct_zero_bits(g, type_entry);
5452 } else if (type_entry->id == ZigTypeIdEnum) {
5453 return resolve_enum_zero_bits(g, type_entry);
5454 } else if (type_entry->id == ZigTypeIdUnion) {
5455 return resolve_union_zero_bits(g, type_entry);
5438 switch (status) {
5439 case ResolveStatusUnstarted:
5440 return ErrorNone;
5441 case ResolveStatusInvalid:
5442 zig_unreachable();
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;
54565470 }
5457 return ErrorNone;
5471 zig_unreachable();
54585472}
54595473
54605474bool ir_get_var_is_comptime(ZigVar *var) {
......@@ -5605,8 +5619,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
56055619 zig_panic("TODO");
56065620 case ZigTypeIdNamespace:
56075621 return a->data.x_import == b->data.x_import;
5608 case ZigTypeIdBlock:
5609 return a->data.x_block == b->data.x_block;
56105622 case ZigTypeIdArgTuple:
56115623 return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index &&
56125624 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) {
57855797 }
57865798 case ZigTypeIdPointer:
57875799 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 }
57945800 case ZigTypeIdArray:
57955801 {
57965802 ZigType *child_type = type_entry->data.array.child_type;
......@@ -5882,12 +5888,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
58825888 }
58835889 case ZigTypeIdErrorUnion:
58845890 {
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, ")");
58865899 return;
58875900 }
58885901 case ZigTypeIdUnion:
58895902 {
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, "}");
58915908 return;
58925909 }
58935910 case ZigTypeIdErrorSet:
......@@ -5959,7 +5976,6 @@ uint32_t type_id_hash(TypeId x) {
59595976 case ZigTypeIdUnion:
59605977 case ZigTypeIdFn:
59615978 case ZigTypeIdNamespace:
5962 case ZigTypeIdBlock:
59635979 case ZigTypeIdBoundFn:
59645980 case ZigTypeIdArgTuple:
59655981 case ZigTypeIdPromise:
......@@ -6006,7 +6022,6 @@ bool type_id_eql(TypeId a, TypeId b) {
60066022 case ZigTypeIdUnion:
60076023 case ZigTypeIdFn:
60086024 case ZigTypeIdNamespace:
6009 case ZigTypeIdBlock:
60106025 case ZigTypeIdBoundFn:
60116026 case ZigTypeIdArgTuple:
60126027 case ZigTypeIdOpaque:
......@@ -6132,7 +6147,6 @@ static const ZigTypeId all_type_ids[] = {
61326147 ZigTypeIdUnion,
61336148 ZigTypeIdFn,
61346149 ZigTypeIdNamespace,
6135 ZigTypeIdBlock,
61366150 ZigTypeIdBoundFn,
61376151 ZigTypeIdArgTuple,
61386152 ZigTypeIdOpaque,
......@@ -6194,16 +6208,14 @@ size_t type_id_index(ZigType *entry) {
61946208 return 18;
61956209 case ZigTypeIdNamespace:
61966210 return 19;
6197 case ZigTypeIdBlock:
6198 return 20;
61996211 case ZigTypeIdBoundFn:
6200 return 21;
6212 return 20;
62016213 case ZigTypeIdArgTuple:
6202 return 22;
6214 return 21;
62036215 case ZigTypeIdOpaque:
6204 return 23;
6216 return 22;
62056217 case ZigTypeIdPromise:
6206 return 24;
6218 return 23;
62076219 }
62086220 zig_unreachable();
62096221}
......@@ -6252,8 +6264,6 @@ const char *type_id_name(ZigTypeId id) {
62526264 return "Fn";
62536265 case ZigTypeIdNamespace:
62546266 return "Namespace";
6255 case ZigTypeIdBlock:
6256 return "Block";
62576267 case ZigTypeIdBoundFn:
62586268 return "BoundFn";
62596269 case ZigTypeIdArgTuple:
......@@ -6278,6 +6288,12 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
62786288 if (is_libc && g->libc_link_lib != nullptr)
62796289 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
62816297 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
62826298 LinkLib *existing_lib = g->link_libs_list.at(i);
62836299 if (buf_eql_buf(existing_lib->name, name)) {
......@@ -6295,7 +6311,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
62956311}
62966312
62976313uint32_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));
62996315 if (type_entry->zero_bits) return 0;
63006316
63016317 // 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) {
63106326 return 1;
63116327 } else {
63126328 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 }
63176329 return llvm_alignment;
63186330 }
63196331}
......@@ -6351,7 +6363,10 @@ bool type_is_global_error_set(ZigType *err_set_type) {
63516363}
63526364
63536365uint32_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;
63556370}
63566371
63576372bool type_can_fail(ZigType *type_entry) {
......@@ -6387,6 +6402,14 @@ not_integer:
63876402 return nullptr;
63886403}
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
63906413X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
63916414 size_t ty_size = type_size(g, ty);
63926415 if (get_codegen_ptr_type(ty) != nullptr)
......@@ -6467,4 +6490,3 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) {
64676490 ty->id == ZigTypeIdUnreachable ||
64686491 get_codegen_ptr_type(ty) != nullptr);
64696492}
6470
src/analyze.hpp+5-4
......@@ -54,14 +54,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *so
5454bool type_is_codegen_pointer(ZigType *type);
5555
5656ZigType *get_codegen_ptr_type(ZigType *type);
57uint32_t get_ptr_align(ZigType *type);
57uint32_t get_ptr_align(CodeGen *g, ZigType *type);
5858bool get_ptr_const(ZigType *type);
5959ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
6060ZigType *container_ref_type(ZigType *type_entry);
6161bool type_is_complete(ZigType *type_entry);
62bool type_is_resolved(ZigType *type_entry, ResolveStatus status);
6263bool type_is_invalid(ZigType *type_entry);
6364bool type_is_global_error_set(ZigType *err_set_type);
64bool type_has_zero_bits_known(ZigType *type_entry);
6565void resolve_container_type(CodeGen *g, ZigType *type_entry);
6666ScopeDecls *get_container_scope(ZigType *type_entry);
6767TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
......@@ -87,10 +87,9 @@ ZigFn *create_fn(AstNode *proto_node);
8787ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
8888void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
8989AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
90ZigFn *scope_get_fn_if_root(Scope *scope);
9190bool type_requires_comptime(ZigType *type_entry);
9291Error 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);
9493void complete_enum(CodeGen *g, ZigType *enum_type);
9594bool ir_get_var_is_comptime(ZigVar *var);
9695bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
......@@ -209,6 +208,8 @@ ZigType *get_primitive_type(CodeGen *g, Buf *name);
209208bool calling_convention_allows_zig_types(CallingConvention cc);
210209const char *calling_convention_name(CallingConvention cc);
211210
211Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents);
212
212213void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
213214X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
214215bool 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) {
193193 return "NullLiteral";
194194 case NodeTypeUndefinedLiteral:
195195 return "UndefinedLiteral";
196 case NodeTypeThisLiteral:
197 return "ThisLiteral";
198196 case NodeTypeIfBoolExpr:
199197 return "IfBoolExpr";
200198 case NodeTypeWhileExpr:
......@@ -897,11 +895,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
897895 }
898896 break;
899897 }
900 case NodeTypeThisLiteral:
901 {
902 fprintf(ar->f, "this");
903 break;
904 }
905898 case NodeTypeBoolLiteral:
906899 {
907900 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) {
7878 return buf;
7979}
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
8185static inline Buf *buf_create_from_str(const char *str) {
8286 return buf_create_from_mem(str, strlen(str));
8387}
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 @@
88#include "analyze.hpp"
99#include "ast_render.hpp"
1010#include "codegen.hpp"
11#include "compiler.hpp"
1112#include "config.h"
1213#include "errmsg.hpp"
1314#include "error.hpp"
1415#include "hash_map.hpp"
1516#include "ir.hpp"
16#include "link.hpp"
1717#include "os.hpp"
1818#include "translate_c.hpp"
1919#include "target.hpp"
......@@ -183,14 +183,14 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
183183 return g;
184184}
185185
186void codegen_destroy(CodeGen *codegen) {
187 LLVMDisposeTargetMachine(codegen->target_machine);
188}
189
190186void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
191187 g->out_h_path = h_path;
192188}
193189
190void codegen_set_output_path(CodeGen *g, Buf *path) {
191 g->wanted_output_file_path = path;
192}
193
194194void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
195195 g->clang_argv = args;
196196 g->clang_argv_len = len;
......@@ -243,10 +243,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
243243 g->root_out_name = out_name;
244244}
245245
246void codegen_set_cache_dir(CodeGen *g, Buf cache_dir) {
247 g->cache_dir = cache_dir;
248}
249
250246void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
251247 g->libc_lib_dir = libc_lib_dir;
252248}
......@@ -779,7 +775,8 @@ static LLVMValueRef gen_store_untyped(CodeGen *g, LLVMValueRef value, LLVMValueR
779775
780776static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, ZigType *ptr_type) {
781777 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);
783780}
784781
785782static 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
797794
798795static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) {
799796 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);
801799}
802800
803801static 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
17721770
17731771 ZigType *usize = g->builtin_types.entry_usize;
17741772 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);
17761774 assert(size_bytes > 0);
17771775 assert(align_bytes > 0);
17781776
......@@ -3162,7 +3160,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31623160 assert(var->value->type == init_value->value.type);
31633161 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
31643162 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);
31663165 } else {
31673166 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
31683167 if (want_safe) {
......@@ -4022,7 +4021,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
40224021 LLVMValueRef ptr_val;
40234022
40244023 if (target_type->id == ZigTypeIdPointer) {
4025 align_bytes = target_type->data.pointer.alignment;
4024 align_bytes = get_ptr_align(g, target_type);
40264025 ptr_val = target_val;
40274026 } else if (target_type->id == ZigTypeIdFn) {
40284027 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
40304029 } else if (target_type->id == ZigTypeIdOptional &&
40314030 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
40324031 {
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);
40344033 ptr_val = target_val;
40354034 } else if (target_type->id == ZigTypeIdOptional &&
40364035 target_type->data.maybe.child_type->id == ZigTypeIdFn)
......@@ -4043,7 +4042,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
40434042 zig_panic("TODO audit this function");
40444043 } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
40454044 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
40484047 size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
40494048 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
41954194 ZigType *ptr_type = instruction->dest_ptr->value.type;
41964195 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);
41994198 return nullptr;
42004199}
42014200
......@@ -4216,9 +4215,8 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns
42164215 assert(src_ptr_type->id == ZigTypeIdPointer);
42174216
42184217 bool is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile);
4219
4220 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, dest_ptr_type->data.pointer.alignment,
4221 src_ptr_casted, src_ptr_type->data.pointer.alignment, len_val, is_volatile);
4218 ZigLLVMBuildMemCpy(g->builder, dest_ptr_casted, get_ptr_align(g, dest_ptr_type),
4219 src_ptr_casted, get_ptr_align(g, src_ptr_type), len_val, is_volatile);
42224220 return nullptr;
42234221}
42244222
......@@ -4629,7 +4627,6 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa
46294627
46304628static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, IrInstructionUnionTag *instruction) {
46314629 ZigType *union_type = instruction->value->value.type;
4632 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
46334630
46344631 ZigType *tag_type = union_type->data.unionation.tag_type;
46354632 if (!type_has_bits(tag_type))
......@@ -4639,6 +4636,7 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
46394636 if (union_type->data.unionation.gen_field_count == 0)
46404637 return union_val;
46414638
4639 assert(union_type->data.unionation.gen_tag_index != SIZE_MAX);
46424640 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val,
46434641 union_type->data.unionation.gen_tag_index, "");
46444642 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
53935391 case ZigTypeIdErrorUnion:
53945392 case ZigTypeIdErrorSet:
53955393 case ZigTypeIdNamespace:
5396 case ZigTypeIdBlock:
53975394 case ZigTypeIdBoundFn:
53985395 case ZigTypeIdArgTuple:
53995396 case ZigTypeIdVoid:
......@@ -5774,12 +5771,24 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
57745771 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
57755772 &const_val->data.x_union.tag);
57765773
5777 LLVMValueRef fields[2];
5774 LLVMValueRef fields[3];
57785775 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
57795776 fields[type_entry->data.unionation.gen_tag_index] = tag_value;
57805777
57815778 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;
57835792 } else {
57845793 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
57855794 }
......@@ -5789,9 +5798,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
57895798 case ZigTypeIdEnum:
57905799 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag);
57915800 case ZigTypeIdFn:
5792 assert(const_val->data.x_ptr.special == ConstPtrSpecialFunction);
5793 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
5794 return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry);
5801 if (const_val->data.x_ptr.special == ConstPtrSpecialFunction) {
5802 assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
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 }
57955811 case ZigTypeIdPointer:
57965812 return gen_const_val_ptr(g, const_val, name);
57975813 case ZigTypeIdErrorUnion:
......@@ -5819,13 +5835,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58195835 err_payload_value = gen_const_val(g, payload_val, "");
58205836 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);
58215837 }
5822 LLVMValueRef fields[] = {
5823 err_tag_value,
5824 err_payload_value,
5825 };
58265838 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 }
58285856 } else {
5857 LLVMValueRef fields[] = {
5858 err_tag_value,
5859 err_payload_value,
5860 };
58295861 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
58305862 }
58315863 }
......@@ -5840,7 +5872,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58405872 case ZigTypeIdUndefined:
58415873 case ZigTypeIdNull:
58425874 case ZigTypeIdNamespace:
5843 case ZigTypeIdBlock:
58445875 case ZigTypeIdBoundFn:
58455876 case ZigTypeIdArgTuple:
58465877 case ZigTypeIdOpaque:
......@@ -5958,13 +5989,6 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
59585989 // TODO ^^ make an actual global variable
59595990}
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
59685992static void validate_inline_fns(CodeGen *g) {
59695993 for (size_t i = 0; i < g->inline_fns.length; i += 1) {
59705994 ZigFn *fn_entry = g->inline_fns.at(i);
......@@ -5979,8 +6003,6 @@ static void validate_inline_fns(CodeGen *g) {
59796003static void do_code_gen(CodeGen *g) {
59806004 assert(!g->errors.length);
59816005
5982 codegen_add_time_event(g, "Code Generation");
5983
59846006 {
59856007 // create debug type for error sets
59866008 assert(g->err_enumerators.length == g->errors_by_index.length);
......@@ -6283,45 +6305,18 @@ static void do_code_gen(CodeGen *g) {
62836305 char *error = nullptr;
62846306 LLVMVerifyModule(g->module, LLVMAbortProcessAction, &error);
62856307#endif
6308}
62866309
6287 codegen_add_time_event(g, "LLVM Emit Output");
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
6310static void zig_llvm_emit_output(CodeGen *g) {
63196311 bool is_small = g->build_mode == BuildModeSmallRelease;
63206312
6313 Buf *output_path = &g->o_file_output_path;
6314 char *err_msg = nullptr;
63216315 switch (g->emit_file_type) {
63226316 case EmitFileTypeBinary:
63236317 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))
63256320 {
63266321 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
63276322 }
......@@ -6331,22 +6326,22 @@ static void do_code_gen(CodeGen *g) {
63316326
63326327 case EmitFileTypeAssembly:
63336328 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))
63356331 {
63366332 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
63376333 }
63386334 validate_inline_fns(g);
6339 g->link_objects.append(output_path);
63406335 break;
63416336
63426337 case EmitFileTypeLLVMIr:
63436338 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))
63456341 {
63466342 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
63476343 }
63486344 validate_inline_fns(g);
6349 g->link_objects.append(output_path);
63506345 break;
63516346
63526347 default:
......@@ -6399,12 +6394,6 @@ static void define_builtin_types(CodeGen *g) {
63996394 entry->zero_bits = true;
64006395 g->builtin_types.entry_namespace = entry;
64016396 }
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 }
64086397 {
64096398 ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat);
64106399 buf_init_from_str(&entry->name, "comptime_float");
......@@ -6651,7 +6640,7 @@ static void define_builtin_fns(CodeGen *g) {
66516640 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
66526641 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
66536642 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
6654 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2);
6643 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
66556644 create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
66566645 create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2);
66576646 create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2);
......@@ -6685,6 +6674,7 @@ static void define_builtin_fns(CodeGen *g) {
66856674 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
66866675 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
66876676 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6677 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
66886678}
66896679
66906680static const char *bool_to_str(bool b) {
......@@ -6866,7 +6856,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
68666856 " Union: Union,\n"
68676857 " Fn: Fn,\n"
68686858 " Namespace: void,\n"
6869 " Block: void,\n"
68706859 " BoundFn: Fn,\n"
68716860 " ArgTuple: void,\n"
68726861 " Opaque: void,\n"
......@@ -7037,11 +7026,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
70377026 {
70387027 buf_appendf(contents,
70397028 "pub const FloatMode = enum {\n"
7040 " Optimized,\n"
70417029 " Strict,\n"
7030 " Optimized,\n"
70427031 "};\n\n");
7043 assert(FloatModeOptimized == 0);
7044 assert(FloatModeStrict == 1);
7032 assert(FloatModeStrict == 0);
7033 assert(FloatModeOptimized == 1);
70457034 }
70467035 {
70477036 buf_appendf(contents,
......@@ -7049,8 +7038,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
70497038 " Big,\n"
70507039 " Little,\n"
70517040 "};\n\n");
7052 assert(FloatModeOptimized == 0);
7053 assert(FloatModeStrict == 1);
7041 //assert(EndianBig == 0);
7042 //assert(EndianLittle == 1);
70547043 }
70557044 {
70567045 const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
......@@ -7071,36 +7060,84 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
70717060 return contents;
70727061}
70737062
7074static void define_builtin_compile_vars(CodeGen *g) {
7063static Error define_builtin_compile_vars(CodeGen *g) {
70757064 if (g->std_package == nullptr)
7076 return;
7065 return ErrorNone;
70777066
7078 const char *builtin_zig_basename = "builtin.zig";
7079 Buf *builtin_zig_path = buf_alloc();
7080 os_path_join(&g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path);
7067 Error err;
70817068
7082 Buf *contents = codegen_generate_builtin_source(g);
7083 ensure_cache_dir(g);
7084 os_write_file(builtin_zig_path, contents);
7069 Buf *manifest_dir = buf_alloc();
7070 os_path_join(get_stage1_cache_path(), buf_create_from_str("builtin"), manifest_dir);
70857071
7086 Buf *resolved_path = buf_alloc();
7087 Buf *resolve_paths[] = {builtin_zig_path};
7088 *resolved_path = os_path_resolve(resolve_paths, 1);
7072 CacheHash cache_hash;
7073 cache_init(&cache_hash, manifest_dir);
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
70907126 assert(g->root_package);
70917127 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);
70937129 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
70947130 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);
70967132 scan_import(g, g->compile_var_import);
7133
7134 return ErrorNone;
70977135}
70987136
70997137static void init(CodeGen *g) {
71007138 if (g->module)
71017139 return;
71027140
7103
71047141 if (g->llvm_argv_len > 0) {
71057142 const char **args = allocate_nonzero<const char *>(g->llvm_argv_len + 2);
71067143 args[0] = "zig (LLVM option parsing)";
......@@ -7207,7 +7244,11 @@ static void init(CodeGen *g) {
72077244 g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease && g->build_mode != BuildModeSmallRelease;
72087245
72097246 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 }
72117252}
72127253
72137254void codegen_translate_c(CodeGen *g, Buf *full_path) {
......@@ -7253,8 +7294,8 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
72537294 Buf *resolved_path = buf_alloc();
72547295 *resolved_path = os_path_resolve(resolve_paths, 1);
72557296 Buf *import_code = buf_alloc();
7256 int err;
7257 if ((err = os_fetch_file_path(resolved_path, import_code, false))) {
7297 Error err;
7298 if ((err = file_fetch(g, resolved_path, import_code))) {
72587299 zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
72597300 }
72607301
......@@ -7327,23 +7368,32 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
73277368 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");
73287369}
73297370
7330static void gen_root_source(CodeGen *g) {
7371static Buf *get_resolved_root_src_path(CodeGen *g) {
7372 // TODO memoize
73317373 if (buf_len(&g->root_package->root_src_path) == 0)
7332 return;
7374 return nullptr;
73337375
7334 codegen_add_time_event(g, "Semantic Analysis");
7335
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);
7376 Buf rel_full_path = BUF_INIT;
7377 os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, &rel_full_path);
73387378
73397379 Buf *resolved_path = buf_alloc();
7340 Buf *resolve_paths[] = {rel_full_path};
7380 Buf *resolve_paths[] = {&rel_full_path};
73417381 *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
73437391 Buf *source_code = buf_alloc();
73447392 int err;
7345 if ((err = os_fetch_file_path(rel_full_path, source_code, true))) {
7346 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(rel_full_path), err_str(err));
7393 // No need for using the caching system for this file fetch because it is handled
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));
73477397 exit(1);
73487398 }
73497399
......@@ -7408,6 +7458,8 @@ static void gen_global_asm(CodeGen *g) {
74087458 int err;
74097459 for (size_t i = 0; i < g->assembly_files.length; i += 1) {
74107460 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.
74117463 if ((err = os_fetch_file_path(asm_file, &contents, false))) {
74127464 zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
74137465 }
......@@ -7448,7 +7500,6 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
74487500 case ZigTypeIdUndefined:
74497501 case ZigTypeIdNull:
74507502 case ZigTypeIdNamespace:
7451 case ZigTypeIdBlock:
74527503 case ZigTypeIdBoundFn:
74537504 case ZigTypeIdArgTuple:
74547505 case ZigTypeIdErrorUnion:
......@@ -7627,7 +7678,6 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
76277678 case ZigTypeIdMetaType:
76287679 case ZigTypeIdBoundFn:
76297680 case ZigTypeIdNamespace:
7630 case ZigTypeIdBlock:
76317681 case ZigTypeIdComptimeFloat:
76327682 case ZigTypeIdComptimeInt:
76337683 case ZigTypeIdUndefined:
......@@ -7671,19 +7721,11 @@ static Buf *preprocessor_mangle(Buf *src) {
76717721}
76727722
76737723static void gen_h_file(CodeGen *g) {
7674 if (!g->want_h_file)
7675 return;
7676
76777724 GenH gen_h_data = {0};
76787725 GenH *gen_h = &gen_h_data;
76797726
7680 codegen_add_time_event(g, "Generate .h");
7681
76827727 assert(!g->is_test_build);
7683
7684 if (!g->out_h_path) {
7685 g->out_h_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
7686 }
7728 assert(g->out_h_path != nullptr);
76877729
76887730 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");
76897731 if (!out_h)
......@@ -7788,7 +7830,6 @@ static void gen_h_file(CodeGen *g) {
77887830 case ZigTypeIdErrorUnion:
77897831 case ZigTypeIdErrorSet:
77907832 case ZigTypeIdNamespace:
7791 case ZigTypeIdBlock:
77927833 case ZigTypeIdBoundFn:
77937834 case ZigTypeIdArgTuple:
77947835 case ZigTypeIdOptional:
......@@ -7886,14 +7927,231 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
78867927 g->timing_events.append({os_get_time(), name});
78877928}
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;
78908092 assert(g->out_type != OutTypeUnknown);
7891 init(g);
78928093
7893 gen_global_asm(g);
7894 gen_root_source(g);
7895 do_code_gen(g);
7896 gen_h_file(g);
8094 Buf *stage1_dir = get_stage1_cache_path();
8095 Buf *artifact_dir = buf_alloc();
8096 Buf digest = BUF_INIT;
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");
78978155}
78988156
78998157PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path) {
src/codegen.hpp+3-3
......@@ -16,7 +16,6 @@
1616
1717CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
1818 Buf *zig_lib_dir);
19void codegen_destroy(CodeGen *codegen);
2019
2120void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2221void 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);
4746void codegen_set_test_filter(CodeGen *g, Buf *filter);
4847void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
4948void 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);
5149void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
50void codegen_set_output_path(CodeGen *g, Buf *path);
5251void codegen_add_time_event(CodeGen *g, const char *name);
5352void 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
5656PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path);
5757void 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) {
2727 case ErrorNegativeDenominator: return "negative denominator";
2828 case ErrorShiftedOutOneBits: return "exact shift shifted out one bits";
2929 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";
3035 }
3136 return "(invalid error)";
3237}
src/error.hpp+5
......@@ -27,6 +27,11 @@ enum Error {
2727 ErrorNegativeDenominator,
2828 ErrorShiftedOutOneBits,
2929 ErrorCCompileErrors,
30 ErrorEndOfFile,
31 ErrorIsDir,
32 ErrorUnsupportedOperatingSystem,
33 ErrorSharingViolation,
34 ErrorPipeBusy,
3035};
3136
3237const char *err_str(int err);
src/ir.cpp+352-233
......@@ -40,6 +40,7 @@ struct IrAnalyze {
4040
4141enum ConstCastResultId {
4242 ConstCastResultIdOk,
43 ConstCastResultIdInvalid,
4344 ConstCastResultIdErrSet,
4445 ConstCastResultIdErrSetGlobal,
4546 ConstCastResultIdPointerChild,
......@@ -1029,12 +1030,6 @@ static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *
10291030 return &const_instruction->base;
10301031}
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
10381033static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) {
10391034 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
10401035 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
10431038 return &const_instruction->base;
10441039}
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
10561041static IrInstruction *ir_build_const_bool(IrBuilder *irb, Scope *scope, AstNode *source_node, bool value) {
10571042 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
10581043 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,
15771562}
15781563
15791564static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstNode *source_node,
1580 IrInstruction *scope_value, IrInstruction *mode_value)
1565 IrInstruction *mode_value)
15811566{
15821567 IrInstructionSetFloatMode *instruction = ir_build_instruction<IrInstructionSetFloatMode>(irb, scope, source_node);
1583 instruction->scope_value = scope_value;
15841568 instruction->mode_value = mode_value;
15851569
1586 ir_ref_instruction(scope_value, irb->current_basic_block);
15871570 ir_ref_instruction(mode_value, irb->current_basic_block);
15881571
15891572 return &instruction->base;
......@@ -3894,6 +3877,21 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode *
38943877 return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr);
38953878}
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
38973895static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
38983896 assert(node->type == NodeTypeFnCallExpr);
38993897
......@@ -3959,12 +3957,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
39593957 if (arg0_value == irb->codegen->invalid_instruction)
39603958 return arg0_value;
39613959
3962 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
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);
3960 IrInstruction *set_float_mode = ir_build_set_float_mode(irb, scope, node, arg0_value);
39683961 return ir_lval_wrap(irb, scope, set_float_mode, lval);
39693962 }
39703963 case BuiltinFnIdSizeof:
......@@ -4837,6 +4830,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
48374830 IrInstruction *opaque_type = ir_build_opaque_type(irb, scope, node);
48384831 return ir_lval_wrap(irb, scope, opaque_type, lval);
48394832 }
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 }
48404838 case BuiltinFnIdSetAlignStack:
48414839 {
48424840 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
56885686 return ir_build_phi(irb, parent_scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items);
56895687}
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
57185689static IrInstruction *ir_gen_bool_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
57195690 assert(node->type == NodeTypeBoolLiteral);
57205691 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
72927263
72937264 return ir_build_load_ptr(irb, scope, node, unwrapped_ptr);
72947265 }
7295 case NodeTypeThisLiteral:
7296 return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
72977266 case NodeTypeBoolLiteral:
72987267 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
72997268 case NodeTypeArrayType:
......@@ -7522,8 +7491,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
75227491 if (type_has_bits(return_type)) {
75237492 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
75247493 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),
7526 0, 0));
7494 false, false, PtrLenUnknown, 0, 0, 0));
75277495 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
75287496 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
75297497 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
75767544 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
75777545 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
75787546 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),
7580 0, 0));
7547 false, false, PtrLenUnknown, 0, 0, 0));
75817548 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
75827549 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
75837550 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
85488515 ConstCastOnly result = {};
85498516 result.id = ConstCastResultIdOk;
85508517
8518 Error err;
8519
85518520 if (wanted_type == actual_type)
85528521 return result;
85538522
......@@ -8560,6 +8529,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
85608529 {
85618530 ConstCastOnly child = types_match_const_cast_only(ira,
85628531 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
8532 if (child.id == ConstCastResultIdInvalid)
8533 return child;
85638534 if (child.id != ConstCastResultIdOk) {
85648535 result.id = ConstCastResultIdNullWrapPtr;
85658536 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
85768547 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
85778548 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
85788549 {
8579 assert(actual_type->data.pointer.alignment >= wanted_type->data.pointer.alignment);
85808550 return result;
85818551 }
85828552
......@@ -8584,6 +8554,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
85848554 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
85858555 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
85868556 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8557 if (child.id == ConstCastResultIdInvalid)
8558 return child;
85878559 if (child.id != ConstCastResultIdOk) {
85888560 result.id = ConstCastResultIdPointerChild;
85898561 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
......@@ -8592,12 +8564,20 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
85928564 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
85938565 return result;
85948566 }
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 }
85958575 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
85968576 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
85978577 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
85988578 actual_type->data.pointer.bit_offset == wanted_type->data.pointer.bit_offset &&
85998579 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))
86018581 {
86028582 return result;
86038583 }
......@@ -8607,14 +8587,24 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86078587 if (is_slice(wanted_type) && is_slice(actual_type)) {
86088588 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
86098589 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 }
86108598 if ((!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
86118599 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
86128600 actual_ptr_type->data.pointer.bit_offset == wanted_ptr_type->data.pointer.bit_offset &&
86138601 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))
86158603 {
86168604 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
86178605 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
8606 if (child.id == ConstCastResultIdInvalid)
8607 return child;
86188608 if (child.id != ConstCastResultIdOk) {
86198609 result.id = ConstCastResultIdSliceChild;
86208610 result.data.slice_mismatch = allocate_nonzero<ConstCastSliceMismatch>(1);
......@@ -8630,6 +8620,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86308620 if (wanted_type->id == ZigTypeIdOptional && actual_type->id == ZigTypeIdOptional) {
86318621 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.maybe.child_type,
86328622 actual_type->data.maybe.child_type, source_node, wanted_is_mutable);
8623 if (child.id == ConstCastResultIdInvalid)
8624 return child;
86338625 if (child.id != ConstCastResultIdOk) {
86348626 result.id = ConstCastResultIdOptionalChild;
86358627 result.data.optional = allocate_nonzero<ConstCastOptionalMismatch>(1);
......@@ -8644,6 +8636,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86448636 if (wanted_type->id == ZigTypeIdErrorUnion && actual_type->id == ZigTypeIdErrorUnion) {
86458637 ConstCastOnly payload_child = types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type,
86468638 actual_type->data.error_union.payload_type, source_node, wanted_is_mutable);
8639 if (payload_child.id == ConstCastResultIdInvalid)
8640 return payload_child;
86478641 if (payload_child.id != ConstCastResultIdOk) {
86488642 result.id = ConstCastResultIdErrorUnionPayload;
86498643 result.data.error_union_payload = allocate_nonzero<ConstCastErrUnionPayloadMismatch>(1);
......@@ -8654,6 +8648,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
86548648 }
86558649 ConstCastOnly error_set_child = types_match_const_cast_only(ira, wanted_type->data.error_union.err_set_type,
86568650 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;
86578653 if (error_set_child.id != ConstCastResultIdOk) {
86588654 result.id = ConstCastResultIdErrorUnionErrorSet;
86598655 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
87418737 {
87428738 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.fn.fn_type_id.return_type,
87438739 actual_type->data.fn.fn_type_id.return_type, source_node, false);
8740 if (child.id == ConstCastResultIdInvalid)
8741 return child;
87448742 if (child.id != ConstCastResultIdOk) {
87458743 result.id = ConstCastResultIdFnReturnType;
87468744 result.data.return_type = allocate_nonzero<ConstCastOnly>(1);
......@@ -8753,6 +8751,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
87538751 actual_type->data.fn.fn_type_id.async_allocator_type,
87548752 wanted_type->data.fn.fn_type_id.async_allocator_type,
87558753 source_node, false);
8754 if (child.id == ConstCastResultIdInvalid)
8755 return child;
87568756 if (child.id != ConstCastResultIdOk) {
87578757 result.id = ConstCastResultIdAsyncAllocatorType;
87588758 result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);
......@@ -8777,6 +8777,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
87778777
87788778 ConstCastOnly arg_child = types_match_const_cast_only(ira, actual_param_info->type,
87798779 expected_param_info->type, source_node, false);
8780 if (arg_child.id == ConstCastResultIdInvalid)
8781 return arg_child;
87808782 if (arg_child.id != ConstCastResultIdOk) {
87818783 result.id = ConstCastResultIdFnArg;
87828784 result.data.fn_arg.arg_index = i;
......@@ -9270,7 +9272,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
92709272 if (prev_type->id == ZigTypeIdEnum && cur_type->id == ZigTypeIdUnion &&
92719273 (cur_type->data.unionation.decl_node->data.container_decl.auto_enum || cur_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
92729274 {
9273 if ((err = type_ensure_zero_bits_known(ira->codegen, cur_type)))
9275 if ((err = type_resolve(ira->codegen, cur_type, ResolveStatusZeroBitsKnown)))
92749276 return ira->codegen->builtin_types.entry_invalid;
92759277 if (cur_type->data.unionation.tag_type == prev_type) {
92769278 continue;
......@@ -9280,7 +9282,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
92809282 if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdUnion &&
92819283 (prev_type->data.unionation.decl_node->data.container_decl.auto_enum || prev_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
92829284 {
9283 if ((err = type_ensure_zero_bits_known(ira->codegen, prev_type)))
9285 if ((err = type_resolve(ira->codegen, prev_type, ResolveStatusZeroBitsKnown)))
92849286 return ira->codegen->builtin_types.entry_invalid;
92859287 if (prev_type->data.unionation.tag_type == cur_type) {
92869288 prev_inst = cur_inst;
......@@ -9306,8 +9308,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
93069308 ZigType *ptr_type = get_pointer_to_type_extra(
93079309 ira->codegen, prev_inst->value.type->data.array.child_type,
93089310 true, false, PtrLenUnknown,
9309 get_abi_alignment(ira->codegen, prev_inst->value.type->data.array.child_type),
9310 0, 0);
9311 0, 0, 0);
93119312 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
93129313 if (err_set_type != nullptr) {
93139314 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,
95049505 IrInstruction *value, ZigType *wanted_type)
95059506{
95069507 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
95099519 if (instr_is_comptime(value)) {
95109520 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,
95329542static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
95339543 IrInstruction *value, ZigType *wanted_type)
95349544{
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
95379555 if (instr_is_comptime(value)) {
95389556 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,
97199737 ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile)
97209738{
97219739 IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee,
9722 pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile,
9723 get_abi_alignment(ira->codegen, pointee_type));
9740 pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile, 0);
97249741 ir_link_new_instruction(const_instr, instruction);
97259742 return const_instr->value.type;
97269743}
......@@ -10037,20 +10054,24 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
1003710054static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,
1003810055 bool is_const, bool is_volatile)
1003910056{
10057 Error err;
10058
1004010059 if (type_is_invalid(value->value.type))
1004110060 return ira->codegen->invalid_instruction;
1004210061
10062 if ((err = type_resolve(ira->codegen, value->value.type, ResolveStatusZeroBitsKnown)))
10063 return ira->codegen->invalid_instruction;
10064
1004310065 if (instr_is_comptime(value)) {
1004410066 ConstExprValue *val = ir_resolve_const(ira, value, UndefOk);
1004510067 if (!val)
1004610068 return ira->codegen->invalid_instruction;
1004710069 return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
10048 ConstPtrMutComptimeConst, is_const, is_volatile,
10049 get_abi_alignment(ira->codegen, value->value.type));
10070 ConstPtrMutComptimeConst, is_const, is_volatile, 0);
1005010071 }
1005110072
1005210073 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);
1005410075 IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
1005510076 source_instruction->source_node, value, is_const, is_volatile);
1005610077 new_instruction->value.type = ptr_type;
......@@ -10113,7 +10134,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
1011310134 IrInstruction *target, ZigType *wanted_type)
1011410135{
1011510136 Error err;
10116 assert(wanted_type->id == ZigTypeIdInt);
10137 assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt);
1011710138
1011810139 ZigType *actual_type = target->value.type;
1011910140 if ((err = ensure_complete_type(ira->codegen, actual_type)))
......@@ -10139,6 +10160,18 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
1013910160 return result;
1014010161 }
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
1014210175 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
1014310176 source_instr->source_node, target);
1014410177 result->value.type = wanted_type;
......@@ -10164,6 +10197,19 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1016410197 return result;
1016510198 }
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
1016710213 IrInstruction *result = ir_build_union_tag(&ira->new_irb, source_instr->scope,
1016810214 source_instr->source_node, target);
1016910215 result->value.type = wanted_type;
......@@ -10192,9 +10238,9 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1019210238 return ira->codegen->invalid_instruction;
1019310239 TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
1019410240 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)))
1019610242 return ira->codegen->invalid_instruction;
10197 if (!union_field->type_entry->zero_bits) {
10243 if (type_has_bits(union_field->type_entry)) {
1019810244 AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(
1019910245 union_field->enum_field->decl_index);
1020010246 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -10497,7 +10543,10 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
1049710543 ZigType *wanted_type)
1049810544{
1049910545 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));
1050110550 ZigType *array_type = wanted_type->data.pointer.child_type;
1050210551 assert(array_type->id == ZigTypeIdArray);
1050310552 assert(array_type->data.array.len == 1);
......@@ -10544,6 +10593,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1054410593 switch (cast_result->id) {
1054510594 case ConstCastResultIdOk:
1054610595 zig_unreachable();
10596 case ConstCastResultIdInvalid:
10597 zig_unreachable();
1054710598 case ConstCastResultIdOptionalChild: {
1054810599 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
1054910600 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
1064310694 // perfect match or non-const to const
1064410695 ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type,
1064510696 source_node, false);
10697 if (const_cast_result.id == ConstCastResultIdInvalid)
10698 return ira->codegen->invalid_instruction;
1064610699 if (const_cast_result.id == ConstCastResultIdOk) {
1064710700 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
1064810701 }
......@@ -10758,13 +10811,19 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1075810811 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
1075910812 actual_type->id == ZigTypeIdPointer &&
1076010813 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10761 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)
10814 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
1076610815 {
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 }
1076810827 }
1076910828
1077010829 // *[N]T to []T
......@@ -10818,16 +10877,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1081810877 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
1081910878 actual_type->id == ZigTypeIdPointer &&
1082010879 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10821 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)
10880 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
1082610881 {
10827 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_child_type);
10828 if (type_is_invalid(cast1->value.type))
10882 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
1082910883 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 }
1083110897 }
1083210898 }
1083310899
......@@ -10970,7 +11036,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1097011036
1097111037 // cast from union to the enum type of the union
1097211038 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)))
1097411040 return ira->codegen->invalid_instruction;
1097511041
1097611042 if (actual_type->data.unionation.tag_type == wanted_type) {
......@@ -10983,7 +11049,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1098311049 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
1098411050 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
1098511051 {
10986 if ((err = type_ensure_zero_bits_known(ira->codegen, wanted_type)))
11052 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
1098711053 return ira->codegen->invalid_instruction;
1098811054
1098911055 if (wanted_type->data.unionation.tag_type == actual_type) {
......@@ -10997,7 +11063,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1099711063 if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
1099811064 union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
1099911065 {
11000 if ((err = type_ensure_zero_bits_known(ira->codegen, union_type)))
11066 if ((err = type_resolve(ira->codegen, union_type, ResolveStatusZeroBitsKnown)))
1100111067 return ira->codegen->invalid_instruction;
1100211068
1100311069 if (union_type->data.unionation.tag_type == actual_type) {
......@@ -11024,14 +11090,24 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1102411090 actual_type->data.pointer.child_type, source_node,
1102511091 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
1102611092 {
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) {
1102811106 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
1102911107 add_error_note(ira->codegen, msg, value->source_node,
11030 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name),
11031 actual_type->data.pointer.alignment));
11108 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), actual_align));
1103211109 add_error_note(ira->codegen, msg, source_instr->source_node,
11033 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name),
11034 wanted_type->data.pointer.alignment));
11110 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), wanted_align));
1103511111 return ira->codegen->invalid_instruction;
1103611112 }
1103711113 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
1104311119 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
1104411120 actual_type, source_node, !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
1104511121 {
11046 if ((err = type_ensure_zero_bits_known(ira->codegen, actual_type))) {
11122 if ((err = type_resolve(ira->codegen, actual_type, ResolveStatusZeroBitsKnown))) {
1104711123 return ira->codegen->invalid_instruction;
1104811124 }
1104911125 if (!type_has_bits(actual_type)) {
......@@ -11289,8 +11365,7 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
1128911365 return nullptr;
1129011366
1129111367 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
11292 true, false, PtrLenUnknown,
11293 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
11368 true, false, PtrLenUnknown, 0, 0, 0);
1129411369 ZigType *str_type = get_slice_type(ira->codegen, ptr_type);
1129511370 IrInstruction *casted_value = ir_implicit_cast(ira, value, str_type);
1129611371 if (type_is_invalid(casted_value->value.type))
......@@ -11580,8 +11655,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
1158011655 ZigType *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
1158111656 if (type_is_invalid(resolved_type))
1158211657 return resolved_type;
11583 if ((err = type_ensure_zero_bits_known(ira->codegen, resolved_type)))
11584 return resolved_type;
1158511658
1158611659 bool operator_allowed;
1158711660 switch (resolved_type->id) {
......@@ -11603,7 +11676,6 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
1160311676 case ZigTypeIdFn:
1160411677 case ZigTypeIdOpaque:
1160511678 case ZigTypeIdNamespace:
11606 case ZigTypeIdBlock:
1160711679 case ZigTypeIdBoundFn:
1160811680 case ZigTypeIdArgTuple:
1160911681 case ZigTypeIdPromise:
......@@ -11638,6 +11710,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
1163811710 if (casted_op2 == ira->codegen->invalid_instruction)
1163911711 return ira->codegen->builtin_types.entry_invalid;
1164011712
11713 if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown)))
11714 return resolved_type;
11715
1164111716 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);
1164211717 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
1164311718 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
1232412399 out_array_val = out_val;
1232512400 } else if (is_slice(op1_type) || is_slice(op2_type)) {
1232612401 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);
1232812403 result_type = get_slice_type(ira->codegen, ptr_type);
1232912404 out_array_val = create_const_vals(1);
1233012405 out_array_val->special = ConstValSpecialStatic;
......@@ -12345,8 +12420,7 @@ static ZigType *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *instruc
1234512420 new_len += 1; // null byte
1234612421
1234712422 // TODO make this `[*]null T` instead of `[*]T`
12348 result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false,
12349 PtrLenUnknown, get_abi_alignment(ira->codegen, child_type), 0, 0);
12423 result_type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0);
1235012424
1235112425 out_array_val = create_const_vals(1);
1235212426 out_array_val->special = ConstValSpecialStatic;
......@@ -12444,10 +12518,22 @@ static ZigType *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *
1244412518 if (type_is_invalid(op1_type))
1244512519 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
1244712527 ZigType *op2_type = ir_resolve_type(ira, instruction->op2->other);
1244812528 if (type_is_invalid(op2_type))
1244912529 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
1245112537 if (type_is_global_error_set(op1_type) ||
1245212538 type_is_global_error_set(op2_type))
1245312539 {
......@@ -12559,7 +12645,7 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
1255912645 if (type_is_invalid(result_type)) {
1256012646 result_type = ira->codegen->builtin_types.entry_invalid;
1256112647 } else {
12562 if ((err = type_ensure_zero_bits_known(ira->codegen, result_type))) {
12648 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) {
1256312649 result_type = ira->codegen->builtin_types.entry_invalid;
1256412650 }
1256512651 }
......@@ -12627,6 +12713,11 @@ static ZigType *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDec
1262712713 }
1262812714
1262912715 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 }
1263012721 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
1263112722 } else {
1263212723 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
1279212883 case ZigTypeIdErrorUnion:
1279312884 case ZigTypeIdErrorSet:
1279412885 case ZigTypeIdNamespace:
12795 case ZigTypeIdBlock:
1279612886 case ZigTypeIdBoundFn:
1279712887 case ZigTypeIdArgTuple:
1279812888 case ZigTypeIdOpaque:
......@@ -12817,7 +12907,6 @@ static ZigType *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExpor
1281712907 case ZigTypeIdErrorSet:
1281812908 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
1281912909 case ZigTypeIdNamespace:
12820 case ZigTypeIdBlock:
1282112910 case ZigTypeIdBoundFn:
1282212911 case ZigTypeIdArgTuple:
1282312912 case ZigTypeIdOpaque:
......@@ -13098,7 +13187,6 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
1309813187static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1309913188 ZigVar *var)
1310013189{
13101 Error err;
1310213190 while (var->next_var != nullptr) {
1310313191 var = var->next_var;
1310413192 }
......@@ -13156,8 +13244,6 @@ no_mem_slot:
1315613244 instruction->scope, instruction->source_node, var);
1315713245 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,
1315813246 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
1316213248 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
1316313249 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
1335413440 IrInstruction *casted_new_stack = nullptr;
1335513441 if (call_instruction->new_stack != nullptr) {
1335613442 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
13357 false, false, PtrLenUnknown,
13358 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8), 0, 0);
13443 false, false, PtrLenUnknown, 0, 0, 0);
1335913444 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
1336013445 IrInstruction *new_stack = call_instruction->new_stack->other;
1336113446 if (type_is_invalid(new_stack->value.type))
......@@ -13534,7 +13619,7 @@ static ZigType *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instr
1353413619 inst_fn_type_id.return_type = specified_return_type;
1353513620 }
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)))
1353813623 return ira->codegen->builtin_types.entry_invalid;
1353913624
1354013625 if (type_requires_comptime(specified_return_type)) {
......@@ -13875,7 +13960,6 @@ static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instru
1387513960 case ZigTypeIdUnion:
1387613961 case ZigTypeIdFn:
1387713962 case ZigTypeIdNamespace:
13878 case ZigTypeIdBlock:
1387913963 case ZigTypeIdBoundFn:
1388013964 case ZigTypeIdArgTuple:
1388113965 case ZigTypeIdPromise:
......@@ -14211,7 +14295,7 @@ static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
1421114295 ptr_type->data.pointer.child_type,
1421214296 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1421314297 ptr_len,
14214 ptr_type->data.pointer.alignment,
14298 ptr_type->data.pointer.explicit_alignment,
1421514299 ptr_type->data.pointer.bit_offset, ptr_type->data.pointer.unaligned_bit_count);
1421614300}
1421714301
......@@ -14263,7 +14347,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
1426314347 return_type = get_pointer_to_type_extra(ira->codegen, child_type,
1426414348 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1426514349 elem_ptr_instruction->ptr_len,
14266 ptr_type->data.pointer.alignment, 0, 0);
14350 ptr_type->data.pointer.explicit_alignment, 0, 0);
1426714351 } else {
1426814352 uint64_t elem_val_scalar;
1426914353 if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
......@@ -14335,7 +14419,7 @@ static ZigType *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionEle
1433514419
1433614420 uint64_t elem_size = type_size(ira->codegen, return_type->data.pointer.child_type);
1433714421 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);
1433914423 if (instr_is_comptime(casted_elem_index)) {
1434014424 uint64_t index = bigint_as_unsigned(&casted_elem_index->value.data.x_bigint);
1434114425 if (array_type->id == ZigTypeIdArray) {
......@@ -14652,9 +14736,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1465214736 }
1465314737
1465414738 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
14655 is_const, is_volatile,
14656 PtrLenSingle,
14657 get_abi_alignment(ira->codegen, field_type), 0, 0);
14739 is_const, is_volatile, PtrLenSingle, 0, 0, 0);
1465814740
1465914741 IrInstruction *result = ir_get_const(ira, source_instr);
1466014742 ConstExprValue *const_val = &result->value;
......@@ -14668,7 +14750,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1466814750
1466914751 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
1467014752 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);
1467214754 return result;
1467314755 } else {
1467414756 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
1500115083 } else if (buf_eql_str(field_name, "alignment")) {
1500215084 bool ptr_is_const = true;
1500315085 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 }
1500415091 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
1500515092 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),
1500715094 ira->codegen->builtin_types.entry_num_lit_int,
1500815095 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
1500915096 } else {
......@@ -15233,7 +15320,6 @@ static ZigType *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeO
1523315320 case ZigTypeIdUndefined:
1523415321 case ZigTypeIdNull:
1523515322 case ZigTypeIdNamespace:
15236 case ZigTypeIdBlock:
1523715323 case ZigTypeIdBoundFn:
1523815324 case ZigTypeIdMetaType:
1523915325 case ZigTypeIdVoid:
......@@ -15342,6 +15428,7 @@ static ZigType *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSet
1534215428 ir_build_const_from(ira, &instruction->base);
1534315429 return ira->codegen->builtin_types.entry_void;
1534415430}
15431
1534515432static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
1534615433 IrInstructionSetRuntimeSafety *set_runtime_safety_instruction)
1534715434{
......@@ -15402,14 +15489,6 @@ static ZigType *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira,
1540215489static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
1540315490 IrInstructionSetFloatMode *instruction)
1540415491{
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
1541315492 if (ira->new_irb.exec->is_inline) {
1541415493 // ignore setFloatMode when running functions at compile time
1541515494 ir_build_const_from(ira, &instruction->base);
......@@ -15418,40 +15497,34 @@ static ZigType *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
1541815497
1541915498 bool *fast_math_on_ptr;
1542015499 AstNode **fast_math_set_node_ptr;
15421 if (target_type->id == ZigTypeIdBlock) {
15422 ScopeBlock *block_scope = (ScopeBlock *)target_val->data.x_block;
15423 fast_math_on_ptr = &block_scope->fast_math_on;
15424 fast_math_set_node_ptr = &block_scope->fast_math_set_node;
15425 } else if (target_type->id == ZigTypeIdFn) {
15426 assert(target_val->data.x_ptr.special == ConstPtrSpecialFunction);
15427 ZigFn *target_fn = target_val->data.x_ptr.data.fn.fn_entry;
15428 assert(target_fn->def_scope);
15429 fast_math_on_ptr = &target_fn->def_scope->fast_math_on;
15430 fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node;
15431 } else if (target_type->id == ZigTypeIdMetaType) {
15432 ScopeDecls *decls_scope;
15433 ZigType *type_arg = target_val->data.x_type;
15434 if (type_arg->id == ZigTypeIdStruct) {
15435 decls_scope = type_arg->data.structure.decls_scope;
15436 } else if (type_arg->id == ZigTypeIdEnum) {
15437 decls_scope = type_arg->data.enumeration.decls_scope;
15438 } else if (type_arg->id == ZigTypeIdUnion) {
15439 decls_scope = type_arg->data.unionation.decls_scope;
15500
15501 Scope *scope = instruction->base.scope;
15502 while (scope != nullptr) {
15503 if (scope->id == ScopeIdBlock) {
15504 ScopeBlock *block_scope = (ScopeBlock *)scope;
15505 fast_math_on_ptr = &block_scope->fast_math_on;
15506 fast_math_set_node_ptr = &block_scope->fast_math_set_node;
15507 break;
15508 } else if (scope->id == ScopeIdFnDef) {
15509 ScopeFnDef *def_scope = (ScopeFnDef *)scope;
15510 ZigFn *target_fn = def_scope->fn_entry;
15511 assert(target_fn->def_scope != nullptr);
15512 fast_math_on_ptr = &target_fn->def_scope->fast_math_on;
15513 fast_math_set_node_ptr = &target_fn->def_scope->fast_math_set_node;
15514 break;
15515 } else if (scope->id == ScopeIdDecls) {
15516 ScopeDecls *decls_scope = (ScopeDecls *)scope;
15517 fast_math_on_ptr = &decls_scope->fast_math_on;
15518 fast_math_set_node_ptr = &decls_scope->fast_math_set_node;
15519 break;
1544015520 } else {
15441 ir_add_error_node(ira, target_instruction->source_node,
15442 buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name)));
15443 return ira->codegen->builtin_types.entry_invalid;
15521 scope = scope->parent;
15522 continue;
1544415523 }
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;
1545115524 }
15525 assert(scope != nullptr);
1545215526
1545315527 IrInstruction *float_mode_value = instruction->mode_value->other;
15454
1545515528 FloatMode float_mode_scalar;
1545615529 if (!ir_resolve_float_mode(ira, float_mode_value, &float_mode_scalar))
1545715530 return ira->codegen->builtin_types.entry_invalid;
......@@ -15474,7 +15547,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1547415547 IrInstructionSliceType *slice_type_instruction)
1547515548{
1547615549 Error err;
15477 uint32_t align_bytes;
15550 uint32_t align_bytes = 0;
1547815551 if (slice_type_instruction->align_value != nullptr) {
1547915552 if (!ir_resolve_align(ira, slice_type_instruction->align_value->other, &align_bytes))
1548015553 return ira->codegen->builtin_types.entry_invalid;
......@@ -15484,12 +15557,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1548415557 if (type_is_invalid(child_type))
1548515558 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
1549315560 bool is_const = slice_type_instruction->is_const;
1549415561 bool is_volatile = slice_type_instruction->is_volatile;
1549515562
......@@ -15499,7 +15566,6 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1549915566 case ZigTypeIdUnreachable:
1550015567 case ZigTypeIdUndefined:
1550115568 case ZigTypeIdNull:
15502 case ZigTypeIdBlock:
1550315569 case ZigTypeIdArgTuple:
1550415570 case ZigTypeIdOpaque:
1550515571 ir_add_error_node(ira, slice_type_instruction->base.source_node,
......@@ -15525,7 +15591,7 @@ static ZigType *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1552515591 case ZigTypeIdBoundFn:
1552615592 case ZigTypeIdPromise:
1552715593 {
15528 if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
15594 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
1552915595 return ira->codegen->builtin_types.entry_invalid;
1553015596 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
1553115597 is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0);
......@@ -15610,7 +15676,6 @@ static ZigType *ir_analyze_instruction_array_type(IrAnalyze *ira,
1561015676 case ZigTypeIdUnreachable:
1561115677 case ZigTypeIdUndefined:
1561215678 case ZigTypeIdNull:
15613 case ZigTypeIdBlock:
1561415679 case ZigTypeIdArgTuple:
1561515680 case ZigTypeIdOpaque:
1561615681 ir_add_error_node(ira, array_type_instruction->base.source_node,
......@@ -15681,7 +15746,6 @@ static ZigType *ir_analyze_instruction_size_of(IrAnalyze *ira,
1568115746 case ZigTypeIdUnreachable:
1568215747 case ZigTypeIdUndefined:
1568315748 case ZigTypeIdNull:
15684 case ZigTypeIdBlock:
1568515749 case ZigTypeIdComptimeFloat:
1568615750 case ZigTypeIdComptimeInt:
1568715751 case ZigTypeIdBoundFn:
......@@ -15767,9 +15831,7 @@ static ZigType *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
1576715831 }
1576815832 ZigType *child_type = type_entry->data.maybe.child_type;
1576915833 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,
15771 PtrLenSingle,
15772 get_abi_alignment(ira->codegen, child_type), 0, 0);
15834 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1577315835
1577415836 if (instr_is_comptime(value)) {
1577515837 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
......@@ -16139,7 +16201,7 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1613916201 return tag_type;
1614016202 }
1614116203 case ZigTypeIdEnum: {
16142 if ((err = type_ensure_zero_bits_known(ira->codegen, target_type)))
16204 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
1614316205 return ira->codegen->builtin_types.entry_invalid;
1614416206 if (target_type->data.enumeration.src_field_count < 2) {
1614516207 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
......@@ -16167,7 +16229,6 @@ static ZigType *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1616716229 case ZigTypeIdUndefined:
1616816230 case ZigTypeIdNull:
1616916231 case ZigTypeIdOptional:
16170 case ZigTypeIdBlock:
1617116232 case ZigTypeIdBoundFn:
1617216233 case ZigTypeIdArgTuple:
1617316234 case ZigTypeIdOpaque:
......@@ -16231,6 +16292,8 @@ static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUn
1623116292}
1623216293
1623316294static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {
16295 Error err;
16296
1623416297 IrInstruction *name_value = import_instruction->name->other;
1623516298 Buf *import_target_str = ir_resolve_str(ira, name_value);
1623616299 if (!import_target_str)
......@@ -16274,8 +16337,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
1627416337 return ira->codegen->builtin_types.entry_namespace;
1627516338 }
1627616339
16277 int err;
16278 if ((err = os_fetch_file_path(resolved_path, import_code, true))) {
16340 if ((err = file_fetch(ira->codegen, resolved_path, import_code))) {
1627916341 if (err == ErrorFileNotFound) {
1628016342 ir_add_error_node(ira, source_node,
1628116343 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
......@@ -16286,6 +16348,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
1628616348 return ira->codegen->builtin_types.entry_invalid;
1628716349 }
1628816350 }
16351
1628916352 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code);
1629016353
1629116354 scan_import(ira->codegen, target_import);
......@@ -16367,7 +16430,7 @@ static ZigType *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruc
1636716430 if (casted_field_value == ira->codegen->invalid_instruction)
1636816431 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)))
1637116434 return ira->codegen->builtin_types.entry_invalid;
1637216435
1637316436 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
1668616749 case ZigTypeIdUnion:
1668716750 case ZigTypeIdFn:
1668816751 case ZigTypeIdNamespace:
16689 case ZigTypeIdBlock:
1669016752 case ZigTypeIdBoundFn:
1669116753 case ZigTypeIdArgTuple:
1669216754 case ZigTypeIdOpaque:
......@@ -16768,7 +16830,7 @@ static ZigType *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstructionErr
1676816830 return ira->codegen->builtin_types.entry_invalid;
1676916831
1677016832 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);
1677216834 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
1677316835 if (casted_value->value.special == ConstValSpecialStatic) {
1677416836 ErrorTableEntry *err = casted_value->value.data.x_err_set;
......@@ -16795,7 +16857,7 @@ static ZigType *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstructi
1679516857 assert(target->value.type->id == ZigTypeIdEnum);
1679616858
1679716859 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)))
1679916861 return ira->codegen->builtin_types.entry_invalid;
1680016862 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
1680116863 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
1681016872 ZigType *u8_ptr_type = get_pointer_to_type_extra(
1681116873 ira->codegen, ira->codegen->builtin_types.entry_u8,
1681216874 true, false, PtrLenUnknown,
16813 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
16814 0, 0);
16875 0, 0, 0);
1681516876 result->value.type = get_slice_type(ira->codegen, u8_ptr_type);
1681616877 return result->value.type;
1681716878}
......@@ -17174,8 +17235,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1717417235 ZigType *u8_ptr = get_pointer_to_type_extra(
1717517236 ira->codegen, ira->codegen->builtin_types.entry_u8,
1717617237 true, false, PtrLenUnknown,
17177 get_abi_alignment(ira->codegen, ira->codegen->builtin_types.entry_u8),
17178 0, 0);
17238 0, 0, 0);
1717917239 fn_def_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
1718017240 if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
1718117241 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
1729517355 ensure_field_index(result->type, "alignment", 3);
1729617356 fields[3].special = ConstValSpecialStatic;
1729717357 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));
1729917359 // child: type
1730017360 ensure_field_index(result->type, "child", 4);
1730117361 fields[4].special = ConstValSpecialStatic;
......@@ -17349,7 +17409,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1734917409 case ZigTypeIdUndefined:
1735017410 case ZigTypeIdNull:
1735117411 case ZigTypeIdNamespace:
17352 case ZigTypeIdBlock:
1735317412 case ZigTypeIdArgTuple:
1735417413 case ZigTypeIdOpaque:
1735517414 *out = nullptr;
......@@ -17959,6 +18018,12 @@ static ZigType *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTy
1795918018}
1796018019
1796118020static 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
1796218027 AstNode *node = instruction->base.source_node;
1796318028 assert(node->type == NodeTypeFnCallExpr);
1796418029 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
1810518170 // load from file system into const expr
1810618171 Buf *file_contents = buf_alloc();
1810718172 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))) {
1810918174 if (err == ErrorFileNotFound) {
1811018175 ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
1811118176 return ira->codegen->builtin_types.entry_invalid;
......@@ -18115,9 +18180,6 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
1811518180 }
1811618181 }
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
1812118183 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1812218184 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
1838318445 return dest_type;
1838418446}
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
1838618460static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
18461 Error err;
18462
1838718463 ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
1838818464 if (type_is_invalid(dest_child_type))
1838918465 return ira->codegen->builtin_types.entry_invalid;
......@@ -18398,15 +18474,23 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
1839818474 if (target->value.type->id == ZigTypeIdPointer) {
1839918475 src_ptr_const = target->value.type->data.pointer.is_const;
1840018476 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;
1840218480 } else if (is_slice(target->value.type)) {
1840318481 ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
1840418482 src_ptr_const = src_ptr_type->data.pointer.is_const;
1840518483 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;
1840718487 } else {
1840818488 src_ptr_const = true;
1840918489 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
1841018494 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
1841118495 }
1841218496
......@@ -18464,6 +18548,8 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
1846418548}
1846518549
1846618550static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
18551 Error err;
18552
1846718553 IrInstruction *target = instruction->target->other;
1846818554 if (type_is_invalid(target->value.type))
1846918555 return ira->codegen->builtin_types.entry_invalid;
......@@ -18476,9 +18562,13 @@ static ZigType *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToB
1847618562
1847718563 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
1847918569 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
1848018570 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);
1848218572 ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
1848318573
1848418574 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
1863618726}
1863718727
1863818728static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemset *instruction) {
18729 Error err;
18730
1863918731 IrInstruction *dest_ptr = instruction->dest_ptr->other;
1864018732 if (type_is_invalid(dest_ptr->value.type))
1864118733 return ira->codegen->builtin_types.entry_invalid;
......@@ -18654,8 +18746,13 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
1865418746
1865518747 ZigType *usize = ira->codegen->builtin_types.entry_usize;
1865618748 ZigType *u8 = ira->codegen->builtin_types.entry_u8;
18657 uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?
18658 dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
18749 uint32_t dest_align;
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 }
1865918756 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, u8, false, dest_is_volatile,
1866018757 PtrLenUnknown, dest_align, 0, 0);
1866118758
......@@ -18728,6 +18825,8 @@ static ZigType *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructionMemse
1872818825}
1872918826
1873018827static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcpy *instruction) {
18828 Error err;
18829
1873118830 IrInstruction *dest_ptr = instruction->dest_ptr->other;
1873218831 if (type_is_invalid(dest_ptr->value.type))
1873318832 return ira->codegen->builtin_types.entry_invalid;
......@@ -18747,10 +18846,22 @@ static ZigType *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructionMemcp
1874718846 dest_uncasted_type->data.pointer.is_volatile;
1874818847 bool src_is_volatile = (src_uncasted_type->id == ZigTypeIdPointer) &&
1874918848 src_uncasted_type->data.pointer.is_volatile;
18750 uint32_t dest_align = (dest_uncasted_type->id == ZigTypeIdPointer) ?
18751 dest_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
18752 uint32_t src_align = (src_uncasted_type->id == ZigTypeIdPointer) ?
18753 src_uncasted_type->data.pointer.alignment : get_abi_alignment(ira->codegen, u8);
18849
18850 uint32_t dest_align;
18851 if (dest_uncasted_type->id == ZigTypeIdPointer) {
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
1875518866 ZigType *usize = ira->codegen->builtin_types.entry_usize;
1875618867 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
1889519006 ZigType *return_type;
1889619007
1889719008 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 }
1890219009 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
1890319010 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
1890419011 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
1890519012 ptr_type->data.pointer.is_const || is_comptime_const,
1890619013 ptr_type->data.pointer.is_volatile,
1890719014 PtrLenUnknown,
18908 byte_alignment, 0, 0);
19015 ptr_type->data.pointer.explicit_alignment, 0, 0);
1890919016 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1891019017 } else if (array_type->id == ZigTypeIdPointer) {
1891119018 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
......@@ -18915,7 +19022,7 @@ static ZigType *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice
1891519022 main_type->data.pointer.child_type,
1891619023 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
1891719024 PtrLenUnknown,
18918 array_type->data.pointer.alignment, 0, 0);
19025 array_type->data.pointer.explicit_alignment, 0, 0);
1891919026 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1892019027 } else {
1892119028 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
1892519032 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.pointer.child_type,
1892619033 array_type->data.pointer.is_const, array_type->data.pointer.is_volatile,
1892719034 PtrLenUnknown,
18928 array_type->data.pointer.alignment, 0, 0);
19035 array_type->data.pointer.explicit_alignment, 0, 0);
1892919036 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1893019037 if (!end) {
1893119038 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
1930619413 return ira->codegen->builtin_types.entry_invalid;
1930719414 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)))
1931019417 return ira->codegen->builtin_types.entry_invalid;
1931119418
1931219419 switch (type_entry->id) {
......@@ -19319,7 +19426,6 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
1931919426 case ZigTypeIdUndefined:
1932019427 case ZigTypeIdNull:
1932119428 case ZigTypeIdNamespace:
19322 case ZigTypeIdBlock:
1932319429 case ZigTypeIdBoundFn:
1932419430 case ZigTypeIdArgTuple:
1932519431 case ZigTypeIdVoid:
......@@ -19351,6 +19457,8 @@ static ZigType *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAli
1935119457}
1935219458
1935319459static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) {
19460 Error err;
19461
1935419462 IrInstruction *type_value = instruction->type_value->other;
1935519463 if (type_is_invalid(type_value->value.type))
1935619464 return ira->codegen->builtin_types.entry_invalid;
......@@ -19394,10 +19502,13 @@ static ZigType *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstruction
1939419502
1939519503 ZigType *expected_ptr_type;
1939619504 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;
1939719508 expected_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_type,
1939819509 false, result_ptr->value.type->data.pointer.is_volatile,
1939919510 PtrLenSingle,
19400 result_ptr->value.type->data.pointer.alignment, 0, 0);
19511 alignment, 0, 0);
1940119512 } else {
1940219513 expected_ptr_type = get_pointer_to_type(ira->codegen, dest_type, false);
1940319514 }
......@@ -19559,8 +19670,7 @@ static ZigType *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
1955919670 }
1956019671 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
1956119672 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19562 PtrLenSingle,
19563 get_abi_alignment(ira->codegen, payload_type), 0, 0);
19673 PtrLenSingle, 0, 0, 0);
1956419674 if (instr_is_comptime(value)) {
1956519675 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
1956619676 if (!ptr_val)
......@@ -19639,7 +19749,7 @@ static ZigType *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnP
1963919749 ZigType *param_type = ir_resolve_type(ira, param_type_value);
1964019750 if (type_is_invalid(param_type))
1964119751 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)))
1964319753 return ira->codegen->builtin_types.entry_invalid;
1964419754 if (type_requires_comptime(param_type)) {
1964519755 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
......@@ -19914,7 +20024,7 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
1991420024 }
1991520025
1991620026 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);
1991820028 ZigType *str_type = get_slice_type(ira->codegen, u8_ptr_type);
1991920029 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
1992020030 if (type_is_invalid(casted_msg->value.type))
......@@ -19927,6 +20037,8 @@ static ZigType *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic
1992720037}
1992820038
1992920039static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint32_t align_bytes, bool safety_check_on) {
20040 Error err;
20041
1993020042 ZigType *target_type = target->value.type;
1993120043 assert(!type_is_invalid(target_type));
1993220044
......@@ -19935,7 +20047,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1993520047
1993620048 if (target_type->id == ZigTypeIdPointer) {
1993720049 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;
1993920052 } else if (target_type->id == ZigTypeIdFn) {
1994020053 FnTypeId fn_type_id = target_type->data.fn.fn_type_id;
1994120054 old_align_bytes = fn_type_id.alignment;
......@@ -19945,7 +20058,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1994520058 target_type->data.maybe.child_type->id == ZigTypeIdPointer)
1994620059 {
1994720060 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;
1994920063 ZigType *better_ptr_type = adjust_ptr_align(ira->codegen, ptr_type, align_bytes);
1995020064
1995120065 result_type = get_optional_type(ira->codegen, better_ptr_type);
......@@ -19959,7 +20073,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1995920073 result_type = get_optional_type(ira->codegen, fn_type);
1996020074 } else if (is_slice(target_type)) {
1996120075 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;
1996320078 ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);
1996420079 result_type = get_slice_type(ira->codegen, result_ptr_type);
1996520080 } else {
......@@ -20038,8 +20153,13 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
2003820153 return dest_type;
2003920154 }
2004020155
20041 uint32_t src_align_bytes = get_ptr_align(src_type);
20042 uint32_t dest_align_bytes = get_ptr_align(dest_type);
20156 uint32_t src_align_bytes;
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
2004420164 if (dest_align_bytes > src_align_bytes) {
2004520165 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
2005620176
2005720177 // Keep the bigger alignment, it can only help-
2005820178 // 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)))
2006020180 return ira->codegen->builtin_types.entry_invalid;
2006120181
2006220182 IrInstruction *result;
......@@ -20080,7 +20200,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2008020200 case ZigTypeIdBoundFn:
2008120201 case ZigTypeIdArgTuple:
2008220202 case ZigTypeIdNamespace:
20083 case ZigTypeIdBlock:
2008420203 case ZigTypeIdUnreachable:
2008520204 case ZigTypeIdComptimeFloat:
2008620205 case ZigTypeIdComptimeInt:
......@@ -20147,7 +20266,6 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2014720266 case ZigTypeIdBoundFn:
2014820267 case ZigTypeIdArgTuple:
2014920268 case ZigTypeIdNamespace:
20150 case ZigTypeIdBlock:
2015120269 case ZigTypeIdUnreachable:
2015220270 case ZigTypeIdComptimeFloat:
2015320271 case ZigTypeIdComptimeInt:
......@@ -20227,7 +20345,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
2022720345 case ZigTypeIdBoundFn:
2022820346 case ZigTypeIdArgTuple:
2022920347 case ZigTypeIdNamespace:
20230 case ZigTypeIdBlock:
2023120348 case ZigTypeIdUnreachable:
2023220349 case ZigTypeIdComptimeFloat:
2023320350 case ZigTypeIdComptimeInt:
......@@ -20253,7 +20370,6 @@ static ZigType *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBit
2025320370 case ZigTypeIdBoundFn:
2025420371 case ZigTypeIdArgTuple:
2025520372 case ZigTypeIdNamespace:
20256 case ZigTypeIdBlock:
2025720373 case ZigTypeIdUnreachable:
2025820374 case ZigTypeIdComptimeFloat:
2025920375 case ZigTypeIdComptimeInt:
......@@ -20308,7 +20424,7 @@ static ZigType *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionI
2030820424 return ira->codegen->builtin_types.entry_invalid;
2030920425 }
2031020426
20311 if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))
20427 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
2031220428 return ira->codegen->builtin_types.entry_invalid;
2031320429 if (!type_has_bits(dest_type)) {
2031420430 ir_add_error(ira, dest_type_value,
......@@ -20459,12 +20575,15 @@ static ZigType *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstructionPtr
2045920575 if (instruction->align_value != nullptr) {
2046020576 if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes))
2046120577 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;
2046220580 } else {
20463 if ((err = type_ensure_zero_bits_known(ira->codegen, child_type)))
20581 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
2046420582 return ira->codegen->builtin_types.entry_invalid;
20465 align_bytes = get_abi_alignment(ira->codegen, child_type);
20583 align_bytes = 0;
2046620584 }
2046720585
20586
2046820587 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
2046920588 out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type,
2047020589 instruction->is_const, instruction->is_volatile,
......@@ -21108,7 +21227,7 @@ static ZigType *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstruction
2110821227 return ira->codegen->builtin_types.entry_invalid;
2110921228 }
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)))
2111221231 return ira->codegen->builtin_types.entry_invalid;
2111321232
2111421233 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
2113121250 return ira->codegen->builtin_types.entry_invalid;
2113221251 }
2113321252
21134 if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type)))
21253 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
2113521254 return ira->codegen->builtin_types.entry_invalid;
2113621255
2113721256 ZigType *tag_type = dest_type->data.enumeration.tag_int_type;
src/link.cpp+18-61
......@@ -5,7 +5,6 @@
55 * See http://opensource.org/licenses/MIT
66 */
77
8#include "link.hpp"
98#include "os.hpp"
109#include "config.h"
1110#include "codegen.hpp"
......@@ -13,7 +12,6 @@
1312
1413struct LinkJob {
1514 CodeGen *codegen;
16 Buf out_file;
1715 ZigList<const char *> args;
1816 bool link_in_crt;
1917 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)
4442 child_gen->verbose_llvm_ir = parent_gen->verbose_llvm_ir;
4543 child_gen->verbose_cimport = parent_gen->verbose_cimport;
4644
47 codegen_set_cache_dir(child_gen, parent_gen->cache_dir);
48
4945 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
5046 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)
6258 new_link_lib->provided_explicitly = link_lib->provided_explicitly;
6359 }
6460
65 codegen_build(child_gen);
66 const char *o_ext = target_o_file_ext(&child_gen->zig_target);
67 Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);
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;
61 child_gen->enable_cache = true;
62 codegen_build_and_link(child_gen);
63 return &child_gen->output_file_path;
7564}
7665
7766static Buf *build_o(CodeGen *parent_gen, const char *oname) {
......@@ -239,15 +228,15 @@ static void construct_linker_job_elf(LinkJob *lj) {
239228 } else if (shared) {
240229 lj->args.append("-shared");
241230
242 if (buf_len(&lj->out_file) == 0) {
243 buf_appendf(&lj->out_file, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
231 if (buf_len(&g->output_file_path) == 0) {
232 buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
244233 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
245234 }
246235 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
247236 }
248237
249238 lj->args.append("-o");
250 lj->args.append(buf_ptr(&lj->out_file));
239 lj->args.append(buf_ptr(&g->output_file_path));
251240
252241 if (lj->link_in_crt) {
253242 const char *crt1o;
......@@ -399,7 +388,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
399388
400389 lj->args.append("--relocatable"); // So lld doesn't look for _start.
401390 lj->args.append("-o");
402 lj->args.append(buf_ptr(&lj->out_file));
391 lj->args.append(buf_ptr(&g->output_file_path));
403392
404393 // .o files
405394 for (size_t i = 0; i < g->link_objects.length; i += 1) {
......@@ -480,7 +469,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
480469 // }
481470 //}
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
485474 if (g->libc_link_lib != nullptr) {
486475 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) {
587576 buf_appendf(def_contents, "\n");
588577
589578 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);
591580 os_write_file(def_path, def_contents);
592581
593582 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
596585 gen_lib_args.resize(0);
597586 gen_lib_args.append("link");
......@@ -799,8 +788,8 @@ static void construct_linker_job_macho(LinkJob *lj) {
799788 //lj->args.append("-install_name");
800789 //lj->args.append(buf_ptr(dylib_install_name));
801790
802 if (buf_len(&lj->out_file) == 0) {
803 buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
791 if (buf_len(&g->output_file_path) == 0) {
792 buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
804793 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
805794 }
806795 }
......@@ -834,13 +823,13 @@ static void construct_linker_job_macho(LinkJob *lj) {
834823 }
835824
836825 lj->args.append("-o");
837 lj->args.append(buf_ptr(&lj->out_file));
826 lj->args.append(buf_ptr(&g->output_file_path));
838827
839828 for (size_t i = 0; i < g->rpath_list.length; i += 1) {
840829 Buf *rpath = g->rpath_list.at(i);
841830 add_rpath(lj, rpath);
842831 }
843 add_rpath(lj, &lj->out_file);
832 add_rpath(lj, &g->output_file_path);
844833
845834 if (shared) {
846835 lj->args.append("-headerpad_max_install_names");
......@@ -944,7 +933,8 @@ static void construct_linker_job(LinkJob *lj) {
944933 }
945934}
946935
947void codegen_link(CodeGen *g, const char *out_file) {
936void codegen_link(CodeGen *g) {
937 assert(g->out_type != OutTypeObj);
948938 codegen_add_time_event(g, "Build Dependencies");
949939
950940 LinkJob lj = {0};
......@@ -955,11 +945,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
955945
956946 lj.rpath_table.init(4);
957947 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
964949 if (g->verbose_llvm_ir) {
965950 fprintf(stderr, "\nOptimization:\n");
......@@ -968,35 +953,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
968953 LLVMDumpModule(g->module);
969954 }
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
993956 if (g->out_type == OutTypeLib && g->is_static) {
994 // invoke `ar`
995 // example:
996 // # static link into libfoo.a
997 // ar rcs libfoo.a foo1.o foo2.o
998 zig_panic("TODO invoke ar");
999 return;
957 fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");
958 exit(1);
1000959 }
1001960
1002961 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) {
1019978 fprintf(stderr, "%s\n", buf_ptr(&diag));
1020979 exit(1);
1021980 }
1022
1023 codegen_add_time_event(g, "Done");
1024981}
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 @@
88#include "ast_render.hpp"
99#include "buffer.hpp"
1010#include "codegen.hpp"
11#include "compiler.hpp"
1112#include "config.h"
1213#include "error.hpp"
13#include "link.hpp"
1414#include "os.hpp"
1515#include "target.hpp"
1616
......@@ -24,6 +24,7 @@ static int usage(const char *arg0) {
2424 " build-lib [source] create library from source or object files\n"
2525 " build-obj [source] create object from source or assembly\n"
2626 " builtin show the source code of that @import(\"builtin\")\n"
27 " id print the base64-encoded compiler id\n"
2728 " run [source] create executable and run immediately\n"
2829 " translate-c [source] convert c code to zig code\n"
2930 " targets list available compilation targets\n"
......@@ -33,9 +34,10 @@ static int usage(const char *arg0) {
3334 "Compile Options:\n"
3435 " --assembly [source] add assembly file to build\n"
3536 " --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"
3638 " --color [auto|off|on] enable or disable colored error messages\n"
3739 " --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"
3941 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
4042 " --name [name] override output name\n"
4143 " --output [file] override destination path\n"
......@@ -256,6 +258,24 @@ static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) {
256258 }
257259}
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
259279int main(int argc, char **argv) {
260280 if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
261281 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) {
270290 return 0;
271291 }
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
273304 os_init();
274305
275306 char *arg0 = argv[0];
......@@ -289,6 +320,7 @@ int main(int argc, char **argv) {
289320 bool verbose_llvm_ir = false;
290321 bool verbose_cimport = false;
291322 ErrColor color = ErrColorAuto;
323 CacheOpt enable_cache = CacheOptAuto;
292324 const char *libc_lib_dir = nullptr;
293325 const char *libc_static_lib_dir = nullptr;
294326 const char *libc_include_dir = nullptr;
......@@ -325,8 +357,7 @@ int main(int argc, char **argv) {
325357 CliPkg *cur_pkg = allocate<CliPkg>(1);
326358 BuildMode build_mode = BuildModeDebug;
327359 ZigList<const char *> test_exec_args = {0};
328 int comptime_args_end = 0;
329 int runtime_args_start = argc;
360 int runtime_args_start = -1;
330361 bool no_rosegment_workaround = false;
331362
332363 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
......@@ -370,8 +401,9 @@ int main(int argc, char **argv) {
370401 Buf *build_runner_path = buf_alloc();
371402 os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);
372403
373
374404 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);
375407 codegen_set_out_name(g, buf_create_from_str("build"));
376408
377409 Buf *build_file_buf = buf_create_from_str(build_file);
......@@ -380,6 +412,7 @@ int main(int argc, char **argv) {
380412 Buf build_file_dirname = BUF_INIT;
381413 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
382414
415
383416 Buf full_cache_dir = BUF_INIT;
384417 if (cache_dir == nullptr) {
385418 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) {
388421 full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
389422 }
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
395424 args.items[1] = buf_ptr(&build_file_dirname);
396425 args.items[2] = buf_ptr(&full_cache_dir);
397426
......@@ -459,15 +488,14 @@ int main(int argc, char **argv) {
459488 PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
460489 buf_ptr(&build_file_basename));
461490 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
462 codegen_build(g);
463 codegen_link(g, buf_ptr(path_to_build_exe));
464 codegen_destroy(g);
491 g->enable_cache = get_cache_opt(enable_cache, true);
492 codegen_build_and_link(g);
465493
466494 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);
468496 if (term.how != TerminationIdClean || term.code != 0) {
469497 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));
471499 for (size_t i = 0; i < args.length; i += 1) {
472500 fprintf(stderr, " %s", args.at(i));
473501 }
......@@ -476,15 +504,11 @@ int main(int argc, char **argv) {
476504 return (term.how == TerminationIdClean) ? term.code : -1;
477505 }
478506
479 for (int i = 1; i < argc; i += 1, comptime_args_end += 1) {
507 for (int i = 1; i < argc; i += 1) {
480508 char *arg = argv[i];
481509
482510 if (arg[0] == '-') {
483 if (strcmp(arg, "--") == 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) {
511 if (strcmp(arg, "--release-fast") == 0) {
488512 build_mode = BuildModeFastRelease;
489513 } else if (strcmp(arg, "--release-safe") == 0) {
490514 build_mode = BuildModeSafeRelease;
......@@ -516,7 +540,7 @@ int main(int argc, char **argv) {
516540 no_rosegment_workaround = true;
517541 } else if (strcmp(arg, "--each-lib-rpath") == 0) {
518542 each_lib_rpath = true;
519 } else if (strcmp(arg, "--enable-timing-info") == 0) {
543 } else if (strcmp(arg, "-ftime-report") == 0) {
520544 timing_info = true;
521545 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
522546 test_exec_args.append(nullptr);
......@@ -562,6 +586,17 @@ int main(int argc, char **argv) {
562586 fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
563587 return usage(arg0);
564588 }
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 }
565600 } else if (strcmp(arg, "--emit") == 0) {
566601 if (strcmp(argv[i], "asm") == 0) {
567602 emit_file_type = EmitFileTypeAssembly;
......@@ -681,6 +716,10 @@ int main(int argc, char **argv) {
681716 case CmdTest:
682717 if (!in_file) {
683718 in_file = arg;
719 if (cmd == CmdRun) {
720 runtime_args_start = i + 1;
721 break; // rest of the args are for the program
722 }
684723 } else {
685724 fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
686725 return usage(arg0);
......@@ -790,32 +829,18 @@ int main(int argc, char **argv) {
790829
791830 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
792831
793 Buf full_cache_dir = BUF_INIT;
794 Buf *run_exec_path = buf_alloc();
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);
832 if (cmd == CmdRun && buf_out_name == nullptr) {
833 buf_out_name = buf_create_from_str("run");
809834 }
810
811835 Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
812836
813837 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);
814840 codegen_set_out_name(g, buf_out_name);
815841 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
816842 codegen_set_is_test(g, cmd == CmdTest);
817843 codegen_set_linker_script(g, linker_script);
818 codegen_set_cache_dir(g, full_cache_dir);
819844 if (each_lib_rpath)
820845 codegen_set_each_lib_rpath(g, each_lib_rpath);
821846
......@@ -885,6 +910,8 @@ int main(int argc, char **argv) {
885910 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
886911 }
887912
913 if (out_file)
914 codegen_set_output_path(g, buf_create_from_str(out_file));
888915 if (out_file_h)
889916 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
890917
......@@ -904,8 +931,8 @@ int main(int argc, char **argv) {
904931 if (cmd == CmdBuild || cmd == CmdRun) {
905932 codegen_set_emit_file_type(g, emit_file_type);
906933
907 codegen_build(g);
908 codegen_link(g, out_file);
934 g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
935 codegen_build_and_link(g);
909936 if (timing_info)
910937 codegen_print_timing_report(g, stdout);
911938
......@@ -915,12 +942,26 @@ int main(int argc, char **argv) {
915942 args.append(argv[i]);
916943 }
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();
918951 Termination term;
919 os_spawn_process(buf_ptr(run_exec_path), args, &term);
952 os_spawn_process(exec_path, args, &term);
920953 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();
921964 }
922
923 return EXIT_SUCCESS;
924965 } else if (cmd == CmdTranslateC) {
925966 codegen_translate_c(g, in_file_buf);
926967 ast_render(g, stdout, g->root_import->root, 4);
......@@ -933,11 +974,16 @@ int main(int argc, char **argv) {
933974 ZigTarget native;
934975 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;
939985 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
942988 for (size_t i = 0; i < test_exec_args.length; i += 1) {
943989 if (test_exec_args.items[i] == nullptr) {
......@@ -945,9 +991,6 @@ int main(int argc, char **argv) {
945991 }
946992 }
947993
948 codegen_build(g);
949 codegen_link(g, buf_ptr(test_exe_path));
950
951994 if (!target_can_exec(&native, target)) {
952995 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
953996 buf_ptr(test_exe_path));
......@@ -969,8 +1012,6 @@ int main(int argc, char **argv) {
9691012 if (term.how != TerminationIdClean || term.code != 0) {
9701013 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
9711014 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
972 } else if (timing_info) {
973 codegen_print_timing_report(g, stdout);
9741015 }
9751016 return (term.how == TerminationIdClean) ? term.code : -1;
9761017 } else {
src/os.cpp+479-120
......@@ -24,6 +24,7 @@
2424#endif
2525
2626#include <windows.h>
27#include <shlobj.h>
2728#include <io.h>
2829#include <fcntl.h>
2930
......@@ -40,6 +41,10 @@ typedef SSIZE_T ssize_t;
4041
4142#endif
4243
44#if defined(ZIG_OS_LINUX)
45#include <link.h>
46#endif
47
4348
4449#if defined(__MACH__)
4550#include <mach/clock.h>
......@@ -57,54 +62,6 @@ static clock_serv_t cclock;
5762#include <errno.h>
5863#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
10865#if defined(ZIG_OS_POSIX)
10966static void populate_termination(Termination *term, int status) {
11067 if (WIFEXITED(status)) {
......@@ -765,7 +722,7 @@ Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
765722#endif
766723}
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) {
769726 static const ssize_t buf_size = 0x2000;
770727 buf_resize(out_buf, buf_size);
771728 ssize_t actual_buf_len = 0;
......@@ -801,7 +758,7 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
801758 if (amt_read != buf_size) {
802759 if (feof(f)) {
803760 buf_resize(out_buf, actual_buf_len);
804 return 0;
761 return ErrorNone;
805762 } else {
806763 return ErrorFileSystem;
807764 }
......@@ -813,13 +770,13 @@ int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
813770 zig_unreachable();
814771}
815772
816int os_file_exists(Buf *full_path, bool *result) {
773Error os_file_exists(Buf *full_path, bool *result) {
817774#if defined(ZIG_OS_WINDOWS)
818775 *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;
819 return 0;
776 return ErrorNone;
820777#else
821778 *result = access(buf_ptr(full_path), F_OK) != -1;
822 return 0;
779 return ErrorNone;
823780#endif
824781}
825782
......@@ -878,13 +835,15 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,
878835
879836 FILE *stdout_f = fdopen(stdout_pipe[0], "rb");
880837 FILE *stderr_f = fdopen(stderr_pipe[0], "rb");
881 os_fetch_file(stdout_f, out_stdout, false);
882 os_fetch_file(stderr_f, out_stderr, false);
838 Error err1 = os_fetch_file(stdout_f, out_stdout, false);
839 Error err2 = os_fetch_file(stderr_f, out_stderr, false);
883840
884841 fclose(stdout_f);
885842 fclose(stderr_f);
886843
887 return 0;
844 if (err1) return err1;
845 if (err2) return err2;
846 return ErrorNone;
888847 }
889848}
890849#endif
......@@ -1016,6 +975,22 @@ static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
1016975}
1017976#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
1019994int os_exec_process(const char *exe, ZigList<const char *> &args,
1020995 Termination *term, Buf *out_stderr, Buf *out_stdout)
1021996{
......@@ -1092,7 +1067,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) {
10921067 }
10931068}
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) {
10961071 FILE *f = fopen(buf_ptr(full_path), "rb");
10971072 if (!f) {
10981073 switch (errno) {
......@@ -1111,7 +1086,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
11111086 return ErrorFileSystem;
11121087 }
11131088 }
1114 int result = os_fetch_file(f, out_contents, skip_shebang);
1089 Error result = os_fetch_file(f, out_contents, skip_shebang);
11151090 fclose(f);
11161091 return result;
11171092}
......@@ -1282,44 +1257,6 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
12821257#endif
12831258}
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
13231260int os_delete_file(Buf *path) {
13241261 if (remove(buf_ptr(path))) {
13251262 return ErrorFileSystem;
......@@ -1368,16 +1305,16 @@ double os_get_time(void) {
13681305#endif
13691306}
13701307
1371int os_make_path(Buf *path) {
1308Error os_make_path(Buf *path) {
13721309 Buf resolved_path = os_path_resolve(&path, 1);
13731310
13741311 size_t end_index = buf_len(&resolved_path);
1375 int err;
1312 Error err;
13761313 while (true) {
13771314 if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
13781315 if (err == ErrorPathAlreadyExists) {
13791316 if (end_index == buf_len(&resolved_path))
1380 return 0;
1317 return ErrorNone;
13811318 } else if (err == ErrorFileNotFound) {
13821319 // march end_index backward until next path component
13831320 while (true) {
......@@ -1391,7 +1328,7 @@ int os_make_path(Buf *path) {
13911328 }
13921329 }
13931330 if (end_index == buf_len(&resolved_path))
1394 return 0;
1331 return ErrorNone;
13951332 // march end_index forward until next path component
13961333 while (true) {
13971334 end_index += 1;
......@@ -1399,10 +1336,10 @@ int os_make_path(Buf *path) {
13991336 break;
14001337 }
14011338 }
1402 return 0;
1339 return ErrorNone;
14031340}
14041341
1405int os_make_dir(Buf *path) {
1342Error os_make_dir(Buf *path) {
14061343#if defined(ZIG_OS_WINDOWS)
14071344 if (!CreateDirectory(buf_ptr(path), NULL)) {
14081345 if (GetLastError() == ERROR_ALREADY_EXISTS)
......@@ -1413,7 +1350,7 @@ int os_make_dir(Buf *path) {
14131350 return ErrorAccess;
14141351 return ErrorUnexpected;
14151352 }
1416 return 0;
1353 return ErrorNone;
14171354#else
14181355 if (mkdir(buf_ptr(path), 0755) == -1) {
14191356 if (errno == EEXIST)
......@@ -1424,7 +1361,7 @@ int os_make_dir(Buf *path) {
14241361 return ErrorAccess;
14251362 return ErrorUnexpected;
14261363 }
1427 return 0;
1364 return ErrorNone;
14281365#endif
14291366}
14301367
......@@ -1447,7 +1384,7 @@ int os_init(void) {
14471384 return 0;
14481385}
14491386
1450int os_self_exe_path(Buf *out_path) {
1387Error os_self_exe_path(Buf *out_path) {
14511388#if defined(ZIG_OS_WINDOWS)
14521389 buf_resize(out_path, 256);
14531390 for (;;) {
......@@ -1457,7 +1394,7 @@ int os_self_exe_path(Buf *out_path) {
14571394 }
14581395 if (copied_amt < buf_len(out_path)) {
14591396 buf_resize(out_path, copied_amt);
1460 return 0;
1397 return ErrorNone;
14611398 }
14621399 buf_resize(out_path, buf_len(out_path) * 2);
14631400 }
......@@ -1480,27 +1417,21 @@ int os_self_exe_path(Buf *out_path) {
14801417 char *real_path = realpath(buf_ptr(tmp), buf_ptr(out_path));
14811418 if (!real_path) {
14821419 buf_init_from_buf(out_path, tmp);
1483 return 0;
1420 return ErrorNone;
14841421 }
14851422
14861423 // Resize out_path for the correct length.
14871424 buf_resize(out_path, strlen(buf_ptr(out_path)));
14881425
1489 return 0;
1426 return ErrorNone;
14901427#elif defined(ZIG_OS_LINUX)
1491 buf_resize(out_path, 256);
1492 for (;;) {
1493 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
1494 if (amt == -1) {
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;
1428 buf_resize(out_path, PATH_MAX);
1429 ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
1430 if (amt == -1) {
1431 return ErrorUnexpected;
15031432 }
1433 buf_resize(out_path, amt);
1434 return ErrorNone;
15041435#endif
15051436 return ErrorFileNotFound;
15061437}
......@@ -1685,3 +1616,431 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
16851616 return ErrorFileNotFound;
16861617#endif
16871618}
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 @@
1313#include "error.hpp"
1414#include "zig_llvm.h"
1515#include "windows_sdk.h"
16#include "result.hpp"
1617
1718#include <stdio.h>
1819#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
2053enum TermColor {
2154 TermColorRed,
2255 TermColorGreen,
......@@ -38,11 +71,23 @@ struct Termination {
3871 int code;
3972};
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
4185int os_init(void);
4286
4387void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
4488int os_exec_process(const char *exe, ZigList<const char *> &args,
4589 Termination *term, Buf *out_stderr, Buf *out_stdout);
90Error os_execv(const char *exe, const char **argv);
4691
4792void os_path_dirname(Buf *full_path, Buf *out_dirname);
4893void 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);
5297Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
5398bool 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);
58int os_make_dir(Buf *path);
103Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);
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
60111void os_write_file(Buf *full_path, Buf *contents);
61112int os_copy_file(Buf *src_path, Buf *dest_path);
62113
63int 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);
114Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
115Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
65116
66117int os_get_cwd(Buf *out_cwd);
67118
......@@ -71,49 +122,21 @@ void os_stderr_set_color(TermColor color);
71122int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
72123int 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
76127int os_rename(Buf *src_path, Buf *dest_path);
77128double os_get_time(void);
78129
79130bool 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
83136int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
84137int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
85138int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
86139
87#if defined(__APPLE__)
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
140Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
118141
119142#endif
src/parser.cpp+1-8
......@@ -700,7 +700,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
700700
701701/*
702702PrimaryExpression = 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"
704704ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
705705*/
706706static 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
756756 AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token);
757757 *token_index += 1;
758758 return node;
759 } else if (token->id == TokenIdKeywordThis) {
760 AstNode *node = ast_create_node(pc, NodeTypeThisLiteral, token);
761 *token_index += 1;
762 return node;
763759 } else if (token->id == TokenIdKeywordUnreachable) {
764760 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
765761 *token_index += 1;
......@@ -3021,9 +3017,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30213017 case NodeTypeUndefinedLiteral:
30223018 // none
30233019 break;
3024 case NodeTypeThisLiteral:
3025 // none
3026 break;
30273020 case NodeTypeIfBoolExpr:
30283021 visit_field(&node->data.if_bool_expr.condition, visit, context);
30293022 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) {
812812 }
813813}
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
815831enum FloatAbi {
816832 FloatAbiHard,
817833 FloatAbiSoft,
src/target.hpp+1
......@@ -114,6 +114,7 @@ const char *target_o_file_ext(ZigTarget *target);
114114const char *target_asm_file_ext(ZigTarget *target);
115115const char *target_llvm_ir_file_ext(ZigTarget *target);
116116const 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
118119Buf *target_dynamic_linker(ZigTarget *target);
119120
src/tokenizer.cpp-2
......@@ -146,7 +146,6 @@ static const struct ZigKeyword zig_keywords[] = {
146146 {"suspend", TokenIdKeywordSuspend},
147147 {"switch", TokenIdKeywordSwitch},
148148 {"test", TokenIdKeywordTest},
149 {"this", TokenIdKeywordThis},
150149 {"true", TokenIdKeywordTrue},
151150 {"try", TokenIdKeywordTry},
152151 {"undefined", TokenIdKeywordUndefined},
......@@ -1588,7 +1587,6 @@ const char * token_name(TokenId id) {
15881587 case TokenIdKeywordStruct: return "struct";
15891588 case TokenIdKeywordSwitch: return "switch";
15901589 case TokenIdKeywordTest: return "test";
1591 case TokenIdKeywordThis: return "this";
15921590 case TokenIdKeywordTrue: return "true";
15931591 case TokenIdKeywordTry: return "try";
15941592 case TokenIdKeywordUndefined: return "undefined";
src/tokenizer.hpp-1
......@@ -87,7 +87,6 @@ enum TokenId {
8787 TokenIdKeywordSuspend,
8888 TokenIdKeywordSwitch,
8989 TokenIdKeywordTest,
90 TokenIdKeywordThis,
9190 TokenIdKeywordTrue,
9291 TokenIdKeywordTry,
9392 TokenIdKeywordUndefined,
src/util.cpp+49
......@@ -43,3 +43,52 @@ uint32_t ptr_hash(const void *ptr) {
4343bool ptr_eq(const void *a, const void *b) {
4444 return a == b;
4545}
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) {
254254 memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
255255}
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
257270#endif
src/zig_llvm.cpp+8-1
......@@ -30,6 +30,7 @@
3030#include <llvm/PassRegistry.h>
3131#include <llvm/Support/FileSystem.h>
3232#include <llvm/Support/TargetParser.h>
33#include <llvm/Support/Timer.h>
3334#include <llvm/Support/raw_ostream.h>
3435#include <llvm/Target/TargetMachine.h>
3536#include <llvm/Transforms/Coroutines.h>
......@@ -82,8 +83,11 @@ static const bool assertions_on = false;
8283#endif
8384
8485bool 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)
8688{
89 TimePassesIsEnabled = time_report;
90
8791 std::error_code EC;
8892 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
8993 if (EC) {
......@@ -183,6 +187,9 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
183187 }
184188 }
185189
190 if (time_report) {
191 TimerGroup::printAll(errs());
192 }
186193 return false;
187194}
188195
src/zig_llvm.h+2-1
......@@ -55,7 +55,8 @@ enum ZigLLVM_EmitOutputType {
5555};
5656
5757ZIG_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
6061ZIG_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 {
1111
1212pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
1313 return struct {
14 const Self = this;
14 const Self = @This();
1515
1616 /// Use toSlice instead of slicing this directly, because if you don't
1717 /// 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 {
66 return struct {
77 unprotected_value: T,
88
9 pub const Self = this;
9 pub const Self = @This();
1010
1111 pub fn init(init_val: T) Self {
1212 return Self{ .unprotected_value = init_val };
std/atomic/queue.zig+2-2
......@@ -12,7 +12,7 @@ pub fn Queue(comptime T: type) type {
1212 tail: ?*Node,
1313 mutex: std.Mutex,
1414
15 pub const Self = this;
15 pub const Self = @This();
1616 pub const Node = std.LinkedList(T).Node;
1717
1818 pub fn init() Self {
......@@ -114,7 +114,7 @@ pub fn Queue(comptime T: type) type {
114114
115115 fn dumpRecursive(optional_node: ?*Node, indent: usize) void {
116116 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;
118118 stderr.writeByteNTimes(' ', indent) catch return;
119119 if (optional_node) |node| {
120120 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 {
99 root: ?*Node,
1010 lock: u8,
1111
12 pub const Self = this;
12 pub const Self = @This();
1313
1414 pub const Node = struct {
1515 next: ?*Node,
std/build.zig+27-1
......@@ -232,6 +232,8 @@ pub const Builder = struct {
232232 }
233233
234234 pub fn make(self: *Builder, step_names: []const []const u8) !void {
235 try self.makePath(self.cache_root);
236
235237 var wanted_steps = ArrayList(*Step).init(self.allocator);
236238 defer wanted_steps.deinit();
237239
......@@ -1641,6 +1643,7 @@ pub const TestStep = struct {
16411643 lib_paths: ArrayList([]const u8),
16421644 object_files: ArrayList([]const u8),
16431645 no_rosegment: bool,
1646 output_path: ?[]const u8,
16441647
16451648 pub fn init(builder: *Builder, root_src: []const u8) TestStep {
16461649 const step_name = builder.fmt("test {}", root_src);
......@@ -1659,6 +1662,7 @@ pub const TestStep = struct {
16591662 .lib_paths = ArrayList([]const u8).init(builder.allocator),
16601663 .object_files = ArrayList([]const u8).init(builder.allocator),
16611664 .no_rosegment = false,
1665 .output_path = null,
16621666 };
16631667 }
16641668
......@@ -1682,6 +1686,24 @@ pub const TestStep = struct {
16821686 self.build_mode = mode;
16831687 }
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
16851707 pub fn linkSystemLibrary(self: *TestStep, name: []const u8) void {
16861708 self.link_libs.put(name) catch unreachable;
16871709 }
......@@ -1746,6 +1768,10 @@ pub const TestStep = struct {
17461768 builtin.Mode.ReleaseSmall => try zig_args.append("--release-small"),
17471769 }
17481770
1771 const output_path = builder.pathFromRoot(self.getOutputPath());
1772 try zig_args.append("--output");
1773 try zig_args.append(output_path);
1774
17491775 switch (self.target) {
17501776 Target.Native => {},
17511777 Target.Cross => |cross_target| {
......@@ -1864,7 +1890,7 @@ const InstallArtifactStep = struct {
18641890 artifact: *LibExeObjStep,
18651891 dest_file: []const u8,
18661892
1867 const Self = this;
1893 const Self = @This();
18681894
18691895 pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
18701896 const dest_dir = switch (artifact.kind) {
std/coff.zig+23-29
......@@ -8,9 +8,9 @@ const ArrayList = std.ArrayList;
88
99// CoffHeader.machine values
1010// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313(v=vs.85).aspx
11const IMAGE_FILE_MACHINE_I386 = 0x014c;
12const IMAGE_FILE_MACHINE_IA64 = 0x0200;
13const IMAGE_FILE_MACHINE_AMD64 = 0x8664;
11const IMAGE_FILE_MACHINE_I386 = 0x014c;
12const IMAGE_FILE_MACHINE_IA64 = 0x0200;
13const IMAGE_FILE_MACHINE_AMD64 = 0x8664;
1414
1515// OptionalHeader.magic values
1616// 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;
2020const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
2121const DEBUG_DIRECTORY = 6;
2222
23pub const CoffError = error {
23pub const CoffError = error{
2424 InvalidPEMagic,
2525 InvalidPEHeader,
2626 InvalidMachine,
......@@ -56,24 +56,21 @@ pub const Coff = struct {
5656
5757 var pe_header_magic: [4]u8 = undefined;
5858 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 }))
6060 return error.InvalidPEHeader;
6161
62 self.coff_header = CoffHeader {
62 self.coff_header = CoffHeader{
6363 .machine = try in.readIntLe(u16),
64 .number_of_sections = try in.readIntLe(u16),
65 .timedate_stamp = try in.readIntLe(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32),
67 .number_of_symbols = try in.readIntLe(u32),
68 .size_of_optional_header = try in.readIntLe(u16),
69 .characteristics = try in.readIntLe(u16),
64 .number_of_sections = try in.readIntLe(u16),
65 .timedate_stamp = try in.readIntLe(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32),
67 .number_of_symbols = try in.readIntLe(u32),
68 .size_of_optional_header = try in.readIntLe(u16),
69 .characteristics = try in.readIntLe(u16),
7070 };
7171
7272 switch (self.coff_header.machine) {
73 IMAGE_FILE_MACHINE_I386,
74 IMAGE_FILE_MACHINE_AMD64,
75 IMAGE_FILE_MACHINE_IA64
76 => {},
73 IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_IA64 => {},
7774 else => return error.InvalidMachine,
7875 }
7976
......@@ -89,11 +86,9 @@ pub const Coff = struct {
8986 var skip_size: u16 = undefined;
9087 if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
9188 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 18 * @sizeOf(u32);
92 }
93 else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
89 } else if (self.pe_header.magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
9490 skip_size = 2 * @sizeOf(u8) + 8 * @sizeOf(u16) + 12 * @sizeOf(u32) + 5 * @sizeOf(u64);
95 }
96 else
91 } else
9792 return error.InvalidPEMagic;
9893
9994 try self.in_file.seekForward(skip_size);
......@@ -103,7 +98,7 @@ pub const Coff = struct {
10398 return error.InvalidPEHeader;
10499
105100 for (self.pe_header.data_directory) |*data_dir| {
106 data_dir.* = OptionalHeader.DataDirectory {
101 data_dir.* = OptionalHeader.DataDirectory{
107102 .virtual_address = try in.readIntLe(u32),
108103 .size = try in.readIntLe(u32),
109104 };
......@@ -114,7 +109,7 @@ pub const Coff = struct {
114109 try self.loadSections();
115110 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
118113 // debug_directory.
119114 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];
120115 const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data;
......@@ -159,10 +154,10 @@ pub const Coff = struct {
159154 var i: u16 = 0;
160155 while (i < self.coff_header.number_of_sections) : (i += 1) {
161156 try in.readNoEof(name[0..]);
162 try self.sections.append(Section {
163 .header = SectionHeader {
157 try self.sections.append(Section{
158 .header = SectionHeader{
164159 .name = name,
165 .misc = SectionHeader.Misc { .physical_address = try in.readIntLe(u32) },
160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
166161 .virtual_address = try in.readIntLe(u32),
167162 .size_of_raw_data = try in.readIntLe(u32),
168163 .pointer_to_raw_data = try in.readIntLe(u32),
......@@ -184,7 +179,6 @@ pub const Coff = struct {
184179 }
185180 return null;
186181 }
187
188182};
189183
190184const CoffHeader = struct {
......@@ -194,13 +188,13 @@ const CoffHeader = struct {
194188 pointer_to_symbol_table: u32,
195189 number_of_symbols: u32,
196190 size_of_optional_header: u16,
197 characteristics: u16
191 characteristics: u16,
198192};
199193
200194const OptionalHeader = struct {
201195 const DataDirectory = struct {
202196 virtual_address: u32,
203 size: u32
197 size: u32,
204198 };
205199
206200 magic: u16,
......@@ -214,7 +208,7 @@ pub const Section = struct {
214208const SectionHeader = struct {
215209 const Misc = union {
216210 physical_address: u32,
217 virtual_size: u32
211 virtual_size: u32,
218212 };
219213
220214 name: [8]u8,
std/crypto/blake2.zig+2-2
......@@ -33,7 +33,7 @@ pub const Blake2s256 = Blake2s(256);
3333
3434fn Blake2s(comptime out_len: usize) type {
3535 return struct {
36 const Self = this;
36 const Self = @This();
3737 const block_length = 64;
3838 const digest_length = out_len / 8;
3939
......@@ -266,7 +266,7 @@ pub const Blake2b512 = Blake2b(512);
266266
267267fn Blake2b(comptime out_len: usize) type {
268268 return struct {
269 const Self = this;
269 const Self = @This();
270270 const block_length = 128;
271271 const digest_length = out_len / 8;
272272
std/crypto/hmac.zig+1-1
......@@ -9,7 +9,7 @@ pub const HmacSha256 = Hmac(crypto.Sha256);
99
1010pub fn Hmac(comptime Hash: type) type {
1111 return struct {
12 const Self = this;
12 const Self = @This();
1313 pub const mac_length = Hash.digest_length;
1414 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
2828}
2929
3030pub const Md5 = struct {
31 const Self = this;
31 const Self = @This();
3232 const block_length = 64;
3333 const digest_length = 16;
3434
std/crypto/poly1305.zig+1-1
......@@ -10,7 +10,7 @@ const readInt = std.mem.readInt;
1010const writeInt = std.mem.writeInt;
1111
1212pub const Poly1305 = struct {
13 const Self = this;
13 const Self = @This();
1414
1515 pub const mac_length = 16;
1616 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 {
2525}
2626
2727pub const Sha1 = struct {
28 const Self = this;
28 const Self = @This();
2929 const block_length = 64;
3030 const digest_length = 20;
3131
std/crypto/sha2.zig+2-2
......@@ -77,7 +77,7 @@ pub const Sha256 = Sha2_32(Sha256Params);
7777
7878fn Sha2_32(comptime params: Sha2Params32) type {
7979 return struct {
80 const Self = this;
80 const Self = @This();
8181 const block_length = 64;
8282 const digest_length = params.out_len / 8;
8383
......@@ -418,7 +418,7 @@ pub const Sha512 = Sha2_64(Sha512Params);
418418
419419fn Sha2_64(comptime params: Sha2Params64) type {
420420 return struct {
421 const Self = this;
421 const Self = @This();
422422 const block_length = 128;
423423 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);
1212
1313fn Keccak(comptime bits: usize, comptime delim: u8) type {
1414 return struct {
15 const Self = this;
15 const Self = @This();
1616 const block_length = 200;
1717 const digest_length = bits / 8;
1818
std/crypto/x25519.zig+1-1
......@@ -115,7 +115,7 @@ pub const X25519 = struct {
115115 return !zerocmp(u8, out);
116116 }
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 {
119119 var base_point = []u8{9} ++ []u8{0} ** 31;
120120 return create(public_key, private_key, base_point);
121121 }
std/debug/index.zig+15-14
......@@ -242,9 +242,12 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
242242 }
243243}
244244
245pub fn writeCurrentStackTraceWindows(out_stream: var, debug_info: *DebugInfo,
246 tty_color: bool, start_addr: ?usize) !void
247{
245pub fn writeCurrentStackTraceWindows(
246 out_stream: var,
247 debug_info: *DebugInfo,
248 tty_color: bool,
249 start_addr: ?usize,
250) !void {
248251 var addr_buf: [1024]usize = undefined;
249252 const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast
250253 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
391394 break :subsections null;
392395 }
393396 };
394
397
395398 if (tty_color) {
396399 setTtyColor(TtyColor.White);
397400 if (opt_line_info) |li| {
......@@ -438,7 +441,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
438441 }
439442}
440443
441const TtyColor = enum{
444const TtyColor = enum {
442445 Red,
443446 Green,
444447 Cyan,
......@@ -465,18 +468,16 @@ fn setTtyColor(tty_color: TtyColor) void {
465468 // TODO handle errors
466469 switch (tty_color) {
467470 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);
469472 },
470473 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);
472475 },
473476 TtyColor.Cyan => {
474 _ = windows.SetConsoleTextAttribute(stderr_file.handle,
475 windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE|windows.FOREGROUND_INTENSITY);
477 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY);
476478 },
477479 TtyColor.White, TtyColor.Bold => {
478 _ = windows.SetConsoleTextAttribute(stderr_file.handle,
479 windows.FOREGROUND_RED|windows.FOREGROUND_GREEN|windows.FOREGROUND_BLUE|windows.FOREGROUND_INTENSITY);
480 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY);
480481 },
481482 TtyColor.Dim => {
482483 _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY);
......@@ -915,7 +916,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
915916 } else {
916917 return error.MissingDebugInfo;
917918 };
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];
919920 const strings = @ptrCast([*]u8, hdr_base + symtab.stroff)[0..symtab.strsize];
920921
921922 const symbols_buf = try allocator.alloc(MachoSymbol, syms.len);
......@@ -1496,14 +1497,14 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
14961497 const segcmd = while (ncmd != 0) : (ncmd -= 1) {
14971498 const lc = @ptrCast(*const std.macho.load_command, ptr);
14981499 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)),
15001501 else => {},
15011502 }
15021503 ptr += lc.cmdsize; // TODO https://github.com/ziglang/zig/issues/1403
15031504 } else {
15041505 return error.MissingDebugInfo;
15051506 };
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];
15071508 for (sections) |*sect| {
15081509 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
15091510 (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 {
2525 buffer_index: usize,
2626 buffer_len: usize,
2727
28 const SelfChannel = this;
28 const SelfChannel = @This();
2929 const GetNode = struct {
3030 tick_node: *Loop.NextTickNode,
3131 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
109109 .base = Loop.ResumeNode{
110110 .id = Loop.ResumeNode.Id.Basic,
111111 .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 },
112119 },
113120 };
114 const completion_key = @ptrToInt(&resume_node.base);
115 // TODO support concurrent async ops on the file handle
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 };
121 // TODO only call create io completion port once per fd
122 _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined);
125123 loop.beginOneEvent();
126124 errdefer loop.finishOneEvent();
127125
128126 errdefer {
129 _ = windows.CancelIoEx(fd, &overlapped);
127 _ = windows.CancelIoEx(fd, &resume_node.base.overlapped);
130128 }
131129 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);
133131 }
134132 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) {
136134 const err = windows.GetLastError();
137135 return switch (err) {
138136 windows.ERROR.IO_PENDING => unreachable,
......@@ -243,37 +241,36 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
243241 .base = Loop.ResumeNode{
244242 .id = Loop.ResumeNode.Id.Basic,
245243 .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 },
246251 },
247252 };
248 const completion_key = @ptrToInt(&resume_node.base);
249 // TODO support concurrent async ops on the file handle
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 };
253 // TODO only call create io completion port once per fd
254 _ = windows.CreateIoCompletionPort(fd, loop.os_data.io_port, undefined, undefined);
259255 loop.beginOneEvent();
260256 errdefer loop.finishOneEvent();
261257
262258 errdefer {
263 _ = windows.CancelIoEx(fd, &overlapped);
259 _ = windows.CancelIoEx(fd, &resume_node.base.overlapped);
264260 }
265261 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);
267263 }
268264 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) {
270266 const err = windows.GetLastError();
271 return switch (err) {
267 switch (err) {
272268 windows.ERROR.IO_PENDING => unreachable,
273 windows.ERROR.OPERATION_ABORTED => error.OperationAborted,
274 windows.ERROR.BROKEN_PIPE => error.BrokenPipe,
275 else => os.unexpectedErrorWindows(err),
276 };
269 windows.ERROR.OPERATION_ABORTED => return error.OperationAborted,
270 windows.ERROR.BROKEN_PIPE => return error.BrokenPipe,
271 windows.ERROR.HANDLE_EOF => return usize(bytes_transferred),
272 else => return os.unexpectedErrorWindows(err),
273 }
277274 }
278275 return usize(bytes_transferred);
279276}
......@@ -727,7 +724,7 @@ pub fn Watch(comptime V: type) type {
727724
728725 const FileToHandle = std.AutoHashMap([]const u8, promise);
729726
730 const Self = this;
727 const Self = @This();
731728
732729 pub const Event = struct {
733730 id: Id,
......@@ -1074,23 +1071,22 @@ pub fn Watch(comptime V: type) type {
10741071 .base = Loop.ResumeNode{
10751072 .id = Loop.ResumeNode.Id.Basic,
10761073 .handle = @handle(),
1074 .overlapped = windows.OVERLAPPED{
1075 .Internal = 0,
1076 .InternalHigh = 0,
1077 .Offset = 0,
1078 .OffsetHigh = 0,
1079 .hEvent = null,
1080 },
10771081 },
10781082 };
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 };
10871083 var event_buf: [4096]u8 align(@alignOf(windows.FILE_NOTIFY_INFORMATION)) = undefined;
10881084
10891085 // TODO handle this error not in the channel but in the setup
10901086 _ = os.windowsCreateIoCompletionPort(
10911087 dir_handle,
10921088 self.channel.loop.os_data.io_port,
1093 completion_key,
1089 undefined,
10941090 undefined,
10951091 ) catch |err| {
10961092 await (async self.channel.put(err) catch unreachable);
......@@ -1103,7 +1099,7 @@ pub fn Watch(comptime V: type) type {
11031099 self.channel.loop.beginOneEvent();
11041100 errdefer self.channel.loop.finishOneEvent();
11051101 errdefer {
1106 _ = windows.CancelIoEx(dir_handle, &overlapped);
1102 _ = windows.CancelIoEx(dir_handle, &resume_node.base.overlapped);
11071103 }
11081104 suspend {
11091105 _ = windows.ReadDirectoryChangesW(
......@@ -1116,13 +1112,13 @@ pub fn Watch(comptime V: type) type {
11161112 windows.FILE_NOTIFY_CHANGE_LAST_WRITE | windows.FILE_NOTIFY_CHANGE_LAST_ACCESS |
11171113 windows.FILE_NOTIFY_CHANGE_CREATION | windows.FILE_NOTIFY_CHANGE_SECURITY,
11181114 null, // number of bytes transferred (unused for async)
1119 &overlapped,
1115 &resume_node.base.overlapped,
11201116 null, // completion routine - unused because we use IOCP
11211117 );
11221118 }
11231119 }
11241120 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) {
11261122 const errno = windows.GetLastError();
11271123 const err = switch (errno) {
11281124 else => os.unexpectedErrorWindows(errno),
std/event/future.zig+1-1
......@@ -21,7 +21,7 @@ pub fn Future(comptime T: type) type {
2121 /// 2 - finished
2222 available: u8,
2323
24 const Self = this;
24 const Self = @This();
2525 const Queue = std.atomic.Queue(promise);
2626
2727 pub fn init(loop: *Loop) Self {
std/event/group.zig+1-1
......@@ -13,7 +13,7 @@ pub fn Group(comptime ReturnType: type) type {
1313 alloc_stack: Stack,
1414 lock: Lock,
1515
16 const Self = this;
16 const Self = @This();
1717
1818 const Error = switch (@typeInfo(ReturnType)) {
1919 builtin.TypeId.ErrorUnion => |payload| payload.error_set,
std/event/locked.zig+1-1
......@@ -10,7 +10,7 @@ pub fn Locked(comptime T: type) type {
1010 lock: Lock,
1111 private_data: T,
1212
13 const Self = this;
13 const Self = @This();
1414
1515 pub const HeldLock = struct {
1616 value: *T,
std/event/loop.zig+30-14
......@@ -27,6 +27,19 @@ pub const Loop = struct {
2727 pub const ResumeNode = struct {
2828 id: Id,
2929 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
3144 pub const Id = enum {
3245 Basic,
......@@ -101,6 +114,7 @@ pub const Loop = struct {
101114 .final_resume_node = ResumeNode{
102115 .id = ResumeNode.Id.Stop,
103116 .handle = undefined,
117 .overlapped = ResumeNode.overlapped_init,
104118 },
105119 };
106120 const extra_thread_count = thread_count - 1;
......@@ -153,6 +167,7 @@ pub const Loop = struct {
153167 .base = ResumeNode{
154168 .id = ResumeNode.Id.EventFd,
155169 .handle = undefined,
170 .overlapped = ResumeNode.overlapped_init,
156171 },
157172 .eventfd = try os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),
158173 .epoll_op = posix.EPOLL_CTL_ADD,
......@@ -225,6 +240,7 @@ pub const Loop = struct {
225240 .base = ResumeNode{
226241 .id = ResumeNode.Id.EventFd,
227242 .handle = undefined,
243 .overlapped = ResumeNode.overlapped_init,
228244 },
229245 // this one is for sending events
230246 .kevent = posix.Kevent{
......@@ -311,6 +327,7 @@ pub const Loop = struct {
311327 .base = ResumeNode{
312328 .id = ResumeNode.Id.EventFd,
313329 .handle = undefined,
330 .overlapped = ResumeNode.overlapped_init,
314331 },
315332 // this one is for sending events
316333 .completion_key = @ptrToInt(&eventfd_node.data.base),
......@@ -325,8 +342,8 @@ pub const Loop = struct {
325342 var i: usize = 0;
326343 while (i < extra_thread_index) : (i += 1) {
327344 while (true) {
328 const overlapped = @intToPtr(?*windows.OVERLAPPED, 0x1);
329 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, @ptrToInt(&self.final_resume_node), overlapped) catch continue;
345 const overlapped = &self.final_resume_node.overlapped;
346 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
330347 break;
331348 }
332349 }
......@@ -398,6 +415,7 @@ pub const Loop = struct {
398415 .base = ResumeNode{
399416 .id = ResumeNode.Id.Basic,
400417 .handle = @handle(),
418 .overlapped = ResumeNode.overlapped_init,
401419 },
402420 };
403421 try self.linuxAddFd(fd, &resume_node.base, flags);
......@@ -413,6 +431,7 @@ pub const Loop = struct {
413431 .base = ResumeNode{
414432 .id = ResumeNode.Id.Basic,
415433 .handle = @handle(),
434 .overlapped = ResumeNode.overlapped_init,
416435 },
417436 .kev = undefined,
418437 };
......@@ -489,15 +508,11 @@ pub const Loop = struct {
489508 };
490509 },
491510 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);
496511 os.windowsPostQueuedCompletionStatus(
497512 self.os_data.io_port,
498513 undefined,
499 eventfd_node.completion_key,
500 overlapped,
514 undefined,
515 &eventfd_node.base.overlapped,
501516 ) catch {
502517 self.next_tick_queue.unget(next_tick_node);
503518 self.available_eventfd_resume_nodes.push(resume_stack_node);
......@@ -606,8 +621,8 @@ pub const Loop = struct {
606621 var i: usize = 0;
607622 while (i < self.extra_threads.len + 1) : (i += 1) {
608623 while (true) {
609 const overlapped = @intToPtr(?*windows.OVERLAPPED, 0x1);
610 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, @ptrToInt(&self.final_resume_node), overlapped) catch continue;
624 const overlapped = &self.final_resume_node.overlapped;
625 os.windowsPostQueuedCompletionStatus(self.os_data.io_port, undefined, undefined, overlapped) catch continue;
611626 break;
612627 }
613628 }
......@@ -680,17 +695,18 @@ pub const Loop = struct {
680695 },
681696 builtin.Os.windows => {
682697 var completion_key: usize = undefined;
683 while (true) {
698 const overlapped = while (true) {
684699 var nbytes: windows.DWORD = undefined;
685700 var overlapped: ?*windows.OVERLAPPED = undefined;
686701 switch (os.windowsGetQueuedCompletionStatus(self.os_data.io_port, &nbytes, &completion_key, &overlapped, windows.INFINITE)) {
687702 os.WindowsWaitResult.Aborted => return,
688703 os.WindowsWaitResult.Normal => {},
704 os.WindowsWaitResult.EOF => {},
689705 os.WindowsWaitResult.Cancelled => continue,
690706 }
691 if (overlapped != null) break;
692 }
693 const resume_node = @intToPtr(*ResumeNode, completion_key);
707 if (overlapped) |o| break o;
708 } else unreachable; // TODO else unreachable should not be necessary
709 const resume_node = @fieldParentPtr(ResumeNode, "overlapped", overlapped);
694710 const handle = resume_node.handle;
695711 const resume_node_id = resume_node.id;
696712 switch (resume_node_id) {
std/event/rwlocked.zig+1-1
......@@ -10,7 +10,7 @@ pub fn RwLocked(comptime T: type) type {
1010 lock: RwLock,
1111 locked_data: T,
1212
13 const Self = this;
13 const Self = @This();
1414
1515 pub const HeldReadLock = struct {
1616 value: *const T,
std/event/tcp.zig+2-1
......@@ -32,6 +32,7 @@ pub const Server = struct {
3232 .listen_resume_node = event.Loop.ResumeNode{
3333 .id = event.Loop.ResumeNode.Id.Basic,
3434 .handle = undefined,
35 .overlapped = event.Loop.ResumeNode.overlapped_init,
3536 },
3637 };
3738 }
......@@ -131,7 +132,7 @@ test "listen on a port, send bytes, receive bytes" {
131132 const MyServer = struct {
132133 tcp_server: Server,
133134
134 const Self = this;
135 const Self = @This();
135136 async<*mem.Allocator> fn handler(tcp_server: *Server, _addr: *const std.net.Address, _socket: *const std.os.File) void {
136137 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
137138 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
std/fmt/index.zig+1-1
......@@ -1183,7 +1183,7 @@ test "fmt.format" {
11831183 //custom type format
11841184 {
11851185 const Vec2 = struct {
1186 const SelfType = this;
1186 const SelfType = @This();
11871187 x: f32,
11881188 y: f32,
11891189
std/hash/crc.zig+2-2
......@@ -20,7 +20,7 @@ pub const Crc32 = Crc32WithPoly(Polynomial.IEEE);
2020// slicing-by-8 crc32 implementation.
2121pub fn Crc32WithPoly(comptime poly: u32) type {
2222 return struct {
23 const Self = this;
23 const Self = @This();
2424 const lookup_tables = comptime block: {
2525 @setEvalBranchQuota(20000);
2626 var tables: [8][256]u32 = undefined;
......@@ -117,7 +117,7 @@ test "crc32 castagnoli" {
117117// half-byte lookup table implementation.
118118pub fn Crc32SmallWithPoly(comptime poly: u32) type {
119119 return struct {
120 const Self = this;
120 const Self = @This();
121121 const lookup_table = comptime block: {
122122 var table: [16]u32 = undefined;
123123
std/hash/fnv.zig+1-1
......@@ -13,7 +13,7 @@ pub const Fnv1a_128 = Fnv1a(u128, 0x1000000000000000000013b, 0x6c62272e07bb01426
1313
1414fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
1515 return struct {
16 const Self = this;
16 const Self = @This();
1717
1818 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)
2525 debug.assert(c_rounds > 0 and d_rounds > 0);
2626
2727 return struct {
28 const Self = this;
28 const Self = @This();
2929 const digest_size = 64;
3030 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
2222 // this is used to detect bugs where a hashtable is edited while an iterator is running.
2323 modification_count: debug_u32,
2424
25 const Self = this;
25 const Self = @This();
2626
2727 pub const KV = struct {
2828 key: K,
......@@ -472,7 +472,6 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
472472 builtin.TypeId.Promise, builtin.TypeId.Fn => return autoHash(@ptrToInt(key), rng),
473473
474474 builtin.TypeId.Namespace,
475 builtin.TypeId.Block,
476475 builtin.TypeId.BoundFn,
477476 builtin.TypeId.ComptimeFloat,
478477 builtin.TypeId.ComptimeInt,
......@@ -517,7 +516,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
517516 builtin.TypeId.ComptimeFloat,
518517 builtin.TypeId.ComptimeInt,
519518 builtin.TypeId.Namespace,
520 builtin.TypeId.Block,
521519 builtin.TypeId.Promise,
522520 builtin.TypeId.Enum,
523521 builtin.TypeId.BoundFn,
std/heap.zig+1-1
......@@ -385,7 +385,7 @@ pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) Stack
385385
386386pub fn StackFallbackAllocator(comptime size: usize) type {
387387 return struct {
388 const Self = this;
388 const Self = @This();
389389
390390 buffer: [size]u8,
391391 allocator: Allocator,
std/io.zig+6-6
......@@ -76,7 +76,7 @@ pub const FileOutStream = struct {
7676
7777pub fn InStream(comptime ReadError: type) type {
7878 return struct {
79 const Self = this;
79 const Self = @This();
8080 pub const Error = ReadError;
8181
8282 /// 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 {
218218
219219pub fn OutStream(comptime WriteError: type) type {
220220 return struct {
221 const Self = this;
221 const Self = @This();
222222 pub const Error = WriteError;
223223
224224 writeFn: fn (self: *Self, bytes: []const u8) Error!void,
......@@ -291,7 +291,7 @@ pub fn BufferedInStream(comptime Error: type) type {
291291
292292pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type {
293293 return struct {
294 const Self = this;
294 const Self = @This();
295295 const Stream = InStream(Error);
296296
297297 pub stream: Stream,
......@@ -361,7 +361,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
361361/// This makes look-ahead style parsing much easier.
362362pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
363363 return struct {
364 const Self = this;
364 const Self = @This();
365365 pub const Error = InStreamError;
366366 pub const Stream = InStream(Error);
367367
......@@ -424,7 +424,7 @@ pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) typ
424424}
425425
426426pub const SliceInStream = struct {
427 const Self = this;
427 const Self = @This();
428428 pub const Error = error{};
429429 pub const Stream = InStream(Error);
430430
......@@ -505,7 +505,7 @@ pub fn BufferedOutStream(comptime Error: type) type {
505505
506506pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamError: type) type {
507507 return struct {
508 const Self = this;
508 const Self = @This();
509509 pub const Stream = OutStream(Error);
510510 pub const Error = OutStreamError;
511511
std/lazy_init.zig+1-1
......@@ -18,7 +18,7 @@ fn LazyInit(comptime T: type) type {
1818 state: u8, // TODO make this an enum
1919 data: Data,
2020
21 const Self = this;
21 const Self = @This();
2222
2323 // TODO this isn't working for void, investigate and then remove this special case
2424 const Data = if (@sizeOf(T) == 0) u8 else T;
std/linked_list.zig+1-1
......@@ -7,7 +7,7 @@ const Allocator = mem.Allocator;
77/// Generic doubly linked list.
88pub fn LinkedList(comptime T: type) type {
99 return struct {
10 const Self = this;
10 const Self = @This();
1111
1212 /// Node inside the linked list wrapping the actual data.
1313 pub const Node = struct {
std/math/complex/cosh.zig+2-2
......@@ -44,7 +44,7 @@ fn cosh32(z: *const Complex(f32)) Complex(f32) {
4444 else if (ix < 0x4340b1e7) {
4545 const v = Complex(f32).new(math.fabs(x), y);
4646 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));
4848 }
4949 // x >= 192.7: result always overflows
5050 else {
......@@ -112,7 +112,7 @@ fn cosh64(z: *const Complex(f64)) Complex(f64) {
112112 else if (ix < 0x4096bbaa) {
113113 const v = Complex(f64).new(math.fabs(x), y);
114114 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));
116116 }
117117 // x >= 1455: result always overflows
118118 else {
std/math/complex/exp.zig+4-5
......@@ -69,7 +69,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
6969 const y = z.im;
7070
7171 const fy = @bitCast(u64, y);
72 const hy = u32(fy >> 32) & 0x7fffffff;
72 const hy = @intCast(u32, (fy >> 32) & 0x7fffffff);
7373 const ly = @truncate(u32, fy);
7474
7575 // cexp(x + i0) = exp(x) + i0
......@@ -78,7 +78,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
7878 }
7979
8080 const fx = @bitCast(u64, x);
81 const hx = u32(fx >> 32);
81 const hx = @intCast(u32, fx >> 32);
8282 const lx = @truncate(u32, fx);
8383
8484 // cexp(0 + iy) = cos(y) + isin(y)
......@@ -101,8 +101,7 @@ fn exp64(z: Complex(f64)) Complex(f64) {
101101
102102 // 709.7 <= x <= 1454.3 so must scale
103103 if (hx >= exp_overflow and hx <= cexp_overflow) {
104 const r = ldexp_cexp(z, 0);
105 return r.*;
104 return ldexp_cexp(z, 0);
106105 } // - x < exp_overflow => exp(x) won't overflow (common)
107106 // - x > cexp_overflow, so exp(x) * s overflows for s > 0
108107 // - x = +-inf
......@@ -124,7 +123,7 @@ test "complex.cexp32" {
124123}
125124
126125test "complex.cexp64" {
127 const a = Complex(f32).new(5, 3);
126 const a = Complex(f64).new(5, 3);
128127 const c = exp(a);
129128
130129 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;
2525
2626pub fn Complex(comptime T: type) type {
2727 return struct {
28 const Self = this;
28 const Self = @This();
2929
3030 re: T,
3131 im: T,
std/math/complex/sinh.zig+2-2
......@@ -44,7 +44,7 @@ fn sinh32(z: Complex(f32)) Complex(f32) {
4444 else if (ix < 0x4340b1e7) {
4545 const v = Complex(f32).new(math.fabs(x), y);
4646 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);
4848 }
4949 // x >= 192.7: result always overflows
5050 else {
......@@ -111,7 +111,7 @@ fn sinh64(z: Complex(f64)) Complex(f64) {
111111 else if (ix < 0x4096bbaa) {
112112 const v = Complex(f64).new(math.fabs(x), y);
113113 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);
115115 }
116116 // x >= 1455: result always overflows
117117 else {
std/mem.zig+1-1
......@@ -3,7 +3,7 @@ const debug = std.debug;
33const assert = debug.assert;
44const math = std.math;
55const builtin = @import("builtin");
6const mem = this;
6const mem = @This();
77
88pub const Allocator = struct {
99 pub const Error = error{OutOfMemory};
std/net.zig+1-1
......@@ -1,7 +1,7 @@
11const std = @import("index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const net = this;
4const net = @This();
55const posix = std.os.posix;
66const 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
658658 // environment variables to programs that were not, which seems unlikely.
659659 // More investigation is needed.
660660 if (windows.CreateProcessW(
661 app_name, cmd_line, null, null, windows.TRUE, windows.CREATE_UNICODE_ENVIRONMENT,
662 @ptrCast(?*c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation,
661 app_name,
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,
663671 ) == 0) {
664672 const err = windows.GetLastError();
665673 switch (err) {
std/os/index.zig+20-18
......@@ -6,7 +6,7 @@ const is_posix = switch (builtin.os) {
66 builtin.Os.linux, builtin.Os.macosx => true,
77 else => false,
88};
9const os = this;
9const os = @This();
1010
1111test "std.os" {
1212 _ = @import("child_process.zig");
......@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
343343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
344344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
345345 const write_err = posix.getErrno(rc);
346 if (write_err > 0) {
347 return switch (write_err) {
348 posix.EINTR => continue,
349 posix.EINVAL, posix.EFAULT => unreachable,
350 posix.EAGAIN => PosixWriteError.WouldBlock,
351 posix.EBADF => PosixWriteError.FileClosed,
352 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,
353 posix.EDQUOT => PosixWriteError.DiskQuota,
354 posix.EFBIG => PosixWriteError.FileTooBig,
355 posix.EIO => PosixWriteError.InputOutput,
356 posix.ENOSPC => PosixWriteError.NoSpaceLeft,
357 posix.EPERM => PosixWriteError.AccessDenied,
358 posix.EPIPE => PosixWriteError.BrokenPipe,
359 else => unexpectedErrorPosix(write_err),
360 };
346 switch (write_err) {
347 0 => {
348 index += rc;
349 continue;
350 },
351 posix.EINTR => continue,
352 posix.EINVAL => unreachable,
353 posix.EFAULT => unreachable,
354 posix.EAGAIN => return PosixWriteError.WouldBlock,
355 posix.EBADF => return PosixWriteError.FileClosed,
356 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
357 posix.EDQUOT => return PosixWriteError.DiskQuota,
358 posix.EFBIG => return PosixWriteError.FileTooBig,
359 posix.EIO => return PosixWriteError.InputOutput,
360 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
361 posix.EPERM => return PosixWriteError.AccessDenied,
362 posix.EPIPE => return PosixWriteError.BrokenPipe,
363 else => return unexpectedErrorPosix(write_err),
361364 }
362 index += rc;
363365 }
364366}
365367
......@@ -1614,7 +1616,7 @@ pub const Dir = struct {
16141616 return null;
16151617 }
16161618 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{ '.', '.' }))
16181620 continue;
16191621 // Trust that Windows gives us valid UTF-16LE
16201622 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;
206206pub const FILE_NOTIFY_CHANGE_FILE_NAME = 1;
207207pub const FILE_NOTIFY_CHANGE_ATTRIBUTES = 4;
208208
209
210209pub const CONSOLE_SCREEN_BUFFER_INFO = extern struct {
211210 dwSize: COORD,
212211 dwCursorPosition: COORD,
std/os/windows/util.zig+5-2
......@@ -52,7 +52,8 @@ pub const WriteError = error{
5252};
5353
5454pub 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) {
5657 const err = windows.GetLastError();
5758 return switch (err) {
5859 windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources,
......@@ -222,7 +223,7 @@ pub fn windowsFindFirstFile(
222223 dir_path: []const u8,
223224 find_file_data: *windows.WIN32_FIND_DATAW,
224225) !windows.HANDLE {
225 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, []u16{'\\', '*', 0});
226 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, []u16{ '\\', '*', 0 });
226227 const handle = windows.FindFirstFileW(&dir_path_w, find_file_data);
227228
228229 if (handle == windows.INVALID_HANDLE_VALUE) {
......@@ -277,6 +278,7 @@ pub const WindowsWaitResult = enum {
277278 Normal,
278279 Aborted,
279280 Cancelled,
281 EOF,
280282};
281283
282284pub 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
285287 switch (err) {
286288 windows.ERROR.ABANDONED_WAIT_0 => return WindowsWaitResult.Aborted,
287289 windows.ERROR.OPERATION_ABORTED => return WindowsWaitResult.Cancelled,
290 windows.ERROR.HANDLE_EOF => return WindowsWaitResult.EOF,
288291 else => {
289292 if (std.debug.runtime_safety) {
290293 std.debug.panic("unexpected error: {}\n", err);
std/pdb.zig+98-63
......@@ -64,19 +64,35 @@ pub const ModInfo = packed struct {
6464};
6565
6666pub const SectionMapHeader = packed struct {
67 Count: u16, /// Number of segment descriptors
68 LogCount: u16, /// Number of logical segment descriptors
67 /// Number of segment descriptors
68 Count: u16,
69
70 /// Number of logical segment descriptors
71 LogCount: u16,
6972};
7073
7174pub const SectionMapEntry = packed struct {
72 Flags: u16 , /// See the SectionMapEntryFlags enum below.
73 Ovl: u16 , /// Logical overlay number
74 Group: u16 , /// Group index into descriptor array.
75 Frame: u16 ,
76 SectionName: u16 , /// Byte index of segment / group name in string table, or 0xFFFF.
77 ClassName: u16 , /// Byte index of class in string table, or 0xFFFF.
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.
79 SectionLength: u32 , /// Byte count of the segment or group.
75 /// See the SectionMapEntryFlags enum below.
76 Flags: u16,
77
78 /// Logical overlay number
79 Ovl: u16,
80
81 /// Group index into descriptor array.
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,
8096};
8197
8298pub const StreamType = enum(u16) {
......@@ -290,13 +306,13 @@ pub const SymbolKind = packed enum(u16) {
290306pub const TypeIndex = u32;
291307
292308pub const ProcSym = packed struct {
293 Parent: u32 ,
294 End: u32 ,
295 Next: u32 ,
296 CodeSize: u32 ,
297 DbgStart: u32 ,
298 DbgEnd: u32 ,
299 FunctionType: TypeIndex ,
309 Parent: u32,
310 End: u32,
311 Next: u32,
312 CodeSize: u32,
313 DbgStart: u32,
314 DbgEnd: u32,
315 FunctionType: TypeIndex,
300316 CodeOffset: u32,
301317 Segment: u16,
302318 Flags: ProcSymFlags,
......@@ -315,25 +331,34 @@ pub const ProcSymFlags = packed struct {
315331 HasOptimizedDebugInfo: bool,
316332};
317333
318pub const SectionContrSubstreamVersion = enum(u32) {
319 Ver60 = 0xeffe0000 + 19970605,
320 V2 = 0xeffe0000 + 20140516
334pub const SectionContrSubstreamVersion = enum(u32) {
335 Ver60 = 0xeffe0000 + 19970605,
336 V2 = 0xeffe0000 + 20140516,
321337};
322338
323339pub const RecordPrefix = packed struct {
324 RecordLen: u16, /// Record length, starting from &RecordKind.
325 RecordKind: SymbolKind, /// Record kind enum (SymRecordKind or TypeRecordKind)
340 /// Record length, starting from &RecordKind.
341 RecordLen: u16,
342
343 /// Record kind enum (SymRecordKind or TypeRecordKind)
344 RecordKind: SymbolKind,
326345};
327346
328347pub const LineFragmentHeader = packed struct {
329 RelocOffset: u32, /// Code offset of line contribution.
330 RelocSegment: u16, /// Code segment of line contribution.
348 /// Code offset of line contribution.
349 RelocOffset: u32,
350
351 /// Code segment of line contribution.
352 RelocSegment: u16,
331353 Flags: LineFlags,
332 CodeSize: u32, /// Code size of this line contribution.
354
355 /// Code size of this line contribution.
356 CodeSize: u32,
333357};
334358
335359pub const LineFlags = packed struct {
336 LF_HaveColumns: bool, /// CV_LINES_HAVE_COLUMNS
360 /// CV_LINES_HAVE_COLUMNS
361 LF_HaveColumns: bool,
337362 unused: u15,
338363};
339364
......@@ -348,12 +373,14 @@ pub const LineBlockFragmentHeader = packed struct {
348373 /// table of the actual name.
349374 NameIndex: u32,
350375 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
355381pub const LineNumberEntry = packed struct {
356 Offset: u32, /// Offset to start of code bytes for line number
382 /// Offset to start of code bytes for line number
383 Offset: u32,
357384 Flags: u32,
358385
359386 /// TODO runtime crash when I make the actual type of Flags this
......@@ -371,42 +398,53 @@ pub const ColumnNumberEntry = packed struct {
371398
372399/// Checksum bytes follow.
373400pub const FileChecksumEntryHeader = packed struct {
374 FileNameOffset: u32, /// Byte offset of filename in global string table.
375 ChecksumSize: u8, /// Number of bytes of checksum.
376 ChecksumKind: u8, /// FileChecksumKind
401 /// Byte offset of filename in global string table.
402 FileNameOffset: u32,
403
404 /// Number of bytes of checksum.
405 ChecksumSize: u8,
406
407 /// FileChecksumKind
408 ChecksumKind: u8,
377409};
378410
379411pub const DebugSubsectionKind = packed enum(u32) {
380 None = 0,
381 Symbols = 0xf1,
382 Lines = 0xf2,
383 StringTable = 0xf3,
384 FileChecksums = 0xf4,
385 FrameData = 0xf5,
386 InlineeLines = 0xf6,
387 CrossScopeImports = 0xf7,
388 CrossScopeExports = 0xf8,
389
390 // These appear to relate to .Net assembly info.
391 ILLines = 0xf9,
392 FuncMDTokenMap = 0xfa,
393 TypeMDTokenMap = 0xfb,
394 MergedAssemblyInput = 0xfc,
395
396 CoffSymbolRVA = 0xfd,
412 None = 0,
413 Symbols = 0xf1,
414 Lines = 0xf2,
415 StringTable = 0xf3,
416 FileChecksums = 0xf4,
417 FrameData = 0xf5,
418 InlineeLines = 0xf6,
419 CrossScopeImports = 0xf7,
420 CrossScopeExports = 0xf8,
421
422 // These appear to relate to .Net assembly info.
423 ILLines = 0xf9,
424 FuncMDTokenMap = 0xfa,
425 TypeMDTokenMap = 0xfb,
426 MergedAssemblyInput = 0xfc,
427
428 CoffSymbolRVA = 0xfd,
397429};
398430
399
400431pub const DebugSubsectionHeader = packed struct {
401 Kind: DebugSubsectionKind, /// codeview::DebugSubsectionKind enum
402 Length: u32, /// number of bytes occupied by this record.
403};
432 /// codeview::DebugSubsectionKind enum
433 Kind: DebugSubsectionKind,
404434
435 /// number of bytes occupied by this record.
436 Length: u32,
437};
405438
406439pub const PDBStringTableHeader = packed struct {
407 Signature: u32, /// PDBStringTableSignature
408 HashVersion: u32, /// 1 or 2
409 ByteSize: u32, /// Number of bytes of names buffer.
440 /// PDBStringTableSignature
441 Signature: u32,
442
443 /// 1 or 2
444 HashVersion: u32,
445
446 /// Number of bytes of names buffer.
447 ByteSize: u32,
410448};
411449
412450pub const Pdb = struct {
......@@ -456,7 +494,7 @@ const Msf = struct {
456494 switch (superblock.BlockSize) {
457495 // llvm only supports 4096 but we can handle any of these values
458496 512, 1024, 2048, 4096 => {},
459 else => return error.InvalidDebugInfo
497 else => return error.InvalidDebugInfo,
460498 }
461499
462500 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())
......@@ -536,7 +574,6 @@ const SuperBlock = packed struct {
536574 /// The number of ulittle32_t’s in this array is given by
537575 /// ceil(NumDirectoryBytes / BlockSize).
538576 BlockMapAddr: u32,
539
540577};
541578
542579const MsfStream = struct {
......@@ -552,14 +589,12 @@ const MsfStream = struct {
552589 pub const Stream = io.InStream(Error);
553590
554591 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{
556593 .in_file = file,
557594 .pos = 0,
558595 .blocks = try allocator.alloc(u32, block_count),
559596 .block_size = block_size,
560 .stream = Stream {
561 .readFn = readFn,
562 },
597 .stream = Stream{ .readFn = readFn },
563598 };
564599
565600 var file_stream = io.FileInStream.init(file);
......@@ -597,7 +632,7 @@ const MsfStream = struct {
597632
598633 var size: usize = 0;
599634 for (buffer) |*byte| {
600 byte.* = try in.readByte();
635 byte.* = try in.readByte();
601636
602637 offset += 1;
603638 size += 1;
std/segmented_list.zig+1-1
......@@ -75,7 +75,7 @@ const Allocator = std.mem.Allocator;
7575/// size is small. `prealloc_item_count` must be 0, or a power of 2.
7676pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {
7777 return struct {
78 const Self = this;
78 const Self = @This();
7979 const prealloc_exp = blk: {
8080 // we don't use the prealloc_exp constant when prealloc_item_count is 0.
8181 assert(prealloc_item_count != 0);
std/zig/ast.zig+2-2
......@@ -231,7 +231,7 @@ pub const Error = union(enum) {
231231
232232 fn SingleTokenError(comptime msg: []const u8) type {
233233 return struct {
234 const ThisError = this;
234 const ThisError = @This();
235235
236236 token: TokenIndex,
237237
......@@ -244,7 +244,7 @@ pub const Error = union(enum) {
244244
245245 fn SimpleError(comptime msg: []const u8) type {
246246 return struct {
247 const ThisError = this;
247 const ThisError = @This();
248248
249249 token: TokenIndex,
250250
std/zig/bench.zig+1-1
......@@ -24,7 +24,7 @@ pub fn main() !void {
2424 const mb_per_sec = bytes_per_sec / (1024 * 1024);
2525
2626 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;
2828 try stdout.print("{.3} MiB/s, {} KiB used \n", mb_per_sec, memory_used / 1024);
2929}
3030
std/zig/parser_test.zig+1-1
......@@ -1354,7 +1354,7 @@ test "zig fmt: indexing" {
13541354test "zig fmt: struct declaration" {
13551355 try testCanonical(
13561356 \\const S = struct {
1357 \\ const Self = this;
1357 \\ const Self = @This();
13581358 \\ f1: u8,
13591359 \\ pub f3: u8,
13601360 \\
std/zig/render.zig+1-1
......@@ -20,7 +20,7 @@ pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@typeOf(
2020
2121 // make a passthrough stream that checks whether something changed
2222 const MyStream = struct {
23 const MyStream = this;
23 const MyStream = @This();
2424 const StreamError = @typeOf(stream).Child.Error;
2525 const Stream = std.io.OutStream(StreamError);
2626
test/behavior.zig+3
......@@ -10,7 +10,10 @@ comptime {
1010 _ = @import("cases/bool.zig");
1111 _ = @import("cases/bugs/1111.zig");
1212 _ = @import("cases/bugs/1277.zig");
13 _ = @import("cases/bugs/1322.zig");
14 _ = @import("cases/bugs/1381.zig");
1315 _ = @import("cases/bugs/1421.zig");
16 _ = @import("cases/bugs/1442.zig");
1417 _ = @import("cases/bugs/394.zig");
1518 _ = @import("cases/bugs/655.zig");
1619 _ = @import("cases/bugs/656.zig");
test/cases/align.zig+7
......@@ -212,3 +212,10 @@ fn fnWithAlignedStack() i32 {
212212 @setAlignStack(256);
213213 return 1234;
214214}
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" {
6464
6565fn Struct(comptime T: type) type {
6666 return struct {
67 const Self = this;
67 const Self = @This();
6868 x: T,
6969
7070 fn pointer(self: *const Self) Self {
......@@ -106,7 +106,7 @@ const Enum = enum {
106106
107107test "implicitly cast indirect pointer to maybe-indirect pointer" {
108108 const S = struct {
109 const Self = this;
109 const Self = @This();
110110 x: u8,
111111 fn constConst(p: *const *const Self) u8 {
112112 return p.*.x;
......@@ -526,3 +526,14 @@ test "*usize to *void" {
526526 var v = @ptrCast(*void, &i);
527527 v.* = {};
528528}
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" {
275275}
276276
277277fn fnWithFloatMode() f32 {
278 @setFloatMode(this, builtin.FloatMode.Strict);
278 @setFloatMode(builtin.FloatMode.Strict);
279279 return 1234.0;
280280}
281281
......@@ -628,7 +628,7 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
628628 const S = struct {
629629 a: u8,
630630
631 fn b(comptime s: this) u8 {
631 fn b(comptime s: @This()) u8 {
632632 return s.a;
633633 }
634634 };
test/cases/misc.zig-3
......@@ -510,9 +510,6 @@ test "@typeId" {
510510 assert(@typeId(AUnion) == Tid.Union);
511511 assert(@typeId(fn () void) == Tid.Fn);
512512 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
513 assert(@typeId(@typeOf(x: {
514 break :x this;
515 })) == Tid.Block);
516513 // TODO bound fn
517514 // TODO arg tuple
518515 // TODO opaque
test/cases/reflection.zig+1-1
......@@ -1,6 +1,6 @@
11const assert = @import("std").debug.assert;
22const mem = @import("std").mem;
3const reflection = this;
3const reflection = @This();
44
55test "reflection: array, pointer, optional, error union type child" {
66 comptime {
test/cases/struct.zig+2-2
......@@ -423,10 +423,10 @@ fn alloc(comptime T: type) []T {
423423
424424test "call method with mutable reference to struct with no fields" {
425425 const S = struct {
426 fn doC(s: *const this) bool {
426 fn doC(s: *const @This()) bool {
427427 return true;
428428 }
429 fn do(s: *this) bool {
429 fn do(s: *@This()) bool {
430430 return true;
431431 }
432432 };
test/cases/this.zig+2-11
......@@ -1,10 +1,10 @@
11const assert = @import("std").debug.assert;
22
3const module = this;
3const module = @This();
44
55fn Point(comptime T: type) type {
66 return struct {
7 const Self = this;
7 const Self = @This();
88 x: T,
99 y: T,
1010
......@@ -19,11 +19,6 @@ fn add(x: i32, y: i32) i32 {
1919 return x + y;
2020}
2121
22fn factorial(x: i32) i32 {
23 const selfFn = this;
24 return if (x == 0) 1 else x * selfFn(x - 1);
25}
26
2722test "this refer to module call private fn" {
2823 assert(module.add(1, 2) == 3);
2924}
......@@ -37,7 +32,3 @@ test "this refer to container" {
3732 assert(pt.x == 13);
3833 assert(pt.y == 35);
3934}
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 {
166166 assert(TypeId(typeinfo_info) == TypeId.Union);
167167 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
168168 assert(typeinfo_info.Union.tag_type.? == TypeId);
169 assert(typeinfo_info.Union.fields.len == 25);
169 assert(typeinfo_info.Union.fields.len == 24);
170170 assert(typeinfo_info.Union.fields[4].enum_field != null);
171171 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
172172 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
......@@ -217,7 +217,7 @@ fn testStruct() void {
217217}
218218
219219const TestStruct = packed struct {
220 const Self = this;
220 const Self = @This();
221221
222222 fieldA: usize,
223223 fieldB: void,
test/cases/union.zig+39
......@@ -324,3 +324,42 @@ test "tagged union with no payloads" {
324324 @TagType(UnionEnumNoPayloads).B => {},
325325 }
326326}
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 @@
11const tests = @import("tests.zig");
22
33pub 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
417 cases.add(
518 "variable initialization compile error then referenced",
619 \\fn Undeclared() type {
......@@ -3431,7 +3444,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
34313444 \\
34323445 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
34333446 ,
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'",
34353448 );
34363449
34373450 cases.add(
......@@ -3800,11 +3813,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
38003813 \\ return struct {
38013814 \\ b: B(),
38023815 \\
3803 \\ const Self = this;
3816 \\ const Self = @This();
38043817 \\
38053818 \\ fn B() type {
38063819 \\ return struct {
3807 \\ const Self = this;
3820 \\ const Self = @This();
38083821 \\ };
38093822 \\ }
38103823 \\ };
......@@ -3983,8 +3996,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
39833996 cases.add(
39843997 "@setFloatMode twice for same scope",
39853998 \\export fn foo() void {
3986 \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized);
3987 \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized);
3999 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);
4000 \\ @setFloatMode(@import("builtin").FloatMode.Optimized);
39884001 \\}
39894002 ,
39904003 ".tmp_source.zig:3:5: error: float mode set twice for same scope",
......@@ -4301,12 +4314,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
43014314 \\ var a = undefined;
43024315 \\ var b = 1;
43034316 \\ var c = 1.0;
4304 \\ var d = this;
4305 \\ var e = null;
4306 \\ var f = opaque.*;
4307 \\ var g = i32;
4308 \\ var h = @import("std",);
4309 \\ var i = (Foo {}).bar;
4317 \\ var d = null;
4318 \\ var e = opaque.*;
4319 \\ var f = i32;
4320 \\ var g = @import("std",);
4321 \\ var h = (Foo {}).bar;
43104322 \\
43114323 \\ var z: noreturn = return;
43124324 \\}
......@@ -4319,13 +4331,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
43194331 ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
43204332 ".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
43214333 ".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",
4323 ".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",
4324 ".tmp_source.zig:12:4: error: variable of type 'Opaque' not allowed",
4325 ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime",
4326 ".tmp_source.zig:14:4: error: variable of type '(namespace)' 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",
4328 ".tmp_source.zig:17:4: error: unreachable code",
4334 ".tmp_source.zig:10:4: error: variable of type '(null)' must be const or comptime",
4335 ".tmp_source.zig:11:4: error: variable of type 'Opaque' not allowed",
4336 ".tmp_source.zig:12: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",
4338 ".tmp_source.zig:14:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime",
4339 ".tmp_source.zig:16:4: error: unreachable code",
43294340 );
43304341
43314342 cases.add(
test/standalone/brace_expansion/main.zig+1-1
......@@ -191,7 +191,7 @@ pub fn main() !void {
191191 var stdin_buf = try Buffer.initSize(global_allocator, 0);
192192 defer stdin_buf.deinit();
193193
194 var stdin_adapter = io.FileInStream.init(&stdin_file);
194 var stdin_adapter = io.FileInStream.init(stdin_file);
195195 try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));
196196
197197 var result_buf = try Buffer.initSize(global_allocator, 0);