| author | |
| committer | |
| log | 63ebd9d12e48765514777418e12f55576ff63509 |
| tree | 05f40973b86f91bffd6458247bd9cd2c3d66b72d |
| parent | a2e1be0346c364c4327dc2b81bbcdeca12414dab |
| parent | 5687323cd2a759dfdf9533e46e3de8cddb1b55b7 |
| signature | Commit is signed but in an unrecognized format. |
45 files changed, 1354 insertions(+), 725 deletions(-)
CMakeLists.txt+10-11| ... | @@ -209,7 +209,7 @@ else() | ... | @@ -209,7 +209,7 @@ else() |
| 209 | else() | 209 | else() |
| 210 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment") | 210 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment") |
| 211 | if(MINGW) | 211 | if(MINGW) |
| 212 | set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format") | 212 | set(ZIG_LLD_COMPILE_FLAGS "${ZIG_LLD_COMPILE_FLAGS} -D__STDC_FORMAT_MACROS -D__USE_MINGW_ANSI_STDIO") |
| 213 | endif() | 213 | endif() |
| 214 | endif() | 214 | endif() |
| 215 | set_target_properties(embedded_lld_lib PROPERTIES | 215 | set_target_properties(embedded_lld_lib PROPERTIES |
| ... | @@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3") | ... | @@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3") |
| 511 | 511 | ||
| 512 | set(EXE_LDFLAGS " ") | 512 | set(EXE_LDFLAGS " ") |
| 513 | if(MSVC) | 513 | if(MSVC) |
| 514 | set(EXE_LDFLAGS "/STACK:16777216") | 514 | set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216") |
| 515 | elseif(MINGW) | 515 | elseif(MINGW) |
| 516 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216") | 516 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216") |
| 517 | endif() | 517 | endif() |
| 518 | 518 | ||
| 519 | if(ZIG_STATIC) | 519 | if(ZIG_STATIC) |
| 520 | if(APPLE) | 520 | if(APPLE) |
| 521 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++") | 521 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++") |
| 522 | elseif(MINGW) | 522 | elseif(MINGW) |
| 523 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -lz3 -lz -lgomp -Wl,--no-whole-archive") | 523 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic, -lwinpthread -lz3 -lz -lgomp") |
| 524 | else() | 524 | elseif(NOT MSVC) |
| 525 | set(EXE_LDFLAGS "-static") | 525 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static") |
| 526 | endif() | 526 | endif() |
| 527 | else() | ||
| 528 | if(MINGW) | ||
| 529 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -lz3") | ||
| 530 | endif() | ||
| 527 | endif() | 531 | endif() |
| 528 | 532 | ||
| 529 | if(ZIG_TEST_COVERAGE) | 533 | if(ZIG_TEST_COVERAGE) |
| ... | @@ -559,11 +563,6 @@ if(NOT MSVC) | ... | @@ -559,11 +563,6 @@ if(NOT MSVC) |
| 559 | target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) | 563 | target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) |
| 560 | endif() | 564 | endif() |
| 561 | 565 | ||
| 562 | if(MINGW) | ||
| 563 | find_library(Z3_LIBRARIES NAMES z3 z3.dll) | ||
| 564 | target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES}) | ||
| 565 | endif() | ||
| 566 | |||
| 567 | if(ZIG_DIA_GUIDS_LIB) | 566 | if(ZIG_DIA_GUIDS_LIB) |
| 568 | target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) | 567 | target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) |
| 569 | endif() | 568 | endif() |
doc/docgen.zig+118-118| ... | @@ -742,101 +742,101 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -742,101 +742,101 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 742 | const token = tokenizer.next(); | 742 | const token = tokenizer.next(); |
| 743 | try writeEscaped(out, src[index..token.start]); | 743 | try writeEscaped(out, src[index..token.start]); |
| 744 | switch (token.id) { | 744 | switch (token.id) { |
| 745 | std.zig.Token.Id.Eof => break, | 745 | .Eof => break, |
| 746 | 746 | ||
| 747 | std.zig.Token.Id.Keyword_align, | 747 | .Keyword_align, |
| 748 | std.zig.Token.Id.Keyword_and, | 748 | .Keyword_and, |
| 749 | std.zig.Token.Id.Keyword_asm, | 749 | .Keyword_asm, |
| 750 | std.zig.Token.Id.Keyword_async, | 750 | .Keyword_async, |
| 751 | std.zig.Token.Id.Keyword_await, | 751 | .Keyword_await, |
| 752 | std.zig.Token.Id.Keyword_break, | 752 | .Keyword_break, |
| 753 | std.zig.Token.Id.Keyword_cancel, | 753 | .Keyword_cancel, |
| 754 | std.zig.Token.Id.Keyword_catch, | 754 | .Keyword_catch, |
| 755 | std.zig.Token.Id.Keyword_comptime, | 755 | .Keyword_comptime, |
| 756 | std.zig.Token.Id.Keyword_const, | 756 | .Keyword_const, |
| 757 | std.zig.Token.Id.Keyword_continue, | 757 | .Keyword_continue, |
| 758 | std.zig.Token.Id.Keyword_defer, | 758 | .Keyword_defer, |
| 759 | std.zig.Token.Id.Keyword_else, | 759 | .Keyword_else, |
| 760 | std.zig.Token.Id.Keyword_enum, | 760 | .Keyword_enum, |
| 761 | std.zig.Token.Id.Keyword_errdefer, | 761 | .Keyword_errdefer, |
| 762 | std.zig.Token.Id.Keyword_error, | 762 | .Keyword_error, |
| 763 | std.zig.Token.Id.Keyword_export, | 763 | .Keyword_export, |
| 764 | std.zig.Token.Id.Keyword_extern, | 764 | .Keyword_extern, |
| 765 | std.zig.Token.Id.Keyword_for, | 765 | .Keyword_for, |
| 766 | std.zig.Token.Id.Keyword_if, | 766 | .Keyword_if, |
| 767 | std.zig.Token.Id.Keyword_inline, | 767 | .Keyword_inline, |
| 768 | std.zig.Token.Id.Keyword_nakedcc, | 768 | .Keyword_nakedcc, |
| 769 | std.zig.Token.Id.Keyword_noalias, | 769 | .Keyword_noalias, |
| 770 | std.zig.Token.Id.Keyword_or, | 770 | .Keyword_or, |
| 771 | std.zig.Token.Id.Keyword_orelse, | 771 | .Keyword_orelse, |
| 772 | std.zig.Token.Id.Keyword_packed, | 772 | .Keyword_packed, |
| 773 | std.zig.Token.Id.Keyword_promise, | 773 | .Keyword_promise, |
| 774 | std.zig.Token.Id.Keyword_pub, | 774 | .Keyword_pub, |
| 775 | std.zig.Token.Id.Keyword_resume, | 775 | .Keyword_resume, |
| 776 | std.zig.Token.Id.Keyword_return, | 776 | .Keyword_return, |
| 777 | std.zig.Token.Id.Keyword_linksection, | 777 | .Keyword_linksection, |
| 778 | std.zig.Token.Id.Keyword_stdcallcc, | 778 | .Keyword_stdcallcc, |
| 779 | std.zig.Token.Id.Keyword_struct, | 779 | .Keyword_struct, |
| 780 | std.zig.Token.Id.Keyword_suspend, | 780 | .Keyword_suspend, |
| 781 | std.zig.Token.Id.Keyword_switch, | 781 | .Keyword_switch, |
| 782 | std.zig.Token.Id.Keyword_test, | 782 | .Keyword_test, |
| 783 | std.zig.Token.Id.Keyword_threadlocal, | 783 | .Keyword_threadlocal, |
| 784 | std.zig.Token.Id.Keyword_try, | 784 | .Keyword_try, |
| 785 | std.zig.Token.Id.Keyword_union, | 785 | .Keyword_union, |
| 786 | std.zig.Token.Id.Keyword_unreachable, | 786 | .Keyword_unreachable, |
| 787 | std.zig.Token.Id.Keyword_usingnamespace, | 787 | .Keyword_usingnamespace, |
| 788 | std.zig.Token.Id.Keyword_var, | 788 | .Keyword_var, |
| 789 | std.zig.Token.Id.Keyword_volatile, | 789 | .Keyword_volatile, |
| 790 | std.zig.Token.Id.Keyword_allowzero, | 790 | .Keyword_allowzero, |
| 791 | std.zig.Token.Id.Keyword_while, | 791 | .Keyword_while, |
| 792 | => { | 792 | => { |
| 793 | try out.write("<span class=\"tok-kw\">"); | 793 | try out.write("<span class=\"tok-kw\">"); |
| 794 | try writeEscaped(out, src[token.start..token.end]); | 794 | try writeEscaped(out, src[token.start..token.end]); |
| 795 | try out.write("</span>"); | 795 | try out.write("</span>"); |
| 796 | }, | 796 | }, |
| 797 | 797 | ||
| 798 | std.zig.Token.Id.Keyword_fn => { | 798 | .Keyword_fn => { |
| 799 | try out.write("<span class=\"tok-kw\">"); | 799 | try out.write("<span class=\"tok-kw\">"); |
| 800 | try writeEscaped(out, src[token.start..token.end]); | 800 | try writeEscaped(out, src[token.start..token.end]); |
| 801 | try out.write("</span>"); | 801 | try out.write("</span>"); |
| 802 | next_tok_is_fn = true; | 802 | next_tok_is_fn = true; |
| 803 | }, | 803 | }, |
| 804 | 804 | ||
| 805 | std.zig.Token.Id.Keyword_undefined, | 805 | .Keyword_undefined, |
| 806 | std.zig.Token.Id.Keyword_null, | 806 | .Keyword_null, |
| 807 | std.zig.Token.Id.Keyword_true, | 807 | .Keyword_true, |
| 808 | std.zig.Token.Id.Keyword_false, | 808 | .Keyword_false, |
| 809 | => { | 809 | => { |
| 810 | try out.write("<span class=\"tok-null\">"); | 810 | try out.write("<span class=\"tok-null\">"); |
| 811 | try writeEscaped(out, src[token.start..token.end]); | 811 | try writeEscaped(out, src[token.start..token.end]); |
| 812 | try out.write("</span>"); | 812 | try out.write("</span>"); |
| 813 | }, | 813 | }, |
| 814 | 814 | ||
| 815 | std.zig.Token.Id.StringLiteral, | 815 | .StringLiteral, |
| 816 | std.zig.Token.Id.MultilineStringLiteralLine, | 816 | .MultilineStringLiteralLine, |
| 817 | std.zig.Token.Id.CharLiteral, | 817 | .CharLiteral, |
| 818 | => { | 818 | => { |
| 819 | try out.write("<span class=\"tok-str\">"); | 819 | try out.write("<span class=\"tok-str\">"); |
| 820 | try writeEscaped(out, src[token.start..token.end]); | 820 | try writeEscaped(out, src[token.start..token.end]); |
| 821 | try out.write("</span>"); | 821 | try out.write("</span>"); |
| 822 | }, | 822 | }, |
| 823 | 823 | ||
| 824 | std.zig.Token.Id.Builtin => { | 824 | .Builtin => { |
| 825 | try out.write("<span class=\"tok-builtin\">"); | 825 | try out.write("<span class=\"tok-builtin\">"); |
| 826 | try writeEscaped(out, src[token.start..token.end]); | 826 | try writeEscaped(out, src[token.start..token.end]); |
| 827 | try out.write("</span>"); | 827 | try out.write("</span>"); |
| 828 | }, | 828 | }, |
| 829 | 829 | ||
| 830 | std.zig.Token.Id.LineComment, | 830 | .LineComment, |
| 831 | std.zig.Token.Id.DocComment, | 831 | .DocComment, |
| 832 | std.zig.Token.Id.ShebangLine, | 832 | .ShebangLine, |
| 833 | => { | 833 | => { |
| 834 | try out.write("<span class=\"tok-comment\">"); | 834 | try out.write("<span class=\"tok-comment\">"); |
| 835 | try writeEscaped(out, src[token.start..token.end]); | 835 | try writeEscaped(out, src[token.start..token.end]); |
| 836 | try out.write("</span>"); | 836 | try out.write("</span>"); |
| 837 | }, | 837 | }, |
| 838 | 838 | ||
| 839 | std.zig.Token.Id.Identifier => { | 839 | .Identifier => { |
| 840 | if (prev_tok_was_fn) { | 840 | if (prev_tok_was_fn) { |
| 841 | try out.write("<span class=\"tok-fn\">"); | 841 | try out.write("<span class=\"tok-fn\">"); |
| 842 | try writeEscaped(out, src[token.start..token.end]); | 842 | try writeEscaped(out, src[token.start..token.end]); |
| ... | @@ -864,72 +864,72 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok | ... | @@ -864,72 +864,72 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 864 | } | 864 | } |
| 865 | }, | 865 | }, |
| 866 | 866 | ||
| 867 | std.zig.Token.Id.IntegerLiteral, | 867 | .IntegerLiteral, |
| 868 | std.zig.Token.Id.FloatLiteral, | 868 | .FloatLiteral, |
| 869 | => { | 869 | => { |
| 870 | try out.write("<span class=\"tok-number\">"); | 870 | try out.write("<span class=\"tok-number\">"); |
| 871 | try writeEscaped(out, src[token.start..token.end]); | 871 | try writeEscaped(out, src[token.start..token.end]); |
| 872 | try out.write("</span>"); | 872 | try out.write("</span>"); |
| 873 | }, | 873 | }, |
| 874 | 874 | ||
| 875 | std.zig.Token.Id.Bang, | 875 | .Bang, |
| 876 | std.zig.Token.Id.Pipe, | 876 | .Pipe, |
| 877 | std.zig.Token.Id.PipePipe, | 877 | .PipePipe, |
| 878 | std.zig.Token.Id.PipeEqual, | 878 | .PipeEqual, |
| 879 | std.zig.Token.Id.Equal, | 879 | .Equal, |
| 880 | std.zig.Token.Id.EqualEqual, | 880 | .EqualEqual, |
| 881 | std.zig.Token.Id.EqualAngleBracketRight, | 881 | .EqualAngleBracketRight, |
| 882 | std.zig.Token.Id.BangEqual, | 882 | .BangEqual, |
| 883 | std.zig.Token.Id.LParen, | 883 | .LParen, |
| 884 | std.zig.Token.Id.RParen, | 884 | .RParen, |
| 885 | std.zig.Token.Id.Semicolon, | 885 | .Semicolon, |
| 886 | std.zig.Token.Id.Percent, | 886 | .Percent, |
| 887 | std.zig.Token.Id.PercentEqual, | 887 | .PercentEqual, |
| 888 | std.zig.Token.Id.LBrace, | 888 | .LBrace, |
| 889 | std.zig.Token.Id.RBrace, | 889 | .RBrace, |
| 890 | std.zig.Token.Id.LBracket, | 890 | .LBracket, |
| 891 | std.zig.Token.Id.RBracket, | 891 | .RBracket, |
| 892 | std.zig.Token.Id.Period, | 892 | .Period, |
| 893 | std.zig.Token.Id.Ellipsis2, | 893 | .Ellipsis2, |
| 894 | std.zig.Token.Id.Ellipsis3, | 894 | .Ellipsis3, |
| 895 | std.zig.Token.Id.Caret, | 895 | .Caret, |
| 896 | std.zig.Token.Id.CaretEqual, | 896 | .CaretEqual, |
| 897 | std.zig.Token.Id.Plus, | 897 | .Plus, |
| 898 | std.zig.Token.Id.PlusPlus, | 898 | .PlusPlus, |
| 899 | std.zig.Token.Id.PlusEqual, | 899 | .PlusEqual, |
| 900 | std.zig.Token.Id.PlusPercent, | 900 | .PlusPercent, |
| 901 | std.zig.Token.Id.PlusPercentEqual, | 901 | .PlusPercentEqual, |
| 902 | std.zig.Token.Id.Minus, | 902 | .Minus, |
| 903 | std.zig.Token.Id.MinusEqual, | 903 | .MinusEqual, |
| 904 | std.zig.Token.Id.MinusPercent, | 904 | .MinusPercent, |
| 905 | std.zig.Token.Id.MinusPercentEqual, | 905 | .MinusPercentEqual, |
| 906 | std.zig.Token.Id.Asterisk, | 906 | .Asterisk, |
| 907 | std.zig.Token.Id.AsteriskEqual, | 907 | .AsteriskEqual, |
| 908 | std.zig.Token.Id.AsteriskAsterisk, | 908 | .AsteriskAsterisk, |
| 909 | std.zig.Token.Id.AsteriskPercent, | 909 | .AsteriskPercent, |
| 910 | std.zig.Token.Id.AsteriskPercentEqual, | 910 | .AsteriskPercentEqual, |
| 911 | std.zig.Token.Id.Arrow, | 911 | .Arrow, |
| 912 | std.zig.Token.Id.Colon, | 912 | .Colon, |
| 913 | std.zig.Token.Id.Slash, | 913 | .Slash, |
| 914 | std.zig.Token.Id.SlashEqual, | 914 | .SlashEqual, |
| 915 | std.zig.Token.Id.Comma, | 915 | .Comma, |
| 916 | std.zig.Token.Id.Ampersand, | 916 | .Ampersand, |
| 917 | std.zig.Token.Id.AmpersandEqual, | 917 | .AmpersandEqual, |
| 918 | std.zig.Token.Id.QuestionMark, | 918 | .QuestionMark, |
| 919 | std.zig.Token.Id.AngleBracketLeft, | 919 | .AngleBracketLeft, |
| 920 | std.zig.Token.Id.AngleBracketLeftEqual, | 920 | .AngleBracketLeftEqual, |
| 921 | std.zig.Token.Id.AngleBracketAngleBracketLeft, | 921 | .AngleBracketAngleBracketLeft, |
| 922 | std.zig.Token.Id.AngleBracketAngleBracketLeftEqual, | 922 | .AngleBracketAngleBracketLeftEqual, |
| 923 | std.zig.Token.Id.AngleBracketRight, | 923 | .AngleBracketRight, |
| 924 | std.zig.Token.Id.AngleBracketRightEqual, | 924 | .AngleBracketRightEqual, |
| 925 | std.zig.Token.Id.AngleBracketAngleBracketRight, | 925 | .AngleBracketAngleBracketRight, |
| 926 | std.zig.Token.Id.AngleBracketAngleBracketRightEqual, | 926 | .AngleBracketAngleBracketRightEqual, |
| 927 | std.zig.Token.Id.Tilde, | 927 | .Tilde, |
| 928 | std.zig.Token.Id.BracketStarBracket, | 928 | .BracketStarBracket, |
| 929 | std.zig.Token.Id.BracketStarCBracket, | 929 | .BracketStarCBracket, |
| 930 | => try writeEscaped(out, src[token.start..token.end]), | 930 | => try writeEscaped(out, src[token.start..token.end]), |
| 931 | 931 | ||
| 932 | std.zig.Token.Id.Invalid => return parseError( | 932 | .Invalid, .Invalid_ampersands => return parseError( |
| 933 | docgen_tokenizer, | 933 | docgen_tokenizer, |
| 934 | source_token, | 934 | source_token, |
| 935 | "syntax error", | 935 | "syntax error", |
doc/langref.html.in+16| ... | @@ -6330,6 +6330,22 @@ comptime { | ... | @@ -6330,6 +6330,22 @@ comptime { |
| 6330 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe | 6330 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe |
| 6331 | we can remove this restriction | 6331 | we can remove this restriction |
| 6332 | </p> | 6332 | </p> |
| 6333 | <p> | ||
| 6334 | Supported operations: | ||
| 6335 | </p> | ||
| 6336 | <ul> | ||
| 6337 | <li>{#syntax#}.Xchg{#endsyntax#} - stores the operand unmodified.</li> | ||
| 6338 | <li>{#syntax#}.Add{#endsyntax#} - for integers, twos complement wraparound addition. | ||
| 6339 | Also supports {#link|Floats#}.</li> | ||
| 6340 | <li>{#syntax#}.Sub{#endsyntax#} - for integers, twos complement wraparound subtraction. | ||
| 6341 | Also supports {#link|Floats#}.</li> | ||
| 6342 | <li>{#syntax#}.And{#endsyntax#} - bitwise and</li> | ||
| 6343 | <li>{#syntax#}.Nand{#endsyntax#} - bitwise nand</li> | ||
| 6344 | <li>{#syntax#}.Or{#endsyntax#} - bitwise or</li> | ||
| 6345 | <li>{#syntax#}.Xor{#endsyntax#} - bitwise xor</li> | ||
| 6346 | <li>{#syntax#}.Max{#endsyntax#} - stores the operand if it is larger. Supports integers and floats.</li> | ||
| 6347 | <li>{#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.</li> | ||
| 6348 | </ul> | ||
| 6333 | {#header_close#} | 6349 | {#header_close#} |
| 6334 | {#header_open|@bitCast#} | 6350 | {#header_open|@bitCast#} |
| 6335 | <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> | 6351 | <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> |
src/all_types.hpp+11-7| ... | @@ -366,6 +366,7 @@ enum TldId { | ... | @@ -366,6 +366,7 @@ enum TldId { |
| 366 | TldIdFn, | 366 | TldIdFn, |
| 367 | TldIdContainer, | 367 | TldIdContainer, |
| 368 | TldIdCompTime, | 368 | TldIdCompTime, |
| 369 | TldIdUsingNamespace, | ||
| 369 | }; | 370 | }; |
| 370 | 371 | ||
| 371 | enum TldResolution { | 372 | enum TldResolution { |
| ... | @@ -413,6 +414,12 @@ struct TldCompTime { | ... | @@ -413,6 +414,12 @@ struct TldCompTime { |
| 413 | Tld base; | 414 | Tld base; |
| 414 | }; | 415 | }; |
| 415 | 416 | ||
| 417 | struct TldUsingNamespace { | ||
| 418 | Tld base; | ||
| 419 | |||
| 420 | ConstExprValue *using_namespace_value; | ||
| 421 | }; | ||
| 422 | |||
| 416 | struct TypeEnumField { | 423 | struct TypeEnumField { |
| 417 | Buf *name; | 424 | Buf *name; |
| 418 | BigInt value; | 425 | BigInt value; |
| ... | @@ -453,7 +460,7 @@ enum NodeType { | ... | @@ -453,7 +460,7 @@ enum NodeType { |
| 453 | NodeTypeFieldAccessExpr, | 460 | NodeTypeFieldAccessExpr, |
| 454 | NodeTypePtrDeref, | 461 | NodeTypePtrDeref, |
| 455 | NodeTypeUnwrapOptional, | 462 | NodeTypeUnwrapOptional, |
| 456 | NodeTypeUse, | 463 | NodeTypeUsingNamespace, |
| 457 | NodeTypeBoolLiteral, | 464 | NodeTypeBoolLiteral, |
| 458 | NodeTypeNullLiteral, | 465 | NodeTypeNullLiteral, |
| 459 | NodeTypeUndefinedLiteral, | 466 | NodeTypeUndefinedLiteral, |
| ... | @@ -715,9 +722,6 @@ struct AstNodeArrayType { | ... | @@ -715,9 +722,6 @@ struct AstNodeArrayType { |
| 715 | struct AstNodeUsingNamespace { | 722 | struct AstNodeUsingNamespace { |
| 716 | VisibMod visib_mod; | 723 | VisibMod visib_mod; |
| 717 | AstNode *expr; | 724 | AstNode *expr; |
| 718 | |||
| 719 | TldResolution resolution; | ||
| 720 | ConstExprValue *using_namespace_value; | ||
| 721 | }; | 725 | }; |
| 722 | 726 | ||
| 723 | struct AstNodeIfBoolExpr { | 727 | struct AstNodeIfBoolExpr { |
| ... | @@ -1745,8 +1749,6 @@ struct CodeGen { | ... | @@ -1745,8 +1749,6 @@ struct CodeGen { |
| 1745 | 1749 | ||
| 1746 | ZigList<Tld *> resolve_queue; | 1750 | ZigList<Tld *> resolve_queue; |
| 1747 | size_t resolve_queue_index; | 1751 | size_t resolve_queue_index; |
| 1748 | ZigList<AstNode *> use_queue; | ||
| 1749 | size_t use_queue_index; | ||
| 1750 | ZigList<TimeEvent> timing_events; | 1752 | ZigList<TimeEvent> timing_events; |
| 1751 | ZigList<AstNode *> tld_ref_source_node_stack; | 1753 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1752 | ZigList<ZigFn *> inline_fns; | 1754 | ZigList<ZigFn *> inline_fns; |
| ... | @@ -2005,7 +2007,7 @@ struct ScopeDecls { | ... | @@ -2005,7 +2007,7 @@ struct ScopeDecls { |
| 2005 | Scope base; | 2007 | Scope base; |
| 2006 | 2008 | ||
| 2007 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table; | 2009 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table; |
| 2008 | ZigList<AstNode *> use_decls; | 2010 | ZigList<TldUsingNamespace *> use_decls; |
| 2009 | AstNode *safety_set_node; | 2011 | AstNode *safety_set_node; |
| 2010 | AstNode *fast_math_set_node; | 2012 | AstNode *fast_math_set_node; |
| 2011 | ZigType *import; | 2013 | ZigType *import; |
| ... | @@ -2541,6 +2543,7 @@ struct IrInstructionLoadPtrGen { | ... | @@ -2541,6 +2543,7 @@ struct IrInstructionLoadPtrGen { |
| 2541 | struct IrInstructionStorePtr { | 2543 | struct IrInstructionStorePtr { |
| 2542 | IrInstruction base; | 2544 | IrInstruction base; |
| 2543 | 2545 | ||
| 2546 | bool allow_write_through_const; | ||
| 2544 | IrInstruction *ptr; | 2547 | IrInstruction *ptr; |
| 2545 | IrInstruction *value; | 2548 | IrInstruction *value; |
| 2546 | }; | 2549 | }; |
| ... | @@ -3705,6 +3708,7 @@ enum ResultLocId { | ... | @@ -3705,6 +3708,7 @@ enum ResultLocId { |
| 3705 | struct ResultLoc { | 3708 | struct ResultLoc { |
| 3706 | ResultLocId id; | 3709 | ResultLocId id; |
| 3707 | bool written; | 3710 | bool written; |
| 3711 | bool allow_write_through_const; | ||
| 3708 | IrInstruction *resolved_loc; // result ptr | 3712 | IrInstruction *resolved_loc; // result ptr |
| 3709 | IrInstruction *source_instruction; | 3713 | IrInstruction *source_instruction; |
| 3710 | IrInstruction *gen_instruction; // value to store to the result loc | 3714 | IrInstruction *gen_instruction; // value to store to the result loc |
src/analyze.cpp+138-128| ... | @@ -28,6 +28,8 @@ static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *uni | ... | @@ -28,6 +28,8 @@ static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *uni |
| 28 | static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type); | 28 | static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type); |
| 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); | 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); |
| 30 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status); | 30 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status); |
| 31 | static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope); | ||
| 32 | static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope); | ||
| 31 | 33 | ||
| 32 | static bool is_top_level_struct(ZigType *import) { | 34 | static bool is_top_level_struct(ZigType *import) { |
| 33 | return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; | 35 | return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; |
| ... | @@ -2854,6 +2856,8 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { | ... | @@ -2854,6 +2856,8 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 2854 | add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body")); | 2856 | add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body")); |
| 2855 | return; | 2857 | return; |
| 2856 | } | 2858 | } |
| 2859 | } else if (tld->id == TldIdUsingNamespace) { | ||
| 2860 | g->resolve_queue.append(tld); | ||
| 2857 | } | 2861 | } |
| 2858 | if (is_export) { | 2862 | if (is_export) { |
| 2859 | g->resolve_queue.append(tld); | 2863 | g->resolve_queue.append(tld); |
| ... | @@ -2867,7 +2871,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { | ... | @@ -2867,7 +2871,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 2867 | } | 2871 | } |
| 2868 | } | 2872 | } |
| 2869 | 2873 | ||
| 2870 | { | 2874 | if (tld->name != nullptr) { |
| 2871 | auto entry = decls_scope->decl_table.put_unique(tld->name, tld); | 2875 | auto entry = decls_scope->decl_table.put_unique(tld->name, tld); |
| 2872 | if (entry) { | 2876 | if (entry) { |
| 2873 | Tld *other_tld = entry->value; | 2877 | Tld *other_tld = entry->value; |
| ... | @@ -2875,9 +2879,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { | ... | @@ -2875,9 +2879,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 2875 | add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition is here")); | 2879 | add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition is here")); |
| 2876 | return; | 2880 | return; |
| 2877 | } | 2881 | } |
| 2878 | } | ||
| 2879 | 2882 | ||
| 2880 | { | ||
| 2881 | ZigType *type; | 2883 | ZigType *type; |
| 2882 | if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) { | 2884 | if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) { |
| 2883 | add_node_error(g, tld->source_node, | 2885 | add_node_error(g, tld->source_node, |
| ... | @@ -2977,12 +2979,14 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -2977,12 +2979,14 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2977 | 2979 | ||
| 2978 | break; | 2980 | break; |
| 2979 | } | 2981 | } |
| 2980 | case NodeTypeUse: | 2982 | case NodeTypeUsingNamespace: { |
| 2981 | { | 2983 | VisibMod visib_mod = node->data.using_namespace.visib_mod; |
| 2982 | g->use_queue.append(node); | 2984 | TldUsingNamespace *tld_using_namespace = allocate<TldUsingNamespace>(1); |
| 2983 | decls_scope->use_decls.append(node); | 2985 | init_tld(&tld_using_namespace->base, TldIdUsingNamespace, nullptr, visib_mod, node, &decls_scope->base); |
| 2984 | break; | 2986 | add_top_level_decl(g, decls_scope, &tld_using_namespace->base); |
| 2985 | } | 2987 | decls_scope->use_decls.append(tld_using_namespace); |
| 2988 | break; | ||
| 2989 | } | ||
| 2986 | case NodeTypeTestDecl: | 2990 | case NodeTypeTestDecl: |
| 2987 | preview_test_decl(g, node, decls_scope); | 2991 | preview_test_decl(g, node, decls_scope); |
| 2988 | break; | 2992 | break; |
| ... | @@ -3266,6 +3270,118 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { | ... | @@ -3266,6 +3270,118 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3266 | g->global_vars.append(tld_var); | 3270 | g->global_vars.append(tld_var); |
| 3267 | } | 3271 | } |
| 3268 | 3272 | ||
| 3273 | static void add_symbols_from_container(CodeGen *g, TldUsingNamespace *src_using_namespace, | ||
| 3274 | TldUsingNamespace *dst_using_namespace, ScopeDecls* dest_decls_scope) | ||
| 3275 | { | ||
| 3276 | if (src_using_namespace->base.resolution == TldResolutionUnresolved || | ||
| 3277 | src_using_namespace->base.resolution == TldResolutionResolving) | ||
| 3278 | { | ||
| 3279 | assert(src_using_namespace->base.parent_scope->id == ScopeIdDecls); | ||
| 3280 | ScopeDecls *src_decls_scope = (ScopeDecls *)src_using_namespace->base.parent_scope; | ||
| 3281 | preview_use_decl(g, src_using_namespace, src_decls_scope); | ||
| 3282 | if (src_using_namespace != dst_using_namespace) { | ||
| 3283 | resolve_use_decl(g, src_using_namespace, src_decls_scope); | ||
| 3284 | } | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | ConstExprValue *use_expr = src_using_namespace->using_namespace_value; | ||
| 3288 | if (type_is_invalid(use_expr->type)) { | ||
| 3289 | dest_decls_scope->any_imports_failed = true; | ||
| 3290 | return; | ||
| 3291 | } | ||
| 3292 | |||
| 3293 | dst_using_namespace->base.resolution = TldResolutionOk; | ||
| 3294 | |||
| 3295 | assert(use_expr->special != ConstValSpecialRuntime); | ||
| 3296 | |||
| 3297 | // The source scope for the imported symbols | ||
| 3298 | ScopeDecls *src_scope = get_container_scope(use_expr->data.x_type); | ||
| 3299 | // The top-level container where the symbols are defined, it's used in the | ||
| 3300 | // loop below in order to exclude the ones coming from an import statement | ||
| 3301 | ZigType *src_import = get_scope_import(&src_scope->base); | ||
| 3302 | assert(src_import != nullptr); | ||
| 3303 | |||
| 3304 | if (src_scope->any_imports_failed) { | ||
| 3305 | dest_decls_scope->any_imports_failed = true; | ||
| 3306 | } | ||
| 3307 | |||
| 3308 | auto it = src_scope->decl_table.entry_iterator(); | ||
| 3309 | for (;;) { | ||
| 3310 | auto *entry = it.next(); | ||
| 3311 | if (!entry) | ||
| 3312 | break; | ||
| 3313 | |||
| 3314 | Buf *target_tld_name = entry->key; | ||
| 3315 | Tld *target_tld = entry->value; | ||
| 3316 | |||
| 3317 | if (target_tld->visib_mod == VisibModPrivate) { | ||
| 3318 | continue; | ||
| 3319 | } | ||
| 3320 | |||
| 3321 | if (target_tld->import != src_import) { | ||
| 3322 | continue; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | auto existing_entry = dest_decls_scope->decl_table.put_unique(target_tld_name, target_tld); | ||
| 3326 | if (existing_entry) { | ||
| 3327 | Tld *existing_decl = existing_entry->value; | ||
| 3328 | if (existing_decl != target_tld) { | ||
| 3329 | ErrorMsg *msg = add_node_error(g, dst_using_namespace->base.source_node, | ||
| 3330 | buf_sprintf("import of '%s' overrides existing definition", | ||
| 3331 | buf_ptr(target_tld_name))); | ||
| 3332 | add_error_note(g, msg, existing_decl->source_node, buf_sprintf("previous definition here")); | ||
| 3333 | add_error_note(g, msg, target_tld->source_node, buf_sprintf("imported definition here")); | ||
| 3334 | } | ||
| 3335 | } | ||
| 3336 | } | ||
| 3337 | |||
| 3338 | for (size_t i = 0; i < src_scope->use_decls.length; i += 1) { | ||
| 3339 | TldUsingNamespace *tld_using_namespace = src_scope->use_decls.at(i); | ||
| 3340 | if (tld_using_namespace->base.visib_mod != VisibModPrivate) | ||
| 3341 | add_symbols_from_container(g, tld_using_namespace, dst_using_namespace, dest_decls_scope); | ||
| 3342 | } | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope) { | ||
| 3346 | if (tld_using_namespace->base.resolution == TldResolutionOk || | ||
| 3347 | tld_using_namespace->base.resolution == TldResolutionInvalid) | ||
| 3348 | { | ||
| 3349 | return; | ||
| 3350 | } | ||
| 3351 | add_symbols_from_container(g, tld_using_namespace, tld_using_namespace, dest_decls_scope); | ||
| 3352 | } | ||
| 3353 | |||
| 3354 | static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope) { | ||
| 3355 | if (using_namespace->base.resolution == TldResolutionOk || | ||
| 3356 | using_namespace->base.resolution == TldResolutionInvalid || | ||
| 3357 | using_namespace->using_namespace_value != nullptr) | ||
| 3358 | { | ||
| 3359 | return; | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | using_namespace->base.resolution = TldResolutionResolving; | ||
| 3363 | assert(using_namespace->base.source_node->type == NodeTypeUsingNamespace); | ||
| 3364 | ConstExprValue *result = analyze_const_value(g, &dest_decls_scope->base, | ||
| 3365 | using_namespace->base.source_node->data.using_namespace.expr, g->builtin_types.entry_type, nullptr); | ||
| 3366 | using_namespace->using_namespace_value = result; | ||
| 3367 | |||
| 3368 | if (type_is_invalid(result->type)) { | ||
| 3369 | dest_decls_scope->any_imports_failed = true; | ||
| 3370 | using_namespace->base.resolution = TldResolutionInvalid; | ||
| 3371 | using_namespace->using_namespace_value = &g->invalid_instruction->value; | ||
| 3372 | return; | ||
| 3373 | } | ||
| 3374 | |||
| 3375 | if (!is_container(result->data.x_type)) { | ||
| 3376 | add_node_error(g, using_namespace->base.source_node, | ||
| 3377 | buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&result->data.x_type->name))); | ||
| 3378 | dest_decls_scope->any_imports_failed = true; | ||
| 3379 | using_namespace->base.resolution = TldResolutionInvalid; | ||
| 3380 | using_namespace->using_namespace_value = &g->invalid_instruction->value; | ||
| 3381 | return; | ||
| 3382 | } | ||
| 3383 | } | ||
| 3384 | |||
| 3269 | void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { | 3385 | void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3270 | if (tld->resolution != TldResolutionUnresolved) | 3386 | if (tld->resolution != TldResolutionUnresolved) |
| 3271 | return; | 3387 | return; |
| ... | @@ -3299,6 +3415,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { | ... | @@ -3299,6 +3415,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3299 | resolve_decl_comptime(g, tld_comptime); | 3415 | resolve_decl_comptime(g, tld_comptime); |
| 3300 | break; | 3416 | break; |
| 3301 | } | 3417 | } |
| 3418 | case TldIdUsingNamespace: { | ||
| 3419 | TldUsingNamespace *tld_using_namespace = (TldUsingNamespace *)tld; | ||
| 3420 | assert(tld_using_namespace->base.parent_scope->id == ScopeIdDecls); | ||
| 3421 | ScopeDecls *dest_decls_scope = (ScopeDecls *)tld_using_namespace->base.parent_scope; | ||
| 3422 | preview_use_decl(g, tld_using_namespace, dest_decls_scope); | ||
| 3423 | resolve_use_decl(g, tld_using_namespace, dest_decls_scope); | ||
| 3424 | break; | ||
| 3425 | } | ||
| 3302 | } | 3426 | } |
| 3303 | 3427 | ||
| 3304 | tld->resolution = TldResolutionOk; | 3428 | tld->resolution = TldResolutionOk; |
| ... | @@ -3308,10 +3432,10 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { | ... | @@ -3308,10 +3432,10 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3308 | Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) { | 3432 | Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) { |
| 3309 | // resolve all the using_namespace decls | 3433 | // resolve all the using_namespace decls |
| 3310 | for (size_t i = 0; i < decls_scope->use_decls.length; i += 1) { | 3434 | for (size_t i = 0; i < decls_scope->use_decls.length; i += 1) { |
| 3311 | AstNode *use_decl_node = decls_scope->use_decls.at(i); | 3435 | TldUsingNamespace *tld_using_namespace = decls_scope->use_decls.at(i); |
| 3312 | if (use_decl_node->data.using_namespace.resolution == TldResolutionUnresolved) { | 3436 | if (tld_using_namespace->base.resolution == TldResolutionUnresolved) { |
| 3313 | preview_use_decl(g, use_decl_node, decls_scope); | 3437 | preview_use_decl(g, tld_using_namespace, decls_scope); |
| 3314 | resolve_use_decl(g, use_decl_node, decls_scope); | 3438 | resolve_use_decl(g, tld_using_namespace, decls_scope); |
| 3315 | } | 3439 | } |
| 3316 | } | 3440 | } |
| 3317 | 3441 | ||
| ... | @@ -3752,110 +3876,6 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -3752,110 +3876,6 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { |
| 3752 | analyze_fn_ir(g, fn_table_entry, return_type_node); | 3876 | analyze_fn_ir(g, fn_table_entry, return_type_node); |
| 3753 | } | 3877 | } |
| 3754 | 3878 | ||
| 3755 | static void add_symbols_from_container(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) { | ||
| 3756 | if (src_use_node->data.using_namespace.resolution == TldResolutionUnresolved) { | ||
| 3757 | preview_use_decl(g, src_use_node, decls_scope); | ||
| 3758 | } | ||
| 3759 | |||
| 3760 | ConstExprValue *use_expr = src_use_node->data.using_namespace.using_namespace_value; | ||
| 3761 | if (type_is_invalid(use_expr->type)) { | ||
| 3762 | decls_scope->any_imports_failed = true; | ||
| 3763 | return; | ||
| 3764 | } | ||
| 3765 | |||
| 3766 | dst_use_node->data.using_namespace.resolution = TldResolutionOk; | ||
| 3767 | |||
| 3768 | assert(use_expr->special != ConstValSpecialRuntime); | ||
| 3769 | |||
| 3770 | // The source struct for the imported symbols | ||
| 3771 | ZigType *src_ty = use_expr->data.x_type; | ||
| 3772 | assert(src_ty); | ||
| 3773 | |||
| 3774 | if (!is_container(src_ty)) { | ||
| 3775 | add_node_error(g, dst_use_node, | ||
| 3776 | buf_sprintf("expected struct, enum, or union; found '%s'", buf_ptr(&src_ty->name))); | ||
| 3777 | decls_scope->any_imports_failed = true; | ||
| 3778 | return; | ||
| 3779 | } | ||
| 3780 | |||
| 3781 | // The source scope for the imported symbols | ||
| 3782 | ScopeDecls *src_scope = get_container_scope(src_ty); | ||
| 3783 | // The top-level container where the symbols are defined, it's used in the | ||
| 3784 | // loop below in order to exclude the ones coming from an import statement | ||
| 3785 | ZigType *src_import = get_scope_import(&src_scope->base); | ||
| 3786 | assert(src_import != nullptr); | ||
| 3787 | |||
| 3788 | if (src_scope->any_imports_failed) { | ||
| 3789 | decls_scope->any_imports_failed = true; | ||
| 3790 | } | ||
| 3791 | |||
| 3792 | auto it = src_scope->decl_table.entry_iterator(); | ||
| 3793 | for (;;) { | ||
| 3794 | auto *entry = it.next(); | ||
| 3795 | if (!entry) | ||
| 3796 | break; | ||
| 3797 | |||
| 3798 | Buf *target_tld_name = entry->key; | ||
| 3799 | Tld *target_tld = entry->value; | ||
| 3800 | |||
| 3801 | if (target_tld->visib_mod == VisibModPrivate) { | ||
| 3802 | continue; | ||
| 3803 | } | ||
| 3804 | |||
| 3805 | if (target_tld->import != src_import) { | ||
| 3806 | continue; | ||
| 3807 | } | ||
| 3808 | |||
| 3809 | auto existing_entry = decls_scope->decl_table.put_unique(target_tld_name, target_tld); | ||
| 3810 | if (existing_entry) { | ||
| 3811 | Tld *existing_decl = existing_entry->value; | ||
| 3812 | if (existing_decl != target_tld) { | ||
| 3813 | ErrorMsg *msg = add_node_error(g, dst_use_node, | ||
| 3814 | buf_sprintf("import of '%s' overrides existing definition", | ||
| 3815 | buf_ptr(target_tld_name))); | ||
| 3816 | add_error_note(g, msg, existing_decl->source_node, buf_sprintf("previous definition here")); | ||
| 3817 | add_error_note(g, msg, target_tld->source_node, buf_sprintf("imported definition here")); | ||
| 3818 | } | ||
| 3819 | } | ||
| 3820 | } | ||
| 3821 | |||
| 3822 | for (size_t i = 0; i < src_scope->use_decls.length; i += 1) { | ||
| 3823 | AstNode *use_decl_node = src_scope->use_decls.at(i); | ||
| 3824 | if (use_decl_node->data.using_namespace.visib_mod != VisibModPrivate) | ||
| 3825 | add_symbols_from_container(g, use_decl_node, dst_use_node, decls_scope); | ||
| 3826 | } | ||
| 3827 | } | ||
| 3828 | |||
| 3829 | void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { | ||
| 3830 | assert(node->type == NodeTypeUse); | ||
| 3831 | |||
| 3832 | if (node->data.using_namespace.resolution == TldResolutionOk || | ||
| 3833 | node->data.using_namespace.resolution == TldResolutionInvalid) | ||
| 3834 | { | ||
| 3835 | return; | ||
| 3836 | } | ||
| 3837 | add_symbols_from_container(g, node, node, decls_scope); | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { | ||
| 3841 | assert(node->type == NodeTypeUse); | ||
| 3842 | |||
| 3843 | if (node->data.using_namespace.resolution == TldResolutionOk || | ||
| 3844 | node->data.using_namespace.resolution == TldResolutionInvalid) | ||
| 3845 | { | ||
| 3846 | return; | ||
| 3847 | } | ||
| 3848 | |||
| 3849 | node->data.using_namespace.resolution = TldResolutionResolving; | ||
| 3850 | ConstExprValue *result = analyze_const_value(g, &decls_scope->base, | ||
| 3851 | node->data.using_namespace.expr, g->builtin_types.entry_type, nullptr); | ||
| 3852 | |||
| 3853 | if (type_is_invalid(result->type)) | ||
| 3854 | decls_scope->any_imports_failed = true; | ||
| 3855 | |||
| 3856 | node->data.using_namespace.using_namespace_value = result; | ||
| 3857 | } | ||
| 3858 | |||
| 3859 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, | 3879 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, |
| 3860 | SourceKind source_kind) | 3880 | SourceKind source_kind) |
| 3861 | { | 3881 | { |
| ... | @@ -3975,18 +3995,8 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu | ... | @@ -3975,18 +3995,8 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu |
| 3975 | 3995 | ||
| 3976 | void semantic_analyze(CodeGen *g) { | 3996 | void semantic_analyze(CodeGen *g) { |
| 3977 | while (g->resolve_queue_index < g->resolve_queue.length || | 3997 | while (g->resolve_queue_index < g->resolve_queue.length || |
| 3978 | g->fn_defs_index < g->fn_defs.length || | 3998 | g->fn_defs_index < g->fn_defs.length) |
| 3979 | g->use_queue_index < g->use_queue.length) | ||
| 3980 | { | 3999 | { |
| 3981 | for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { | ||
| 3982 | AstNode *use_decl_node = g->use_queue.at(g->use_queue_index); | ||
| 3983 | // Get the top-level scope where `using_namespace` is used | ||
| 3984 | ScopeDecls *decls_scope = get_container_scope(use_decl_node->owner); | ||
| 3985 | if (use_decl_node->data.using_namespace.resolution == TldResolutionUnresolved) { | ||
| 3986 | preview_use_decl(g, use_decl_node, decls_scope); | ||
| 3987 | resolve_use_decl(g, use_decl_node, decls_scope); | ||
| 3988 | } | ||
| 3989 | } | ||
| 3990 | for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { | 4000 | for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { |
| 3991 | Tld *tld = g->resolve_queue.at(g->resolve_queue_index); | 4001 | Tld *tld = g->resolve_queue.at(g->resolve_queue_index); |
| 3992 | AstNode *source_node = nullptr; | 4002 | AstNode *source_node = nullptr; |
src/analyze.hpp-2| ... | @@ -86,8 +86,6 @@ bool is_array_ref(ZigType *type_entry); | ... | @@ -86,8 +86,6 @@ bool is_array_ref(ZigType *type_entry); |
| 86 | bool is_container_ref(ZigType *type_entry); | 86 | bool is_container_ref(ZigType *type_entry); |
| 87 | bool is_valid_vector_elem_type(ZigType *elem_type); | 87 | bool is_valid_vector_elem_type(ZigType *elem_type); |
| 88 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | 88 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); |
| 89 | void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls* decls_scope); | ||
| 90 | void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls* decls_scope); | ||
| 91 | ZigFn *scope_fn_entry(Scope *scope); | 89 | ZigFn *scope_fn_entry(Scope *scope); |
| 92 | ZigPackage *scope_package(Scope *scope); | 90 | ZigPackage *scope_package(Scope *scope); |
| 93 | ZigType *get_scope_import(Scope *scope); | 91 | ZigType *get_scope_import(Scope *scope); |
src/ast_render.cpp+20-13| ... | @@ -193,8 +193,8 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -193,8 +193,8 @@ static const char *node_type_str(NodeType node_type) { |
| 193 | return "Symbol"; | 193 | return "Symbol"; |
| 194 | case NodeTypePrefixOpExpr: | 194 | case NodeTypePrefixOpExpr: |
| 195 | return "PrefixOpExpr"; | 195 | return "PrefixOpExpr"; |
| 196 | case NodeTypeUse: | 196 | case NodeTypeUsingNamespace: |
| 197 | return "Use"; | 197 | return "UsingNamespace"; |
| 198 | case NodeTypeBoolLiteral: | 198 | case NodeTypeBoolLiteral: |
| 199 | return "BoolLiteral"; | 199 | return "BoolLiteral"; |
| 200 | case NodeTypeNullLiteral: | 200 | case NodeTypeNullLiteral: |
| ... | @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { | ... | @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static bool is_printable(uint8_t c) { | 321 | static bool is_printable(uint8_t c) { |
| 322 | if (c == 0) { | ||
| 323 | return false; | ||
| 324 | } | ||
| 322 | static const uint8_t printables[] = | 325 | static const uint8_t printables[] = |
| 323 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; | 326 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; |
| 324 | for (size_t i = 0; i < array_length(printables); i += 1) { | 327 | for (size_t i = 0; i < array_length(printables); i += 1) { |
| ... | @@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) { | ... | @@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) { |
| 337 | buf_append_str(dest, "\\\""); | 340 | buf_append_str(dest, "\\\""); |
| 338 | } else if (c == '\\') { | 341 | } else if (c == '\\') { |
| 339 | buf_append_str(dest, "\\\\"); | 342 | buf_append_str(dest, "\\\\"); |
| 340 | } else if (c == '\a') { | ||
| 341 | buf_append_str(dest, "\\a"); | ||
| 342 | } else if (c == '\b') { | ||
| 343 | buf_append_str(dest, "\\b"); | ||
| 344 | } else if (c == '\f') { | ||
| 345 | buf_append_str(dest, "\\f"); | ||
| 346 | } else if (c == '\n') { | 343 | } else if (c == '\n') { |
| 347 | buf_append_str(dest, "\\n"); | 344 | buf_append_str(dest, "\\n"); |
| 348 | } else if (c == '\r') { | 345 | } else if (c == '\r') { |
| 349 | buf_append_str(dest, "\\r"); | 346 | buf_append_str(dest, "\\r"); |
| 350 | } else if (c == '\t') { | 347 | } else if (c == '\t') { |
| 351 | buf_append_str(dest, "\\t"); | 348 | buf_append_str(dest, "\\t"); |
| 352 | } else if (c == '\v') { | ||
| 353 | buf_append_str(dest, "\\v"); | ||
| 354 | } else if (is_printable(c)) { | 349 | } else if (is_printable(c)) { |
| 355 | buf_append_char(dest, c); | 350 | buf_append_char(dest, c); |
| 356 | } else { | 351 | } else { |
| ... | @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 630 | case NodeTypeCharLiteral: | 625 | case NodeTypeCharLiteral: |
| 631 | { | 626 | { |
| 632 | uint8_t c = node->data.char_literal.value; | 627 | uint8_t c = node->data.char_literal.value; |
| 633 | if (is_printable(c)) { | 628 | if (c == '\'') { |
| 629 | fprintf(ar->f, "'\\''"); | ||
| 630 | } else if (c == '\"') { | ||
| 631 | fprintf(ar->f, "'\\\"'"); | ||
| 632 | } else if (c == '\\') { | ||
| 633 | fprintf(ar->f, "'\\\\'"); | ||
| 634 | } else if (c == '\n') { | ||
| 635 | fprintf(ar->f, "'\\n'"); | ||
| 636 | } else if (c == '\r') { | ||
| 637 | fprintf(ar->f, "'\\r'"); | ||
| 638 | } else if (c == '\t') { | ||
| 639 | fprintf(ar->f, "'\\t'"); | ||
| 640 | } else if (is_printable(c)) { | ||
| 634 | fprintf(ar->f, "'%c'", c); | 641 | fprintf(ar->f, "'%c'", c); |
| 635 | } else { | 642 | } else { |
| 636 | fprintf(ar->f, "'\\x%02x'", (int)c); | 643 | fprintf(ar->f, "'\\x%02x'", (int)c); |
| ... | @@ -791,7 +798,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -791,7 +798,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 791 | AstNode *decls_node = node->data.container_decl.decls.at(decl_i); | 798 | AstNode *decls_node = node->data.container_decl.decls.at(decl_i); |
| 792 | render_node_grouped(ar, decls_node); | 799 | render_node_grouped(ar, decls_node); |
| 793 | 800 | ||
| 794 | if (decls_node->type == NodeTypeUse || | 801 | if (decls_node->type == NodeTypeUsingNamespace || |
| 795 | decls_node->type == NodeTypeVariableDeclaration || | 802 | decls_node->type == NodeTypeVariableDeclaration || |
| 796 | decls_node->type == NodeTypeFnProto) | 803 | decls_node->type == NodeTypeFnProto) |
| 797 | { | 804 | { |
| ... | @@ -1170,7 +1177,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -1170,7 +1177,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1170 | case NodeTypeParamDecl: | 1177 | case NodeTypeParamDecl: |
| 1171 | case NodeTypeTestDecl: | 1178 | case NodeTypeTestDecl: |
| 1172 | case NodeTypeStructField: | 1179 | case NodeTypeStructField: |
| 1173 | case NodeTypeUse: | 1180 | case NodeTypeUsingNamespace: |
| 1174 | zig_panic("TODO more ast rendering"); | 1181 | zig_panic("TODO more ast rendering"); |
| 1175 | } | 1182 | } |
| 1176 | } | 1183 | } |
src/codegen.cpp+154-139| ... | @@ -89,126 +89,6 @@ static const char *symbols_that_llvm_depends_on[] = { | ... | @@ -89,126 +89,6 @@ static const char *symbols_that_llvm_depends_on[] = { |
| 89 | // TODO probably all of compiler-rt needs to go here | 89 | // TODO probably all of compiler-rt needs to go here |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, | ||
| 93 | OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir, | ||
| 94 | ZigLibCInstallation *libc, Buf *cache_dir) | ||
| 95 | { | ||
| 96 | CodeGen *g = allocate<CodeGen>(1); | ||
| 97 | |||
| 98 | codegen_add_time_event(g, "Initialize"); | ||
| 99 | |||
| 100 | g->subsystem = TargetSubsystemAuto; | ||
| 101 | g->libc = libc; | ||
| 102 | g->zig_target = target; | ||
| 103 | g->cache_dir = cache_dir; | ||
| 104 | |||
| 105 | if (override_lib_dir == nullptr) { | ||
| 106 | g->zig_lib_dir = get_zig_lib_dir(); | ||
| 107 | } else { | ||
| 108 | g->zig_lib_dir = override_lib_dir; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (override_std_dir == nullptr) { | ||
| 112 | g->zig_std_dir = buf_alloc(); | ||
| 113 | os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); | ||
| 114 | } else { | ||
| 115 | g->zig_std_dir = override_std_dir; | ||
| 116 | } | ||
| 117 | |||
| 118 | g->zig_c_headers_dir = buf_alloc(); | ||
| 119 | os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); | ||
| 120 | |||
| 121 | g->build_mode = build_mode; | ||
| 122 | g->out_type = out_type; | ||
| 123 | g->import_table.init(32); | ||
| 124 | g->builtin_fn_table.init(32); | ||
| 125 | g->primitive_type_table.init(32); | ||
| 126 | g->type_table.init(32); | ||
| 127 | g->fn_type_table.init(32); | ||
| 128 | g->error_table.init(16); | ||
| 129 | g->generic_table.init(16); | ||
| 130 | g->llvm_fn_table.init(16); | ||
| 131 | g->memoized_fn_eval_table.init(16); | ||
| 132 | g->exported_symbol_names.init(8); | ||
| 133 | g->external_prototypes.init(8); | ||
| 134 | g->string_literals_table.init(16); | ||
| 135 | g->type_info_cache.init(32); | ||
| 136 | g->is_test_build = false; | ||
| 137 | g->is_single_threaded = false; | ||
| 138 | buf_resize(&g->global_asm, 0); | ||
| 139 | |||
| 140 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { | ||
| 141 | g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr); | ||
| 142 | } | ||
| 143 | |||
| 144 | if (root_src_path) { | ||
| 145 | Buf *root_pkg_path; | ||
| 146 | Buf *rel_root_src_path; | ||
| 147 | if (main_pkg_path == nullptr) { | ||
| 148 | Buf *src_basename = buf_alloc(); | ||
| 149 | Buf *src_dir = buf_alloc(); | ||
| 150 | os_path_split(root_src_path, src_dir, src_basename); | ||
| 151 | |||
| 152 | if (buf_len(src_basename) == 0) { | ||
| 153 | fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); | ||
| 154 | exit(1); | ||
| 155 | } | ||
| 156 | root_pkg_path = src_dir; | ||
| 157 | rel_root_src_path = src_basename; | ||
| 158 | } else { | ||
| 159 | Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1); | ||
| 160 | Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); | ||
| 161 | |||
| 162 | if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { | ||
| 163 | fprintf(stderr, "Root source path '%s' outside main package path '%s'", | ||
| 164 | buf_ptr(root_src_path), buf_ptr(main_pkg_path)); | ||
| 165 | exit(1); | ||
| 166 | } | ||
| 167 | root_pkg_path = main_pkg_path; | ||
| 168 | rel_root_src_path = buf_create_from_mem( | ||
| 169 | buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1, | ||
| 170 | buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1); | ||
| 171 | } | ||
| 172 | |||
| 173 | g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); | ||
| 174 | g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std"); | ||
| 175 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); | ||
| 176 | } else { | ||
| 177 | g->root_package = new_package(".", "", ""); | ||
| 178 | } | ||
| 179 | |||
| 180 | g->root_package->package_table.put(buf_create_from_str("root"), g->root_package); | ||
| 181 | |||
| 182 | g->zig_std_special_dir = buf_alloc(); | ||
| 183 | os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); | ||
| 184 | |||
| 185 | assert(target != nullptr); | ||
| 186 | if (!target->is_native) { | ||
| 187 | g->each_lib_rpath = false; | ||
| 188 | } else { | ||
| 189 | g->each_lib_rpath = true; | ||
| 190 | |||
| 191 | if (target_os_is_darwin(g->zig_target->os)) { | ||
| 192 | init_darwin_native(g); | ||
| 193 | } | ||
| 194 | |||
| 195 | } | ||
| 196 | |||
| 197 | if (target_os_requires_libc(g->zig_target->os)) { | ||
| 198 | g->libc_link_lib = create_link_lib(buf_create_from_str("c")); | ||
| 199 | g->link_libs_list.append(g->libc_link_lib); | ||
| 200 | } | ||
| 201 | |||
| 202 | target_triple_llvm(&g->llvm_triple_str, g->zig_target); | ||
| 203 | g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8; | ||
| 204 | |||
| 205 | if (!target_has_debug_info(g->zig_target)) { | ||
| 206 | g->strip_debug_symbols = true; | ||
| 207 | } | ||
| 208 | |||
| 209 | return g; | ||
| 210 | } | ||
| 211 | |||
| 212 | void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { | 92 | void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { |
| 213 | g->clang_argv = args; | 93 | g->clang_argv = args; |
| 214 | g->clang_argv_len = len; | 94 | g->clang_argv_len = len; |
| ... | @@ -233,10 +113,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc | ... | @@ -233,10 +113,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc |
| 233 | g->version_patch = patch; | 113 | g->version_patch = patch; |
| 234 | } | 114 | } |
| 235 | 115 | ||
| 236 | void codegen_set_is_test(CodeGen *g, bool is_test_build) { | ||
| 237 | g->is_test_build = is_test_build; | ||
| 238 | } | ||
| 239 | |||
| 240 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { | 116 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { |
| 241 | g->emit_file_type = emit_file_type; | 117 | g->emit_file_type = emit_file_type; |
| 242 | } | 118 | } |
| ... | @@ -4582,8 +4458,14 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn | ... | @@ -4582,8 +4458,14 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 4582 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); | 4458 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); |
| 4583 | } | 4459 | } |
| 4584 | 4460 | ||
| 4461 | // When the cmpxchg is discarded, the result location will have no bits. | ||
| 4462 | if (!type_has_bits(instruction->result_loc->value.type)) { | ||
| 4463 | return nullptr; | ||
| 4464 | } | ||
| 4465 | |||
| 4585 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); | 4466 | LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); |
| 4586 | assert(type_has_bits(child_type)); | 4467 | src_assert(result_loc != nullptr, instruction->base.source_node); |
| 4468 | src_assert(type_has_bits(child_type), instruction->base.source_node); | ||
| 4587 | 4469 | ||
| 4588 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); | 4470 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4589 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); | 4471 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); |
| ... | @@ -5486,7 +5368,8 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab | ... | @@ -5486,7 +5368,8 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab |
| 5486 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); | 5368 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); |
| 5487 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, | 5369 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, |
| 5488 | LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); | 5370 | LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); |
| 5489 | gen_store_untyped(g, vector, casted_ptr, get_ptr_align(g, instruction->result_loc->value.type), false); | 5371 | uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type); |
| 5372 | gen_store_untyped(g, vector, casted_ptr, alignment, false); | ||
| 5490 | return result_loc; | 5373 | return result_loc; |
| 5491 | } | 5374 | } |
| 5492 | 5375 | ||
| ... | @@ -5499,7 +5382,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab | ... | @@ -5499,7 +5382,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab |
| 5499 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); | 5382 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); |
| 5500 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, | 5383 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, |
| 5501 | LLVMPointerType(get_llvm_type(g, vector_type), 0), ""); | 5384 | LLVMPointerType(get_llvm_type(g, vector_type), 0), ""); |
| 5502 | return gen_load_untyped(g, casted_ptr, 0, false, ""); | 5385 | ZigType *array_type = instruction->array->value.type; |
| 5386 | assert(array_type->id == ZigTypeIdArray); | ||
| 5387 | uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type); | ||
| 5388 | return gen_load_untyped(g, casted_ptr, alignment, false, ""); | ||
| 5503 | } | 5389 | } |
| 5504 | 5390 | ||
| 5505 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, | 5391 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, |
| ... | @@ -7994,6 +7880,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -7994,6 +7880,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7994 | return contents; | 7880 | return contents; |
| 7995 | } | 7881 | } |
| 7996 | 7882 | ||
| 7883 | static ZigPackage *create_test_runner_pkg(CodeGen *g) { | ||
| 7884 | return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig", "std.special"); | ||
| 7885 | } | ||
| 7886 | |||
| 7887 | static ZigPackage *create_panic_pkg(CodeGen *g) { | ||
| 7888 | return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig", "std.special"); | ||
| 7889 | } | ||
| 7890 | |||
| 7997 | static Error define_builtin_compile_vars(CodeGen *g) { | 7891 | static Error define_builtin_compile_vars(CodeGen *g) { |
| 7998 | if (g->std_package == nullptr) | 7892 | if (g->std_package == nullptr) |
| 7999 | return ErrorNone; | 7893 | return ErrorNone; |
| ... | @@ -8078,8 +7972,16 @@ static Error define_builtin_compile_vars(CodeGen *g) { | ... | @@ -8078,8 +7972,16 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8078 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 7972 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 8079 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 7973 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 8080 | g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); | 7974 | g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); |
| 8081 | g->std_package->package_table.put(buf_create_from_str("root"), | 7975 | ZigPackage *root_pkg; |
| 8082 | g->is_test_build ? g->test_runner_package : g->root_package); | 7976 | if (g->is_test_build) { |
| 7977 | if (g->test_runner_package == nullptr) { | ||
| 7978 | g->test_runner_package = create_test_runner_pkg(g); | ||
| 7979 | } | ||
| 7980 | root_pkg = g->test_runner_package; | ||
| 7981 | } else { | ||
| 7982 | root_pkg = g->root_package; | ||
| 7983 | } | ||
| 7984 | g->std_package->package_table.put(buf_create_from_str("root"), root_pkg); | ||
| 8083 | g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents, | 7985 | g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents, |
| 8084 | SourceKindPkgMain); | 7986 | SourceKindPkgMain); |
| 8085 | 7987 | ||
| ... | @@ -8586,14 +8488,6 @@ static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) { | ... | @@ -8586,14 +8488,6 @@ static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) { |
| 8586 | return package; | 8488 | return package; |
| 8587 | } | 8489 | } |
| 8588 | 8490 | ||
| 8589 | static ZigPackage *create_test_runner_pkg(CodeGen *g) { | ||
| 8590 | return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig", "std.special"); | ||
| 8591 | } | ||
| 8592 | |||
| 8593 | static ZigPackage *create_panic_pkg(CodeGen *g) { | ||
| 8594 | return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig", "std.special"); | ||
| 8595 | } | ||
| 8596 | |||
| 8597 | static void create_test_compile_var_and_add_test_runner(CodeGen *g) { | 8491 | static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 8598 | Error err; | 8492 | Error err; |
| 8599 | 8493 | ||
| ... | @@ -8643,7 +8537,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { | ... | @@ -8643,7 +8537,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 8643 | ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); | 8537 | ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); |
| 8644 | 8538 | ||
| 8645 | update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice); | 8539 | update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice); |
| 8646 | g->test_runner_package = create_test_runner_pkg(g); | 8540 | assert(g->test_runner_package != nullptr); |
| 8647 | g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); | 8541 | g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); |
| 8648 | } | 8542 | } |
| 8649 | 8543 | ||
| ... | @@ -9757,7 +9651,8 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o | ... | @@ -9757,7 +9651,8 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o |
| 9757 | ZigLibCInstallation *libc) | 9651 | ZigLibCInstallation *libc) |
| 9758 | { | 9652 | { |
| 9759 | CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, | 9653 | CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, |
| 9760 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path()); | 9654 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path(), |
| 9655 | false); | ||
| 9761 | child_gen->disable_gen_h = true; | 9656 | child_gen->disable_gen_h = true; |
| 9762 | child_gen->want_stack_check = WantStackCheckDisabled; | 9657 | child_gen->want_stack_check = WantStackCheckDisabled; |
| 9763 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; | 9658 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; |
| ... | @@ -9784,3 +9679,123 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o | ... | @@ -9784,3 +9679,123 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o |
| 9784 | return child_gen; | 9679 | return child_gen; |
| 9785 | } | 9680 | } |
| 9786 | 9681 | ||
| 9682 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, | ||
| 9683 | OutType out_type, BuildMode build_mode, Buf *override_lib_dir, Buf *override_std_dir, | ||
| 9684 | ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build) | ||
| 9685 | { | ||
| 9686 | CodeGen *g = allocate<CodeGen>(1); | ||
| 9687 | |||
| 9688 | codegen_add_time_event(g, "Initialize"); | ||
| 9689 | |||
| 9690 | g->subsystem = TargetSubsystemAuto; | ||
| 9691 | g->libc = libc; | ||
| 9692 | g->zig_target = target; | ||
| 9693 | g->cache_dir = cache_dir; | ||
| 9694 | |||
| 9695 | if (override_lib_dir == nullptr) { | ||
| 9696 | g->zig_lib_dir = get_zig_lib_dir(); | ||
| 9697 | } else { | ||
| 9698 | g->zig_lib_dir = override_lib_dir; | ||
| 9699 | } | ||
| 9700 | |||
| 9701 | if (override_std_dir == nullptr) { | ||
| 9702 | g->zig_std_dir = buf_alloc(); | ||
| 9703 | os_path_join(g->zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir); | ||
| 9704 | } else { | ||
| 9705 | g->zig_std_dir = override_std_dir; | ||
| 9706 | } | ||
| 9707 | |||
| 9708 | g->zig_c_headers_dir = buf_alloc(); | ||
| 9709 | os_path_join(g->zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir); | ||
| 9710 | |||
| 9711 | g->build_mode = build_mode; | ||
| 9712 | g->out_type = out_type; | ||
| 9713 | g->import_table.init(32); | ||
| 9714 | g->builtin_fn_table.init(32); | ||
| 9715 | g->primitive_type_table.init(32); | ||
| 9716 | g->type_table.init(32); | ||
| 9717 | g->fn_type_table.init(32); | ||
| 9718 | g->error_table.init(16); | ||
| 9719 | g->generic_table.init(16); | ||
| 9720 | g->llvm_fn_table.init(16); | ||
| 9721 | g->memoized_fn_eval_table.init(16); | ||
| 9722 | g->exported_symbol_names.init(8); | ||
| 9723 | g->external_prototypes.init(8); | ||
| 9724 | g->string_literals_table.init(16); | ||
| 9725 | g->type_info_cache.init(32); | ||
| 9726 | g->is_test_build = is_test_build; | ||
| 9727 | g->is_single_threaded = false; | ||
| 9728 | buf_resize(&g->global_asm, 0); | ||
| 9729 | |||
| 9730 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { | ||
| 9731 | g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr); | ||
| 9732 | } | ||
| 9733 | |||
| 9734 | if (root_src_path) { | ||
| 9735 | Buf *root_pkg_path; | ||
| 9736 | Buf *rel_root_src_path; | ||
| 9737 | if (main_pkg_path == nullptr) { | ||
| 9738 | Buf *src_basename = buf_alloc(); | ||
| 9739 | Buf *src_dir = buf_alloc(); | ||
| 9740 | os_path_split(root_src_path, src_dir, src_basename); | ||
| 9741 | |||
| 9742 | if (buf_len(src_basename) == 0) { | ||
| 9743 | fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path)); | ||
| 9744 | exit(1); | ||
| 9745 | } | ||
| 9746 | root_pkg_path = src_dir; | ||
| 9747 | rel_root_src_path = src_basename; | ||
| 9748 | } else { | ||
| 9749 | Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1); | ||
| 9750 | Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); | ||
| 9751 | |||
| 9752 | if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { | ||
| 9753 | fprintf(stderr, "Root source path '%s' outside main package path '%s'", | ||
| 9754 | buf_ptr(root_src_path), buf_ptr(main_pkg_path)); | ||
| 9755 | exit(1); | ||
| 9756 | } | ||
| 9757 | root_pkg_path = main_pkg_path; | ||
| 9758 | rel_root_src_path = buf_create_from_mem( | ||
| 9759 | buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1, | ||
| 9760 | buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1); | ||
| 9761 | } | ||
| 9762 | |||
| 9763 | g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); | ||
| 9764 | g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std"); | ||
| 9765 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); | ||
| 9766 | } else { | ||
| 9767 | g->root_package = new_package(".", "", ""); | ||
| 9768 | } | ||
| 9769 | |||
| 9770 | g->root_package->package_table.put(buf_create_from_str("root"), g->root_package); | ||
| 9771 | |||
| 9772 | g->zig_std_special_dir = buf_alloc(); | ||
| 9773 | os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); | ||
| 9774 | |||
| 9775 | assert(target != nullptr); | ||
| 9776 | if (!target->is_native) { | ||
| 9777 | g->each_lib_rpath = false; | ||
| 9778 | } else { | ||
| 9779 | g->each_lib_rpath = true; | ||
| 9780 | |||
| 9781 | if (target_os_is_darwin(g->zig_target->os)) { | ||
| 9782 | init_darwin_native(g); | ||
| 9783 | } | ||
| 9784 | |||
| 9785 | } | ||
| 9786 | |||
| 9787 | if (target_os_requires_libc(g->zig_target->os)) { | ||
| 9788 | g->libc_link_lib = create_link_lib(buf_create_from_str("c")); | ||
| 9789 | g->link_libs_list.append(g->libc_link_lib); | ||
| 9790 | } | ||
| 9791 | |||
| 9792 | target_triple_llvm(&g->llvm_triple_str, g->zig_target); | ||
| 9793 | g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8; | ||
| 9794 | |||
| 9795 | if (!target_has_debug_info(g->zig_target)) { | ||
| 9796 | g->strip_debug_symbols = true; | ||
| 9797 | } | ||
| 9798 | |||
| 9799 | return g; | ||
| 9800 | } | ||
| 9801 |
src/codegen.hpp+1-2| ... | @@ -18,14 +18,13 @@ | ... | @@ -18,14 +18,13 @@ |
| 18 | 18 | ||
| 19 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, | 19 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, |
| 20 | OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, | 20 | OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, |
| 21 | ZigLibCInstallation *libc, Buf *cache_dir); | 21 | ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build); |
| 22 | 22 | ||
| 23 | CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, | 23 | CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, |
| 24 | ZigLibCInstallation *libc); | 24 | ZigLibCInstallation *libc); |
| 25 | 25 | ||
| 26 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); | 26 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 27 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); | 27 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); |
| 28 | void codegen_set_is_test(CodeGen *codegen, bool is_test); | ||
| 29 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); | 28 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); |
| 30 | 29 | ||
| 31 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); | 30 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); |
src/ir.cpp+79-53| ... | @@ -189,7 +189,8 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -189,7 +189,8 @@ static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 189 | static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, | 189 | static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 190 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); | 190 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); |
| 191 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, | 191 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 192 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); | 192 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, |
| 193 | bool non_null_comptime, bool allow_discard); | ||
| 193 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, | 194 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, |
| 194 | IrInstruction *base_ptr, bool safety_check_on, bool initializing); | 195 | IrInstruction *base_ptr, bool safety_check_on, bool initializing); |
| 195 | static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr, | 196 | static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruction *source_instr, |
| ... | @@ -197,7 +198,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct | ... | @@ -197,7 +198,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct |
| 197 | static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, | 198 | static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, |
| 198 | IrInstruction *base_ptr, bool initializing); | 199 | IrInstruction *base_ptr, bool initializing); |
| 199 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, | 200 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 200 | IrInstruction *ptr, IrInstruction *uncasted_value); | 201 | IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const); |
| 201 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 202 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 202 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, | 203 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, |
| 203 | LVal lval, ResultLoc *parent_result_loc); | 204 | LVal lval, ResultLoc *parent_result_loc); |
| ... | @@ -1612,7 +1613,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -1612,7 +1613,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode |
| 1612 | return &unreachable_instruction->base; | 1613 | return &unreachable_instruction->base; |
| 1613 | } | 1614 | } |
| 1614 | 1615 | ||
| 1615 | static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1616 | static IrInstructionStorePtr *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1616 | IrInstruction *ptr, IrInstruction *value) | 1617 | IrInstruction *ptr, IrInstruction *value) |
| 1617 | { | 1618 | { |
| 1618 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node); | 1619 | IrInstructionStorePtr *instruction = ir_build_instruction<IrInstructionStorePtr>(irb, scope, source_node); |
| ... | @@ -1624,7 +1625,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * | ... | @@ -1624,7 +1625,7 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * |
| 1624 | ir_ref_instruction(ptr, irb->current_basic_block); | 1625 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1625 | ir_ref_instruction(value, irb->current_basic_block); | 1626 | ir_ref_instruction(value, irb->current_basic_block); |
| 1626 | 1627 | ||
| 1627 | return &instruction->base; | 1628 | return instruction; |
| 1628 | } | 1629 | } |
| 1629 | 1630 | ||
| 1630 | static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1631 | static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| ... | @@ -4001,12 +4002,20 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no | ... | @@ -4001,12 +4002,20 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, Scope *scope, AstNode *no |
| 4001 | 4002 | ||
| 4002 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { | 4003 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 4003 | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); | 4004 | IrInstruction *lvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op1, scope, LValPtr, nullptr); |
| 4004 | IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); | 4005 | if (lvalue == irb->codegen->invalid_instruction) |
| 4006 | return irb->codegen->invalid_instruction; | ||
| 4007 | |||
| 4008 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); | ||
| 4009 | result_loc_inst->base.id = ResultLocIdInstruction; | ||
| 4010 | result_loc_inst->base.source_instruction = lvalue; | ||
| 4011 | ir_ref_instruction(lvalue, irb->current_basic_block); | ||
| 4012 | ir_build_reset_result(irb, scope, node, &result_loc_inst->base); | ||
| 4005 | 4013 | ||
| 4006 | if (lvalue == irb->codegen->invalid_instruction || rvalue == irb->codegen->invalid_instruction) | 4014 | IrInstruction *rvalue = ir_gen_node_extra(irb, node->data.bin_op_expr.op2, scope, LValNone, |
| 4015 | &result_loc_inst->base); | ||
| 4016 | if (rvalue == irb->codegen->invalid_instruction) | ||
| 4007 | return irb->codegen->invalid_instruction; | 4017 | return irb->codegen->invalid_instruction; |
| 4008 | 4018 | ||
| 4009 | ir_build_store_ptr(irb, scope, node, lvalue, rvalue); | ||
| 4010 | return ir_build_const_void(irb, scope, node); | 4019 | return ir_build_const_void(irb, scope, node); |
| 4011 | } | 4020 | } |
| 4012 | 4021 | ||
| ... | @@ -6042,6 +6051,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A | ... | @@ -6042,6 +6051,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 6042 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); | 6051 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 6043 | result_loc_inst->base.id = ResultLocIdInstruction; | 6052 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 6044 | result_loc_inst->base.source_instruction = field_ptr; | 6053 | result_loc_inst->base.source_instruction = field_ptr; |
| 6054 | result_loc_inst->base.allow_write_through_const = true; | ||
| 6045 | ir_ref_instruction(field_ptr, irb->current_basic_block); | 6055 | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| 6046 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); | 6056 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| 6047 | 6057 | ||
| ... | @@ -6080,6 +6090,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A | ... | @@ -6080,6 +6090,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A |
| 6080 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); | 6090 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 6081 | result_loc_inst->base.id = ResultLocIdInstruction; | 6091 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 6082 | result_loc_inst->base.source_instruction = elem_ptr; | 6092 | result_loc_inst->base.source_instruction = elem_ptr; |
| 6093 | result_loc_inst->base.allow_write_through_const = true; | ||
| 6083 | ir_ref_instruction(elem_ptr, irb->current_basic_block); | 6094 | ir_ref_instruction(elem_ptr, irb->current_basic_block); |
| 6084 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); | 6095 | ir_build_reset_result(irb, scope, expr_node, &result_loc_inst->base); |
| 6085 | 6096 | ||
| ... | @@ -6637,7 +6648,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -6637,7 +6648,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 6637 | 6648 | ||
| 6638 | ir_set_cursor_at_end_and_append_block(irb, continue_block); | 6649 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 6639 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); | 6650 | IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); |
| 6640 | ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)); | 6651 | ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)->allow_write_through_const = true; |
| 6641 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); | 6652 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 6642 | 6653 | ||
| 6643 | IrInstruction *else_result = nullptr; | 6654 | IrInstruction *else_result = nullptr; |
| ... | @@ -8430,7 +8441,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -8430,7 +8441,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 8430 | switch (node->type) { | 8441 | switch (node->type) { |
| 8431 | case NodeTypeStructValueField: | 8442 | case NodeTypeStructValueField: |
| 8432 | case NodeTypeParamDecl: | 8443 | case NodeTypeParamDecl: |
| 8433 | case NodeTypeUse: | 8444 | case NodeTypeUsingNamespace: |
| 8434 | case NodeTypeSwitchProng: | 8445 | case NodeTypeSwitchProng: |
| 8435 | case NodeTypeSwitchRange: | 8446 | case NodeTypeSwitchRange: |
| 8436 | case NodeTypeStructField: | 8447 | case NodeTypeStructField: |
| ... | @@ -11155,7 +11166,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc | ... | @@ -11155,7 +11166,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 11155 | } | 11166 | } |
| 11156 | 11167 | ||
| 11157 | if (result_loc == nullptr) result_loc = no_result_loc(); | 11168 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 11158 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false); | 11169 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, |
| 11170 | false, true); | ||
| 11159 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 11171 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11160 | return result_loc_inst; | 11172 | return result_loc_inst; |
| 11161 | } | 11173 | } |
| ... | @@ -11615,7 +11627,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so | ... | @@ -11615,7 +11627,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so |
| 11615 | } | 11627 | } |
| 11616 | IrInstruction *result_loc_inst = nullptr; | 11628 | IrInstruction *result_loc_inst = nullptr; |
| 11617 | if (result_loc != nullptr) { | 11629 | if (result_loc != nullptr) { |
| 11618 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false); | 11630 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); |
| 11619 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 11631 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11620 | return result_loc_inst; | 11632 | return result_loc_inst; |
| 11621 | } | 11633 | } |
| ... | @@ -11658,7 +11670,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction | ... | @@ -11658,7 +11670,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 11658 | IrInstruction *result_loc_inst; | 11670 | IrInstruction *result_loc_inst; |
| 11659 | if (handle_is_ptr(wanted_type)) { | 11671 | if (handle_is_ptr(wanted_type)) { |
| 11660 | if (result_loc == nullptr) result_loc = no_result_loc(); | 11672 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 11661 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false); | 11673 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); |
| 11662 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 11674 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11663 | return result_loc_inst; | 11675 | return result_loc_inst; |
| 11664 | } | 11676 | } |
| ... | @@ -11743,7 +11755,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so | ... | @@ -11743,7 +11755,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 11743 | IrInstruction *result_loc_inst; | 11755 | IrInstruction *result_loc_inst; |
| 11744 | if (handle_is_ptr(wanted_type)) { | 11756 | if (handle_is_ptr(wanted_type)) { |
| 11745 | if (result_loc == nullptr) result_loc = no_result_loc(); | 11757 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 11746 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false); | 11758 | result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false, true); |
| 11747 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 11759 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11748 | return result_loc_inst; | 11760 | return result_loc_inst; |
| 11749 | } | 11761 | } |
| ... | @@ -11816,7 +11828,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi | ... | @@ -11816,7 +11828,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 11816 | 11828 | ||
| 11817 | IrInstruction *result_loc; | 11829 | IrInstruction *result_loc; |
| 11818 | if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) { | 11830 | if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) { |
| 11819 | result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, false); | 11831 | result_loc = ir_resolve_result(ira, source_instruction, no_result_loc(), value->value.type, nullptr, true, |
| 11832 | false, true); | ||
| 11820 | } else { | 11833 | } else { |
| 11821 | result_loc = nullptr; | 11834 | result_loc = nullptr; |
| 11822 | } | 11835 | } |
| ... | @@ -11860,7 +11873,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s | ... | @@ -11860,7 +11873,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 11860 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); | 11873 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 11861 | 11874 | ||
| 11862 | if (result_loc == nullptr) result_loc = no_result_loc(); | 11875 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 11863 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, true, false); | 11876 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, wanted_type, nullptr, |
| 11877 | true, false, true); | ||
| 11864 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 11878 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11865 | return result_loc_inst; | 11879 | return result_loc_inst; |
| 11866 | } | 11880 | } |
| ... | @@ -12516,7 +12530,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * | ... | @@ -12516,7 +12530,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * |
| 12516 | if (result_loc == nullptr) { | 12530 | if (result_loc == nullptr) { |
| 12517 | result_loc = no_result_loc(); | 12531 | result_loc = no_result_loc(); |
| 12518 | } | 12532 | } |
| 12519 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, true, false); | 12533 | IrInstruction *result_loc_inst = ir_resolve_result(ira, source_instr, result_loc, array_type, nullptr, |
| 12534 | true, false, true); | ||
| 12520 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 12535 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 12521 | return result_loc_inst; | 12536 | return result_loc_inst; |
| 12522 | } | 12537 | } |
| ... | @@ -13097,7 +13112,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -13097,7 +13112,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 13097 | IrInstruction *result_loc_inst; | 13112 | IrInstruction *result_loc_inst; |
| 13098 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { | 13113 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { |
| 13099 | if (result_loc == nullptr) result_loc = no_result_loc(); | 13114 | if (result_loc == nullptr) result_loc = no_result_loc(); |
| 13100 | result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, true, false); | 13115 | result_loc_inst = ir_resolve_result(ira, source_instruction, result_loc, child_type, nullptr, |
| 13116 | true, false, true); | ||
| 13101 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { | 13117 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 13102 | return result_loc_inst; | 13118 | return result_loc_inst; |
| 13103 | } | 13119 | } |
| ... | @@ -14597,7 +14613,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * | ... | @@ -14597,7 +14613,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * |
| 14597 | for (uint64_t x = 0; x < mult_amt; x += 1) { | 14613 | for (uint64_t x = 0; x < mult_amt; x += 1) { |
| 14598 | for (uint64_t y = 0; y < old_array_len; y += 1) { | 14614 | for (uint64_t y = 0; y < old_array_len; y += 1) { |
| 14599 | copy_const_val(&out_val->data.x_array.data.s_none.elements[i], | 14615 | copy_const_val(&out_val->data.x_array.data.s_none.elements[i], |
| 14600 | &array_val->data.x_array.data.s_none.elements[y], true); | 14616 | &array_val->data.x_array.data.s_none.elements[y], false); |
| 14601 | i += 1; | 14617 | i += 1; |
| 14602 | } | 14618 | } |
| 14603 | } | 14619 | } |
| ... | @@ -14834,7 +14850,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, | ... | @@ -14834,7 +14850,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 14834 | // instruction. | 14850 | // instruction. |
| 14835 | assert(deref->value.special != ConstValSpecialRuntime); | 14851 | assert(deref->value.special != ConstValSpecialRuntime); |
| 14836 | var_ptr->value.special = ConstValSpecialRuntime; | 14852 | var_ptr->value.special = ConstValSpecialRuntime; |
| 14837 | ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref); | 14853 | ir_analyze_store_ptr(ira, var_ptr, var_ptr, deref, false); |
| 14838 | } | 14854 | } |
| 14839 | 14855 | ||
| 14840 | if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) { | 14856 | if (var_ptr->value.special == ConstValSpecialStatic && var->mem_slot_index != SIZE_MAX) { |
| ... | @@ -15352,7 +15368,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15352,7 +15368,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15352 | 15368 | ||
| 15353 | if (peer_parent->peers.length == 1) { | 15369 | if (peer_parent->peers.length == 1) { |
| 15354 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, | 15370 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, |
| 15355 | value_type, value, force_runtime, non_null_comptime); | 15371 | value_type, value, force_runtime, non_null_comptime, true); |
| 15356 | result_peer->suspend_pos.basic_block_index = SIZE_MAX; | 15372 | result_peer->suspend_pos.basic_block_index = SIZE_MAX; |
| 15357 | result_peer->suspend_pos.instruction_index = SIZE_MAX; | 15373 | result_peer->suspend_pos.instruction_index = SIZE_MAX; |
| 15358 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || | 15374 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| ... | @@ -15372,7 +15388,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15372,7 +15388,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15372 | if (peer_parent->skipped) { | 15388 | if (peer_parent->skipped) { |
| 15373 | if (non_null_comptime) { | 15389 | if (non_null_comptime) { |
| 15374 | return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, | 15390 | return ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, |
| 15375 | value_type, value, force_runtime, non_null_comptime); | 15391 | value_type, value, force_runtime, non_null_comptime, true); |
| 15376 | } | 15392 | } |
| 15377 | return nullptr; | 15393 | return nullptr; |
| 15378 | } | 15394 | } |
| ... | @@ -15390,7 +15406,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15390,7 +15406,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15390 | } | 15406 | } |
| 15391 | 15407 | ||
| 15392 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, | 15408 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, peer_parent->parent, |
| 15393 | peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime); | 15409 | peer_parent->resolved_type, nullptr, force_runtime, non_null_comptime, true); |
| 15394 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || | 15410 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 15395 | parent_result_loc->value.type->id == ZigTypeIdUnreachable) | 15411 | parent_result_loc->value.type->id == ZigTypeIdUnreachable) |
| 15396 | { | 15412 | { |
| ... | @@ -15440,7 +15456,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15440,7 +15456,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15440 | } | 15456 | } |
| 15441 | 15457 | ||
| 15442 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, | 15458 | IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_bit_cast->parent, |
| 15443 | dest_type, bitcasted_value, force_runtime, non_null_comptime); | 15459 | dest_type, bitcasted_value, force_runtime, non_null_comptime, true); |
| 15444 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || | 15460 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 15445 | parent_result_loc->value.type->id == ZigTypeIdUnreachable) | 15461 | parent_result_loc->value.type->id == ZigTypeIdUnreachable) |
| 15446 | { | 15462 | { |
| ... | @@ -15469,8 +15485,15 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe | ... | @@ -15469,8 +15485,15 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15469 | 15485 | ||
| 15470 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, | 15486 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 15471 | ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime, | 15487 | ResultLoc *result_loc_pass1, ZigType *value_type, IrInstruction *value, bool force_runtime, |
| 15472 | bool non_null_comptime) | 15488 | bool non_null_comptime, bool allow_discard) |
| 15473 | { | 15489 | { |
| 15490 | if (!allow_discard && result_loc_pass1->id == ResultLocIdInstruction && | ||
| 15491 | instr_is_comptime(result_loc_pass1->source_instruction) && | ||
| 15492 | result_loc_pass1->source_instruction->value.type->id == ZigTypeIdPointer && | ||
| 15493 | result_loc_pass1->source_instruction->value.data.x_ptr.special == ConstPtrSpecialDiscard) | ||
| 15494 | { | ||
| 15495 | result_loc_pass1 = no_result_loc(); | ||
| 15496 | } | ||
| 15474 | IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, | 15497 | IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, |
| 15475 | value, force_runtime, non_null_comptime); | 15498 | value, force_runtime, non_null_comptime); |
| 15476 | if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type))) | 15499 | if (result_loc == nullptr || (instr_is_unreachable(result_loc) || type_is_invalid(result_loc->value.type))) |
| ... | @@ -15525,7 +15548,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn | ... | @@ -15525,7 +15548,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn |
| 15525 | if (type_is_invalid(implicit_elem_type)) | 15548 | if (type_is_invalid(implicit_elem_type)) |
| 15526 | return ira->codegen->invalid_instruction; | 15549 | return ira->codegen->invalid_instruction; |
| 15527 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 15550 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 15528 | implicit_elem_type, nullptr, false, true); | 15551 | implicit_elem_type, nullptr, false, true, true); |
| 15529 | if (result_loc != nullptr) | 15552 | if (result_loc != nullptr) |
| 15530 | return result_loc; | 15553 | return result_loc; |
| 15531 | 15554 | ||
| ... | @@ -15534,7 +15557,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn | ... | @@ -15534,7 +15557,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn |
| 15534 | instruction->result_loc->id == ResultLocIdReturn) | 15557 | instruction->result_loc->id == ResultLocIdReturn) |
| 15535 | { | 15558 | { |
| 15536 | result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(), | 15559 | result_loc = ir_resolve_result(ira, &instruction->base, no_result_loc(), |
| 15537 | implicit_elem_type, nullptr, false, true); | 15560 | implicit_elem_type, nullptr, false, true, true); |
| 15538 | if (result_loc != nullptr && | 15561 | if (result_loc != nullptr && |
| 15539 | (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) | 15562 | (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) |
| 15540 | { | 15563 | { |
| ... | @@ -15623,7 +15646,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc | ... | @@ -15623,7 +15646,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc |
| 15623 | ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type); | 15646 | ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type); |
| 15624 | 15647 | ||
| 15625 | IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, no_result_loc(), | 15648 | IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, no_result_loc(), |
| 15626 | async_return_type, nullptr, true, true); | 15649 | async_return_type, nullptr, true, true, false); |
| 15627 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { | 15650 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 15628 | return result_loc; | 15651 | return result_loc; |
| 15629 | } | 15652 | } |
| ... | @@ -15841,7 +15864,7 @@ no_mem_slot: | ... | @@ -15841,7 +15864,7 @@ no_mem_slot: |
| 15841 | } | 15864 | } |
| 15842 | 15865 | ||
| 15843 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, | 15866 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, |
| 15844 | IrInstruction *ptr, IrInstruction *uncasted_value) | 15867 | IrInstruction *ptr, IrInstruction *uncasted_value, bool allow_write_through_const) |
| 15845 | { | 15868 | { |
| 15846 | assert(ptr->value.type->id == ZigTypeIdPointer); | 15869 | assert(ptr->value.type->id == ZigTypeIdPointer); |
| 15847 | 15870 | ||
| ... | @@ -15857,7 +15880,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source | ... | @@ -15857,7 +15880,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15857 | 15880 | ||
| 15858 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | 15881 | ZigType *child_type = ptr->value.type->data.pointer.child_type; |
| 15859 | 15882 | ||
| 15860 | if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) { | 15883 | if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) { |
| 15861 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | 15884 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 15862 | return ira->codegen->invalid_instruction; | 15885 | return ira->codegen->invalid_instruction; |
| 15863 | } | 15886 | } |
| ... | @@ -15936,10 +15959,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source | ... | @@ -15936,10 +15959,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15936 | break; | 15959 | break; |
| 15937 | } | 15960 | } |
| 15938 | 15961 | ||
| 15939 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, | 15962 | IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope, |
| 15940 | ptr, value); | 15963 | source_instr->source_node, ptr, value); |
| 15941 | result->value.type = ira->codegen->builtin_types.entry_void; | 15964 | return &store_ptr->base; |
| 15942 | return result; | ||
| 15943 | } | 15965 | } |
| 15944 | 15966 | ||
| 15945 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, | 15967 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, |
| ... | @@ -16382,7 +16404,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c | ... | @@ -16382,7 +16404,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c |
| 16382 | IrInstruction *result_loc; | 16404 | IrInstruction *result_loc; |
| 16383 | if (handle_is_ptr(impl_fn_type_id->return_type)) { | 16405 | if (handle_is_ptr(impl_fn_type_id->return_type)) { |
| 16384 | result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, | 16406 | result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, |
| 16385 | impl_fn_type_id->return_type, nullptr, true, true); | 16407 | impl_fn_type_id->return_type, nullptr, true, true, false); |
| 16386 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || | 16408 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || |
| 16387 | instr_is_unreachable(result_loc))) | 16409 | instr_is_unreachable(result_loc))) |
| 16388 | { | 16410 | { |
| ... | @@ -16504,7 +16526,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c | ... | @@ -16504,7 +16526,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c |
| 16504 | IrInstruction *result_loc; | 16526 | IrInstruction *result_loc; |
| 16505 | if (handle_is_ptr(return_type)) { | 16527 | if (handle_is_ptr(return_type)) { |
| 16506 | result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, | 16528 | result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc, |
| 16507 | return_type, nullptr, true, true); | 16529 | return_type, nullptr, true, true, false); |
| 16508 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { | 16530 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 16509 | return result_loc; | 16531 | return result_loc; |
| 16510 | } | 16532 | } |
| ... | @@ -17020,7 +17042,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh | ... | @@ -17020,7 +17042,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 17020 | 17042 | ||
| 17021 | // In case resolving the parent activates a suspend, do it now | 17043 | // In case resolving the parent activates a suspend, do it now |
| 17022 | IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent, | 17044 | IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent, |
| 17023 | peer_parent->resolved_type, nullptr, false, false); | 17045 | peer_parent->resolved_type, nullptr, false, false, true); |
| 17024 | if (parent_result_loc != nullptr && | 17046 | if (parent_result_loc != nullptr && |
| 17025 | (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc))) | 17047 | (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc))) |
| 17026 | { | 17048 | { |
| ... | @@ -17477,6 +17499,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -17477,6 +17499,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 17477 | return result; | 17499 | return result; |
| 17478 | } else if (is_slice(array_type)) { | 17500 | } else if (is_slice(array_type)) { |
| 17479 | ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index]; | 17501 | ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index]; |
| 17502 | ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base); | ||
| 17480 | if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { | 17503 | if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 17481 | IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, | 17504 | IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, |
| 17482 | elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false, | 17505 | elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, false, |
| ... | @@ -17663,7 +17686,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction | ... | @@ -17663,7 +17686,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction |
| 17663 | return ira->codegen->invalid_instruction; | 17686 | return ira->codegen->invalid_instruction; |
| 17664 | if (type_is_invalid(struct_val->type)) | 17687 | if (type_is_invalid(struct_val->type)) |
| 17665 | return ira->codegen->invalid_instruction; | 17688 | return ira->codegen->invalid_instruction; |
| 17666 | if (struct_val->special == ConstValSpecialUndef && initializing) { | 17689 | if (initializing && struct_val->special == ConstValSpecialUndef) { |
| 17667 | struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); | 17690 | struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); |
| 17668 | struct_val->special = ConstValSpecialStatic; | 17691 | struct_val->special = ConstValSpecialStatic; |
| 17669 | for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { | 17692 | for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { |
| ... | @@ -17847,6 +17870,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ | ... | @@ -17847,6 +17870,7 @@ static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_ |
| 17847 | switch (tld->id) { | 17870 | switch (tld->id) { |
| 17848 | case TldIdContainer: | 17871 | case TldIdContainer: |
| 17849 | case TldIdCompTime: | 17872 | case TldIdCompTime: |
| 17873 | case TldIdUsingNamespace: | ||
| 17850 | zig_unreachable(); | 17874 | zig_unreachable(); |
| 17851 | case TldIdVar: | 17875 | case TldIdVar: |
| 17852 | { | 17876 | { |
| ... | @@ -18260,7 +18284,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -18260,7 +18284,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc |
| 18260 | if (type_is_invalid(value->value.type)) | 18284 | if (type_is_invalid(value->value.type)) |
| 18261 | return ira->codegen->invalid_instruction; | 18285 | return ira->codegen->invalid_instruction; |
| 18262 | 18286 | ||
| 18263 | return ir_analyze_store_ptr(ira, &instruction->base, ptr, value); | 18287 | return ir_analyze_store_ptr(ira, &instruction->base, ptr, value, instruction->allow_write_through_const); |
| 18264 | } | 18288 | } |
| 18265 | 18289 | ||
| 18266 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { | 18290 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { |
| ... | @@ -18763,7 +18787,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr | ... | @@ -18763,7 +18787,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr |
| 18763 | if (optional_val == nullptr) | 18787 | if (optional_val == nullptr) |
| 18764 | return ira->codegen->invalid_instruction; | 18788 | return ira->codegen->invalid_instruction; |
| 18765 | 18789 | ||
| 18766 | if (initializing && optional_val->special == ConstValSpecialUndef) { | 18790 | if (initializing) { |
| 18767 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | 18791 | switch (type_has_one_possible_value(ira->codegen, child_type)) { |
| 18768 | case OnePossibleValueInvalid: | 18792 | case OnePossibleValueInvalid: |
| 18769 | return ira->codegen->invalid_instruction; | 18793 | return ira->codegen->invalid_instruction; |
| ... | @@ -19668,7 +19692,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -19668,7 +19692,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19668 | 19692 | ||
| 19669 | IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, | 19693 | IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, |
| 19670 | container_type, true); | 19694 | container_type, true); |
| 19671 | ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst); | 19695 | ir_analyze_store_ptr(ira, instruction, field_ptr, runtime_inst, false); |
| 19672 | if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { | 19696 | if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 19673 | const_ptrs.append(field_ptr); | 19697 | const_ptrs.append(field_ptr); |
| 19674 | } else { | 19698 | } else { |
| ... | @@ -19685,7 +19709,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc | ... | @@ -19685,7 +19709,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19685 | IrInstruction *field_result_loc = const_ptrs.at(i); | 19709 | IrInstruction *field_result_loc = const_ptrs.at(i); |
| 19686 | IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); | 19710 | IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); |
| 19687 | field_result_loc->value.special = ConstValSpecialRuntime; | 19711 | field_result_loc->value.special = ConstValSpecialRuntime; |
| 19688 | ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref); | 19712 | ir_analyze_store_ptr(ira, field_result_loc, field_result_loc, deref, false); |
| 19689 | } | 19713 | } |
| 19690 | } | 19714 | } |
| 19691 | } | 19715 | } |
| ... | @@ -19812,7 +19836,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, | ... | @@ -19812,7 +19836,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 19812 | assert(elem_result_loc->value.special == ConstValSpecialStatic); | 19836 | assert(elem_result_loc->value.special == ConstValSpecialStatic); |
| 19813 | IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); | 19837 | IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); |
| 19814 | elem_result_loc->value.special = ConstValSpecialRuntime; | 19838 | elem_result_loc->value.special = ConstValSpecialRuntime; |
| 19815 | ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref); | 19839 | ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false); |
| 19816 | } | 19840 | } |
| 19817 | } | 19841 | } |
| 19818 | } | 19842 | } |
| ... | @@ -21531,7 +21555,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi | ... | @@ -21531,7 +21555,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi |
| 21531 | IrInstruction *result_loc; | 21555 | IrInstruction *result_loc; |
| 21532 | if (handle_is_ptr(result_type)) { | 21556 | if (handle_is_ptr(result_type)) { |
| 21533 | result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 21557 | result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 21534 | result_type, nullptr, true, false); | 21558 | result_type, nullptr, true, false, true); |
| 21535 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { | 21559 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 21536 | return result_loc; | 21560 | return result_loc; |
| 21537 | } | 21561 | } |
| ... | @@ -21788,7 +21812,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru | ... | @@ -21788,7 +21812,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 21788 | } | 21812 | } |
| 21789 | 21813 | ||
| 21790 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 21814 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 21791 | dest_slice_type, nullptr, true, false); | 21815 | dest_slice_type, nullptr, true, false, true); |
| 21792 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { | 21816 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 21793 | return result_loc; | 21817 | return result_loc; |
| 21794 | } | 21818 | } |
| ... | @@ -21865,7 +21889,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct | ... | @@ -21865,7 +21889,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 21865 | } | 21889 | } |
| 21866 | 21890 | ||
| 21867 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 21891 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 21868 | dest_slice_type, nullptr, true, false); | 21892 | dest_slice_type, nullptr, true, false, true); |
| 21869 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { | 21893 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 21870 | return result_loc; | 21894 | return result_loc; |
| 21871 | } | 21895 | } |
| ... | @@ -22607,7 +22631,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction | ... | @@ -22607,7 +22631,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22607 | } | 22631 | } |
| 22608 | 22632 | ||
| 22609 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 22633 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 22610 | return_type, nullptr, true, false); | 22634 | return_type, nullptr, true, false, true); |
| 22611 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { | 22635 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 22612 | return result_loc; | 22636 | return result_loc; |
| 22613 | } | 22637 | } |
| ... | @@ -23259,7 +23283,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct | ... | @@ -23259,7 +23283,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct |
| 23259 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); | 23283 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 23260 | if (err_union_val == nullptr) | 23284 | if (err_union_val == nullptr) |
| 23261 | return ira->codegen->invalid_instruction; | 23285 | return ira->codegen->invalid_instruction; |
| 23262 | if (err_union_val->special == ConstValSpecialUndef && initializing) { | 23286 | if (initializing && err_union_val->special == ConstValSpecialUndef) { |
| 23263 | ConstExprValue *vals = create_const_vals(2); | 23287 | ConstExprValue *vals = create_const_vals(2); |
| 23264 | ConstExprValue *err_set_val = &vals[0]; | 23288 | ConstExprValue *err_set_val = &vals[0]; |
| 23265 | ConstExprValue *payload_val = &vals[1]; | 23289 | ConstExprValue *payload_val = &vals[1]; |
| ... | @@ -24734,10 +24758,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op | ... | @@ -24734,10 +24758,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 24734 | operand_type->data.integral.bit_count)); | 24758 | operand_type->data.integral.bit_count)); |
| 24735 | return ira->codegen->builtin_types.entry_invalid; | 24759 | return ira->codegen->builtin_types.entry_invalid; |
| 24736 | } | 24760 | } |
| 24737 | if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) { | 24761 | uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); |
| 24762 | if (operand_type->data.integral.bit_count > max_atomic_bits) { | ||
| 24738 | ir_add_error(ira, op, | 24763 | ir_add_error(ira, op, |
| 24739 | buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type", | 24764 | buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type", |
| 24740 | operand_type->data.integral.bit_count)); | 24765 | max_atomic_bits, operand_type->data.integral.bit_count)); |
| 24741 | return ira->codegen->builtin_types.entry_invalid; | 24766 | return ira->codegen->builtin_types.entry_invalid; |
| 24742 | } | 24767 | } |
| 24743 | if (!is_power_of_2(operand_type->data.integral.bit_count)) { | 24768 | if (!is_power_of_2(operand_type->data.integral.bit_count)) { |
| ... | @@ -25386,7 +25411,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct | ... | @@ -25386,7 +25411,7 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct |
| 25386 | 25411 | ||
| 25387 | bool was_written = instruction->result_loc->written; | 25412 | bool was_written = instruction->result_loc->written; |
| 25388 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, | 25413 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, |
| 25389 | value->value.type, value, false, false); | 25414 | value->value.type, value, false, false, true); |
| 25390 | if (result_loc != nullptr) { | 25415 | if (result_loc != nullptr) { |
| 25391 | if (type_is_invalid(result_loc->value.type)) | 25416 | if (type_is_invalid(result_loc->value.type)) |
| 25392 | return ira->codegen->invalid_instruction; | 25417 | return ira->codegen->invalid_instruction; |
| ... | @@ -25394,7 +25419,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct | ... | @@ -25394,7 +25419,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct |
| 25394 | return result_loc; | 25419 | return result_loc; |
| 25395 | 25420 | ||
| 25396 | if (!was_written) { | 25421 | if (!was_written) { |
| 25397 | IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value); | 25422 | IrInstruction *store_ptr = ir_analyze_store_ptr(ira, &instruction->base, result_loc, value, |
| 25423 | instruction->result_loc->allow_write_through_const); | ||
| 25398 | if (type_is_invalid(store_ptr->value.type)) { | 25424 | if (type_is_invalid(store_ptr->value.type)) { |
| 25399 | return ira->codegen->invalid_instruction; | 25425 | return ira->codegen->invalid_instruction; |
| 25400 | } | 25426 | } |
| ... | @@ -25418,7 +25444,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst | ... | @@ -25418,7 +25444,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst |
| 25418 | return operand; | 25444 | return operand; |
| 25419 | 25445 | ||
| 25420 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, | 25446 | IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, |
| 25421 | &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false); | 25447 | &instruction->result_loc_bit_cast->base, operand->value.type, operand, false, false, true); |
| 25422 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) | 25448 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) |
| 25423 | return result_loc; | 25449 | return result_loc; |
| 25424 | 25450 |
src/main.cpp+3-4| ... | @@ -583,7 +583,7 @@ int main(int argc, char **argv) { | ... | @@ -583,7 +583,7 @@ int main(int argc, char **argv) { |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 585 | CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe, | 585 | CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe, |
| 586 | BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir); | 586 | BuildModeDebug, override_lib_dir, override_std_dir, nullptr, &full_cache_dir, false); |
| 587 | g->valgrind_support = valgrind_support; | 587 | g->valgrind_support = valgrind_support; |
| 588 | g->enable_time_report = timing_info; | 588 | g->enable_time_report = timing_info; |
| 589 | codegen_set_out_name(g, buf_create_from_str("build")); | 589 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | @@ -1011,7 +1011,7 @@ int main(int argc, char **argv) { | ... | @@ -1011,7 +1011,7 @@ int main(int argc, char **argv) { |
| 1011 | } | 1011 | } |
| 1012 | case CmdBuiltin: { | 1012 | case CmdBuiltin: { |
| 1013 | CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, | 1013 | CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, |
| 1014 | out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr); | 1014 | out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr, false); |
| 1015 | codegen_set_strip(g, strip); | 1015 | codegen_set_strip(g, strip); |
| 1016 | for (size_t i = 0; i < link_libs.length; i += 1) { | 1016 | for (size_t i = 0; i < link_libs.length; i += 1) { |
| 1017 | LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i))); | 1017 | LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i))); |
| ... | @@ -1115,7 +1115,7 @@ int main(int argc, char **argv) { | ... | @@ -1115,7 +1115,7 @@ int main(int argc, char **argv) { |
| 1115 | cache_dir_buf = buf_create_from_str(cache_dir); | 1115 | cache_dir_buf = buf_create_from_str(cache_dir); |
| 1116 | } | 1116 | } |
| 1117 | CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode, | 1117 | CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode, |
| 1118 | override_lib_dir, override_std_dir, libc, cache_dir_buf); | 1118 | override_lib_dir, override_std_dir, libc, cache_dir_buf, cmd == CmdTest); |
| 1119 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); | 1119 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); |
| 1120 | g->valgrind_support = valgrind_support; | 1120 | g->valgrind_support = valgrind_support; |
| 1121 | g->want_pic = want_pic; | 1121 | g->want_pic = want_pic; |
| ... | @@ -1125,7 +1125,6 @@ int main(int argc, char **argv) { | ... | @@ -1125,7 +1125,6 @@ int main(int argc, char **argv) { |
| 1125 | g->enable_time_report = timing_info; | 1125 | g->enable_time_report = timing_info; |
| 1126 | codegen_set_out_name(g, buf_out_name); | 1126 | codegen_set_out_name(g, buf_out_name); |
| 1127 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); | 1127 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 1128 | codegen_set_is_test(g, cmd == CmdTest); | ||
| 1129 | g->want_single_threaded = want_single_threaded; | 1128 | g->want_single_threaded = want_single_threaded; |
| 1130 | codegen_set_linker_script(g, linker_script); | 1129 | codegen_set_linker_script(g, linker_script); |
| 1131 | g->version_script_path = version_script; | 1130 | g->version_script_path = version_script; |
src/parser.cpp+2-2| ... | @@ -676,7 +676,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { | ... | @@ -676,7 +676,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { |
| 676 | AstNode *expr = ast_expect(pc, ast_parse_expr); | 676 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 677 | expect_token(pc, TokenIdSemicolon); | 677 | expect_token(pc, TokenIdSemicolon); |
| 678 | 678 | ||
| 679 | AstNode *res = ast_create_node(pc, NodeTypeUse, usingnamespace); | 679 | AstNode *res = ast_create_node(pc, NodeTypeUsingNamespace, usingnamespace); |
| 680 | res->data.using_namespace.visib_mod = visib_mod; | 680 | res->data.using_namespace.visib_mod = visib_mod; |
| 681 | res->data.using_namespace.expr = expr; | 681 | res->data.using_namespace.expr = expr; |
| 682 | return res; | 682 | return res; |
| ... | @@ -2938,7 +2938,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2938,7 +2938,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2938 | case NodeTypeUnwrapOptional: | 2938 | case NodeTypeUnwrapOptional: |
| 2939 | visit_field(&node->data.unwrap_optional.expr, visit, context); | 2939 | visit_field(&node->data.unwrap_optional.expr, visit, context); |
| 2940 | break; | 2940 | break; |
| 2941 | case NodeTypeUse: | 2941 | case NodeTypeUsingNamespace: |
| 2942 | visit_field(&node->data.using_namespace.expr, visit, context); | 2942 | visit_field(&node->data.using_namespace.expr, visit, context); |
| 2943 | break; | 2943 | break; |
| 2944 | case NodeTypeBoolLiteral: | 2944 | case NodeTypeBoolLiteral: |
src/target.cpp+67-1| ... | @@ -878,6 +878,72 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { | ... | @@ -878,6 +878,72 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { |
| 878 | zig_unreachable(); | 878 | zig_unreachable(); |
| 879 | } | 879 | } |
| 880 | 880 | ||
| 881 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { | ||
| 882 | switch (arch) { | ||
| 883 | case ZigLLVM_UnknownArch: | ||
| 884 | zig_unreachable(); | ||
| 885 | |||
| 886 | case ZigLLVM_avr: | ||
| 887 | case ZigLLVM_msp430: | ||
| 888 | return 16; | ||
| 889 | |||
| 890 | case ZigLLVM_arc: | ||
| 891 | case ZigLLVM_arm: | ||
| 892 | case ZigLLVM_armeb: | ||
| 893 | case ZigLLVM_hexagon: | ||
| 894 | case ZigLLVM_le32: | ||
| 895 | case ZigLLVM_mips: | ||
| 896 | case ZigLLVM_mipsel: | ||
| 897 | case ZigLLVM_nvptx: | ||
| 898 | case ZigLLVM_ppc: | ||
| 899 | case ZigLLVM_r600: | ||
| 900 | case ZigLLVM_riscv32: | ||
| 901 | case ZigLLVM_sparc: | ||
| 902 | case ZigLLVM_sparcel: | ||
| 903 | case ZigLLVM_tce: | ||
| 904 | case ZigLLVM_tcele: | ||
| 905 | case ZigLLVM_thumb: | ||
| 906 | case ZigLLVM_thumbeb: | ||
| 907 | case ZigLLVM_x86: | ||
| 908 | case ZigLLVM_xcore: | ||
| 909 | case ZigLLVM_amdil: | ||
| 910 | case ZigLLVM_hsail: | ||
| 911 | case ZigLLVM_spir: | ||
| 912 | case ZigLLVM_kalimba: | ||
| 913 | case ZigLLVM_lanai: | ||
| 914 | case ZigLLVM_shave: | ||
| 915 | case ZigLLVM_wasm32: | ||
| 916 | case ZigLLVM_renderscript32: | ||
| 917 | return 32; | ||
| 918 | |||
| 919 | case ZigLLVM_aarch64: | ||
| 920 | case ZigLLVM_aarch64_be: | ||
| 921 | case ZigLLVM_aarch64_32: | ||
| 922 | case ZigLLVM_amdgcn: | ||
| 923 | case ZigLLVM_bpfel: | ||
| 924 | case ZigLLVM_bpfeb: | ||
| 925 | case ZigLLVM_le64: | ||
| 926 | case ZigLLVM_mips64: | ||
| 927 | case ZigLLVM_mips64el: | ||
| 928 | case ZigLLVM_nvptx64: | ||
| 929 | case ZigLLVM_ppc64: | ||
| 930 | case ZigLLVM_ppc64le: | ||
| 931 | case ZigLLVM_riscv64: | ||
| 932 | case ZigLLVM_sparcv9: | ||
| 933 | case ZigLLVM_systemz: | ||
| 934 | case ZigLLVM_amdil64: | ||
| 935 | case ZigLLVM_hsail64: | ||
| 936 | case ZigLLVM_spir64: | ||
| 937 | case ZigLLVM_wasm64: | ||
| 938 | case ZigLLVM_renderscript64: | ||
| 939 | return 64; | ||
| 940 | |||
| 941 | case ZigLLVM_x86_64: | ||
| 942 | return 128; | ||
| 943 | } | ||
| 944 | zig_unreachable(); | ||
| 945 | } | ||
| 946 | |||
| 881 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | 947 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 882 | switch (target->os) { | 948 | switch (target->os) { |
| 883 | case OsFreestanding: | 949 | case OsFreestanding: |
| ... | @@ -1524,9 +1590,9 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { | ... | @@ -1524,9 +1590,9 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { |
| 1524 | case OsKFreeBSD: | 1590 | case OsKFreeBSD: |
| 1525 | case OsNetBSD: | 1591 | case OsNetBSD: |
| 1526 | case OsHurd: | 1592 | case OsHurd: |
| 1527 | case OsWindows: | ||
| 1528 | return ZigLLVM_GNU; | 1593 | return ZigLLVM_GNU; |
| 1529 | case OsUefi: | 1594 | case OsUefi: |
| 1595 | case OsWindows: | ||
| 1530 | return ZigLLVM_MSVC; | 1596 | return ZigLLVM_MSVC; |
| 1531 | case OsLinux: | 1597 | case OsLinux: |
| 1532 | case OsWASI: | 1598 | case OsWASI: |
src/target.hpp+1| ... | @@ -195,6 +195,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch); | ... | @@ -195,6 +195,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch); |
| 195 | bool target_supports_libunwind(const ZigTarget *target); | 195 | bool target_supports_libunwind(const ZigTarget *target); |
| 196 | 196 | ||
| 197 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); | 197 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); |
| 198 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch); | ||
| 198 | 199 | ||
| 199 | size_t target_libc_count(void); | 200 | size_t target_libc_count(void); |
| 200 | void target_libc_enum(size_t index, ZigTarget *out_target); | 201 | void target_libc_enum(size_t index, ZigTarget *out_target); |
src/util.hpp+1-1| ... | @@ -43,7 +43,7 @@ ATTRIBUTE_NORETURN | ... | @@ -43,7 +43,7 @@ ATTRIBUTE_NORETURN |
| 43 | ATTRIBUTE_PRINTF(1, 2) | 43 | ATTRIBUTE_PRINTF(1, 2) |
| 44 | void zig_panic(const char *format, ...); | 44 | void zig_panic(const char *format, ...); |
| 45 | 45 | ||
| 46 | #ifdef WIN32 | 46 | #ifdef _WIN32 |
| 47 | #define __func__ __FUNCTION__ | 47 | #define __func__ __FUNCTION__ |
| 48 | #endif | 48 | #endif |
| 49 | 49 |
src/zig_clang.h+1-1| ... | @@ -50,7 +50,7 @@ enum ZigClangAPValueKind { | ... | @@ -50,7 +50,7 @@ enum ZigClangAPValueKind { |
| 50 | struct ZigClangAPValue { | 50 | struct ZigClangAPValue { |
| 51 | enum ZigClangAPValueKind Kind; | 51 | enum ZigClangAPValueKind Kind; |
| 52 | // experimentally-derived size of clang::APValue::DataType | 52 | // experimentally-derived size of clang::APValue::DataType |
| 53 | #if defined(WIN32) && defined(_MSC_VER) | 53 | #if defined(_WIN32) && defined(_MSC_VER) |
| 54 | char Data[52]; | 54 | char Data[52]; |
| 55 | #else | 55 | #else |
| 56 | char Data[68]; | 56 | char Data[68]; |
std/build.zig+47-28| ... | @@ -41,9 +41,11 @@ pub const Builder = struct { | ... | @@ -41,9 +41,11 @@ pub const Builder = struct { |
| 41 | env_map: *BufMap, | 41 | env_map: *BufMap, |
| 42 | top_level_steps: ArrayList(*TopLevelStep), | 42 | top_level_steps: ArrayList(*TopLevelStep), |
| 43 | install_prefix: ?[]const u8, | 43 | install_prefix: ?[]const u8, |
| 44 | search_prefixes: ArrayList([]const u8), | 44 | dest_dir: ?[]const u8, |
| 45 | lib_dir: ?[]const u8, | 45 | lib_dir: ?[]const u8, |
| 46 | exe_dir: ?[]const u8, | 46 | exe_dir: ?[]const u8, |
| 47 | install_path: []const u8, | ||
| 48 | search_prefixes: ArrayList([]const u8), | ||
| 47 | installed_files: ArrayList(InstalledFile), | 49 | installed_files: ArrayList(InstalledFile), |
| 48 | build_root: []const u8, | 50 | build_root: []const u8, |
| 49 | cache_root: []const u8, | 51 | cache_root: []const u8, |
| ... | @@ -125,10 +127,11 @@ pub const Builder = struct { | ... | @@ -125,10 +127,11 @@ pub const Builder = struct { |
| 125 | .top_level_steps = ArrayList(*TopLevelStep).init(allocator), | 127 | .top_level_steps = ArrayList(*TopLevelStep).init(allocator), |
| 126 | .default_step = undefined, | 128 | .default_step = undefined, |
| 127 | .env_map = env_map, | 129 | .env_map = env_map, |
| 128 | .install_prefix = null, | ||
| 129 | .search_prefixes = ArrayList([]const u8).init(allocator), | 130 | .search_prefixes = ArrayList([]const u8).init(allocator), |
| 131 | .install_prefix = null, | ||
| 130 | .lib_dir = null, | 132 | .lib_dir = null, |
| 131 | .exe_dir = null, | 133 | .exe_dir = null, |
| 134 | .dest_dir = env_map.get("DESTDIR"), | ||
| 132 | .installed_files = ArrayList(InstalledFile).init(allocator), | 135 | .installed_files = ArrayList(InstalledFile).init(allocator), |
| 133 | .install_tls = TopLevelStep{ | 136 | .install_tls = TopLevelStep{ |
| 134 | .step = Step.initNoOp("install", allocator), | 137 | .step = Step.initNoOp("install", allocator), |
| ... | @@ -142,6 +145,7 @@ pub const Builder = struct { | ... | @@ -142,6 +145,7 @@ pub const Builder = struct { |
| 142 | .is_release = false, | 145 | .is_release = false, |
| 143 | .override_std_dir = null, | 146 | .override_std_dir = null, |
| 144 | .override_lib_dir = null, | 147 | .override_lib_dir = null, |
| 148 | .install_path = undefined, | ||
| 145 | }; | 149 | }; |
| 146 | try self.top_level_steps.append(&self.install_tls); | 150 | try self.top_level_steps.append(&self.install_tls); |
| 147 | try self.top_level_steps.append(&self.uninstall_tls); | 151 | try self.top_level_steps.append(&self.uninstall_tls); |
| ... | @@ -164,14 +168,19 @@ pub const Builder = struct { | ... | @@ -164,14 +168,19 @@ pub const Builder = struct { |
| 164 | } | 168 | } |
| 165 | 169 | ||
| 166 | fn resolveInstallPrefix(self: *Builder) void { | 170 | fn resolveInstallPrefix(self: *Builder) void { |
| 167 | const prefix = if (self.install_prefix) |prefix| prefix else blk: { | 171 | if (self.dest_dir) |dest_dir| { |
| 168 | const prefix = self.cache_root; | 172 | const install_prefix = self.install_prefix orelse "/usr"; |
| 169 | self.install_prefix = prefix; | 173 | self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable; |
| 170 | break :blk prefix; | 174 | } else { |
| 171 | }; | 175 | const install_prefix = self.install_prefix orelse blk: { |
| 172 | 176 | const p = self.cache_root; | |
| 173 | self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "lib" }) catch unreachable; | 177 | self.install_prefix = p; |
| 174 | self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "bin" }) catch unreachable; | 178 | break :blk p; |
| 179 | }; | ||
| 180 | self.install_path = install_prefix; | ||
| 181 | } | ||
| 182 | self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "lib" }) catch unreachable; | ||
| 183 | self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "bin" }) catch unreachable; | ||
| 175 | } | 184 | } |
| 176 | 185 | ||
| 177 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { | 186 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| ... | @@ -796,11 +805,7 @@ pub const Builder = struct { | ... | @@ -796,11 +805,7 @@ pub const Builder = struct { |
| 796 | return name; | 805 | return name; |
| 797 | } | 806 | } |
| 798 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) }); | 807 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) }); |
| 799 | if (fs.path.real(self.allocator, full_path)) |real_path| { | 808 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 800 | return real_path; | ||
| 801 | } else |_| { | ||
| 802 | continue; | ||
| 803 | } | ||
| 804 | } | 809 | } |
| 805 | } | 810 | } |
| 806 | if (self.env_map.get("PATH")) |PATH| { | 811 | if (self.env_map.get("PATH")) |PATH| { |
| ... | @@ -808,14 +813,10 @@ pub const Builder = struct { | ... | @@ -808,14 +813,10 @@ pub const Builder = struct { |
| 808 | if (fs.path.isAbsolute(name)) { | 813 | if (fs.path.isAbsolute(name)) { |
| 809 | return name; | 814 | return name; |
| 810 | } | 815 | } |
| 811 | var it = mem.tokenize(PATH, []u8{fs.path.delimiter}); | 816 | var it = mem.tokenize(PATH, [_]u8{fs.path.delimiter}); |
| 812 | while (it.next()) |path| { | 817 | while (it.next()) |path| { |
| 813 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); | 818 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); |
| 814 | if (fs.path.real(self.allocator, full_path)) |real_path| { | 819 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 815 | return real_path; | ||
| 816 | } else |_| { | ||
| 817 | continue; | ||
| 818 | } | ||
| 819 | } | 820 | } |
| 820 | } | 821 | } |
| 821 | } | 822 | } |
| ... | @@ -825,11 +826,7 @@ pub const Builder = struct { | ... | @@ -825,11 +826,7 @@ pub const Builder = struct { |
| 825 | } | 826 | } |
| 826 | for (paths) |path| { | 827 | for (paths) |path| { |
| 827 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); | 828 | const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) }); |
| 828 | if (fs.path.real(self.allocator, full_path)) |real_path| { | 829 | return fs.realpathAlloc(self.allocator, full_path) catch continue; |
| 829 | return real_path; | ||
| 830 | } else |_| { | ||
| 831 | continue; | ||
| 832 | } | ||
| 833 | } | 830 | } |
| 834 | } | 831 | } |
| 835 | return error.FileNotFound; | 832 | return error.FileNotFound; |
| ... | @@ -884,7 +881,7 @@ pub const Builder = struct { | ... | @@ -884,7 +881,7 @@ pub const Builder = struct { |
| 884 | 881 | ||
| 885 | fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { | 882 | fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| 886 | const base_dir = switch (dir) { | 883 | const base_dir = switch (dir) { |
| 887 | .Prefix => self.install_prefix.?, | 884 | .Prefix => self.install_path, |
| 888 | .Bin => self.exe_dir.?, | 885 | .Bin => self.exe_dir.?, |
| 889 | .Lib => self.lib_dir.?, | 886 | .Lib => self.lib_dir.?, |
| 890 | }; | 887 | }; |
| ... | @@ -895,6 +892,15 @@ pub const Builder = struct { | ... | @@ -895,6 +892,15 @@ pub const Builder = struct { |
| 895 | } | 892 | } |
| 896 | }; | 893 | }; |
| 897 | 894 | ||
| 895 | test "builder.findProgram compiles" { | ||
| 896 | //allocator: *Allocator, | ||
| 897 | //zig_exe: []const u8, | ||
| 898 | //build_root: []const u8, | ||
| 899 | //cache_root: []const u8, | ||
| 900 | const builder = try Builder.create(std.heap.direct_allocator, "zig", "zig-cache", "zig-cache"); | ||
| 901 | _ = builder.findProgram([_][]const u8{}, [_][]const u8{}) catch null; | ||
| 902 | } | ||
| 903 | |||
| 898 | pub const Version = struct { | 904 | pub const Version = struct { |
| 899 | major: u32, | 905 | major: u32, |
| 900 | minor: u32, | 906 | minor: u32, |
| ... | @@ -1113,6 +1119,9 @@ pub const Target = union(enum) { | ... | @@ -1113,6 +1119,9 @@ pub const Target = union(enum) { |
| 1113 | } | 1119 | } |
| 1114 | 1120 | ||
| 1115 | pub fn libPrefix(self: Target) []const u8 { | 1121 | pub fn libPrefix(self: Target) []const u8 { |
| 1122 | if (self.isWasm()) { | ||
| 1123 | return ""; | ||
| 1124 | } | ||
| 1116 | switch (self.getAbi()) { | 1125 | switch (self.getAbi()) { |
| 1117 | .msvc => return "", | 1126 | .msvc => return "", |
| 1118 | else => return "lib", | 1127 | else => return "lib", |
| ... | @@ -1255,6 +1264,8 @@ pub const LibExeObjStep = struct { | ... | @@ -1255,6 +1264,8 @@ pub const LibExeObjStep = struct { |
| 1255 | libc_file: ?[]const u8 = null, | 1264 | libc_file: ?[]const u8 = null, |
| 1256 | target_glibc: ?Version = null, | 1265 | target_glibc: ?Version = null, |
| 1257 | 1266 | ||
| 1267 | valgrind_support: ?bool = null, | ||
| 1268 | |||
| 1258 | const LinkObject = union(enum) { | 1269 | const LinkObject = union(enum) { |
| 1259 | StaticPath: []const u8, | 1270 | StaticPath: []const u8, |
| 1260 | OtherStep: *LibExeObjStep, | 1271 | OtherStep: *LibExeObjStep, |
| ... | @@ -1791,7 +1802,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1791,7 +1802,7 @@ pub const LibExeObjStep = struct { |
| 1791 | try zig_args.append("--bundle-compiler-rt"); | 1802 | try zig_args.append("--bundle-compiler-rt"); |
| 1792 | } | 1803 | } |
| 1793 | if (self.disable_stack_probing) { | 1804 | if (self.disable_stack_probing) { |
| 1794 | try zig_args.append("--disable-stack-probing"); | 1805 | try zig_args.append("-fno-stack-check"); |
| 1795 | } | 1806 | } |
| 1796 | 1807 | ||
| 1797 | switch (self.target) { | 1808 | switch (self.target) { |
| ... | @@ -1882,6 +1893,14 @@ pub const LibExeObjStep = struct { | ... | @@ -1882,6 +1893,14 @@ pub const LibExeObjStep = struct { |
| 1882 | try zig_args.append("--system-linker-hack"); | 1893 | try zig_args.append("--system-linker-hack"); |
| 1883 | } | 1894 | } |
| 1884 | 1895 | ||
| 1896 | if (self.valgrind_support) |valgrind_support| { | ||
| 1897 | if (valgrind_support) { | ||
| 1898 | try zig_args.append("--enable-valgrind"); | ||
| 1899 | } else { | ||
| 1900 | try zig_args.append("--disable-valgrind"); | ||
| 1901 | } | ||
| 1902 | } | ||
| 1903 | |||
| 1885 | if (self.override_std_dir) |dir| { | 1904 | if (self.override_std_dir) |dir| { |
| 1886 | try zig_args.append("--override-std-dir"); | 1905 | try zig_args.append("--override-std-dir"); |
| 1887 | try zig_args.append(builder.pathFromRoot(dir)); | 1906 | try zig_args.append(builder.pathFromRoot(dir)); |
std/coff.zig+46-6| ... | @@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; | ... | @@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; |
| 19 | const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; | 19 | const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; |
| 20 | 20 | ||
| 21 | const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; | 21 | const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; |
| 22 | const IMAGE_DEBUG_TYPE_CODEVIEW = 2; | ||
| 22 | const DEBUG_DIRECTORY = 6; | 23 | const DEBUG_DIRECTORY = 6; |
| 23 | 24 | ||
| 24 | pub const CoffError = error{ | 25 | pub const CoffError = error{ |
| ... | @@ -28,6 +29,7 @@ pub const CoffError = error{ | ... | @@ -28,6 +29,7 @@ pub const CoffError = error{ |
| 28 | MissingCoffSection, | 29 | MissingCoffSection, |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 32 | // Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format | ||
| 31 | pub const Coff = struct { | 33 | pub const Coff = struct { |
| 32 | in_file: File, | 34 | in_file: File, |
| 33 | allocator: *mem.Allocator, | 35 | allocator: *mem.Allocator, |
| ... | @@ -120,16 +122,43 @@ pub const Coff = struct { | ... | @@ -120,16 +122,43 @@ pub const Coff = struct { |
| 120 | 122 | ||
| 121 | pub fn getPdbPath(self: *Coff, buffer: []u8) !usize { | 123 | pub fn getPdbPath(self: *Coff, buffer: []u8) !usize { |
| 122 | try self.loadSections(); | 124 | try self.loadSections(); |
| 123 | const header = (self.getSection(".rdata") orelse return error.MissingCoffSection).header; | ||
| 124 | 125 | ||
| 125 | // The linker puts a chunk that contains the .pdb path right after the | 126 | const header = blk: { |
| 126 | // debug_directory. | 127 | if (self.getSection(".buildid")) |section| { |
| 128 | break :blk section.header; | ||
| 129 | } else if (self.getSection(".rdata")) |section| { | ||
| 130 | break :blk section.header; | ||
| 131 | } else { | ||
| 132 | return error.MissingCoffSection; | ||
| 133 | } | ||
| 134 | }; | ||
| 135 | |||
| 127 | const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY]; | 136 | const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY]; |
| 128 | const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data; | 137 | const file_offset = debug_dir.virtual_address - header.virtual_address + header.pointer_to_raw_data; |
| 129 | try self.in_file.seekTo(file_offset + debug_dir.size); | ||
| 130 | 138 | ||
| 131 | var file_stream = self.in_file.inStream(); | 139 | var file_stream = self.in_file.inStream(); |
| 132 | const in = &file_stream.stream; | 140 | const in = &file_stream.stream; |
| 141 | try self.in_file.seekTo(file_offset); | ||
| 142 | |||
| 143 | // Find the correct DebugDirectoryEntry, and where its data is stored. | ||
| 144 | // It can be in any section. | ||
| 145 | const debug_dir_entry_count = debug_dir.size / @sizeOf(DebugDirectoryEntry); | ||
| 146 | var i: u32 = 0; | ||
| 147 | blk: while (i < debug_dir_entry_count) : (i += 1) { | ||
| 148 | const debug_dir_entry = try in.readStruct(DebugDirectoryEntry); | ||
| 149 | if (debug_dir_entry.type == IMAGE_DEBUG_TYPE_CODEVIEW) { | ||
| 150 | for (self.sections.toSlice()) |*section| { | ||
| 151 | const section_start = section.header.virtual_address; | ||
| 152 | const section_size = section.header.misc.virtual_size; | ||
| 153 | const rva = debug_dir_entry.address_of_raw_data; | ||
| 154 | const offset = rva - section_start; | ||
| 155 | if (section_start <= rva and offset < section_size and debug_dir_entry.size_of_data <= section_size - offset) { | ||
| 156 | try self.in_file.seekTo(section.header.pointer_to_raw_data + offset); | ||
| 157 | break :blk; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 133 | 162 | ||
| 134 | var cv_signature: [4]u8 = undefined; // CodeView signature | 163 | var cv_signature: [4]u8 = undefined; // CodeView signature |
| 135 | try in.readNoEof(cv_signature[0..]); | 164 | try in.readNoEof(cv_signature[0..]); |
| ... | @@ -141,7 +170,7 @@ pub const Coff = struct { | ... | @@ -141,7 +170,7 @@ pub const Coff = struct { |
| 141 | 170 | ||
| 142 | // Finally read the null-terminated string. | 171 | // Finally read the null-terminated string. |
| 143 | var byte = try in.readByte(); | 172 | var byte = try in.readByte(); |
| 144 | var i: usize = 0; | 173 | i = 0; |
| 145 | while (byte != 0 and i < buffer.len) : (i += 1) { | 174 | while (byte != 0 and i < buffer.len) : (i += 1) { |
| 146 | buffer[i] = byte; | 175 | buffer[i] = byte; |
| 147 | byte = try in.readByte(); | 176 | byte = try in.readByte(); |
| ... | @@ -170,7 +199,7 @@ pub const Coff = struct { | ... | @@ -170,7 +199,7 @@ pub const Coff = struct { |
| 170 | try self.sections.append(Section{ | 199 | try self.sections.append(Section{ |
| 171 | .header = SectionHeader{ | 200 | .header = SectionHeader{ |
| 172 | .name = name, | 201 | .name = name, |
| 173 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, | 202 | .misc = SectionHeader.Misc{ .virtual_size = try in.readIntLittle(u32) }, |
| 174 | .virtual_address = try in.readIntLittle(u32), | 203 | .virtual_address = try in.readIntLittle(u32), |
| 175 | .size_of_raw_data = try in.readIntLittle(u32), | 204 | .size_of_raw_data = try in.readIntLittle(u32), |
| 176 | .pointer_to_raw_data = try in.readIntLittle(u32), | 205 | .pointer_to_raw_data = try in.readIntLittle(u32), |
| ... | @@ -214,6 +243,17 @@ const OptionalHeader = struct { | ... | @@ -214,6 +243,17 @@ const OptionalHeader = struct { |
| 214 | data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory, | 243 | data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory, |
| 215 | }; | 244 | }; |
| 216 | 245 | ||
| 246 | const DebugDirectoryEntry = packed struct { | ||
| 247 | characteristiccs: u32, | ||
| 248 | time_date_stamp: u32, | ||
| 249 | major_version: u16, | ||
| 250 | minor_version: u16, | ||
| 251 | @"type": u32, | ||
| 252 | size_of_data: u32, | ||
| 253 | address_of_raw_data: u32, | ||
| 254 | pointer_to_raw_data: u32, | ||
| 255 | }; | ||
| 256 | |||
| 217 | pub const Section = struct { | 257 | pub const Section = struct { |
| 218 | header: SectionHeader, | 258 | header: SectionHeader, |
| 219 | }; | 259 | }; |
std/debug.zig+54-21| ... | @@ -12,6 +12,7 @@ const coff = std.coff; | ... | @@ -12,6 +12,7 @@ const coff = std.coff; |
| 12 | const pdb = std.pdb; | 12 | const pdb = std.pdb; |
| 13 | const ArrayList = std.ArrayList; | 13 | const ArrayList = std.ArrayList; |
| 14 | const builtin = @import("builtin"); | 14 | const builtin = @import("builtin"); |
| 15 | const root = @import("root"); | ||
| 15 | const maxInt = std.math.maxInt; | 16 | const maxInt = std.math.maxInt; |
| 16 | const File = std.fs.File; | 17 | const File = std.fs.File; |
| 17 | const windows = std.os.windows; | 18 | const windows = std.os.windows; |
| ... | @@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool | ... | @@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool |
| 217 | pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { | 218 | pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { |
| 218 | @setCold(true); | 219 | @setCold(true); |
| 219 | 220 | ||
| 221 | if (enable_segfault_handler) { | ||
| 222 | // If a segfault happens while panicking, we want it to actually segfault, not trigger | ||
| 223 | // the handler. | ||
| 224 | resetSegfaultHandler(); | ||
| 225 | } | ||
| 226 | |||
| 220 | if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { | 227 | if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { |
| 221 | // Panicked during a panic. | 228 | // Panicked during a panic. |
| 222 | 229 | ||
| ... | @@ -368,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres | ... | @@ -368,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 368 | const obj_basename = fs.path.basename(mod.obj_file_name); | 375 | const obj_basename = fs.path.basename(mod.obj_file_name); |
| 369 | 376 | ||
| 370 | var symbol_i: usize = 0; | 377 | var symbol_i: usize = 0; |
| 371 | const symbol_name = while (symbol_i != mod.symbols.len) { | 378 | const symbol_name = if (!mod.populated) "???" else while (symbol_i != mod.symbols.len) { |
| 372 | const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]); | 379 | const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]); |
| 373 | if (prefix.RecordLen < 2) | 380 | if (prefix.RecordLen < 2) |
| 374 | return error.InvalidDebugInfo; | 381 | return error.InvalidDebugInfo; |
| ... | @@ -851,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -851,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 851 | const age = try pdb_stream.stream.readIntLittle(u32); | 858 | const age = try pdb_stream.stream.readIntLittle(u32); |
| 852 | var guid: [16]u8 = undefined; | 859 | var guid: [16]u8 = undefined; |
| 853 | try pdb_stream.stream.readNoEof(guid[0..]); | 860 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 861 | if (version != 20000404) // VC70, only value observed by LLVM team | ||
| 862 | return error.UnknownPDBVersion; | ||
| 854 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) | 863 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) |
| 855 | return error.InvalidDebugInfo; | 864 | return error.PDBMismatch; |
| 856 | // We validated the executable and pdb match. | 865 | // We validated the executable and pdb match. |
| 857 | 866 | ||
| 858 | const string_table_index = str_tab_index: { | 867 | const string_table_index = str_tab_index: { |
| ... | @@ -896,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { | ... | @@ -896,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 896 | return error.MissingDebugInfo; | 905 | return error.MissingDebugInfo; |
| 897 | }; | 906 | }; |
| 898 | 907 | ||
| 899 | di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.InvalidDebugInfo; | 908 | di.pdb.string_table = di.pdb.getStreamById(string_table_index) orelse return error.MissingDebugInfo; |
| 900 | di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo; | 909 | di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo; |
| 901 | 910 | ||
| 902 | const dbi = di.pdb.dbi; | 911 | const dbi = di.pdb.dbi; |
| 903 | 912 | ||
| 904 | // Dbi Header | 913 | // Dbi Header |
| 905 | const dbi_stream_header = try dbi.stream.readStruct(pdb.DbiStreamHeader); | 914 | const dbi_stream_header = try dbi.stream.readStruct(pdb.DbiStreamHeader); |
| 915 | if (dbi_stream_header.VersionHeader != 19990903) // V70, only value observed by LLVM team | ||
| 916 | return error.UnknownPDBVersion; | ||
| 917 | if (dbi_stream_header.Age != age) | ||
| 918 | return error.UnmatchingPDB; | ||
| 919 | |||
| 906 | const mod_info_size = dbi_stream_header.ModInfoSize; | 920 | const mod_info_size = dbi_stream_header.ModInfoSize; |
| 907 | const section_contrib_size = dbi_stream_header.SectionContributionSize; | 921 | const section_contrib_size = dbi_stream_header.SectionContributionSize; |
| 908 | 922 | ||
| ... | @@ -2312,39 +2326,58 @@ fn getDebugInfoAllocator() *mem.Allocator { | ... | @@ -2312,39 +2326,58 @@ fn getDebugInfoAllocator() *mem.Allocator { |
| 2312 | 2326 | ||
| 2313 | /// Whether or not the current target can print useful debug information when a segfault occurs. | 2327 | /// Whether or not the current target can print useful debug information when a segfault occurs. |
| 2314 | pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows; | 2328 | pub const have_segfault_handling_support = (builtin.arch == builtin.Arch.x86_64 and builtin.os == .linux) or builtin.os == .windows; |
| 2329 | pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) | ||
| 2330 | root.enable_segfault_handler | ||
| 2331 | else | ||
| 2332 | runtime_safety and have_segfault_handling_support; | ||
| 2333 | |||
| 2334 | pub fn maybeEnableSegfaultHandler() void { | ||
| 2335 | if (enable_segfault_handler) { | ||
| 2336 | std.debug.attachSegfaultHandler(); | ||
| 2337 | } | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | var windows_segfault_handle: ?windows.HANDLE = null; | ||
| 2315 | 2341 | ||
| 2316 | /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); | 2342 | /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); |
| 2317 | pub fn attachSegfaultHandler() void { | 2343 | pub fn attachSegfaultHandler() void { |
| 2318 | if (!have_segfault_handling_support) { | 2344 | if (!have_segfault_handling_support) { |
| 2319 | @compileError("segfault handler not supported for this target"); | 2345 | @compileError("segfault handler not supported for this target"); |
| 2320 | } | 2346 | } |
| 2321 | switch (builtin.os) { | 2347 | if (windows.is_the_target) { |
| 2322 | .linux => { | 2348 | windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); |
| 2323 | var act = os.Sigaction{ | 2349 | return; |
| 2324 | .sigaction = handleSegfaultLinux, | ||
| 2325 | .mask = os.empty_sigset, | ||
| 2326 | .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), | ||
| 2327 | }; | ||
| 2328 | |||
| 2329 | os.sigaction(os.SIGSEGV, &act, null); | ||
| 2330 | }, | ||
| 2331 | .windows => { | ||
| 2332 | _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); | ||
| 2333 | }, | ||
| 2334 | else => unreachable, | ||
| 2335 | } | 2350 | } |
| 2351 | var act = os.Sigaction{ | ||
| 2352 | .sigaction = handleSegfaultLinux, | ||
| 2353 | .mask = os.empty_sigset, | ||
| 2354 | .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND), | ||
| 2355 | }; | ||
| 2356 | |||
| 2357 | os.sigaction(os.SIGSEGV, &act, null); | ||
| 2336 | } | 2358 | } |
| 2337 | 2359 | ||
| 2338 | extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { | 2360 | fn resetSegfaultHandler() void { |
| 2339 | // Reset to the default handler so that if a segfault happens in this handler it will crash | 2361 | if (windows.is_the_target) { |
| 2340 | // the process. Also when this handler returns, the original instruction will be repeated | 2362 | if (windows_segfault_handle) |handle| { |
| 2341 | // and the resulting segfault will crash the process rather than continually dump stack traces. | 2363 | assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0); |
| 2364 | windows_segfault_handle = null; | ||
| 2365 | } | ||
| 2366 | return; | ||
| 2367 | } | ||
| 2342 | var act = os.Sigaction{ | 2368 | var act = os.Sigaction{ |
| 2343 | .sigaction = os.SIG_DFL, | 2369 | .sigaction = os.SIG_DFL, |
| 2344 | .mask = os.empty_sigset, | 2370 | .mask = os.empty_sigset, |
| 2345 | .flags = 0, | 2371 | .flags = 0, |
| 2346 | }; | 2372 | }; |
| 2347 | os.sigaction(os.SIGSEGV, &act, null); | 2373 | os.sigaction(os.SIGSEGV, &act, null); |
| 2374 | } | ||
| 2375 | |||
| 2376 | extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn { | ||
| 2377 | // Reset to the default handler so that if a segfault happens in this handler it will crash | ||
| 2378 | // the process. Also when this handler returns, the original instruction will be repeated | ||
| 2379 | // and the resulting segfault will crash the process rather than continually dump stack traces. | ||
| 2380 | resetSegfaultHandler(); | ||
| 2348 | 2381 | ||
| 2349 | const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); | 2382 | const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); |
| 2350 | const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); | 2383 | const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); |
std/fmt.zig+20-1| ... | @@ -374,9 +374,10 @@ pub fn formatType( | ... | @@ -374,9 +374,10 @@ pub fn formatType( |
| 374 | return output(context, "{ ... }"); | 374 | return output(context, "{ ... }"); |
| 375 | } | 375 | } |
| 376 | comptime var field_i = 0; | 376 | comptime var field_i = 0; |
| 377 | try output(context, "{"); | ||
| 377 | inline while (field_i < @memberCount(T)) : (field_i += 1) { | 378 | inline while (field_i < @memberCount(T)) : (field_i += 1) { |
| 378 | if (field_i == 0) { | 379 | if (field_i == 0) { |
| 379 | try output(context, "{ ."); | 380 | try output(context, " ."); |
| 380 | } else { | 381 | } else { |
| 381 | try output(context, ", ."); | 382 | try output(context, ", ."); |
| 382 | } | 383 | } |
| ... | @@ -425,6 +426,9 @@ pub fn formatType( | ... | @@ -425,6 +426,9 @@ pub fn formatType( |
| 425 | if (info.child == u8) { | 426 | if (info.child == u8) { |
| 426 | return formatText(value, fmt, options, context, Errors, output); | 427 | return formatText(value, fmt, options, context, Errors, output); |
| 427 | } | 428 | } |
| 429 | if (value.len == 0) { | ||
| 430 | return format(context, Errors, output, "[0]{}", @typeName(T.Child)); | ||
| 431 | } | ||
| 428 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); | 432 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 429 | }, | 433 | }, |
| 430 | .Fn => { | 434 | .Fn => { |
| ... | @@ -1439,6 +1443,21 @@ test "struct.self-referential" { | ... | @@ -1439,6 +1443,21 @@ test "struct.self-referential" { |
| 1439 | try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst); | 1443 | try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst); |
| 1440 | } | 1444 | } |
| 1441 | 1445 | ||
| 1446 | test "struct.zero-size" { | ||
| 1447 | const A = struct { | ||
| 1448 | fn foo() void {} | ||
| 1449 | }; | ||
| 1450 | const B = struct { | ||
| 1451 | a: A, | ||
| 1452 | c: i32, | ||
| 1453 | }; | ||
| 1454 | |||
| 1455 | const a = A{}; | ||
| 1456 | const b = B{ .a = a, .c = 0 }; | ||
| 1457 | |||
| 1458 | try testFmt("B{ .a = A{ }, .c = 0 }", "{}", b); | ||
| 1459 | } | ||
| 1460 | |||
| 1442 | test "bytes.hex" { | 1461 | test "bytes.hex" { |
| 1443 | const some_bytes = "\xCA\xFE\xBA\xBE"; | 1462 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 1444 | try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes); | 1463 | try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes); |
std/os.zig+21| ... | @@ -133,6 +133,11 @@ fn getRandomBytesDevURandom(buf: []u8) !void { | ... | @@ -133,6 +133,11 @@ fn getRandomBytesDevURandom(buf: []u8) !void { |
| 133 | const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0); | 133 | const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0); |
| 134 | defer close(fd); | 134 | defer close(fd); |
| 135 | 135 | ||
| 136 | const st = try fstat(fd); | ||
| 137 | if (!S_ISCHR(st.mode)) { | ||
| 138 | return error.NoDevice; | ||
| 139 | } | ||
| 140 | |||
| 136 | const stream = &std.fs.File.openHandle(fd).inStream().stream; | 141 | const stream = &std.fs.File.openHandle(fd).inStream().stream; |
| 137 | stream.readNoEof(buf) catch return error.Unexpected; | 142 | stream.readNoEof(buf) catch return error.Unexpected; |
| 138 | } | 143 | } |
| ... | @@ -2053,6 +2058,22 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void { | ... | @@ -2053,6 +2058,22 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void { |
| 2053 | } | 2058 | } |
| 2054 | } | 2059 | } |
| 2055 | 2060 | ||
| 2061 | /// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string. | ||
| 2062 | /// Otherwise use `access` or `accessC`. | ||
| 2063 | /// TODO currently this ignores `mode`. | ||
| 2064 | pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!void { | ||
| 2065 | const ret = try windows.GetFileAttributesW(path); | ||
| 2066 | if (ret != windows.INVALID_FILE_ATTRIBUTES) { | ||
| 2067 | return; | ||
| 2068 | } | ||
| 2069 | switch (windows.kernel32.GetLastError()) { | ||
| 2070 | windows.ERROR.FILE_NOT_FOUND => return error.FileNotFound, | ||
| 2071 | windows.ERROR.PATH_NOT_FOUND => return error.FileNotFound, | ||
| 2072 | windows.ERROR.ACCESS_DENIED => return error.PermissionDenied, | ||
| 2073 | else => |err| return windows.unexpectedError(err), | ||
| 2074 | } | ||
| 2075 | } | ||
| 2076 | |||
| 2056 | pub const PipeError = error{ | 2077 | pub const PipeError = error{ |
| 2057 | SystemFdQuotaExceeded, | 2078 | SystemFdQuotaExceeded, |
| 2058 | ProcessFdQuotaExceeded, | 2079 | ProcessFdQuotaExceeded, |
std/os/bits/darwin.zig+59| ... | @@ -1116,3 +1116,62 @@ pub const stack_t = extern struct { | ... | @@ -1116,3 +1116,62 @@ pub const stack_t = extern struct { |
| 1116 | ss_size: isize, | 1116 | ss_size: isize, |
| 1117 | ss_flags: i32, | 1117 | ss_flags: i32, |
| 1118 | }; | 1118 | }; |
| 1119 | |||
| 1120 | pub const S_IFMT = 0o170000; | ||
| 1121 | |||
| 1122 | pub const S_IFIFO = 0o010000; | ||
| 1123 | pub const S_IFCHR = 0o020000; | ||
| 1124 | pub const S_IFDIR = 0o040000; | ||
| 1125 | pub const S_IFBLK = 0o060000; | ||
| 1126 | pub const S_IFREG = 0o100000; | ||
| 1127 | pub const S_IFLNK = 0o120000; | ||
| 1128 | pub const S_IFSOCK = 0o140000; | ||
| 1129 | pub const S_IFWHT = 0o160000; | ||
| 1130 | |||
| 1131 | pub const S_ISUID = 0o4000; | ||
| 1132 | pub const S_ISGID = 0o2000; | ||
| 1133 | pub const S_ISVTX = 0o1000; | ||
| 1134 | pub const S_IRWXU = 0o700; | ||
| 1135 | pub const S_IRUSR = 0o400; | ||
| 1136 | pub const S_IWUSR = 0o200; | ||
| 1137 | pub const S_IXUSR = 0o100; | ||
| 1138 | pub const S_IRWXG = 0o070; | ||
| 1139 | pub const S_IRGRP = 0o040; | ||
| 1140 | pub const S_IWGRP = 0o020; | ||
| 1141 | pub const S_IXGRP = 0o010; | ||
| 1142 | pub const S_IRWXO = 0o007; | ||
| 1143 | pub const S_IROTH = 0o004; | ||
| 1144 | pub const S_IWOTH = 0o002; | ||
| 1145 | pub const S_IXOTH = 0o001; | ||
| 1146 | |||
| 1147 | pub fn S_ISFIFO(m: u32) bool { | ||
| 1148 | return m & S_IFMT == S_IFIFO; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | pub fn S_ISCHR(m: u32) bool { | ||
| 1152 | return m & S_IFMT == S_IFCHR; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | pub fn S_ISDIR(m: u32) bool { | ||
| 1156 | return m & S_IFMT == S_IFDIR; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | pub fn S_ISBLK(m: u32) bool { | ||
| 1160 | return m & S_IFMT == S_IFBLK; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | pub fn S_ISREG(m: u32) bool { | ||
| 1164 | return m & S_IFMT == S_IFREG; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | pub fn S_ISLNK(m: u32) bool { | ||
| 1168 | return m & S_IFMT == S_IFLNK; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | pub fn S_ISSOCK(m: u32) bool { | ||
| 1172 | return m & S_IFMT == S_IFSOCK; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | pub fn S_IWHT(m: u32) bool { | ||
| 1176 | return m & S_IFMT == S_IFWHT; | ||
| 1177 | } |
std/os/bits/freebsd.zig+59| ... | @@ -876,3 +876,62 @@ pub const stack_t = extern struct { | ... | @@ -876,3 +876,62 @@ pub const stack_t = extern struct { |
| 876 | ss_size: isize, | 876 | ss_size: isize, |
| 877 | ss_flags: i32, | 877 | ss_flags: i32, |
| 878 | }; | 878 | }; |
| 879 | |||
| 880 | pub const S_IFMT = 0o170000; | ||
| 881 | |||
| 882 | pub const S_IFIFO = 0o010000; | ||
| 883 | pub const S_IFCHR = 0o020000; | ||
| 884 | pub const S_IFDIR = 0o040000; | ||
| 885 | pub const S_IFBLK = 0o060000; | ||
| 886 | pub const S_IFREG = 0o100000; | ||
| 887 | pub const S_IFLNK = 0o120000; | ||
| 888 | pub const S_IFSOCK = 0o140000; | ||
| 889 | pub const S_IFWHT = 0o160000; | ||
| 890 | |||
| 891 | pub const S_ISUID = 0o4000; | ||
| 892 | pub const S_ISGID = 0o2000; | ||
| 893 | pub const S_ISVTX = 0o1000; | ||
| 894 | pub const S_IRWXU = 0o700; | ||
| 895 | pub const S_IRUSR = 0o400; | ||
| 896 | pub const S_IWUSR = 0o200; | ||
| 897 | pub const S_IXUSR = 0o100; | ||
| 898 | pub const S_IRWXG = 0o070; | ||
| 899 | pub const S_IRGRP = 0o040; | ||
| 900 | pub const S_IWGRP = 0o020; | ||
| 901 | pub const S_IXGRP = 0o010; | ||
| 902 | pub const S_IRWXO = 0o007; | ||
| 903 | pub const S_IROTH = 0o004; | ||
| 904 | pub const S_IWOTH = 0o002; | ||
| 905 | pub const S_IXOTH = 0o001; | ||
| 906 | |||
| 907 | pub fn S_ISFIFO(m: u32) bool { | ||
| 908 | return m & S_IFMT == S_IFIFO; | ||
| 909 | } | ||
| 910 | |||
| 911 | pub fn S_ISCHR(m: u32) bool { | ||
| 912 | return m & S_IFMT == S_IFCHR; | ||
| 913 | } | ||
| 914 | |||
| 915 | pub fn S_ISDIR(m: u32) bool { | ||
| 916 | return m & S_IFMT == S_IFDIR; | ||
| 917 | } | ||
| 918 | |||
| 919 | pub fn S_ISBLK(m: u32) bool { | ||
| 920 | return m & S_IFMT == S_IFBLK; | ||
| 921 | } | ||
| 922 | |||
| 923 | pub fn S_ISREG(m: u32) bool { | ||
| 924 | return m & S_IFMT == S_IFREG; | ||
| 925 | } | ||
| 926 | |||
| 927 | pub fn S_ISLNK(m: u32) bool { | ||
| 928 | return m & S_IFMT == S_IFLNK; | ||
| 929 | } | ||
| 930 | |||
| 931 | pub fn S_ISSOCK(m: u32) bool { | ||
| 932 | return m & S_IFMT == S_IFSOCK; | ||
| 933 | } | ||
| 934 | |||
| 935 | pub fn S_IWHT(m: u32) bool { | ||
| 936 | return m & S_IFMT == S_IFWHT; | ||
| 937 | } |
std/os/darwin.zig+1| ... | @@ -5,3 +5,4 @@ pub const is_the_target = switch (builtin.os) { | ... | @@ -5,3 +5,4 @@ pub const is_the_target = switch (builtin.os) { |
| 5 | else => false, | 5 | else => false, |
| 6 | }; | 6 | }; |
| 7 | pub usingnamespace std.c; | 7 | pub usingnamespace std.c; |
| 8 | pub usingnamespace @import("bits.zig"); | ||
| \ No newline at end of file | |||
std/os/freebsd.zig+1| ... | @@ -2,3 +2,4 @@ const std = @import("../std.zig"); | ... | @@ -2,3 +2,4 @@ const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | pub const is_the_target = builtin.os == .freebsd; | 3 | pub const is_the_target = builtin.os == .freebsd; |
| 4 | pub usingnamespace std.c; | 4 | pub usingnamespace std.c; |
| 5 | pub usingnamespace @import("bits.zig"); | ||
| \ No newline at end of file | |||
std/os/windows/kernel32.zig+1| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | usingnamespace @import("bits.zig"); | 1 | usingnamespace @import("bits.zig"); |
| 2 | 2 | ||
| 3 | pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void; | 3 | pub extern "kernel32" stdcallcc fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) ?*c_void; |
| 4 | pub extern "kernel32" stdcallcc fn RemoveVectoredExceptionHandler(Handle: HANDLE) c_ulong; | ||
| 4 | 5 | ||
| 5 | pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL; | 6 | pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL; |
| 6 | 7 |
std/pdb.zig+73-44| ... | @@ -499,45 +499,78 @@ const Msf = struct { | ... | @@ -499,45 +499,78 @@ const Msf = struct { |
| 499 | 499 | ||
| 500 | const superblock = try in.readStruct(SuperBlock); | 500 | const superblock = try in.readStruct(SuperBlock); |
| 501 | 501 | ||
| 502 | // Sanity checks | ||
| 502 | if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic)) | 503 | if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic)) |
| 503 | return error.InvalidDebugInfo; | 504 | return error.InvalidDebugInfo; |
| 504 | 505 | if (superblock.FreeBlockMapBlock != 1 and superblock.FreeBlockMapBlock != 2) | |
| 506 | return error.InvalidDebugInfo; | ||
| 507 | if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos()) | ||
| 508 | return error.InvalidDebugInfo; | ||
| 505 | switch (superblock.BlockSize) { | 509 | switch (superblock.BlockSize) { |
| 506 | // llvm only supports 4096 but we can handle any of these values | 510 | // llvm only supports 4096 but we can handle any of these values |
| 507 | 512, 1024, 2048, 4096 => {}, | 511 | 512, 1024, 2048, 4096 => {}, |
| 508 | else => return error.InvalidDebugInfo, | 512 | else => return error.InvalidDebugInfo, |
| 509 | } | 513 | } |
| 510 | 514 | ||
| 511 | if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos()) | 515 | const dir_block_count = blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize); |
| 512 | return error.InvalidDebugInfo; | 516 | if (dir_block_count > superblock.BlockSize / @sizeOf(u32)) |
| 517 | return error.UnhandledBigDirectoryStream; // cf. BlockMapAddr comment. | ||
| 513 | 518 | ||
| 514 | self.directory = try MsfStream.init( | 519 | try file.seekTo(superblock.BlockSize * superblock.BlockMapAddr); |
| 520 | var dir_blocks = try allocator.alloc(u32, dir_block_count); | ||
| 521 | for (dir_blocks) |*b| { | ||
| 522 | b.* = try in.readIntLittle(u32); | ||
| 523 | } | ||
| 524 | self.directory = MsfStream.init( | ||
| 515 | superblock.BlockSize, | 525 | superblock.BlockSize, |
| 516 | blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize), | ||
| 517 | superblock.BlockSize * superblock.BlockMapAddr, | ||
| 518 | file, | 526 | file, |
| 519 | allocator, | 527 | dir_blocks, |
| 520 | ); | 528 | ); |
| 521 | 529 | ||
| 530 | const begin = self.directory.pos; | ||
| 522 | const stream_count = try self.directory.stream.readIntLittle(u32); | 531 | const stream_count = try self.directory.stream.readIntLittle(u32); |
| 523 | |||
| 524 | const stream_sizes = try allocator.alloc(u32, stream_count); | 532 | const stream_sizes = try allocator.alloc(u32, stream_count); |
| 525 | for (stream_sizes) |*s| { | 533 | defer allocator.free(stream_sizes); |
| 534 | |||
| 535 | // Microsoft's implementation uses u32(-1) for inexistant streams. | ||
| 536 | // These streams are not used, but still participate in the file | ||
| 537 | // and must be taken into account when resolving stream indices. | ||
| 538 | const Nil = 0xFFFFFFFF; | ||
| 539 | for (stream_sizes) |*s, i| { | ||
| 526 | const size = try self.directory.stream.readIntLittle(u32); | 540 | const size = try self.directory.stream.readIntLittle(u32); |
| 527 | s.* = blockCountFromSize(size, superblock.BlockSize); | 541 | s.* = if (size == Nil) 0 else blockCountFromSize(size, superblock.BlockSize); |
| 528 | } | 542 | } |
| 529 | 543 | ||
| 530 | self.streams = try allocator.alloc(MsfStream, stream_count); | 544 | self.streams = try allocator.alloc(MsfStream, stream_count); |
| 531 | for (self.streams) |*stream, i| { | 545 | for (self.streams) |*stream, i| { |
| 532 | stream.* = try MsfStream.init( | 546 | const size = stream_sizes[i]; |
| 533 | superblock.BlockSize, | 547 | if (size == 0) { |
| 534 | stream_sizes[i], | 548 | stream.* = MsfStream{ |
| 535 | // MsfStream.init expects the file to be at the part where it reads [N]u32 | 549 | .blocks = [_]u32{}, |
| 536 | try file.getPos(), | 550 | }; |
| 537 | file, | 551 | } else { |
| 538 | allocator, | 552 | var blocks = try allocator.alloc(u32, size); |
| 539 | ); | 553 | var j: u32 = 0; |
| 554 | while (j < size) : (j += 1) { | ||
| 555 | const block_id = try self.directory.stream.readIntLittle(u32); | ||
| 556 | const n = (block_id % superblock.BlockSize); | ||
| 557 | // 0 is for SuperBlock, 1 and 2 for FPMs. | ||
| 558 | if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > try file.getEndPos()) | ||
| 559 | return error.InvalidBlockIndex; | ||
| 560 | blocks[j] = block_id; | ||
| 561 | } | ||
| 562 | |||
| 563 | stream.* = MsfStream.init( | ||
| 564 | superblock.BlockSize, | ||
| 565 | file, | ||
| 566 | blocks, | ||
| 567 | ); | ||
| 568 | } | ||
| 540 | } | 569 | } |
| 570 | |||
| 571 | const end = self.directory.pos; | ||
| 572 | if (end - begin != superblock.NumDirectoryBytes) | ||
| 573 | return error.InvalidStreamDirectory; | ||
| 541 | } | 574 | } |
| 542 | }; | 575 | }; |
| 543 | 576 | ||
| ... | @@ -574,7 +607,6 @@ const SuperBlock = packed struct { | ... | @@ -574,7 +607,6 @@ const SuperBlock = packed struct { |
| 574 | NumDirectoryBytes: u32, | 607 | NumDirectoryBytes: u32, |
| 575 | 608 | ||
| 576 | Unknown: u32, | 609 | Unknown: u32, |
| 577 | |||
| 578 | /// The index of a block within the MSF file. At this block is an array of | 610 | /// The index of a block within the MSF file. At this block is an array of |
| 579 | /// ulittle32_t’s listing the blocks that the stream directory resides on. | 611 | /// ulittle32_t’s listing the blocks that the stream directory resides on. |
| 580 | /// For large MSF files, the stream directory (which describes the block | 612 | /// For large MSF files, the stream directory (which describes the block |
| ... | @@ -584,45 +616,41 @@ const SuperBlock = packed struct { | ... | @@ -584,45 +616,41 @@ const SuperBlock = packed struct { |
| 584 | /// and the stream directory itself can be stitched together accordingly. | 616 | /// and the stream directory itself can be stitched together accordingly. |
| 585 | /// The number of ulittle32_t’s in this array is given by | 617 | /// The number of ulittle32_t’s in this array is given by |
| 586 | /// ceil(NumDirectoryBytes / BlockSize). | 618 | /// ceil(NumDirectoryBytes / BlockSize). |
| 619 | // Note: microsoft-pdb code actually suggests this is a variable-length | ||
| 620 | // array. If the indices of blocks occupied by the Stream Directory didn't | ||
| 621 | // fit in one page, there would be other u32 following it. | ||
| 622 | // This would mean the Stream Directory is bigger than BlockSize / sizeof(u32) | ||
| 623 | // blocks. We're not even close to this with a 1GB pdb file, and LLVM didn't | ||
| 624 | // implement it so we're kind of safe making this assumption for now. | ||
| 587 | BlockMapAddr: u32, | 625 | BlockMapAddr: u32, |
| 588 | }; | 626 | }; |
| 589 | 627 | ||
| 590 | const MsfStream = struct { | 628 | const MsfStream = struct { |
| 591 | in_file: File, | 629 | in_file: File = undefined, |
| 592 | pos: u64, | 630 | pos: u64 = undefined, |
| 593 | blocks: []u32, | 631 | blocks: []u32 = undefined, |
| 594 | block_size: u32, | 632 | block_size: u32 = undefined, |
| 595 | 633 | ||
| 596 | /// Implementation of InStream trait for Pdb.MsfStream | 634 | /// Implementation of InStream trait for Pdb.MsfStream |
| 597 | stream: Stream, | 635 | stream: Stream = undefined, |
| 598 | 636 | ||
| 599 | pub const Error = @typeOf(read).ReturnType.ErrorSet; | 637 | pub const Error = @typeOf(read).ReturnType.ErrorSet; |
| 600 | pub const Stream = io.InStream(Error); | 638 | pub const Stream = io.InStream(Error); |
| 601 | 639 | ||
| 602 | fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream { | 640 | fn init(block_size: u32, file: File, blocks: []u32) MsfStream { |
| 603 | var stream = MsfStream{ | 641 | const stream = MsfStream{ |
| 604 | .in_file = file, | 642 | .in_file = file, |
| 605 | .pos = 0, | 643 | .pos = 0, |
| 606 | .blocks = try allocator.alloc(u32, block_count), | 644 | .blocks = blocks, |
| 607 | .block_size = block_size, | 645 | .block_size = block_size, |
| 608 | .stream = Stream{ .readFn = readFn }, | 646 | .stream = Stream{ .readFn = readFn }, |
| 609 | }; | 647 | }; |
| 610 | 648 | ||
| 611 | var file_stream = file.inStream(); | ||
| 612 | const in = &file_stream.stream; | ||
| 613 | try file.seekTo(pos); | ||
| 614 | |||
| 615 | var i: u32 = 0; | ||
| 616 | while (i < block_count) : (i += 1) { | ||
| 617 | stream.blocks[i] = try in.readIntLittle(u32); | ||
| 618 | } | ||
| 619 | |||
| 620 | return stream; | 649 | return stream; |
| 621 | } | 650 | } |
| 622 | 651 | ||
| 623 | fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { | 652 | fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { |
| 624 | var list = ArrayList(u8).init(allocator); | 653 | var list = ArrayList(u8).init(allocator); |
| 625 | defer list.deinit(); | ||
| 626 | while (true) { | 654 | while (true) { |
| 627 | const byte = try self.stream.readByte(); | 655 | const byte = try self.stream.readByte(); |
| 628 | if (byte == 0) { | 656 | if (byte == 0) { |
| ... | @@ -642,11 +670,12 @@ const MsfStream = struct { | ... | @@ -642,11 +670,12 @@ const MsfStream = struct { |
| 642 | const in = &file_stream.stream; | 670 | const in = &file_stream.stream; |
| 643 | 671 | ||
| 644 | var size: usize = 0; | 672 | var size: usize = 0; |
| 645 | for (buffer) |*byte| { | 673 | var rem_buffer = buffer; |
| 646 | byte.* = try in.readByte(); | 674 | while (size < buffer.len) { |
| 647 | 675 | const size_to_read = math.min(self.block_size - offset, rem_buffer.len); | |
| 648 | offset += 1; | 676 | size += try in.read(rem_buffer[0..size_to_read]); |
| 649 | size += 1; | 677 | rem_buffer = buffer[size..]; |
| 678 | offset += size_to_read; | ||
| 650 | 679 | ||
| 651 | // If we're at the end of a block, go to the next one. | 680 | // If we're at the end of a block, go to the next one. |
| 652 | if (offset == self.block_size) { | 681 | if (offset == self.block_size) { |
| ... | @@ -657,8 +686,8 @@ const MsfStream = struct { | ... | @@ -657,8 +686,8 @@ const MsfStream = struct { |
| 657 | } | 686 | } |
| 658 | } | 687 | } |
| 659 | 688 | ||
| 660 | self.pos += size; | 689 | self.pos += buffer.len; |
| 661 | return size; | 690 | return buffer.len; |
| 662 | } | 691 | } |
| 663 | 692 | ||
| 664 | fn seekBy(self: *MsfStream, len: i64) !void { | 693 | fn seekBy(self: *MsfStream, len: i64) !void { |
std/process.zig+1-2| ... | @@ -146,13 +146,12 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned | ... | @@ -146,13 +146,12 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned |
| 146 | error.Unexpected => return error.EnvironmentVariableNotFound, | 146 | error.Unexpected => return error.EnvironmentVariableNotFound, |
| 147 | else => |e| return e, | 147 | else => |e| return e, |
| 148 | }; | 148 | }; |
| 149 | |||
| 150 | if (result > buf.len) { | 149 | if (result > buf.len) { |
| 151 | buf = try allocator.realloc(buf, result); | 150 | buf = try allocator.realloc(buf, result); |
| 152 | continue; | 151 | continue; |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) { | 154 | return std.unicode.utf16leToUtf8Alloc(allocator, buf[0..result]) catch |err| switch (err) { |
| 156 | error.DanglingSurrogateHalf => return error.InvalidUtf8, | 155 | error.DanglingSurrogateHalf => return error.InvalidUtf8, |
| 157 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, | 156 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, |
| 158 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, | 157 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, |
std/rb.zig+51-3| ... | @@ -93,7 +93,8 @@ pub const Node = struct { | ... | @@ -93,7 +93,8 @@ pub const Node = struct { |
| 93 | comptime { | 93 | comptime { |
| 94 | assert(@alignOf(*Node) >= 2); | 94 | assert(@alignOf(*Node) >= 2); |
| 95 | } | 95 | } |
| 96 | return @intToPtr(*Node, node.parent_and_color & ~mask); | 96 | const maybe_ptr = node.parent_and_color & ~mask; |
| 97 | return if (maybe_ptr == 0) null else @intToPtr(*Node, maybe_ptr); | ||
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | fn setColor(node: *Node, color: Color) void { | 100 | fn setColor(node: *Node, color: Color) void { |
| ... | @@ -233,10 +234,13 @@ pub const Tree = struct { | ... | @@ -233,10 +234,13 @@ pub const Tree = struct { |
| 233 | return null; | 234 | return null; |
| 234 | } | 235 | } |
| 235 | 236 | ||
| 237 | /// lookup searches for the value of key, using binary search. It will | ||
| 238 | /// return a pointer to the node if it is there, otherwise it will return null. | ||
| 239 | /// Complexity guaranteed O(log n), where n is the number of nodes book-kept | ||
| 240 | /// by tree. | ||
| 236 | pub fn lookup(tree: *Tree, key: *Node) ?*Node { | 241 | pub fn lookup(tree: *Tree, key: *Node) ?*Node { |
| 237 | var parent: *Node = undefined; | 242 | var parent: ?*Node = undefined; |
| 238 | var is_left: bool = undefined; | 243 | var is_left: bool = undefined; |
| 239 | |||
| 240 | return doLookup(key, tree, &parent, &is_left); | 244 | return doLookup(key, tree, &parent, &is_left); |
| 241 | } | 245 | } |
| 242 | 246 | ||
| ... | @@ -544,3 +548,47 @@ test "rb" { | ... | @@ -544,3 +548,47 @@ test "rb" { |
| 544 | num = testGetNumber(num.node.next().?); | 548 | num = testGetNumber(num.node.next().?); |
| 545 | } | 549 | } |
| 546 | } | 550 | } |
| 551 | |||
| 552 | |||
| 553 | test "inserting and looking up" { | ||
| 554 | var tree: Tree = undefined; | ||
| 555 | tree.init(testCompare); | ||
| 556 | var number: testNumber = undefined; | ||
| 557 | number.value = 1000; | ||
| 558 | _ = tree.insert(&number.node); | ||
| 559 | var dup: testNumber = undefined; | ||
| 560 | //Assert that tuples with identical value fields finds the same pointer | ||
| 561 | dup.value = 1000; | ||
| 562 | assert(tree.lookup(&dup.node) == &number.node); | ||
| 563 | //Assert that tuples with identical values do not clobber when inserted. | ||
| 564 | _ = tree.insert(&dup.node); | ||
| 565 | assert(tree.lookup(&dup.node) == &number.node); | ||
| 566 | assert(tree.lookup(&number.node) != &dup.node); | ||
| 567 | assert(testGetNumber(tree.lookup(&dup.node).?).value == testGetNumber(&dup.node).value); | ||
| 568 | //Assert that if looking for a non-existing value, return null. | ||
| 569 | var non_existing_value: testNumber = undefined; | ||
| 570 | non_existing_value.value = 1234; | ||
| 571 | assert(tree.lookup(&non_existing_value.node) == null); | ||
| 572 | } | ||
| 573 | |||
| 574 | test "multiple inserts, followed by calling first and last" { | ||
| 575 | var tree: Tree = undefined; | ||
| 576 | tree.init(testCompare); | ||
| 577 | var zeroth: testNumber = undefined; | ||
| 578 | zeroth.value = 0; | ||
| 579 | var first: testNumber = undefined; | ||
| 580 | first.value = 1; | ||
| 581 | var second: testNumber = undefined; | ||
| 582 | second.value = 2; | ||
| 583 | var third: testNumber = undefined; | ||
| 584 | third.value = 3; | ||
| 585 | _ = tree.insert(&zeroth.node); | ||
| 586 | _ = tree.insert(&first.node); | ||
| 587 | _ = tree.insert(&second.node); | ||
| 588 | _ = tree.insert(&third.node); | ||
| 589 | assert(testGetNumber(tree.first().?).value == 0); | ||
| 590 | assert(testGetNumber(tree.last().?).value == 3); | ||
| 591 | var lookupNode: testNumber = undefined; | ||
| 592 | lookupNode.value = 3; | ||
| 593 | assert(tree.lookup(&lookupNode.node) == &third.node); | ||
| 594 | } |
std/segmented_list.zig+18-11| ... | @@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator; | ... | @@ -77,15 +77,19 @@ const Allocator = std.mem.Allocator; |
| 77 | pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { | 77 | pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { |
| 78 | return struct { | 78 | return struct { |
| 79 | const Self = @This(); | 79 | const Self = @This(); |
| 80 | const prealloc_exp = blk: { | 80 | const ShelfIndex = std.math.Log2Int(usize); |
| 81 | // we don't use the prealloc_exp constant when prealloc_item_count is 0. | ||
| 82 | assert(prealloc_item_count != 0); | ||
| 83 | assert(std.math.isPowerOfTwo(prealloc_item_count)); | ||
| 84 | 81 | ||
| 85 | const value = std.math.log2_int(usize, prealloc_item_count); | 82 | const prealloc_exp: ShelfIndex = blk: { |
| 86 | break :blk @typeOf(1)(value); | 83 | // we don't use the prealloc_exp constant when prealloc_item_count is 0 |
| 84 | // but lazy-init may still be triggered by other code so supply a value | ||
| 85 | if (prealloc_item_count == 0) { | ||
| 86 | break :blk 0; | ||
| 87 | } else { | ||
| 88 | assert(std.math.isPowerOfTwo(prealloc_item_count)); | ||
| 89 | const value = std.math.log2_int(usize, prealloc_item_count); | ||
| 90 | break :blk value; | ||
| 91 | } | ||
| 87 | }; | 92 | }; |
| 88 | const ShelfIndex = std.math.Log2Int(usize); | ||
| 89 | 93 | ||
| 90 | prealloc_segment: [prealloc_item_count]T, | 94 | prealloc_segment: [prealloc_item_count]T, |
| 91 | dynamic_segments: [][*]T, | 95 | dynamic_segments: [][*]T, |
| ... | @@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type | ... | @@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 157 | 161 | ||
| 158 | /// Grows or shrinks capacity to match usage. | 162 | /// Grows or shrinks capacity to match usage. |
| 159 | pub fn setCapacity(self: *Self, new_capacity: usize) !void { | 163 | pub fn setCapacity(self: *Self, new_capacity: usize) !void { |
| 160 | if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) { | 164 | if (prealloc_item_count != 0) { |
| 161 | return self.shrinkCapacity(new_capacity); | 165 | if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { |
| 162 | } else { | 166 | return self.shrinkCapacity(new_capacity); |
| 163 | return self.growCapacity(new_capacity); | 167 | } |
| 164 | } | 168 | } |
| 169 | return self.growCapacity(new_capacity); | ||
| 165 | } | 170 | } |
| 166 | 171 | ||
| 167 | /// Only grows capacity, or retains current capacity | 172 | /// Only grows capacity, or retains current capacity |
| ... | @@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { | ... | @@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { |
| 399 | testing.expect(item == i); | 404 | testing.expect(item == i); |
| 400 | list.shrinkCapacity(list.len); | 405 | list.shrinkCapacity(list.len); |
| 401 | } | 406 | } |
| 407 | |||
| 408 | try list.setCapacity(0); | ||
| 402 | } | 409 | } |
std/special/start.zig+6-16| ... | @@ -24,16 +24,6 @@ comptime { | ... | @@ -24,16 +24,6 @@ comptime { |
| 24 | } | 24 | } |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | fn enableSegfaultHandler() void { | ||
| 28 | const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler")) | ||
| 29 | root.enable_segfault_handler | ||
| 30 | else | ||
| 31 | std.debug.runtime_safety and std.debug.have_segfault_handling_support; | ||
| 32 | if (enable_segfault_handler) { | ||
| 33 | std.debug.attachSegfaultHandler(); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | extern fn wasm_freestanding_start() void { | 27 | extern fn wasm_freestanding_start() void { |
| 38 | _ = callMain(); | 28 | _ = callMain(); |
| 39 | } | 29 | } |
| ... | @@ -45,13 +35,13 @@ nakedcc fn _start() noreturn { | ... | @@ -45,13 +35,13 @@ nakedcc fn _start() noreturn { |
| 45 | 35 | ||
| 46 | switch (builtin.arch) { | 36 | switch (builtin.arch) { |
| 47 | .x86_64 => { | 37 | .x86_64 => { |
| 48 | argc_ptr = asm ("lea (%%rsp), %[argc]" | 38 | argc_ptr = asm ("" |
| 49 | : [argc] "=r" (-> [*]usize) | 39 | : [argc] "={rsp}" (-> [*]usize) |
| 50 | ); | 40 | ); |
| 51 | }, | 41 | }, |
| 52 | .i386 => { | 42 | .i386 => { |
| 53 | argc_ptr = asm ("lea (%%esp), %[argc]" | 43 | argc_ptr = asm ("" |
| 54 | : [argc] "=r" (-> [*]usize) | 44 | : [argc] "={esp}" (-> [*]usize) |
| 55 | ); | 45 | ); |
| 56 | }, | 46 | }, |
| 57 | .aarch64, .aarch64_be => { | 47 | .aarch64, .aarch64_be => { |
| ... | @@ -77,7 +67,7 @@ extern fn WinMainCRTStartup() noreturn { | ... | @@ -77,7 +67,7 @@ extern fn WinMainCRTStartup() noreturn { |
| 77 | _ = @import("start_windows_tls.zig"); | 67 | _ = @import("start_windows_tls.zig"); |
| 78 | } | 68 | } |
| 79 | 69 | ||
| 80 | enableSegfaultHandler(); | 70 | std.debug.maybeEnableSegfaultHandler(); |
| 81 | 71 | ||
| 82 | std.os.windows.kernel32.ExitProcess(callMain()); | 72 | std.os.windows.kernel32.ExitProcess(callMain()); |
| 83 | } | 73 | } |
| ... | @@ -118,7 +108,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { | ... | @@ -118,7 +108,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { |
| 118 | std.os.argv = argv[0..argc]; | 108 | std.os.argv = argv[0..argc]; |
| 119 | std.os.environ = envp; | 109 | std.os.environ = envp; |
| 120 | 110 | ||
| 121 | enableSegfaultHandler(); | 111 | std.debug.maybeEnableSegfaultHandler(); |
| 122 | 112 | ||
| 123 | return callMain(); | 113 | return callMain(); |
| 124 | } | 114 | } |
std/std.zig+1| ... | @@ -105,6 +105,7 @@ test "std" { | ... | @@ -105,6 +105,7 @@ test "std" { |
| 105 | _ = @import("packed_int_array.zig"); | 105 | _ = @import("packed_int_array.zig"); |
| 106 | _ = @import("priority_queue.zig"); | 106 | _ = @import("priority_queue.zig"); |
| 107 | _ = @import("rand.zig"); | 107 | _ = @import("rand.zig"); |
| 108 | _ = @import("rb.zig"); | ||
| 108 | _ = @import("sort.zig"); | 109 | _ = @import("sort.zig"); |
| 109 | _ = @import("testing.zig"); | 110 | _ = @import("testing.zig"); |
| 110 | _ = @import("thread.zig"); | 111 | _ = @import("thread.zig"); |
std/zig/ast.zig+109-100| ... | @@ -159,101 +159,99 @@ pub const Error = union(enum) { | ... | @@ -159,101 +159,99 @@ pub const Error = union(enum) { |
| 159 | 159 | ||
| 160 | pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { | 160 | pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { |
| 161 | switch (self.*) { | 161 | switch (self.*) { |
| 162 | // TODO https://github.com/ziglang/zig/issues/683 | 162 | .InvalidToken => |*x| return x.render(tokens, stream), |
| 163 | @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), | 163 | .ExpectedContainerMembers => |*x| return x.render(tokens, stream), |
| 164 | @TagType(Error).ExpectedContainerMembers => |*x| return x.render(tokens, stream), | 164 | .ExpectedStringLiteral => |*x| return x.render(tokens, stream), |
| 165 | @TagType(Error).ExpectedStringLiteral => |*x| return x.render(tokens, stream), | 165 | .ExpectedIntegerLiteral => |*x| return x.render(tokens, stream), |
| 166 | @TagType(Error).ExpectedIntegerLiteral => |*x| return x.render(tokens, stream), | 166 | .ExpectedPubItem => |*x| return x.render(tokens, stream), |
| 167 | @TagType(Error).ExpectedPubItem => |*x| return x.render(tokens, stream), | 167 | .ExpectedIdentifier => |*x| return x.render(tokens, stream), |
| 168 | @TagType(Error).ExpectedIdentifier => |*x| return x.render(tokens, stream), | 168 | .ExpectedStatement => |*x| return x.render(tokens, stream), |
| 169 | @TagType(Error).ExpectedStatement => |*x| return x.render(tokens, stream), | 169 | .ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), |
| 170 | @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), | 170 | .ExpectedVarDecl => |*x| return x.render(tokens, stream), |
| 171 | @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream), | 171 | .ExpectedReturnType => |*x| return x.render(tokens, stream), |
| 172 | @TagType(Error).ExpectedReturnType => |*x| return x.render(tokens, stream), | 172 | .ExpectedAggregateKw => |*x| return x.render(tokens, stream), |
| 173 | @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream), | 173 | .UnattachedDocComment => |*x| return x.render(tokens, stream), |
| 174 | @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream), | 174 | .ExpectedEqOrSemi => |*x| return x.render(tokens, stream), |
| 175 | @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream), | 175 | .ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream), |
| 176 | @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream), | 176 | .ExpectedSemiOrElse => |*x| return x.render(tokens, stream), |
| 177 | @TagType(Error).ExpectedSemiOrElse => |*x| return x.render(tokens, stream), | 177 | .ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream), |
| 178 | @TagType(Error).ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream), | 178 | .ExpectedLBrace => |*x| return x.render(tokens, stream), |
| 179 | @TagType(Error).ExpectedLBrace => |*x| return x.render(tokens, stream), | 179 | .ExpectedColonOrRParen => |*x| return x.render(tokens, stream), |
| 180 | @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream), | 180 | .ExpectedLabelable => |*x| return x.render(tokens, stream), |
| 181 | @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream), | 181 | .ExpectedInlinable => |*x| return x.render(tokens, stream), |
| 182 | @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream), | 182 | .ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream), |
| 183 | @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream), | 183 | .ExpectedCall => |*x| return x.render(tokens, stream), |
| 184 | @TagType(Error).ExpectedCall => |*x| return x.render(tokens, stream), | 184 | .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), |
| 185 | @TagType(Error).ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), | 185 | .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), |
| 186 | @TagType(Error).ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), | 186 | .ExtraAlignQualifier => |*x| return x.render(tokens, stream), |
| 187 | @TagType(Error).ExtraAlignQualifier => |*x| return x.render(tokens, stream), | 187 | .ExtraConstQualifier => |*x| return x.render(tokens, stream), |
| 188 | @TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream), | 188 | .ExtraVolatileQualifier => |*x| return x.render(tokens, stream), |
| 189 | @TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream), | 189 | .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), |
| 190 | @TagType(Error).ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), | 190 | .ExpectedTypeExpr => |*x| return x.render(tokens, stream), |
| 191 | @TagType(Error).ExpectedTypeExpr => |*x| return x.render(tokens, stream), | 191 | .ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream), |
| 192 | @TagType(Error).ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream), | 192 | .ExpectedParamType => |*x| return x.render(tokens, stream), |
| 193 | @TagType(Error).ExpectedParamType => |*x| return x.render(tokens, stream), | 193 | .ExpectedExpr => |*x| return x.render(tokens, stream), |
| 194 | @TagType(Error).ExpectedExpr => |*x| return x.render(tokens, stream), | 194 | .ExpectedPrimaryExpr => |*x| return x.render(tokens, stream), |
| 195 | @TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream), | 195 | .ExpectedToken => |*x| return x.render(tokens, stream), |
| 196 | @TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream), | 196 | .ExpectedCommaOrEnd => |*x| return x.render(tokens, stream), |
| 197 | @TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream), | 197 | .ExpectedParamList => |*x| return x.render(tokens, stream), |
| 198 | @TagType(Error).ExpectedParamList => |*x| return x.render(tokens, stream), | 198 | .ExpectedPayload => |*x| return x.render(tokens, stream), |
| 199 | @TagType(Error).ExpectedPayload => |*x| return x.render(tokens, stream), | 199 | .ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream), |
| 200 | @TagType(Error).ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream), | 200 | .ExpectedBlockOrExpression => |*x| return x.render(tokens, stream), |
| 201 | @TagType(Error).ExpectedBlockOrExpression => |*x| return x.render(tokens, stream), | 201 | .ExpectedExprOrAssignment => |*x| return x.render(tokens, stream), |
| 202 | @TagType(Error).ExpectedExprOrAssignment => |*x| return x.render(tokens, stream), | 202 | .ExpectedPrefixExpr => |*x| return x.render(tokens, stream), |
| 203 | @TagType(Error).ExpectedPrefixExpr => |*x| return x.render(tokens, stream), | 203 | .ExpectedLoopExpr => |*x| return x.render(tokens, stream), |
| 204 | @TagType(Error).ExpectedLoopExpr => |*x| return x.render(tokens, stream), | 204 | .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), |
| 205 | @TagType(Error).ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), | 205 | .ExpectedSuffixOp => |*x| return x.render(tokens, stream), |
| 206 | @TagType(Error).ExpectedSuffixOp => |*x| return x.render(tokens, stream), | ||
| 207 | } | 206 | } |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | pub fn loc(self: *const Error) TokenIndex { | 209 | pub fn loc(self: *const Error) TokenIndex { |
| 211 | switch (self.*) { | 210 | switch (self.*) { |
| 212 | // TODO https://github.com/ziglang/zig/issues/683 | 211 | .InvalidToken => |x| return x.token, |
| 213 | @TagType(Error).InvalidToken => |x| return x.token, | 212 | .ExpectedContainerMembers => |x| return x.token, |
| 214 | @TagType(Error).ExpectedContainerMembers => |x| return x.token, | 213 | .ExpectedStringLiteral => |x| return x.token, |
| 215 | @TagType(Error).ExpectedStringLiteral => |x| return x.token, | 214 | .ExpectedIntegerLiteral => |x| return x.token, |
| 216 | @TagType(Error).ExpectedIntegerLiteral => |x| return x.token, | 215 | .ExpectedPubItem => |x| return x.token, |
| 217 | @TagType(Error).ExpectedPubItem => |x| return x.token, | 216 | .ExpectedIdentifier => |x| return x.token, |
| 218 | @TagType(Error).ExpectedIdentifier => |x| return x.token, | 217 | .ExpectedStatement => |x| return x.token, |
| 219 | @TagType(Error).ExpectedStatement => |x| return x.token, | 218 | .ExpectedVarDeclOrFn => |x| return x.token, |
| 220 | @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, | 219 | .ExpectedVarDecl => |x| return x.token, |
| 221 | @TagType(Error).ExpectedVarDecl => |x| return x.token, | 220 | .ExpectedReturnType => |x| return x.token, |
| 222 | @TagType(Error).ExpectedReturnType => |x| return x.token, | 221 | .ExpectedAggregateKw => |x| return x.token, |
| 223 | @TagType(Error).ExpectedAggregateKw => |x| return x.token, | 222 | .UnattachedDocComment => |x| return x.token, |
| 224 | @TagType(Error).UnattachedDocComment => |x| return x.token, | 223 | .ExpectedEqOrSemi => |x| return x.token, |
| 225 | @TagType(Error).ExpectedEqOrSemi => |x| return x.token, | 224 | .ExpectedSemiOrLBrace => |x| return x.token, |
| 226 | @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token, | 225 | .ExpectedSemiOrElse => |x| return x.token, |
| 227 | @TagType(Error).ExpectedSemiOrElse => |x| return x.token, | 226 | .ExpectedLabelOrLBrace => |x| return x.token, |
| 228 | @TagType(Error).ExpectedLabelOrLBrace => |x| return x.token, | 227 | .ExpectedLBrace => |x| return x.token, |
| 229 | @TagType(Error).ExpectedLBrace => |x| return x.token, | 228 | .ExpectedColonOrRParen => |x| return x.token, |
| 230 | @TagType(Error).ExpectedColonOrRParen => |x| return x.token, | 229 | .ExpectedLabelable => |x| return x.token, |
| 231 | @TagType(Error).ExpectedLabelable => |x| return x.token, | 230 | .ExpectedInlinable => |x| return x.token, |
| 232 | @TagType(Error).ExpectedInlinable => |x| return x.token, | 231 | .ExpectedAsmOutputReturnOrType => |x| return x.token, |
| 233 | @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token, | 232 | .ExpectedCall => |x| return x.node.firstToken(), |
| 234 | @TagType(Error).ExpectedCall => |x| return x.node.firstToken(), | 233 | .ExpectedCallOrFnProto => |x| return x.node.firstToken(), |
| 235 | @TagType(Error).ExpectedCallOrFnProto => |x| return x.node.firstToken(), | 234 | .ExpectedSliceOrRBracket => |x| return x.token, |
| 236 | @TagType(Error).ExpectedSliceOrRBracket => |x| return x.token, | 235 | .ExtraAlignQualifier => |x| return x.token, |
| 237 | @TagType(Error).ExtraAlignQualifier => |x| return x.token, | 236 | .ExtraConstQualifier => |x| return x.token, |
| 238 | @TagType(Error).ExtraConstQualifier => |x| return x.token, | 237 | .ExtraVolatileQualifier => |x| return x.token, |
| 239 | @TagType(Error).ExtraVolatileQualifier => |x| return x.token, | 238 | .ExtraAllowZeroQualifier => |x| return x.token, |
| 240 | @TagType(Error).ExtraAllowZeroQualifier => |x| return x.token, | 239 | .ExpectedTypeExpr => |x| return x.token, |
| 241 | @TagType(Error).ExpectedTypeExpr => |x| return x.token, | 240 | .ExpectedPrimaryTypeExpr => |x| return x.token, |
| 242 | @TagType(Error).ExpectedPrimaryTypeExpr => |x| return x.token, | 241 | .ExpectedParamType => |x| return x.token, |
| 243 | @TagType(Error).ExpectedParamType => |x| return x.token, | 242 | .ExpectedExpr => |x| return x.token, |
| 244 | @TagType(Error).ExpectedExpr => |x| return x.token, | 243 | .ExpectedPrimaryExpr => |x| return x.token, |
| 245 | @TagType(Error).ExpectedPrimaryExpr => |x| return x.token, | 244 | .ExpectedToken => |x| return x.token, |
| 246 | @TagType(Error).ExpectedToken => |x| return x.token, | 245 | .ExpectedCommaOrEnd => |x| return x.token, |
| 247 | @TagType(Error).ExpectedCommaOrEnd => |x| return x.token, | 246 | .ExpectedParamList => |x| return x.token, |
| 248 | @TagType(Error).ExpectedParamList => |x| return x.token, | 247 | .ExpectedPayload => |x| return x.token, |
| 249 | @TagType(Error).ExpectedPayload => |x| return x.token, | 248 | .ExpectedBlockOrAssignment => |x| return x.token, |
| 250 | @TagType(Error).ExpectedBlockOrAssignment => |x| return x.token, | 249 | .ExpectedBlockOrExpression => |x| return x.token, |
| 251 | @TagType(Error).ExpectedBlockOrExpression => |x| return x.token, | 250 | .ExpectedExprOrAssignment => |x| return x.token, |
| 252 | @TagType(Error).ExpectedExprOrAssignment => |x| return x.token, | 251 | .ExpectedPrefixExpr => |x| return x.token, |
| 253 | @TagType(Error).ExpectedPrefixExpr => |x| return x.token, | 252 | .ExpectedLoopExpr => |x| return x.token, |
| 254 | @TagType(Error).ExpectedLoopExpr => |x| return x.token, | 253 | .ExpectedDerefOrUnwrap => |x| return x.token, |
| 255 | @TagType(Error).ExpectedDerefOrUnwrap => |x| return x.token, | 254 | .ExpectedSuffixOp => |x| return x.token, |
| 256 | @TagType(Error).ExpectedSuffixOp => |x| return x.token, | ||
| 257 | } | 255 | } |
| 258 | } | 256 | } |
| 259 | 257 | ||
| ... | @@ -320,8 +318,19 @@ pub const Error = union(enum) { | ... | @@ -320,8 +318,19 @@ pub const Error = union(enum) { |
| 320 | expected_id: Token.Id, | 318 | expected_id: Token.Id, |
| 321 | 319 | ||
| 322 | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { | 320 | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { |
| 323 | const token_name = @tagName(tokens.at(self.token).id); | 321 | const found_token = tokens.at(self.token); |
| 324 | return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name); | 322 | switch (found_token.id) { |
| 323 | .Invalid_ampersands => { | ||
| 324 | return stream.print("`&&` is invalid. Note that `and` is boolean AND."); | ||
| 325 | }, | ||
| 326 | .Invalid => { | ||
| 327 | return stream.print("expected {}, found invalid bytes", @tagName(self.expected_id)); | ||
| 328 | }, | ||
| 329 | else => { | ||
| 330 | const token_name = @tagName(found_token.id); | ||
| 331 | return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name); | ||
| 332 | }, | ||
| 333 | } | ||
| 325 | } | 334 | } |
| 326 | }; | 335 | }; |
| 327 | 336 | ||
| ... | @@ -1708,15 +1717,15 @@ pub const Node = struct { | ... | @@ -1708,15 +1717,15 @@ pub const Node = struct { |
| 1708 | i -= 1; | 1717 | i -= 1; |
| 1709 | 1718 | ||
| 1710 | switch (self.op) { | 1719 | switch (self.op) { |
| 1711 | @TagType(Op).Call => |*call_info| { | 1720 | .Call => |*call_info| { |
| 1712 | if (i < call_info.params.len) return call_info.params.at(i).*; | 1721 | if (i < call_info.params.len) return call_info.params.at(i).*; |
| 1713 | i -= call_info.params.len; | 1722 | i -= call_info.params.len; |
| 1714 | }, | 1723 | }, |
| 1715 | Op.ArrayAccess => |index_expr| { | 1724 | .ArrayAccess => |index_expr| { |
| 1716 | if (i < 1) return index_expr; | 1725 | if (i < 1) return index_expr; |
| 1717 | i -= 1; | 1726 | i -= 1; |
| 1718 | }, | 1727 | }, |
| 1719 | @TagType(Op).Slice => |range| { | 1728 | .Slice => |range| { |
| 1720 | if (i < 1) return range.start; | 1729 | if (i < 1) return range.start; |
| 1721 | i -= 1; | 1730 | i -= 1; |
| 1722 | 1731 | ||
| ... | @@ -1725,16 +1734,16 @@ pub const Node = struct { | ... | @@ -1725,16 +1734,16 @@ pub const Node = struct { |
| 1725 | i -= 1; | 1734 | i -= 1; |
| 1726 | } | 1735 | } |
| 1727 | }, | 1736 | }, |
| 1728 | Op.ArrayInitializer => |*exprs| { | 1737 | .ArrayInitializer => |*exprs| { |
| 1729 | if (i < exprs.len) return exprs.at(i).*; | 1738 | if (i < exprs.len) return exprs.at(i).*; |
| 1730 | i -= exprs.len; | 1739 | i -= exprs.len; |
| 1731 | }, | 1740 | }, |
| 1732 | Op.StructInitializer => |*fields| { | 1741 | .StructInitializer => |*fields| { |
| 1733 | if (i < fields.len) return fields.at(i).*; | 1742 | if (i < fields.len) return fields.at(i).*; |
| 1734 | i -= fields.len; | 1743 | i -= fields.len; |
| 1735 | }, | 1744 | }, |
| 1736 | Op.UnwrapOptional, | 1745 | .UnwrapOptional, |
| 1737 | Op.Deref, | 1746 | .Deref, |
| 1738 | => {}, | 1747 | => {}, |
| 1739 | } | 1748 | } |
| 1740 | 1749 | ||
| ... | @@ -1743,7 +1752,7 @@ pub const Node = struct { | ... | @@ -1743,7 +1752,7 @@ pub const Node = struct { |
| 1743 | 1752 | ||
| 1744 | pub fn firstToken(self: *const SuffixOp) TokenIndex { | 1753 | pub fn firstToken(self: *const SuffixOp) TokenIndex { |
| 1745 | switch (self.op) { | 1754 | switch (self.op) { |
| 1746 | @TagType(Op).Call => |*call_info| if (call_info.async_attr) |async_attr| return async_attr.firstToken(), | 1755 | .Call => |*call_info| if (call_info.async_attr) |async_attr| return async_attr.firstToken(), |
| 1747 | else => {}, | 1756 | else => {}, |
| 1748 | } | 1757 | } |
| 1749 | return self.lhs.firstToken(); | 1758 | return self.lhs.firstToken(); |
std/zig/parse.zig+1-1| ... | @@ -774,7 +774,7 @@ fn parseBoolAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node | ... | @@ -774,7 +774,7 @@ fn parseBoolAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 774 | arena, | 774 | arena, |
| 775 | it, | 775 | it, |
| 776 | tree, | 776 | tree, |
| 777 | SimpleBinOpParseFn(.Keyword_and, Node.InfixOp.Op.BoolAnd), | 777 | SimpleBinOpParseFn(.Keyword_and, .BoolAnd), |
| 778 | parseCompareExpr, | 778 | parseCompareExpr, |
| 779 | .Infinitely, | 779 | .Infinitely, |
| 780 | ); | 780 | ); |
std/zig/parser_test.zig+26| ... | @@ -2267,6 +2267,32 @@ test "zig fmt: file ends with struct field" { | ... | @@ -2267,6 +2267,32 @@ test "zig fmt: file ends with struct field" { |
| 2267 | ); | 2267 | ); |
| 2268 | } | 2268 | } |
| 2269 | 2269 | ||
| 2270 | test "zig fmt: comments at several places in struct init" { | ||
| 2271 | try testTransform( | ||
| 2272 | \\var bar = Bar{ | ||
| 2273 | \\ .x = 10, // test | ||
| 2274 | \\ .y = "test" | ||
| 2275 | \\ // test | ||
| 2276 | \\}; | ||
| 2277 | \\ | ||
| 2278 | , | ||
| 2279 | \\var bar = Bar{ | ||
| 2280 | \\ .x = 10, // test | ||
| 2281 | \\ .y = "test", // test | ||
| 2282 | \\}; | ||
| 2283 | \\ | ||
| 2284 | ); | ||
| 2285 | |||
| 2286 | try testCanonical( | ||
| 2287 | \\var bar = Bar{ // test | ||
| 2288 | \\ .x = 10, // test | ||
| 2289 | \\ .y = "test", | ||
| 2290 | \\ // test | ||
| 2291 | \\}; | ||
| 2292 | \\ | ||
| 2293 | ); | ||
| 2294 | } | ||
| 2295 | |||
| 2270 | const std = @import("std"); | 2296 | const std = @import("std"); |
| 2271 | const mem = std.mem; | 2297 | const mem = std.mem; |
| 2272 | const warn = std.debug.warn; | 2298 | const warn = std.debug.warn; |
std/zig/render.zig+7-1| ... | @@ -2020,7 +2020,13 @@ fn renderTokenOffset( | ... | @@ -2020,7 +2020,13 @@ fn renderTokenOffset( |
| 2020 | 2020 | ||
| 2021 | const after_comment_token = tree.tokens.at(token_index + offset); | 2021 | const after_comment_token = tree.tokens.at(token_index + offset); |
| 2022 | const next_line_indent = switch (after_comment_token.id) { | 2022 | const next_line_indent = switch (after_comment_token.id) { |
| 2023 | Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent - indent_delta, | 2023 | Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => blk: { |
| 2024 | if (indent > indent_delta) { | ||
| 2025 | break :blk indent - indent_delta; | ||
| 2026 | } else { | ||
| 2027 | break :blk 0; | ||
| 2028 | } | ||
| 2029 | }, | ||
| 2024 | else => indent, | 2030 | else => indent, |
| 2025 | }; | 2031 | }; |
| 2026 | try stream.writeByteNTimes(' ', next_line_indent); | 2032 | try stream.writeByteNTimes(' ', next_line_indent); |
std/zig/tokenizer.zig+6| ... | @@ -77,6 +77,7 @@ pub const Token = struct { | ... | @@ -77,6 +77,7 @@ pub const Token = struct { |
| 77 | 77 | ||
| 78 | pub const Id = enum { | 78 | pub const Id = enum { |
| 79 | Invalid, | 79 | Invalid, |
| 80 | Invalid_ampersands, | ||
| 80 | Identifier, | 81 | Identifier, |
| 81 | StringLiteral, | 82 | StringLiteral, |
| 82 | MultilineStringLiteralLine, | 83 | MultilineStringLiteralLine, |
| ... | @@ -484,6 +485,11 @@ pub const Tokenizer = struct { | ... | @@ -484,6 +485,11 @@ pub const Tokenizer = struct { |
| 484 | }, | 485 | }, |
| 485 | 486 | ||
| 486 | State.Ampersand => switch (c) { | 487 | State.Ampersand => switch (c) { |
| 488 | '&' => { | ||
| 489 | result.id = Token.Id.Invalid_ampersands; | ||
| 490 | self.index += 1; | ||
| 491 | break; | ||
| 492 | }, | ||
| 487 | '=' => { | 493 | '=' => { |
| 488 | result.id = Token.Id.AmpersandEqual; | 494 | result.id = Token.Id.AmpersandEqual; |
| 489 | self.index += 1; | 495 | self.index += 1; |
test/compile_errors.zig+9-9| ... | @@ -201,7 +201,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -201,7 +201,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 201 | \\ return error.OutOfMemory; | 201 | \\ return error.OutOfMemory; |
| 202 | \\} | 202 | \\} |
| 203 | , | 203 | , |
| 204 | "tmp.zig:2:7: error: error is discarded", | 204 | "tmp.zig:2:12: error: error is discarded", |
| 205 | ); | 205 | ); |
| 206 | 206 | ||
| 207 | cases.add( | 207 | cases.add( |
| ... | @@ -234,7 +234,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -234,7 +234,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 234 | 234 | ||
| 235 | cases.add( | 235 | cases.add( |
| 236 | "usingnamespace with wrong type", | 236 | "usingnamespace with wrong type", |
| 237 | \\use void; | 237 | \\usingnamespace void; |
| 238 | , | 238 | , |
| 239 | "tmp.zig:1:1: error: expected struct, enum, or union; found 'void'", | 239 | "tmp.zig:1:1: error: expected struct, enum, or union; found 'void'", |
| 240 | ); | 240 | ); |
| ... | @@ -2740,7 +2740,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2740,7 +2740,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2740 | \\ 3 = 3; | 2740 | \\ 3 = 3; |
| 2741 | \\} | 2741 | \\} |
| 2742 | , | 2742 | , |
| 2743 | "tmp.zig:2:7: error: cannot assign to constant", | 2743 | "tmp.zig:2:9: error: cannot assign to constant", |
| 2744 | ); | 2744 | ); |
| 2745 | 2745 | ||
| 2746 | cases.add( | 2746 | cases.add( |
| ... | @@ -2750,7 +2750,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2750,7 +2750,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2750 | \\ a = 4; | 2750 | \\ a = 4; |
| 2751 | \\} | 2751 | \\} |
| 2752 | , | 2752 | , |
| 2753 | "tmp.zig:3:7: error: cannot assign to constant", | 2753 | "tmp.zig:3:9: error: cannot assign to constant", |
| 2754 | ); | 2754 | ); |
| 2755 | 2755 | ||
| 2756 | cases.add( | 2756 | cases.add( |
| ... | @@ -2820,7 +2820,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2820,7 +2820,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2820 | \\} | 2820 | \\} |
| 2821 | \\export fn entry() void { f(); } | 2821 | \\export fn entry() void { f(); } |
| 2822 | , | 2822 | , |
| 2823 | "tmp.zig:3:7: error: cannot assign to constant", | 2823 | "tmp.zig:3:9: error: cannot assign to constant", |
| 2824 | ); | 2824 | ); |
| 2825 | 2825 | ||
| 2826 | cases.add( | 2826 | cases.add( |
| ... | @@ -3883,7 +3883,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -3883,7 +3883,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3883 | \\ | 3883 | \\ |
| 3884 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | 3884 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } |
| 3885 | , | 3885 | , |
| 3886 | "tmp.zig:6:24: error: unable to evaluate constant expression", | 3886 | "tmp.zig:6:26: error: unable to evaluate constant expression", |
| 3887 | "tmp.zig:4:17: note: called from here", | 3887 | "tmp.zig:4:17: note: called from here", |
| 3888 | ); | 3888 | ); |
| 3889 | 3889 | ||
| ... | @@ -4133,7 +4133,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4133,7 +4133,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4133 | \\ cstr[0] = 'W'; | 4133 | \\ cstr[0] = 'W'; |
| 4134 | \\} | 4134 | \\} |
| 4135 | , | 4135 | , |
| 4136 | "tmp.zig:3:11: error: cannot assign to constant", | 4136 | "tmp.zig:3:13: error: cannot assign to constant", |
| 4137 | ); | 4137 | ); |
| 4138 | 4138 | ||
| 4139 | cases.add( | 4139 | cases.add( |
| ... | @@ -4143,7 +4143,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4143,7 +4143,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4143 | \\ cstr[0] = 'W'; | 4143 | \\ cstr[0] = 'W'; |
| 4144 | \\} | 4144 | \\} |
| 4145 | , | 4145 | , |
| 4146 | "tmp.zig:3:11: error: cannot assign to constant", | 4146 | "tmp.zig:3:13: error: cannot assign to constant", |
| 4147 | ); | 4147 | ); |
| 4148 | 4148 | ||
| 4149 | cases.add( | 4149 | cases.add( |
| ... | @@ -4291,7 +4291,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -4291,7 +4291,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4291 | \\ f.field = 0; | 4291 | \\ f.field = 0; |
| 4292 | \\} | 4292 | \\} |
| 4293 | , | 4293 | , |
| 4294 | "tmp.zig:6:13: error: cannot assign to constant", | 4294 | "tmp.zig:6:15: error: cannot assign to constant", |
| 4295 | ); | 4295 | ); |
| 4296 | 4296 | ||
| 4297 | cases.add( | 4297 | cases.add( |
test/stage1/behavior.zig+1| ... | @@ -93,6 +93,7 @@ comptime { | ... | @@ -93,6 +93,7 @@ comptime { |
| 93 | _ = @import("behavior/undefined.zig"); | 93 | _ = @import("behavior/undefined.zig"); |
| 94 | _ = @import("behavior/underscore.zig"); | 94 | _ = @import("behavior/underscore.zig"); |
| 95 | _ = @import("behavior/union.zig"); | 95 | _ = @import("behavior/union.zig"); |
| 96 | _ = @import("behavior/usingnamespace.zig"); | ||
| 96 | _ = @import("behavior/var_args.zig"); | 97 | _ = @import("behavior/var_args.zig"); |
| 97 | _ = @import("behavior/vector.zig"); | 98 | _ = @import("behavior/vector.zig"); |
| 98 | _ = @import("behavior/void.zig"); | 99 | _ = @import("behavior/void.zig"); |
test/stage1/behavior/atomics.zig+31| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 3 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| ... | @@ -69,3 +70,33 @@ test "cmpxchg with ptr" { | ... | @@ -69,3 +70,33 @@ test "cmpxchg with ptr" { |
| 69 | expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | 70 | expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); |
| 70 | expect(x == &data2); | 71 | expect(x == &data2); |
| 71 | } | 72 | } |
| 73 | |||
| 74 | // TODO this test is disabled until this issue is resolved: | ||
| 75 | // https://github.com/ziglang/zig/issues/2883 | ||
| 76 | // otherwise cross compiling will result in: | ||
| 77 | // lld: error: undefined symbol: __sync_val_compare_and_swap_16 | ||
| 78 | //test "128-bit cmpxchg" { | ||
| 79 | // var x: u128 align(16) = 1234; // TODO: https://github.com/ziglang/zig/issues/2987 | ||
| 80 | // if (@cmpxchgWeak(u128, &x, 99, 5678, .SeqCst, .SeqCst)) |x1| { | ||
| 81 | // expect(x1 == 1234); | ||
| 82 | // } else { | ||
| 83 | // @panic("cmpxchg should have failed"); | ||
| 84 | // } | ||
| 85 | // | ||
| 86 | // while (@cmpxchgWeak(u128, &x, 1234, 5678, .SeqCst, .SeqCst)) |x1| { | ||
| 87 | // expect(x1 == 1234); | ||
| 88 | // } | ||
| 89 | // expect(x == 5678); | ||
| 90 | // | ||
| 91 | // expect(@cmpxchgStrong(u128, &x, 5678, 42, .SeqCst, .SeqCst) == null); | ||
| 92 | // expect(x == 42); | ||
| 93 | //} | ||
| 94 | |||
| 95 | test "cmpxchg with ignored result" { | ||
| 96 | var x: i32 = 1234; | ||
| 97 | var ptr = &x; | ||
| 98 | |||
| 99 | _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic); | ||
| 100 | |||
| 101 | expectEqual(i32(5678), x); | ||
| 102 | } |
test/stage1/behavior/eval.zig+10| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 3 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| 4 | 5 | ||
| 5 | test "compile time recursion" { | 6 | test "compile time recursion" { |
| ... | @@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" { | ... | @@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" { |
| 794 | lol_this_doesnt_exist = nonsense; | 795 | lol_this_doesnt_exist = nonsense; |
| 795 | } | 796 | } |
| 796 | } | 797 | } |
| 798 | |||
| 799 | test "comptime assign int to optional int" { | ||
| 800 | comptime { | ||
| 801 | var x: ?i32 = null; | ||
| 802 | x = 2; | ||
| 803 | x.? *= 10; | ||
| 804 | expectEqual(20, x.?); | ||
| 805 | } | ||
| 806 | } |
test/stage1/behavior/fn.zig+19| ... | @@ -228,3 +228,22 @@ test "implicit cast fn call result to optional in field result" { | ... | @@ -228,3 +228,22 @@ test "implicit cast fn call result to optional in field result" { |
| 228 | S.entry(); | 228 | S.entry(); |
| 229 | comptime S.entry(); | 229 | comptime S.entry(); |
| 230 | } | 230 | } |
| 231 | |||
| 232 | test "discard the result of a function that returns a struct" { | ||
| 233 | const S = struct { | ||
| 234 | fn entry() void { | ||
| 235 | _ = func(); | ||
| 236 | } | ||
| 237 | |||
| 238 | fn func() Foo { | ||
| 239 | return undefined; | ||
| 240 | } | ||
| 241 | |||
| 242 | const Foo = struct { | ||
| 243 | a: u64, | ||
| 244 | b: u64, | ||
| 245 | }; | ||
| 246 | }; | ||
| 247 | S.entry(); | ||
| 248 | comptime S.entry(); | ||
| 249 | } |
test/stage1/behavior/usingnamespace.zig created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | fn Foo(comptime T: type) type { | ||
| 4 | return struct { | ||
| 5 | usingnamespace T; | ||
| 6 | }; | ||
| 7 | } | ||
| 8 | |||
| 9 | test "usingnamespace inside a generic struct" { | ||
| 10 | const std2 = Foo(std); | ||
| 11 | const testing2 = Foo(std.testing); | ||
| 12 | std2.testing.expect(true); | ||
| 13 | testing2.expect(true); | ||
| 14 | } | ||
test/stage1/behavior/vector.zig+6| ... | @@ -74,3 +74,9 @@ test "implicit cast vector to array" { | ... | @@ -74,3 +74,9 @@ test "implicit cast vector to array" { |
| 74 | S.doTheTest(); | 74 | S.doTheTest(); |
| 75 | comptime S.doTheTest(); | 75 | comptime S.doTheTest(); |
| 76 | } | 76 | } |
| 77 | |||
| 78 | test "array to vector" { | ||
| 79 | var foo: f32 = 3.14; | ||
| 80 | var arr = [4]f32{ foo, 1.5, 0.0, 0.0 }; | ||
| 81 | var vec: @Vector(4, f32) = arr; | ||
| 82 | } |
test/translate_c.zig+34| ... | @@ -1780,6 +1780,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1780,6 +1780,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1780 | \\} | 1780 | \\} |
| 1781 | ); | 1781 | ); |
| 1782 | 1782 | ||
| 1783 | cases.addC("escape sequences", | ||
| 1784 | \\const char *escapes() { | ||
| 1785 | \\char a = '\'', | ||
| 1786 | \\ b = '\\', | ||
| 1787 | \\ c = '\a', | ||
| 1788 | \\ d = '\b', | ||
| 1789 | \\ e = '\f', | ||
| 1790 | \\ f = '\n', | ||
| 1791 | \\ g = '\r', | ||
| 1792 | \\ h = '\t', | ||
| 1793 | \\ i = '\v', | ||
| 1794 | \\ j = '\0', | ||
| 1795 | \\ k = '\"'; | ||
| 1796 | \\ return "\'\\\a\b\f\n\r\t\v\0\""; | ||
| 1797 | \\} | ||
| 1798 | \\ | ||
| 1799 | , | ||
| 1800 | \\pub export fn escapes() [*c]const u8 { | ||
| 1801 | \\ var a: u8 = u8('\''); | ||
| 1802 | \\ var b: u8 = u8('\\'); | ||
| 1803 | \\ var c: u8 = u8('\x07'); | ||
| 1804 | \\ var d: u8 = u8('\x08'); | ||
| 1805 | \\ var e: u8 = u8('\x0c'); | ||
| 1806 | \\ var f: u8 = u8('\n'); | ||
| 1807 | \\ var g: u8 = u8('\r'); | ||
| 1808 | \\ var h: u8 = u8('\t'); | ||
| 1809 | \\ var i: u8 = u8('\x0b'); | ||
| 1810 | \\ var j: u8 = u8('\x00'); | ||
| 1811 | \\ var k: u8 = u8('\"'); | ||
| 1812 | \\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\""; | ||
| 1813 | \\} | ||
| 1814 | \\ | ||
| 1815 | ); | ||
| 1816 | |||
| 1783 | /////////////// Cases for only stage1 because stage2 behavior is better //////////////// | 1817 | /////////////// Cases for only stage1 because stage2 behavior is better //////////////// |
| 1784 | cases.addC("Parameterless function prototypes", | 1818 | cases.addC("Parameterless function prototypes", |
| 1785 | \\void foo() {} | 1819 | \\void foo() {} |