| 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 | 209 | else() |
| 210 | 210 | set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment") |
| 211 | 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 | 213 | endif() |
| 214 | 214 | endif() |
| 215 | 215 | set_target_properties(embedded_lld_lib PROPERTIES |
| ... | ... | @@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3") |
| 511 | 511 | |
| 512 | 512 | set(EXE_LDFLAGS " ") |
| 513 | 513 | if(MSVC) |
| 514 | set(EXE_LDFLAGS "/STACK:16777216") | |
| 514 | set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216") | |
| 515 | 515 | elseif(MINGW) |
| 516 | 516 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216") |
| 517 | 517 | endif() |
| 518 | 518 | |
| 519 | 519 | if(ZIG_STATIC) |
| 520 | 520 | if(APPLE) |
| 521 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++") | |
| 521 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++") | |
| 522 | 522 | elseif(MINGW) |
| 523 | set(EXE_LDFLAGS "-static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -lz3 -lz -lgomp -Wl,--no-whole-archive") | |
| 524 | else() | |
| 525 | set(EXE_LDFLAGS "-static") | |
| 523 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic, -lwinpthread -lz3 -lz -lgomp") | |
| 524 | elseif(NOT MSVC) | |
| 525 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -static") | |
| 526 | 526 | endif() |
| 527 | else() | |
| 528 | if(MINGW) | |
| 529 | set(EXE_LDFLAGS "${EXE_LDFLAGS} -lz3") | |
| 530 | endif() | |
| 527 | 531 | endif() |
| 528 | 532 | |
| 529 | 533 | if(ZIG_TEST_COVERAGE) |
| ... | ... | @@ -559,11 +563,6 @@ if(NOT MSVC) |
| 559 | 563 | target_link_libraries(compiler LINK_PUBLIC ${LIBXML2}) |
| 560 | 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 | 566 | if(ZIG_DIA_GUIDS_LIB) |
| 568 | 567 | target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) |
| 569 | 568 | endif() |
doc/docgen.zig+118-118| ... | ... | @@ -742,101 +742,101 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok |
| 742 | 742 | const token = tokenizer.next(); |
| 743 | 743 | try writeEscaped(out, src[index..token.start]); |
| 744 | 744 | switch (token.id) { |
| 745 | std.zig.Token.Id.Eof => break, | |
| 746 | ||
| 747 | std.zig.Token.Id.Keyword_align, | |
| 748 | std.zig.Token.Id.Keyword_and, | |
| 749 | std.zig.Token.Id.Keyword_asm, | |
| 750 | std.zig.Token.Id.Keyword_async, | |
| 751 | std.zig.Token.Id.Keyword_await, | |
| 752 | std.zig.Token.Id.Keyword_break, | |
| 753 | std.zig.Token.Id.Keyword_cancel, | |
| 754 | std.zig.Token.Id.Keyword_catch, | |
| 755 | std.zig.Token.Id.Keyword_comptime, | |
| 756 | std.zig.Token.Id.Keyword_const, | |
| 757 | std.zig.Token.Id.Keyword_continue, | |
| 758 | std.zig.Token.Id.Keyword_defer, | |
| 759 | std.zig.Token.Id.Keyword_else, | |
| 760 | std.zig.Token.Id.Keyword_enum, | |
| 761 | std.zig.Token.Id.Keyword_errdefer, | |
| 762 | std.zig.Token.Id.Keyword_error, | |
| 763 | std.zig.Token.Id.Keyword_export, | |
| 764 | std.zig.Token.Id.Keyword_extern, | |
| 765 | std.zig.Token.Id.Keyword_for, | |
| 766 | std.zig.Token.Id.Keyword_if, | |
| 767 | std.zig.Token.Id.Keyword_inline, | |
| 768 | std.zig.Token.Id.Keyword_nakedcc, | |
| 769 | std.zig.Token.Id.Keyword_noalias, | |
| 770 | std.zig.Token.Id.Keyword_or, | |
| 771 | std.zig.Token.Id.Keyword_orelse, | |
| 772 | std.zig.Token.Id.Keyword_packed, | |
| 773 | std.zig.Token.Id.Keyword_promise, | |
| 774 | std.zig.Token.Id.Keyword_pub, | |
| 775 | std.zig.Token.Id.Keyword_resume, | |
| 776 | std.zig.Token.Id.Keyword_return, | |
| 777 | std.zig.Token.Id.Keyword_linksection, | |
| 778 | std.zig.Token.Id.Keyword_stdcallcc, | |
| 779 | std.zig.Token.Id.Keyword_struct, | |
| 780 | std.zig.Token.Id.Keyword_suspend, | |
| 781 | std.zig.Token.Id.Keyword_switch, | |
| 782 | std.zig.Token.Id.Keyword_test, | |
| 783 | std.zig.Token.Id.Keyword_threadlocal, | |
| 784 | std.zig.Token.Id.Keyword_try, | |
| 785 | std.zig.Token.Id.Keyword_union, | |
| 786 | std.zig.Token.Id.Keyword_unreachable, | |
| 787 | std.zig.Token.Id.Keyword_usingnamespace, | |
| 788 | std.zig.Token.Id.Keyword_var, | |
| 789 | std.zig.Token.Id.Keyword_volatile, | |
| 790 | std.zig.Token.Id.Keyword_allowzero, | |
| 791 | std.zig.Token.Id.Keyword_while, | |
| 745 | .Eof => break, | |
| 746 | ||
| 747 | .Keyword_align, | |
| 748 | .Keyword_and, | |
| 749 | .Keyword_asm, | |
| 750 | .Keyword_async, | |
| 751 | .Keyword_await, | |
| 752 | .Keyword_break, | |
| 753 | .Keyword_cancel, | |
| 754 | .Keyword_catch, | |
| 755 | .Keyword_comptime, | |
| 756 | .Keyword_const, | |
| 757 | .Keyword_continue, | |
| 758 | .Keyword_defer, | |
| 759 | .Keyword_else, | |
| 760 | .Keyword_enum, | |
| 761 | .Keyword_errdefer, | |
| 762 | .Keyword_error, | |
| 763 | .Keyword_export, | |
| 764 | .Keyword_extern, | |
| 765 | .Keyword_for, | |
| 766 | .Keyword_if, | |
| 767 | .Keyword_inline, | |
| 768 | .Keyword_nakedcc, | |
| 769 | .Keyword_noalias, | |
| 770 | .Keyword_or, | |
| 771 | .Keyword_orelse, | |
| 772 | .Keyword_packed, | |
| 773 | .Keyword_promise, | |
| 774 | .Keyword_pub, | |
| 775 | .Keyword_resume, | |
| 776 | .Keyword_return, | |
| 777 | .Keyword_linksection, | |
| 778 | .Keyword_stdcallcc, | |
| 779 | .Keyword_struct, | |
| 780 | .Keyword_suspend, | |
| 781 | .Keyword_switch, | |
| 782 | .Keyword_test, | |
| 783 | .Keyword_threadlocal, | |
| 784 | .Keyword_try, | |
| 785 | .Keyword_union, | |
| 786 | .Keyword_unreachable, | |
| 787 | .Keyword_usingnamespace, | |
| 788 | .Keyword_var, | |
| 789 | .Keyword_volatile, | |
| 790 | .Keyword_allowzero, | |
| 791 | .Keyword_while, | |
| 792 | 792 | => { |
| 793 | 793 | try out.write("<span class=\"tok-kw\">"); |
| 794 | 794 | try writeEscaped(out, src[token.start..token.end]); |
| 795 | 795 | try out.write("</span>"); |
| 796 | 796 | }, |
| 797 | 797 | |
| 798 | std.zig.Token.Id.Keyword_fn => { | |
| 798 | .Keyword_fn => { | |
| 799 | 799 | try out.write("<span class=\"tok-kw\">"); |
| 800 | 800 | try writeEscaped(out, src[token.start..token.end]); |
| 801 | 801 | try out.write("</span>"); |
| 802 | 802 | next_tok_is_fn = true; |
| 803 | 803 | }, |
| 804 | 804 | |
| 805 | std.zig.Token.Id.Keyword_undefined, | |
| 806 | std.zig.Token.Id.Keyword_null, | |
| 807 | std.zig.Token.Id.Keyword_true, | |
| 808 | std.zig.Token.Id.Keyword_false, | |
| 805 | .Keyword_undefined, | |
| 806 | .Keyword_null, | |
| 807 | .Keyword_true, | |
| 808 | .Keyword_false, | |
| 809 | 809 | => { |
| 810 | 810 | try out.write("<span class=\"tok-null\">"); |
| 811 | 811 | try writeEscaped(out, src[token.start..token.end]); |
| 812 | 812 | try out.write("</span>"); |
| 813 | 813 | }, |
| 814 | 814 | |
| 815 | std.zig.Token.Id.StringLiteral, | |
| 816 | std.zig.Token.Id.MultilineStringLiteralLine, | |
| 817 | std.zig.Token.Id.CharLiteral, | |
| 815 | .StringLiteral, | |
| 816 | .MultilineStringLiteralLine, | |
| 817 | .CharLiteral, | |
| 818 | 818 | => { |
| 819 | 819 | try out.write("<span class=\"tok-str\">"); |
| 820 | 820 | try writeEscaped(out, src[token.start..token.end]); |
| 821 | 821 | try out.write("</span>"); |
| 822 | 822 | }, |
| 823 | 823 | |
| 824 | std.zig.Token.Id.Builtin => { | |
| 824 | .Builtin => { | |
| 825 | 825 | try out.write("<span class=\"tok-builtin\">"); |
| 826 | 826 | try writeEscaped(out, src[token.start..token.end]); |
| 827 | 827 | try out.write("</span>"); |
| 828 | 828 | }, |
| 829 | 829 | |
| 830 | std.zig.Token.Id.LineComment, | |
| 831 | std.zig.Token.Id.DocComment, | |
| 832 | std.zig.Token.Id.ShebangLine, | |
| 830 | .LineComment, | |
| 831 | .DocComment, | |
| 832 | .ShebangLine, | |
| 833 | 833 | => { |
| 834 | 834 | try out.write("<span class=\"tok-comment\">"); |
| 835 | 835 | try writeEscaped(out, src[token.start..token.end]); |
| 836 | 836 | try out.write("</span>"); |
| 837 | 837 | }, |
| 838 | 838 | |
| 839 | std.zig.Token.Id.Identifier => { | |
| 839 | .Identifier => { | |
| 840 | 840 | if (prev_tok_was_fn) { |
| 841 | 841 | try out.write("<span class=\"tok-fn\">"); |
| 842 | 842 | try writeEscaped(out, src[token.start..token.end]); |
| ... | ... | @@ -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, | |
| 868 | std.zig.Token.Id.FloatLiteral, | |
| 867 | .IntegerLiteral, | |
| 868 | .FloatLiteral, | |
| 869 | 869 | => { |
| 870 | 870 | try out.write("<span class=\"tok-number\">"); |
| 871 | 871 | try writeEscaped(out, src[token.start..token.end]); |
| 872 | 872 | try out.write("</span>"); |
| 873 | 873 | }, |
| 874 | 874 | |
| 875 | std.zig.Token.Id.Bang, | |
| 876 | std.zig.Token.Id.Pipe, | |
| 877 | std.zig.Token.Id.PipePipe, | |
| 878 | std.zig.Token.Id.PipeEqual, | |
| 879 | std.zig.Token.Id.Equal, | |
| 880 | std.zig.Token.Id.EqualEqual, | |
| 881 | std.zig.Token.Id.EqualAngleBracketRight, | |
| 882 | std.zig.Token.Id.BangEqual, | |
| 883 | std.zig.Token.Id.LParen, | |
| 884 | std.zig.Token.Id.RParen, | |
| 885 | std.zig.Token.Id.Semicolon, | |
| 886 | std.zig.Token.Id.Percent, | |
| 887 | std.zig.Token.Id.PercentEqual, | |
| 888 | std.zig.Token.Id.LBrace, | |
| 889 | std.zig.Token.Id.RBrace, | |
| 890 | std.zig.Token.Id.LBracket, | |
| 891 | std.zig.Token.Id.RBracket, | |
| 892 | std.zig.Token.Id.Period, | |
| 893 | std.zig.Token.Id.Ellipsis2, | |
| 894 | std.zig.Token.Id.Ellipsis3, | |
| 895 | std.zig.Token.Id.Caret, | |
| 896 | std.zig.Token.Id.CaretEqual, | |
| 897 | std.zig.Token.Id.Plus, | |
| 898 | std.zig.Token.Id.PlusPlus, | |
| 899 | std.zig.Token.Id.PlusEqual, | |
| 900 | std.zig.Token.Id.PlusPercent, | |
| 901 | std.zig.Token.Id.PlusPercentEqual, | |
| 902 | std.zig.Token.Id.Minus, | |
| 903 | std.zig.Token.Id.MinusEqual, | |
| 904 | std.zig.Token.Id.MinusPercent, | |
| 905 | std.zig.Token.Id.MinusPercentEqual, | |
| 906 | std.zig.Token.Id.Asterisk, | |
| 907 | std.zig.Token.Id.AsteriskEqual, | |
| 908 | std.zig.Token.Id.AsteriskAsterisk, | |
| 909 | std.zig.Token.Id.AsteriskPercent, | |
| 910 | std.zig.Token.Id.AsteriskPercentEqual, | |
| 911 | std.zig.Token.Id.Arrow, | |
| 912 | std.zig.Token.Id.Colon, | |
| 913 | std.zig.Token.Id.Slash, | |
| 914 | std.zig.Token.Id.SlashEqual, | |
| 915 | std.zig.Token.Id.Comma, | |
| 916 | std.zig.Token.Id.Ampersand, | |
| 917 | std.zig.Token.Id.AmpersandEqual, | |
| 918 | std.zig.Token.Id.QuestionMark, | |
| 919 | std.zig.Token.Id.AngleBracketLeft, | |
| 920 | std.zig.Token.Id.AngleBracketLeftEqual, | |
| 921 | std.zig.Token.Id.AngleBracketAngleBracketLeft, | |
| 922 | std.zig.Token.Id.AngleBracketAngleBracketLeftEqual, | |
| 923 | std.zig.Token.Id.AngleBracketRight, | |
| 924 | std.zig.Token.Id.AngleBracketRightEqual, | |
| 925 | std.zig.Token.Id.AngleBracketAngleBracketRight, | |
| 926 | std.zig.Token.Id.AngleBracketAngleBracketRightEqual, | |
| 927 | std.zig.Token.Id.Tilde, | |
| 928 | std.zig.Token.Id.BracketStarBracket, | |
| 929 | std.zig.Token.Id.BracketStarCBracket, | |
| 875 | .Bang, | |
| 876 | .Pipe, | |
| 877 | .PipePipe, | |
| 878 | .PipeEqual, | |
| 879 | .Equal, | |
| 880 | .EqualEqual, | |
| 881 | .EqualAngleBracketRight, | |
| 882 | .BangEqual, | |
| 883 | .LParen, | |
| 884 | .RParen, | |
| 885 | .Semicolon, | |
| 886 | .Percent, | |
| 887 | .PercentEqual, | |
| 888 | .LBrace, | |
| 889 | .RBrace, | |
| 890 | .LBracket, | |
| 891 | .RBracket, | |
| 892 | .Period, | |
| 893 | .Ellipsis2, | |
| 894 | .Ellipsis3, | |
| 895 | .Caret, | |
| 896 | .CaretEqual, | |
| 897 | .Plus, | |
| 898 | .PlusPlus, | |
| 899 | .PlusEqual, | |
| 900 | .PlusPercent, | |
| 901 | .PlusPercentEqual, | |
| 902 | .Minus, | |
| 903 | .MinusEqual, | |
| 904 | .MinusPercent, | |
| 905 | .MinusPercentEqual, | |
| 906 | .Asterisk, | |
| 907 | .AsteriskEqual, | |
| 908 | .AsteriskAsterisk, | |
| 909 | .AsteriskPercent, | |
| 910 | .AsteriskPercentEqual, | |
| 911 | .Arrow, | |
| 912 | .Colon, | |
| 913 | .Slash, | |
| 914 | .SlashEqual, | |
| 915 | .Comma, | |
| 916 | .Ampersand, | |
| 917 | .AmpersandEqual, | |
| 918 | .QuestionMark, | |
| 919 | .AngleBracketLeft, | |
| 920 | .AngleBracketLeftEqual, | |
| 921 | .AngleBracketAngleBracketLeft, | |
| 922 | .AngleBracketAngleBracketLeftEqual, | |
| 923 | .AngleBracketRight, | |
| 924 | .AngleBracketRightEqual, | |
| 925 | .AngleBracketAngleBracketRight, | |
| 926 | .AngleBracketAngleBracketRightEqual, | |
| 927 | .Tilde, | |
| 928 | .BracketStarBracket, | |
| 929 | .BracketStarCBracket, | |
| 930 | 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 | 933 | docgen_tokenizer, |
| 934 | 934 | source_token, |
| 935 | 935 | "syntax error", |
doc/langref.html.in+16| ... | ... | @@ -6330,6 +6330,22 @@ comptime { |
| 6330 | 6330 | TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe |
| 6331 | 6331 | we can remove this restriction |
| 6332 | 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 | 6349 | {#header_close#} |
| 6334 | 6350 | {#header_open|@bitCast#} |
| 6335 | 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 | 366 | TldIdFn, |
| 367 | 367 | TldIdContainer, |
| 368 | 368 | TldIdCompTime, |
| 369 | TldIdUsingNamespace, | |
| 369 | 370 | }; |
| 370 | 371 | |
| 371 | 372 | enum TldResolution { |
| ... | ... | @@ -413,6 +414,12 @@ struct TldCompTime { |
| 413 | 414 | Tld base; |
| 414 | 415 | }; |
| 415 | 416 | |
| 417 | struct TldUsingNamespace { | |
| 418 | Tld base; | |
| 419 | ||
| 420 | ConstExprValue *using_namespace_value; | |
| 421 | }; | |
| 422 | ||
| 416 | 423 | struct TypeEnumField { |
| 417 | 424 | Buf *name; |
| 418 | 425 | BigInt value; |
| ... | ... | @@ -453,7 +460,7 @@ enum NodeType { |
| 453 | 460 | NodeTypeFieldAccessExpr, |
| 454 | 461 | NodeTypePtrDeref, |
| 455 | 462 | NodeTypeUnwrapOptional, |
| 456 | NodeTypeUse, | |
| 463 | NodeTypeUsingNamespace, | |
| 457 | 464 | NodeTypeBoolLiteral, |
| 458 | 465 | NodeTypeNullLiteral, |
| 459 | 466 | NodeTypeUndefinedLiteral, |
| ... | ... | @@ -715,9 +722,6 @@ struct AstNodeArrayType { |
| 715 | 722 | struct AstNodeUsingNamespace { |
| 716 | 723 | VisibMod visib_mod; |
| 717 | 724 | AstNode *expr; |
| 718 | ||
| 719 | TldResolution resolution; | |
| 720 | ConstExprValue *using_namespace_value; | |
| 721 | 725 | }; |
| 722 | 726 | |
| 723 | 727 | struct AstNodeIfBoolExpr { |
| ... | ... | @@ -1745,8 +1749,6 @@ struct CodeGen { |
| 1745 | 1749 | |
| 1746 | 1750 | ZigList<Tld *> resolve_queue; |
| 1747 | 1751 | size_t resolve_queue_index; |
| 1748 | ZigList<AstNode *> use_queue; | |
| 1749 | size_t use_queue_index; | |
| 1750 | 1752 | ZigList<TimeEvent> timing_events; |
| 1751 | 1753 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1752 | 1754 | ZigList<ZigFn *> inline_fns; |
| ... | ... | @@ -2005,7 +2007,7 @@ struct ScopeDecls { |
| 2005 | 2007 | Scope base; |
| 2006 | 2008 | |
| 2007 | 2009 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table; |
| 2008 | ZigList<AstNode *> use_decls; | |
| 2010 | ZigList<TldUsingNamespace *> use_decls; | |
| 2009 | 2011 | AstNode *safety_set_node; |
| 2010 | 2012 | AstNode *fast_math_set_node; |
| 2011 | 2013 | ZigType *import; |
| ... | ... | @@ -2541,6 +2543,7 @@ struct IrInstructionLoadPtrGen { |
| 2541 | 2543 | struct IrInstructionStorePtr { |
| 2542 | 2544 | IrInstruction base; |
| 2543 | 2545 | |
| 2546 | bool allow_write_through_const; | |
| 2544 | 2547 | IrInstruction *ptr; |
| 2545 | 2548 | IrInstruction *value; |
| 2546 | 2549 | }; |
| ... | ... | @@ -3705,6 +3708,7 @@ enum ResultLocId { |
| 3705 | 3708 | struct ResultLoc { |
| 3706 | 3709 | ResultLocId id; |
| 3707 | 3710 | bool written; |
| 3711 | bool allow_write_through_const; | |
| 3708 | 3712 | IrInstruction *resolved_loc; // result ptr |
| 3709 | 3713 | IrInstruction *source_instruction; |
| 3710 | 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 | 28 | static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type); |
| 29 | 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); |
| 30 | 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 | 34 | static bool is_top_level_struct(ZigType *import) { |
| 33 | 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 | 2856 | add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body")); |
| 2855 | 2857 | return; |
| 2856 | 2858 | } |
| 2859 | } else if (tld->id == TldIdUsingNamespace) { | |
| 2860 | g->resolve_queue.append(tld); | |
| 2857 | 2861 | } |
| 2858 | 2862 | if (is_export) { |
| 2859 | 2863 | g->resolve_queue.append(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 | 2875 | auto entry = decls_scope->decl_table.put_unique(tld->name, tld); |
| 2872 | 2876 | if (entry) { |
| 2873 | 2877 | Tld *other_tld = entry->value; |
| ... | ... | @@ -2875,9 +2879,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 2875 | 2879 | add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition is here")); |
| 2876 | 2880 | return; |
| 2877 | 2881 | } |
| 2878 | } | |
| 2879 | 2882 | |
| 2880 | { | |
| 2881 | 2883 | ZigType *type; |
| 2882 | 2884 | if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) { |
| 2883 | 2885 | add_node_error(g, tld->source_node, |
| ... | ... | @@ -2977,12 +2979,14 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2977 | 2979 | |
| 2978 | 2980 | break; |
| 2979 | 2981 | } |
| 2980 | case NodeTypeUse: | |
| 2981 | { | |
| 2982 | g->use_queue.append(node); | |
| 2983 | decls_scope->use_decls.append(node); | |
| 2984 | break; | |
| 2985 | } | |
| 2982 | case NodeTypeUsingNamespace: { | |
| 2983 | VisibMod visib_mod = node->data.using_namespace.visib_mod; | |
| 2984 | TldUsingNamespace *tld_using_namespace = allocate<TldUsingNamespace>(1); | |
| 2985 | init_tld(&tld_using_namespace->base, TldIdUsingNamespace, nullptr, visib_mod, node, &decls_scope->base); | |
| 2986 | add_top_level_decl(g, decls_scope, &tld_using_namespace->base); | |
| 2987 | decls_scope->use_decls.append(tld_using_namespace); | |
| 2988 | break; | |
| 2989 | } | |
| 2986 | 2990 | case NodeTypeTestDecl: |
| 2987 | 2991 | preview_test_decl(g, node, decls_scope); |
| 2988 | 2992 | break; |
| ... | ... | @@ -3266,6 +3270,118 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3266 | 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 | 3385 | void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3270 | 3386 | if (tld->resolution != TldResolutionUnresolved) |
| 3271 | 3387 | return; |
| ... | ... | @@ -3299,6 +3415,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3299 | 3415 | resolve_decl_comptime(g, tld_comptime); |
| 3300 | 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 | 3428 | tld->resolution = TldResolutionOk; |
| ... | ... | @@ -3308,10 +3432,10 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { |
| 3308 | 3432 | Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) { |
| 3309 | 3433 | // resolve all the using_namespace decls |
| 3310 | 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); | |
| 3312 | if (use_decl_node->data.using_namespace.resolution == TldResolutionUnresolved) { | |
| 3313 | preview_use_decl(g, use_decl_node, decls_scope); | |
| 3314 | resolve_use_decl(g, use_decl_node, decls_scope); | |
| 3435 | TldUsingNamespace *tld_using_namespace = decls_scope->use_decls.at(i); | |
| 3436 | if (tld_using_namespace->base.resolution == TldResolutionUnresolved) { | |
| 3437 | preview_use_decl(g, tld_using_namespace, 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 | 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 | 3879 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code, |
| 3860 | 3880 | SourceKind source_kind) |
| 3861 | 3881 | { |
| ... | ... | @@ -3975,18 +3995,8 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu |
| 3975 | 3995 | |
| 3976 | 3996 | void semantic_analyze(CodeGen *g) { |
| 3977 | 3997 | while (g->resolve_queue_index < g->resolve_queue.length || |
| 3978 | g->fn_defs_index < g->fn_defs.length || | |
| 3979 | g->use_queue_index < g->use_queue.length) | |
| 3998 | g->fn_defs_index < g->fn_defs.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 | 4000 | for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { |
| 3991 | 4001 | Tld *tld = g->resolve_queue.at(g->resolve_queue_index); |
| 3992 | 4002 | AstNode *source_node = nullptr; |
src/analyze.hpp-2| ... | ... | @@ -86,8 +86,6 @@ bool is_array_ref(ZigType *type_entry); |
| 86 | 86 | bool is_container_ref(ZigType *type_entry); |
| 87 | 87 | bool is_valid_vector_elem_type(ZigType *elem_type); |
| 88 | 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 | 89 | ZigFn *scope_fn_entry(Scope *scope); |
| 92 | 90 | ZigPackage *scope_package(Scope *scope); |
| 93 | 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 | 193 | return "Symbol"; |
| 194 | 194 | case NodeTypePrefixOpExpr: |
| 195 | 195 | return "PrefixOpExpr"; |
| 196 | case NodeTypeUse: | |
| 197 | return "Use"; | |
| 196 | case NodeTypeUsingNamespace: | |
| 197 | return "UsingNamespace"; | |
| 198 | 198 | case NodeTypeBoolLiteral: |
| 199 | 199 | return "BoolLiteral"; |
| 200 | 200 | case NodeTypeNullLiteral: |
| ... | ... | @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | static bool is_printable(uint8_t c) { |
| 322 | if (c == 0) { | |
| 323 | return false; | |
| 324 | } | |
| 322 | 325 | static const uint8_t printables[] = |
| 323 | 326 | " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; |
| 324 | 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 | 340 | buf_append_str(dest, "\\\""); |
| 338 | 341 | } else if (c == '\\') { |
| 339 | 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 | 343 | } else if (c == '\n') { |
| 347 | 344 | buf_append_str(dest, "\\n"); |
| 348 | 345 | } else if (c == '\r') { |
| 349 | 346 | buf_append_str(dest, "\\r"); |
| 350 | 347 | } else if (c == '\t') { |
| 351 | 348 | buf_append_str(dest, "\\t"); |
| 352 | } else if (c == '\v') { | |
| 353 | buf_append_str(dest, "\\v"); | |
| 354 | 349 | } else if (is_printable(c)) { |
| 355 | 350 | buf_append_char(dest, c); |
| 356 | 351 | } else { |
| ... | ... | @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 630 | 625 | case NodeTypeCharLiteral: |
| 631 | 626 | { |
| 632 | 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 | 641 | fprintf(ar->f, "'%c'", c); |
| 635 | 642 | } else { |
| 636 | 643 | fprintf(ar->f, "'\\x%02x'", (int)c); |
| ... | ... | @@ -791,7 +798,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 791 | 798 | AstNode *decls_node = node->data.container_decl.decls.at(decl_i); |
| 792 | 799 | render_node_grouped(ar, decls_node); |
| 793 | 800 | |
| 794 | if (decls_node->type == NodeTypeUse || | |
| 801 | if (decls_node->type == NodeTypeUsingNamespace || | |
| 795 | 802 | decls_node->type == NodeTypeVariableDeclaration || |
| 796 | 803 | decls_node->type == NodeTypeFnProto) |
| 797 | 804 | { |
| ... | ... | @@ -1170,7 +1177,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1170 | 1177 | case NodeTypeParamDecl: |
| 1171 | 1178 | case NodeTypeTestDecl: |
| 1172 | 1179 | case NodeTypeStructField: |
| 1173 | case NodeTypeUse: | |
| 1180 | case NodeTypeUsingNamespace: | |
| 1174 | 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 | 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 | 92 | void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { |
| 213 | 93 | g->clang_argv = args; |
| 214 | 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 | 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 | 116 | void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { |
| 241 | 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 | 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 | 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 | 4470 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4589 | 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 | 5368 | LLVMValueRef vector = ir_llvm_value(g, instruction->vector); |
| 5487 | 5369 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, |
| 5488 | 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 | 5373 | return result_loc; |
| 5491 | 5374 | } |
| 5492 | 5375 | |
| ... | ... | @@ -5499,7 +5382,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab |
| 5499 | 5382 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); |
| 5500 | 5383 | LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, |
| 5501 | 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 | 5391 | static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -7994,6 +7880,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 7994 | 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 | 7891 | static Error define_builtin_compile_vars(CodeGen *g) { |
| 7998 | 7892 | if (g->std_package == nullptr) |
| 7999 | 7893 | return ErrorNone; |
| ... | ... | @@ -8078,8 +7972,16 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8078 | 7972 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 8079 | 7973 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 8080 | 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"), | |
| 8082 | g->is_test_build ? g->test_runner_package : g->root_package); | |
| 7975 | ZigPackage *root_pkg; | |
| 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 | 7985 | g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents, |
| 8084 | 7986 | SourceKindPkgMain); |
| 8085 | 7987 | |
| ... | ... | @@ -8586,14 +8488,6 @@ static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) { |
| 8586 | 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 | 8491 | static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 8598 | 8492 | Error err; |
| 8599 | 8493 | |
| ... | ... | @@ -8643,7 +8537,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { |
| 8643 | 8537 | ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); |
| 8644 | 8538 | |
| 8645 | 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 | 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 | 9651 | ZigLibCInstallation *libc) |
| 9758 | 9652 | { |
| 9759 | 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 | 9656 | child_gen->disable_gen_h = true; |
| 9762 | 9657 | child_gen->want_stack_check = WantStackCheckDisabled; |
| 9763 | 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 | 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 | 18 | |
| 19 | 19 | CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, |
| 20 | 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 | 23 | CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, |
| 24 | 24 | ZigLibCInstallation *libc); |
| 25 | 25 | |
| 26 | 26 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 27 | 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 | 28 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); |
| 30 | 29 | |
| 31 | 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 | 189 | static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 190 | 190 | ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime); |
| 191 | 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 | 194 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, |
| 194 | 195 | IrInstruction *base_ptr, bool safety_check_on, bool initializing); |
| 195 | 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 | 198 | static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr, |
| 198 | 199 | IrInstruction *base_ptr, bool initializing); |
| 199 | 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 | 202 | static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 202 | 203 | IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node, |
| 203 | 204 | LVal lval, ResultLoc *parent_result_loc); |
| ... | ... | @@ -1612,7 +1613,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode |
| 1612 | 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 | 1617 | IrInstruction *ptr, IrInstruction *value) |
| 1617 | 1618 | { |
| 1618 | 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 | 1625 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1625 | 1626 | ir_ref_instruction(value, irb->current_basic_block); |
| 1626 | 1627 | |
| 1627 | return &instruction->base; | |
| 1628 | return instruction; | |
| 1628 | 1629 | } |
| 1629 | 1630 | |
| 1630 | 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 | 4002 | |
| 4002 | 4003 | static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 4003 | 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 | 4017 | return irb->codegen->invalid_instruction; |
| 4008 | 4018 | |
| 4009 | ir_build_store_ptr(irb, scope, node, lvalue, rvalue); | |
| 4010 | 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 | 6051 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 6043 | 6052 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 6044 | 6053 | result_loc_inst->base.source_instruction = field_ptr; |
| 6054 | result_loc_inst->base.allow_write_through_const = true; | |
| 6045 | 6055 | ir_ref_instruction(field_ptr, irb->current_basic_block); |
| 6046 | 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 | 6090 | ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); |
| 6081 | 6091 | result_loc_inst->base.id = ResultLocIdInstruction; |
| 6082 | 6092 | result_loc_inst->base.source_instruction = elem_ptr; |
| 6093 | result_loc_inst->base.allow_write_through_const = true; | |
| 6083 | 6094 | ir_ref_instruction(elem_ptr, irb->current_basic_block); |
| 6084 | 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 | 6648 | |
| 6638 | 6649 | ir_set_cursor_at_end_and_append_block(irb, continue_block); |
| 6639 | 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 | 6652 | ir_build_br(irb, child_scope, node, cond_block, is_comptime); |
| 6642 | 6653 | |
| 6643 | 6654 | IrInstruction *else_result = nullptr; |
| ... | ... | @@ -8430,7 +8441,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 8430 | 8441 | switch (node->type) { |
| 8431 | 8442 | case NodeTypeStructValueField: |
| 8432 | 8443 | case NodeTypeParamDecl: |
| 8433 | case NodeTypeUse: | |
| 8444 | case NodeTypeUsingNamespace: | |
| 8434 | 8445 | case NodeTypeSwitchProng: |
| 8435 | 8446 | case NodeTypeSwitchRange: |
| 8436 | 8447 | case NodeTypeStructField: |
| ... | ... | @@ -11155,7 +11166,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 11155 | 11166 | } |
| 11156 | 11167 | |
| 11157 | 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 | 11171 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11160 | 11172 | return result_loc_inst; |
| 11161 | 11173 | } |
| ... | ... | @@ -11615,7 +11627,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so |
| 11615 | 11627 | } |
| 11616 | 11628 | IrInstruction *result_loc_inst = nullptr; |
| 11617 | 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 | 11631 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11620 | 11632 | return result_loc_inst; |
| 11621 | 11633 | } |
| ... | ... | @@ -11658,7 +11670,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 11658 | 11670 | IrInstruction *result_loc_inst; |
| 11659 | 11671 | if (handle_is_ptr(wanted_type)) { |
| 11660 | 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 | 11674 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11663 | 11675 | return result_loc_inst; |
| 11664 | 11676 | } |
| ... | ... | @@ -11743,7 +11755,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 11743 | 11755 | IrInstruction *result_loc_inst; |
| 11744 | 11756 | if (handle_is_ptr(wanted_type)) { |
| 11745 | 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 | 11759 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11748 | 11760 | return result_loc_inst; |
| 11749 | 11761 | } |
| ... | ... | @@ -11816,7 +11828,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 11816 | 11828 | |
| 11817 | 11829 | IrInstruction *result_loc; |
| 11818 | 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 | 11833 | } else { |
| 11821 | 11834 | result_loc = nullptr; |
| 11822 | 11835 | } |
| ... | ... | @@ -11860,7 +11873,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 11860 | 11873 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 11861 | 11874 | |
| 11862 | 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 | 11878 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 11865 | 11879 | return result_loc_inst; |
| 11866 | 11880 | } |
| ... | ... | @@ -12516,7 +12530,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction * |
| 12516 | 12530 | if (result_loc == nullptr) { |
| 12517 | 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 | 12535 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 12521 | 12536 | return result_loc_inst; |
| 12522 | 12537 | } |
| ... | ... | @@ -13097,7 +13112,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 13097 | 13112 | IrInstruction *result_loc_inst; |
| 13098 | 13113 | if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) { |
| 13099 | 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 | 13117 | if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) { |
| 13102 | 13118 | return result_loc_inst; |
| 13103 | 13119 | } |
| ... | ... | @@ -14597,7 +14613,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp * |
| 14597 | 14613 | for (uint64_t x = 0; x < mult_amt; x += 1) { |
| 14598 | 14614 | for (uint64_t y = 0; y < old_array_len; y += 1) { |
| 14599 | 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 | 14617 | i += 1; |
| 14602 | 14618 | } |
| 14603 | 14619 | } |
| ... | ... | @@ -14834,7 +14850,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, |
| 14834 | 14850 | // instruction. |
| 14835 | 14851 | assert(deref->value.special != ConstValSpecialRuntime); |
| 14836 | 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 | 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 | 15368 | |
| 15353 | 15369 | if (peer_parent->peers.length == 1) { |
| 15354 | 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 | 15372 | result_peer->suspend_pos.basic_block_index = SIZE_MAX; |
| 15357 | 15373 | result_peer->suspend_pos.instruction_index = SIZE_MAX; |
| 15358 | 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 | 15388 | if (peer_parent->skipped) { |
| 15373 | 15389 | if (non_null_comptime) { |
| 15374 | 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 | 15393 | return nullptr; |
| 15378 | 15394 | } |
| ... | ... | @@ -15390,7 +15406,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe |
| 15390 | 15406 | } |
| 15391 | 15407 | |
| 15392 | 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 | 15410 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 15395 | 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 | 15456 | } |
| 15441 | 15457 | |
| 15442 | 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 | 15460 | if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || |
| 15445 | 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 | 15485 | |
| 15470 | 15486 | static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr, |
| 15471 | 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 | 15497 | IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type, |
| 15475 | 15498 | value, force_runtime, non_null_comptime); |
| 15476 | 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 | 15548 | if (type_is_invalid(implicit_elem_type)) |
| 15526 | 15549 | return ira->codegen->invalid_instruction; |
| 15527 | 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 | 15552 | if (result_loc != nullptr) |
| 15530 | 15553 | return result_loc; |
| 15531 | 15554 | |
| ... | ... | @@ -15534,7 +15557,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn |
| 15534 | 15557 | instruction->result_loc->id == ResultLocIdReturn) |
| 15535 | 15558 | { |
| 15536 | 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 | 15561 | if (result_loc != nullptr && |
| 15539 | 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 | 15646 | ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type); |
| 15624 | 15647 | |
| 15625 | 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 | 15650 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 15628 | 15651 | return result_loc; |
| 15629 | 15652 | } |
| ... | ... | @@ -15841,7 +15864,7 @@ no_mem_slot: |
| 15841 | 15864 | } |
| 15842 | 15865 | |
| 15843 | 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 | 15869 | assert(ptr->value.type->id == ZigTypeIdPointer); |
| 15847 | 15870 | |
| ... | ... | @@ -15857,7 +15880,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15857 | 15880 | |
| 15858 | 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 | 15884 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); |
| 15862 | 15885 | return ira->codegen->invalid_instruction; |
| 15863 | 15886 | } |
| ... | ... | @@ -15936,10 +15959,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source |
| 15936 | 15959 | break; |
| 15937 | 15960 | } |
| 15938 | 15961 | |
| 15939 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, | |
| 15940 | ptr, value); | |
| 15941 | result->value.type = ira->codegen->builtin_types.entry_void; | |
| 15942 | return result; | |
| 15962 | IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope, | |
| 15963 | source_instr->source_node, ptr, value); | |
| 15964 | return &store_ptr->base; | |
| 15943 | 15965 | } |
| 15944 | 15966 | |
| 15945 | 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 | 16404 | IrInstruction *result_loc; |
| 16383 | 16405 | if (handle_is_ptr(impl_fn_type_id->return_type)) { |
| 16384 | 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 | 16408 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || |
| 16387 | 16409 | instr_is_unreachable(result_loc))) |
| 16388 | 16410 | { |
| ... | ... | @@ -16504,7 +16526,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c |
| 16504 | 16526 | IrInstruction *result_loc; |
| 16505 | 16527 | if (handle_is_ptr(return_type)) { |
| 16506 | 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 | 16530 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 16509 | 16531 | return result_loc; |
| 16510 | 16532 | } |
| ... | ... | @@ -17020,7 +17042,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 17020 | 17042 | |
| 17021 | 17043 | // In case resolving the parent activates a suspend, do it now |
| 17022 | 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 | 17046 | if (parent_result_loc != nullptr && |
| 17025 | 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 | 17499 | return result; |
| 17478 | 17500 | } else if (is_slice(array_type)) { |
| 17479 | 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 | 17503 | if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 17481 | 17504 | IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, |
| 17482 | 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 | 17686 | return ira->codegen->invalid_instruction; |
| 17664 | 17687 | if (type_is_invalid(struct_val->type)) |
| 17665 | 17688 | return ira->codegen->invalid_instruction; |
| 17666 | if (struct_val->special == ConstValSpecialUndef && initializing) { | |
| 17689 | if (initializing && struct_val->special == ConstValSpecialUndef) { | |
| 17667 | 17690 | struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); |
| 17668 | 17691 | struct_val->special = ConstValSpecialStatic; |
| 17669 | 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 | 17870 | switch (tld->id) { |
| 17848 | 17871 | case TldIdContainer: |
| 17849 | 17872 | case TldIdCompTime: |
| 17873 | case TldIdUsingNamespace: | |
| 17850 | 17874 | zig_unreachable(); |
| 17851 | 17875 | case TldIdVar: |
| 17852 | 17876 | { |
| ... | ... | @@ -18260,7 +18284,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc |
| 18260 | 18284 | if (type_is_invalid(value->value.type)) |
| 18261 | 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 | 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 | 18787 | if (optional_val == nullptr) |
| 18764 | 18788 | return ira->codegen->invalid_instruction; |
| 18765 | 18789 | |
| 18766 | if (initializing && optional_val->special == ConstValSpecialUndef) { | |
| 18790 | if (initializing) { | |
| 18767 | 18791 | switch (type_has_one_possible_value(ira->codegen, child_type)) { |
| 18768 | 18792 | case OnePossibleValueInvalid: |
| 18769 | 18793 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -19668,7 +19692,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19668 | 19692 | |
| 19669 | 19693 | IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc, |
| 19670 | 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 | 19696 | if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 19673 | 19697 | const_ptrs.append(field_ptr); |
| 19674 | 19698 | } else { |
| ... | ... | @@ -19685,7 +19709,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 19685 | 19709 | IrInstruction *field_result_loc = const_ptrs.at(i); |
| 19686 | 19710 | IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr); |
| 19687 | 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 | 19836 | assert(elem_result_loc->value.special == ConstValSpecialStatic); |
| 19813 | 19837 | IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr); |
| 19814 | 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 | 21555 | IrInstruction *result_loc; |
| 21532 | 21556 | if (handle_is_ptr(result_type)) { |
| 21533 | 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 | 21559 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 21536 | 21560 | return result_loc; |
| 21537 | 21561 | } |
| ... | ... | @@ -21788,7 +21812,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru |
| 21788 | 21812 | } |
| 21789 | 21813 | |
| 21790 | 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 | 21816 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) { |
| 21793 | 21817 | return result_loc; |
| 21794 | 21818 | } |
| ... | ... | @@ -21865,7 +21889,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 21865 | 21889 | } |
| 21866 | 21890 | |
| 21867 | 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 | 21893 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 21870 | 21894 | return result_loc; |
| 21871 | 21895 | } |
| ... | ... | @@ -22607,7 +22631,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 22607 | 22631 | } |
| 22608 | 22632 | |
| 22609 | 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 | 22635 | if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) { |
| 22612 | 22636 | return result_loc; |
| 22613 | 22637 | } |
| ... | ... | @@ -23259,7 +23283,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct |
| 23259 | 23283 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); |
| 23260 | 23284 | if (err_union_val == nullptr) |
| 23261 | 23285 | return ira->codegen->invalid_instruction; |
| 23262 | if (err_union_val->special == ConstValSpecialUndef && initializing) { | |
| 23286 | if (initializing && err_union_val->special == ConstValSpecialUndef) { | |
| 23263 | 23287 | ConstExprValue *vals = create_const_vals(2); |
| 23264 | 23288 | ConstExprValue *err_set_val = &vals[0]; |
| 23265 | 23289 | ConstExprValue *payload_val = &vals[1]; |
| ... | ... | @@ -24734,10 +24758,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 24734 | 24758 | operand_type->data.integral.bit_count)); |
| 24735 | 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 | 24763 | ir_add_error(ira, op, |
| 24739 | buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type", | |
| 24740 | operand_type->data.integral.bit_count)); | |
| 24764 | buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type", | |
| 24765 | max_atomic_bits, operand_type->data.integral.bit_count)); | |
| 24741 | 24766 | return ira->codegen->builtin_types.entry_invalid; |
| 24742 | 24767 | } |
| 24743 | 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 | 25411 | |
| 25387 | 25412 | bool was_written = instruction->result_loc->written; |
| 25388 | 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 | 25415 | if (result_loc != nullptr) { |
| 25391 | 25416 | if (type_is_invalid(result_loc->value.type)) |
| 25392 | 25417 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -25394,7 +25419,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct |
| 25394 | 25419 | return result_loc; |
| 25395 | 25420 | |
| 25396 | 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 | 25424 | if (type_is_invalid(store_ptr->value.type)) { |
| 25399 | 25425 | return ira->codegen->invalid_instruction; |
| 25400 | 25426 | } |
| ... | ... | @@ -25418,7 +25444,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst |
| 25418 | 25444 | return operand; |
| 25419 | 25445 | |
| 25420 | 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 | 25448 | if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) |
| 25423 | 25449 | return result_loc; |
| 25424 | 25450 |
src/main.cpp+3-4| ... | ... | @@ -583,7 +583,7 @@ int main(int argc, char **argv) { |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 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 | 587 | g->valgrind_support = valgrind_support; |
| 588 | 588 | g->enable_time_report = timing_info; |
| 589 | 589 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | ... | @@ -1011,7 +1011,7 @@ int main(int argc, char **argv) { |
| 1011 | 1011 | } |
| 1012 | 1012 | case CmdBuiltin: { |
| 1013 | 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 | 1015 | codegen_set_strip(g, strip); |
| 1016 | 1016 | for (size_t i = 0; i < link_libs.length; i += 1) { |
| 1017 | 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 | 1115 | cache_dir_buf = buf_create_from_str(cache_dir); |
| 1116 | 1116 | } |
| 1117 | 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 | 1119 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); |
| 1120 | 1120 | g->valgrind_support = valgrind_support; |
| 1121 | 1121 | g->want_pic = want_pic; |
| ... | ... | @@ -1125,7 +1125,6 @@ int main(int argc, char **argv) { |
| 1125 | 1125 | g->enable_time_report = timing_info; |
| 1126 | 1126 | codegen_set_out_name(g, buf_out_name); |
| 1127 | 1127 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 1128 | codegen_set_is_test(g, cmd == CmdTest); | |
| 1129 | 1128 | g->want_single_threaded = want_single_threaded; |
| 1130 | 1129 | codegen_set_linker_script(g, linker_script); |
| 1131 | 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 | 676 | AstNode *expr = ast_expect(pc, ast_parse_expr); |
| 677 | 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 | 680 | res->data.using_namespace.visib_mod = visib_mod; |
| 681 | 681 | res->data.using_namespace.expr = expr; |
| 682 | 682 | return res; |
| ... | ... | @@ -2938,7 +2938,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2938 | 2938 | case NodeTypeUnwrapOptional: |
| 2939 | 2939 | visit_field(&node->data.unwrap_optional.expr, visit, context); |
| 2940 | 2940 | break; |
| 2941 | case NodeTypeUse: | |
| 2941 | case NodeTypeUsingNamespace: | |
| 2942 | 2942 | visit_field(&node->data.using_namespace.expr, visit, context); |
| 2943 | 2943 | break; |
| 2944 | 2944 | case NodeTypeBoolLiteral: |
src/target.cpp+67-1| ... | ... | @@ -878,6 +878,72 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { |
| 878 | 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 | 947 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 882 | 948 | switch (target->os) { |
| 883 | 949 | case OsFreestanding: |
| ... | ... | @@ -1524,9 +1590,9 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { |
| 1524 | 1590 | case OsKFreeBSD: |
| 1525 | 1591 | case OsNetBSD: |
| 1526 | 1592 | case OsHurd: |
| 1527 | case OsWindows: | |
| 1528 | 1593 | return ZigLLVM_GNU; |
| 1529 | 1594 | case OsUefi: |
| 1595 | case OsWindows: | |
| 1530 | 1596 | return ZigLLVM_MSVC; |
| 1531 | 1597 | case OsLinux: |
| 1532 | 1598 | case OsWASI: |
src/target.hpp+1| ... | ... | @@ -195,6 +195,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch); |
| 195 | 195 | bool target_supports_libunwind(const ZigTarget *target); |
| 196 | 196 | |
| 197 | 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 | 200 | size_t target_libc_count(void); |
| 200 | 201 | void target_libc_enum(size_t index, ZigTarget *out_target); |
src/util.hpp+1-1| ... | ... | @@ -43,7 +43,7 @@ ATTRIBUTE_NORETURN |
| 43 | 43 | ATTRIBUTE_PRINTF(1, 2) |
| 44 | 44 | void zig_panic(const char *format, ...); |
| 45 | 45 | |
| 46 | #ifdef WIN32 | |
| 46 | #ifdef _WIN32 | |
| 47 | 47 | #define __func__ __FUNCTION__ |
| 48 | 48 | #endif |
| 49 | 49 |
src/zig_clang.h+1-1| ... | ... | @@ -50,7 +50,7 @@ enum ZigClangAPValueKind { |
| 50 | 50 | struct ZigClangAPValue { |
| 51 | 51 | enum ZigClangAPValueKind Kind; |
| 52 | 52 | // experimentally-derived size of clang::APValue::DataType |
| 53 | #if defined(WIN32) && defined(_MSC_VER) | |
| 53 | #if defined(_WIN32) && defined(_MSC_VER) | |
| 54 | 54 | char Data[52]; |
| 55 | 55 | #else |
| 56 | 56 | char Data[68]; |
std/build.zig+47-28| ... | ... | @@ -41,9 +41,11 @@ pub const Builder = struct { |
| 41 | 41 | env_map: *BufMap, |
| 42 | 42 | top_level_steps: ArrayList(*TopLevelStep), |
| 43 | 43 | install_prefix: ?[]const u8, |
| 44 | search_prefixes: ArrayList([]const u8), | |
| 44 | dest_dir: ?[]const u8, | |
| 45 | 45 | lib_dir: ?[]const u8, |
| 46 | 46 | exe_dir: ?[]const u8, |
| 47 | install_path: []const u8, | |
| 48 | search_prefixes: ArrayList([]const u8), | |
| 47 | 49 | installed_files: ArrayList(InstalledFile), |
| 48 | 50 | build_root: []const u8, |
| 49 | 51 | cache_root: []const u8, |
| ... | ... | @@ -125,10 +127,11 @@ pub const Builder = struct { |
| 125 | 127 | .top_level_steps = ArrayList(*TopLevelStep).init(allocator), |
| 126 | 128 | .default_step = undefined, |
| 127 | 129 | .env_map = env_map, |
| 128 | .install_prefix = null, | |
| 129 | 130 | .search_prefixes = ArrayList([]const u8).init(allocator), |
| 131 | .install_prefix = null, | |
| 130 | 132 | .lib_dir = null, |
| 131 | 133 | .exe_dir = null, |
| 134 | .dest_dir = env_map.get("DESTDIR"), | |
| 132 | 135 | .installed_files = ArrayList(InstalledFile).init(allocator), |
| 133 | 136 | .install_tls = TopLevelStep{ |
| 134 | 137 | .step = Step.initNoOp("install", allocator), |
| ... | ... | @@ -142,6 +145,7 @@ pub const Builder = struct { |
| 142 | 145 | .is_release = false, |
| 143 | 146 | .override_std_dir = null, |
| 144 | 147 | .override_lib_dir = null, |
| 148 | .install_path = undefined, | |
| 145 | 149 | }; |
| 146 | 150 | try self.top_level_steps.append(&self.install_tls); |
| 147 | 151 | try self.top_level_steps.append(&self.uninstall_tls); |
| ... | ... | @@ -164,14 +168,19 @@ pub const Builder = struct { |
| 164 | 168 | } |
| 165 | 169 | |
| 166 | 170 | fn resolveInstallPrefix(self: *Builder) void { |
| 167 | const prefix = if (self.install_prefix) |prefix| prefix else blk: { | |
| 168 | const prefix = self.cache_root; | |
| 169 | self.install_prefix = prefix; | |
| 170 | break :blk prefix; | |
| 171 | }; | |
| 172 | ||
| 173 | self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "lib" }) catch unreachable; | |
| 174 | self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "bin" }) catch unreachable; | |
| 171 | if (self.dest_dir) |dest_dir| { | |
| 172 | const install_prefix = self.install_prefix orelse "/usr"; | |
| 173 | self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable; | |
| 174 | } else { | |
| 175 | const install_prefix = self.install_prefix orelse blk: { | |
| 176 | const p = self.cache_root; | |
| 177 | self.install_prefix = p; | |
| 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 | 186 | pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep { |
| ... | ... | @@ -796,11 +805,7 @@ pub const Builder = struct { |
| 796 | 805 | return name; |
| 797 | 806 | } |
| 798 | 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| { | |
| 800 | return real_path; | |
| 801 | } else |_| { | |
| 802 | continue; | |
| 803 | } | |
| 808 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | |
| 804 | 809 | } |
| 805 | 810 | } |
| 806 | 811 | if (self.env_map.get("PATH")) |PATH| { |
| ... | ... | @@ -808,14 +813,10 @@ pub const Builder = struct { |
| 808 | 813 | if (fs.path.isAbsolute(name)) { |
| 809 | 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 | 817 | while (it.next()) |path| { |
| 813 | 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| { | |
| 815 | return real_path; | |
| 816 | } else |_| { | |
| 817 | continue; | |
| 818 | } | |
| 819 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | |
| 819 | 820 | } |
| 820 | 821 | } |
| 821 | 822 | } |
| ... | ... | @@ -825,11 +826,7 @@ pub const Builder = struct { |
| 825 | 826 | } |
| 826 | 827 | for (paths) |path| { |
| 827 | 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 real_path; | |
| 830 | } else |_| { | |
| 831 | continue; | |
| 832 | } | |
| 829 | return fs.realpathAlloc(self.allocator, full_path) catch continue; | |
| 833 | 830 | } |
| 834 | 831 | } |
| 835 | 832 | return error.FileNotFound; |
| ... | ... | @@ -884,7 +881,7 @@ pub const Builder = struct { |
| 884 | 881 | |
| 885 | 882 | fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { |
| 886 | 883 | const base_dir = switch (dir) { |
| 887 | .Prefix => self.install_prefix.?, | |
| 884 | .Prefix => self.install_path, | |
| 888 | 885 | .Bin => self.exe_dir.?, |
| 889 | 886 | .Lib => self.lib_dir.?, |
| 890 | 887 | }; |
| ... | ... | @@ -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 | 904 | pub const Version = struct { |
| 899 | 905 | major: u32, |
| 900 | 906 | minor: u32, |
| ... | ... | @@ -1113,6 +1119,9 @@ pub const Target = union(enum) { |
| 1113 | 1119 | } |
| 1114 | 1120 | |
| 1115 | 1121 | pub fn libPrefix(self: Target) []const u8 { |
| 1122 | if (self.isWasm()) { | |
| 1123 | return ""; | |
| 1124 | } | |
| 1116 | 1125 | switch (self.getAbi()) { |
| 1117 | 1126 | .msvc => return "", |
| 1118 | 1127 | else => return "lib", |
| ... | ... | @@ -1255,6 +1264,8 @@ pub const LibExeObjStep = struct { |
| 1255 | 1264 | libc_file: ?[]const u8 = null, |
| 1256 | 1265 | target_glibc: ?Version = null, |
| 1257 | 1266 | |
| 1267 | valgrind_support: ?bool = null, | |
| 1268 | ||
| 1258 | 1269 | const LinkObject = union(enum) { |
| 1259 | 1270 | StaticPath: []const u8, |
| 1260 | 1271 | OtherStep: *LibExeObjStep, |
| ... | ... | @@ -1791,7 +1802,7 @@ pub const LibExeObjStep = struct { |
| 1791 | 1802 | try zig_args.append("--bundle-compiler-rt"); |
| 1792 | 1803 | } |
| 1793 | 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 | 1808 | switch (self.target) { |
| ... | ... | @@ -1882,6 +1893,14 @@ pub const LibExeObjStep = struct { |
| 1882 | 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 | 1904 | if (self.override_std_dir) |dir| { |
| 1886 | 1905 | try zig_args.append("--override-std-dir"); |
| 1887 | 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 | 19 | const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; |
| 20 | 20 | |
| 21 | 21 | const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; |
| 22 | const IMAGE_DEBUG_TYPE_CODEVIEW = 2; | |
| 22 | 23 | const DEBUG_DIRECTORY = 6; |
| 23 | 24 | |
| 24 | 25 | pub const CoffError = error{ |
| ... | ... | @@ -28,6 +29,7 @@ pub const CoffError = error{ |
| 28 | 29 | MissingCoffSection, |
| 29 | 30 | }; |
| 30 | 31 | |
| 32 | // Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format | |
| 31 | 33 | pub const Coff = struct { |
| 32 | 34 | in_file: File, |
| 33 | 35 | allocator: *mem.Allocator, |
| ... | ... | @@ -120,16 +122,43 @@ pub const Coff = struct { |
| 120 | 122 | |
| 121 | 123 | pub fn getPdbPath(self: *Coff, buffer: []u8) !usize { |
| 122 | 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 | // debug_directory. | |
| 126 | const header = blk: { | |
| 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 | 136 | const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY]; |
| 128 | 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 | 139 | var file_stream = self.in_file.inStream(); |
| 132 | 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 | 163 | var cv_signature: [4]u8 = undefined; // CodeView signature |
| 135 | 164 | try in.readNoEof(cv_signature[0..]); |
| ... | ... | @@ -141,7 +170,7 @@ pub const Coff = struct { |
| 141 | 170 | |
| 142 | 171 | // Finally read the null-terminated string. |
| 143 | 172 | var byte = try in.readByte(); |
| 144 | var i: usize = 0; | |
| 173 | i = 0; | |
| 145 | 174 | while (byte != 0 and i < buffer.len) : (i += 1) { |
| 146 | 175 | buffer[i] = byte; |
| 147 | 176 | byte = try in.readByte(); |
| ... | ... | @@ -170,7 +199,7 @@ pub const Coff = struct { |
| 170 | 199 | try self.sections.append(Section{ |
| 171 | 200 | .header = SectionHeader{ |
| 172 | 201 | .name = name, |
| 173 | .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) }, | |
| 202 | .misc = SectionHeader.Misc{ .virtual_size = try in.readIntLittle(u32) }, | |
| 174 | 203 | .virtual_address = try in.readIntLittle(u32), |
| 175 | 204 | .size_of_raw_data = try in.readIntLittle(u32), |
| 176 | 205 | .pointer_to_raw_data = try in.readIntLittle(u32), |
| ... | ... | @@ -214,6 +243,17 @@ const OptionalHeader = struct { |
| 214 | 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 | 257 | pub const Section = struct { |
| 218 | 258 | header: SectionHeader, |
| 219 | 259 | }; |
std/debug.zig+54-21| ... | ... | @@ -12,6 +12,7 @@ const coff = std.coff; |
| 12 | 12 | const pdb = std.pdb; |
| 13 | 13 | const ArrayList = std.ArrayList; |
| 14 | 14 | const builtin = @import("builtin"); |
| 15 | const root = @import("root"); | |
| 15 | 16 | const maxInt = std.math.maxInt; |
| 16 | 17 | const File = std.fs.File; |
| 17 | 18 | const windows = std.os.windows; |
| ... | ... | @@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool |
| 217 | 218 | pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { |
| 218 | 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 | 227 | if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { |
| 221 | 228 | // Panicked during a panic. |
| 222 | 229 | |
| ... | ... | @@ -368,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres |
| 368 | 375 | const obj_basename = fs.path.basename(mod.obj_file_name); |
| 369 | 376 | |
| 370 | 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 | 379 | const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]); |
| 373 | 380 | if (prefix.RecordLen < 2) |
| 374 | 381 | return error.InvalidDebugInfo; |
| ... | ... | @@ -851,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 851 | 858 | const age = try pdb_stream.stream.readIntLittle(u32); |
| 852 | 859 | var guid: [16]u8 = undefined; |
| 853 | 860 | try pdb_stream.stream.readNoEof(guid[0..]); |
| 861 | if (version != 20000404) // VC70, only value observed by LLVM team | |
| 862 | return error.UnknownPDBVersion; | |
| 854 | 863 | if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age) |
| 855 | return error.InvalidDebugInfo; | |
| 864 | return error.PDBMismatch; | |
| 856 | 865 | // We validated the executable and pdb match. |
| 857 | 866 | |
| 858 | 867 | const string_table_index = str_tab_index: { |
| ... | ... | @@ -896,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo { |
| 896 | 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 | 909 | di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo; |
| 901 | 910 | |
| 902 | 911 | const dbi = di.pdb.dbi; |
| 903 | 912 | |
| 904 | 913 | // Dbi Header |
| 905 | 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 | 920 | const mod_info_size = dbi_stream_header.ModInfoSize; |
| 907 | 921 | const section_contrib_size = dbi_stream_header.SectionContributionSize; |
| 908 | 922 | |
| ... | ... | @@ -2312,39 +2326,58 @@ fn getDebugInfoAllocator() *mem.Allocator { |
| 2312 | 2326 | |
| 2313 | 2327 | /// Whether or not the current target can print useful debug information when a segfault occurs. |
| 2314 | 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 | 2342 | /// Attaches a global SIGSEGV handler which calls @panic("segmentation fault"); |
| 2317 | 2343 | pub fn attachSegfaultHandler() void { |
| 2318 | 2344 | if (!have_segfault_handling_support) { |
| 2319 | 2345 | @compileError("segfault handler not supported for this target"); |
| 2320 | 2346 | } |
| 2321 | switch (builtin.os) { | |
| 2322 | .linux => { | |
| 2323 | var act = os.Sigaction{ | |
| 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, | |
| 2347 | if (windows.is_the_target) { | |
| 2348 | windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows); | |
| 2349 | return; | |
| 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 { | |
| 2339 | // Reset to the default handler so that if a segfault happens in this handler it will crash | |
| 2340 | // the process. Also when this handler returns, the original instruction will be repeated | |
| 2341 | // and the resulting segfault will crash the process rather than continually dump stack traces. | |
| 2360 | fn resetSegfaultHandler() void { | |
| 2361 | if (windows.is_the_target) { | |
| 2362 | if (windows_segfault_handle) |handle| { | |
| 2363 | assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0); | |
| 2364 | windows_segfault_handle = null; | |
| 2365 | } | |
| 2366 | return; | |
| 2367 | } | |
| 2342 | 2368 | var act = os.Sigaction{ |
| 2343 | 2369 | .sigaction = os.SIG_DFL, |
| 2344 | 2370 | .mask = os.empty_sigset, |
| 2345 | 2371 | .flags = 0, |
| 2346 | 2372 | }; |
| 2347 | 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 | 2382 | const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); |
| 2350 | 2383 | const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]); |
std/fmt.zig+20-1| ... | ... | @@ -374,9 +374,10 @@ pub fn formatType( |
| 374 | 374 | return output(context, "{ ... }"); |
| 375 | 375 | } |
| 376 | 376 | comptime var field_i = 0; |
| 377 | try output(context, "{"); | |
| 377 | 378 | inline while (field_i < @memberCount(T)) : (field_i += 1) { |
| 378 | 379 | if (field_i == 0) { |
| 379 | try output(context, "{ ."); | |
| 380 | try output(context, " ."); | |
| 380 | 381 | } else { |
| 381 | 382 | try output(context, ", ."); |
| 382 | 383 | } |
| ... | ... | @@ -425,6 +426,9 @@ pub fn formatType( |
| 425 | 426 | if (info.child == u8) { |
| 426 | 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 | 432 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 429 | 433 | }, |
| 430 | 434 | .Fn => { |
| ... | ... | @@ -1439,6 +1443,21 @@ test "struct.self-referential" { |
| 1439 | 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 | 1461 | test "bytes.hex" { |
| 1443 | 1462 | const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 1444 | 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 | 133 | const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0); |
| 134 | 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 | 141 | const stream = &std.fs.File.openHandle(fd).inStream().stream; |
| 137 | 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 | 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 | 2077 | pub const PipeError = error{ |
| 2057 | 2078 | SystemFdQuotaExceeded, |
| 2058 | 2079 | ProcessFdQuotaExceeded, |
std/os/bits/darwin.zig+59| ... | ... | @@ -1116,3 +1116,62 @@ pub const stack_t = extern struct { |
| 1116 | 1116 | ss_size: isize, |
| 1117 | 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 | 876 | ss_size: isize, |
| 877 | 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 | 5 | else => false, |
| 6 | 6 | }; |
| 7 | 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 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | pub const is_the_target = builtin.os == .freebsd; |
| 4 | 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 | 1 | usingnamespace @import("bits.zig"); |
| 2 | 2 | |
| 3 | 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 | 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 | 499 | |
| 500 | 500 | const superblock = try in.readStruct(SuperBlock); |
| 501 | 501 | |
| 502 | // Sanity checks | |
| 502 | 503 | if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic)) |
| 503 | 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 | 509 | switch (superblock.BlockSize) { |
| 506 | 510 | // llvm only supports 4096 but we can handle any of these values |
| 507 | 511 | 512, 1024, 2048, 4096 => {}, |
| 508 | 512 | else => return error.InvalidDebugInfo, |
| 509 | 513 | } |
| 510 | 514 | |
| 511 | if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos()) | |
| 512 | return error.InvalidDebugInfo; | |
| 515 | const dir_block_count = blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize); | |
| 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 | 525 | superblock.BlockSize, |
| 516 | blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize), | |
| 517 | superblock.BlockSize * superblock.BlockMapAddr, | |
| 518 | 526 | file, |
| 519 | allocator, | |
| 527 | dir_blocks, | |
| 520 | 528 | ); |
| 521 | 529 | |
| 530 | const begin = self.directory.pos; | |
| 522 | 531 | const stream_count = try self.directory.stream.readIntLittle(u32); |
| 523 | ||
| 524 | 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 | 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 | 544 | self.streams = try allocator.alloc(MsfStream, stream_count); |
| 531 | 545 | for (self.streams) |*stream, i| { |
| 532 | stream.* = try MsfStream.init( | |
| 533 | superblock.BlockSize, | |
| 534 | stream_sizes[i], | |
| 535 | // MsfStream.init expects the file to be at the part where it reads [N]u32 | |
| 536 | try file.getPos(), | |
| 537 | file, | |
| 538 | allocator, | |
| 539 | ); | |
| 546 | const size = stream_sizes[i]; | |
| 547 | if (size == 0) { | |
| 548 | stream.* = MsfStream{ | |
| 549 | .blocks = [_]u32{}, | |
| 550 | }; | |
| 551 | } else { | |
| 552 | var blocks = try allocator.alloc(u32, size); | |
| 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 | 607 | NumDirectoryBytes: u32, |
| 575 | 608 | |
| 576 | 609 | Unknown: u32, |
| 577 | ||
| 578 | 610 | /// The index of a block within the MSF file. At this block is an array of |
| 579 | 611 | /// ulittle32_t’s listing the blocks that the stream directory resides on. |
| 580 | 612 | /// For large MSF files, the stream directory (which describes the block |
| ... | ... | @@ -584,45 +616,41 @@ const SuperBlock = packed struct { |
| 584 | 616 | /// and the stream directory itself can be stitched together accordingly. |
| 585 | 617 | /// The number of ulittle32_t’s in this array is given by |
| 586 | 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 | 625 | BlockMapAddr: u32, |
| 588 | 626 | }; |
| 589 | 627 | |
| 590 | 628 | const MsfStream = struct { |
| 591 | in_file: File, | |
| 592 | pos: u64, | |
| 593 | blocks: []u32, | |
| 594 | block_size: u32, | |
| 629 | in_file: File = undefined, | |
| 630 | pos: u64 = undefined, | |
| 631 | blocks: []u32 = undefined, | |
| 632 | block_size: u32 = undefined, | |
| 595 | 633 | |
| 596 | 634 | /// Implementation of InStream trait for Pdb.MsfStream |
| 597 | stream: Stream, | |
| 635 | stream: Stream = undefined, | |
| 598 | 636 | |
| 599 | 637 | pub const Error = @typeOf(read).ReturnType.ErrorSet; |
| 600 | 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 { | |
| 603 | var stream = MsfStream{ | |
| 640 | fn init(block_size: u32, file: File, blocks: []u32) MsfStream { | |
| 641 | const stream = MsfStream{ | |
| 604 | 642 | .in_file = file, |
| 605 | 643 | .pos = 0, |
| 606 | .blocks = try allocator.alloc(u32, block_count), | |
| 644 | .blocks = blocks, | |
| 607 | 645 | .block_size = block_size, |
| 608 | 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 | 649 | return stream; |
| 621 | 650 | } |
| 622 | 651 | |
| 623 | 652 | fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { |
| 624 | 653 | var list = ArrayList(u8).init(allocator); |
| 625 | defer list.deinit(); | |
| 626 | 654 | while (true) { |
| 627 | 655 | const byte = try self.stream.readByte(); |
| 628 | 656 | if (byte == 0) { |
| ... | ... | @@ -642,11 +670,12 @@ const MsfStream = struct { |
| 642 | 670 | const in = &file_stream.stream; |
| 643 | 671 | |
| 644 | 672 | var size: usize = 0; |
| 645 | for (buffer) |*byte| { | |
| 646 | byte.* = try in.readByte(); | |
| 647 | ||
| 648 | offset += 1; | |
| 649 | size += 1; | |
| 673 | var rem_buffer = buffer; | |
| 674 | while (size < buffer.len) { | |
| 675 | const size_to_read = math.min(self.block_size - offset, rem_buffer.len); | |
| 676 | size += try in.read(rem_buffer[0..size_to_read]); | |
| 677 | rem_buffer = buffer[size..]; | |
| 678 | offset += size_to_read; | |
| 650 | 679 | |
| 651 | 680 | // If we're at the end of a block, go to the next one. |
| 652 | 681 | if (offset == self.block_size) { |
| ... | ... | @@ -657,8 +686,8 @@ const MsfStream = struct { |
| 657 | 686 | } |
| 658 | 687 | } |
| 659 | 688 | |
| 660 | self.pos += size; | |
| 661 | return size; | |
| 689 | self.pos += buffer.len; | |
| 690 | return buffer.len; | |
| 662 | 691 | } |
| 663 | 692 | |
| 664 | 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 | 146 | error.Unexpected => return error.EnvironmentVariableNotFound, |
| 147 | 147 | else => |e| return e, |
| 148 | 148 | }; |
| 149 | ||
| 150 | 149 | if (result > buf.len) { |
| 151 | 150 | buf = try allocator.realloc(buf, result); |
| 152 | 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 | 155 | error.DanglingSurrogateHalf => return error.InvalidUtf8, |
| 157 | 156 | error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8, |
| 158 | 157 | error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8, |
std/rb.zig+51-3| ... | ... | @@ -93,7 +93,8 @@ pub const Node = struct { |
| 93 | 93 | comptime { |
| 94 | 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 | 100 | fn setColor(node: *Node, color: Color) void { |
| ... | ... | @@ -233,10 +234,13 @@ pub const Tree = struct { |
| 233 | 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 | 241 | pub fn lookup(tree: *Tree, key: *Node) ?*Node { |
| 237 | var parent: *Node = undefined; | |
| 242 | var parent: ?*Node = undefined; | |
| 238 | 243 | var is_left: bool = undefined; |
| 239 | ||
| 240 | 244 | return doLookup(key, tree, &parent, &is_left); |
| 241 | 245 | } |
| 242 | 246 | |
| ... | ... | @@ -544,3 +548,47 @@ test "rb" { |
| 544 | 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 | 77 | pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type { |
| 78 | 78 | return struct { |
| 79 | 79 | const Self = @This(); |
| 80 | const prealloc_exp = blk: { | |
| 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)); | |
| 80 | const ShelfIndex = std.math.Log2Int(usize); | |
| 84 | 81 | |
| 85 | const value = std.math.log2_int(usize, prealloc_item_count); | |
| 86 | break :blk @typeOf(1)(value); | |
| 82 | const prealloc_exp: ShelfIndex = blk: { | |
| 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 | 94 | prealloc_segment: [prealloc_item_count]T, |
| 91 | 95 | dynamic_segments: [][*]T, |
| ... | ... | @@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 157 | 161 | |
| 158 | 162 | /// Grows or shrinks capacity to match usage. |
| 159 | 163 | pub fn setCapacity(self: *Self, new_capacity: usize) !void { |
| 160 | if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) { | |
| 161 | return self.shrinkCapacity(new_capacity); | |
| 162 | } else { | |
| 163 | return self.growCapacity(new_capacity); | |
| 164 | if (prealloc_item_count != 0) { | |
| 165 | if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { | |
| 166 | return self.shrinkCapacity(new_capacity); | |
| 167 | } | |
| 164 | 168 | } |
| 169 | return self.growCapacity(new_capacity); | |
| 165 | 170 | } |
| 166 | 171 | |
| 167 | 172 | /// Only grows capacity, or retains current capacity |
| ... | ... | @@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void { |
| 399 | 404 | testing.expect(item == i); |
| 400 | 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 | 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 | 27 | extern fn wasm_freestanding_start() void { |
| 38 | 28 | _ = callMain(); |
| 39 | 29 | } |
| ... | ... | @@ -45,13 +35,13 @@ nakedcc fn _start() noreturn { |
| 45 | 35 | |
| 46 | 36 | switch (builtin.arch) { |
| 47 | 37 | .x86_64 => { |
| 48 | argc_ptr = asm ("lea (%%rsp), %[argc]" | |
| 49 | : [argc] "=r" (-> [*]usize) | |
| 38 | argc_ptr = asm ("" | |
| 39 | : [argc] "={rsp}" (-> [*]usize) | |
| 50 | 40 | ); |
| 51 | 41 | }, |
| 52 | 42 | .i386 => { |
| 53 | argc_ptr = asm ("lea (%%esp), %[argc]" | |
| 54 | : [argc] "=r" (-> [*]usize) | |
| 43 | argc_ptr = asm ("" | |
| 44 | : [argc] "={esp}" (-> [*]usize) | |
| 55 | 45 | ); |
| 56 | 46 | }, |
| 57 | 47 | .aarch64, .aarch64_be => { |
| ... | ... | @@ -77,7 +67,7 @@ extern fn WinMainCRTStartup() noreturn { |
| 77 | 67 | _ = @import("start_windows_tls.zig"); |
| 78 | 68 | } |
| 79 | 69 | |
| 80 | enableSegfaultHandler(); | |
| 70 | std.debug.maybeEnableSegfaultHandler(); | |
| 81 | 71 | |
| 82 | 72 | std.os.windows.kernel32.ExitProcess(callMain()); |
| 83 | 73 | } |
| ... | ... | @@ -118,7 +108,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { |
| 118 | 108 | std.os.argv = argv[0..argc]; |
| 119 | 109 | std.os.environ = envp; |
| 120 | 110 | |
| 121 | enableSegfaultHandler(); | |
| 111 | std.debug.maybeEnableSegfaultHandler(); | |
| 122 | 112 | |
| 123 | 113 | return callMain(); |
| 124 | 114 | } |
std/std.zig+1| ... | ... | @@ -105,6 +105,7 @@ test "std" { |
| 105 | 105 | _ = @import("packed_int_array.zig"); |
| 106 | 106 | _ = @import("priority_queue.zig"); |
| 107 | 107 | _ = @import("rand.zig"); |
| 108 | _ = @import("rb.zig"); | |
| 108 | 109 | _ = @import("sort.zig"); |
| 109 | 110 | _ = @import("testing.zig"); |
| 110 | 111 | _ = @import("thread.zig"); |
std/zig/ast.zig+109-100| ... | ... | @@ -159,101 +159,99 @@ pub const Error = union(enum) { |
| 159 | 159 | |
| 160 | 160 | pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { |
| 161 | 161 | switch (self.*) { |
| 162 | // TODO https://github.com/ziglang/zig/issues/683 | |
| 163 | @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), | |
| 164 | @TagType(Error).ExpectedContainerMembers => |*x| return x.render(tokens, stream), | |
| 165 | @TagType(Error).ExpectedStringLiteral => |*x| return x.render(tokens, stream), | |
| 166 | @TagType(Error).ExpectedIntegerLiteral => |*x| return x.render(tokens, stream), | |
| 167 | @TagType(Error).ExpectedPubItem => |*x| return x.render(tokens, stream), | |
| 168 | @TagType(Error).ExpectedIdentifier => |*x| return x.render(tokens, stream), | |
| 169 | @TagType(Error).ExpectedStatement => |*x| return x.render(tokens, stream), | |
| 170 | @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), | |
| 171 | @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream), | |
| 172 | @TagType(Error).ExpectedReturnType => |*x| return x.render(tokens, stream), | |
| 173 | @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream), | |
| 174 | @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream), | |
| 175 | @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream), | |
| 176 | @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream), | |
| 177 | @TagType(Error).ExpectedSemiOrElse => |*x| return x.render(tokens, stream), | |
| 178 | @TagType(Error).ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream), | |
| 179 | @TagType(Error).ExpectedLBrace => |*x| return x.render(tokens, stream), | |
| 180 | @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream), | |
| 181 | @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream), | |
| 182 | @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream), | |
| 183 | @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream), | |
| 184 | @TagType(Error).ExpectedCall => |*x| return x.render(tokens, stream), | |
| 185 | @TagType(Error).ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), | |
| 186 | @TagType(Error).ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), | |
| 187 | @TagType(Error).ExtraAlignQualifier => |*x| return x.render(tokens, stream), | |
| 188 | @TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream), | |
| 189 | @TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream), | |
| 190 | @TagType(Error).ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), | |
| 191 | @TagType(Error).ExpectedTypeExpr => |*x| return x.render(tokens, stream), | |
| 192 | @TagType(Error).ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream), | |
| 193 | @TagType(Error).ExpectedParamType => |*x| return x.render(tokens, stream), | |
| 194 | @TagType(Error).ExpectedExpr => |*x| return x.render(tokens, stream), | |
| 195 | @TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream), | |
| 196 | @TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream), | |
| 197 | @TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream), | |
| 198 | @TagType(Error).ExpectedParamList => |*x| return x.render(tokens, stream), | |
| 199 | @TagType(Error).ExpectedPayload => |*x| return x.render(tokens, stream), | |
| 200 | @TagType(Error).ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream), | |
| 201 | @TagType(Error).ExpectedBlockOrExpression => |*x| return x.render(tokens, stream), | |
| 202 | @TagType(Error).ExpectedExprOrAssignment => |*x| return x.render(tokens, stream), | |
| 203 | @TagType(Error).ExpectedPrefixExpr => |*x| return x.render(tokens, stream), | |
| 204 | @TagType(Error).ExpectedLoopExpr => |*x| return x.render(tokens, stream), | |
| 205 | @TagType(Error).ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), | |
| 206 | @TagType(Error).ExpectedSuffixOp => |*x| return x.render(tokens, stream), | |
| 162 | .InvalidToken => |*x| return x.render(tokens, stream), | |
| 163 | .ExpectedContainerMembers => |*x| return x.render(tokens, stream), | |
| 164 | .ExpectedStringLiteral => |*x| return x.render(tokens, stream), | |
| 165 | .ExpectedIntegerLiteral => |*x| return x.render(tokens, stream), | |
| 166 | .ExpectedPubItem => |*x| return x.render(tokens, stream), | |
| 167 | .ExpectedIdentifier => |*x| return x.render(tokens, stream), | |
| 168 | .ExpectedStatement => |*x| return x.render(tokens, stream), | |
| 169 | .ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), | |
| 170 | .ExpectedVarDecl => |*x| return x.render(tokens, stream), | |
| 171 | .ExpectedReturnType => |*x| return x.render(tokens, stream), | |
| 172 | .ExpectedAggregateKw => |*x| return x.render(tokens, stream), | |
| 173 | .UnattachedDocComment => |*x| return x.render(tokens, stream), | |
| 174 | .ExpectedEqOrSemi => |*x| return x.render(tokens, stream), | |
| 175 | .ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream), | |
| 176 | .ExpectedSemiOrElse => |*x| return x.render(tokens, stream), | |
| 177 | .ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream), | |
| 178 | .ExpectedLBrace => |*x| return x.render(tokens, stream), | |
| 179 | .ExpectedColonOrRParen => |*x| return x.render(tokens, stream), | |
| 180 | .ExpectedLabelable => |*x| return x.render(tokens, stream), | |
| 181 | .ExpectedInlinable => |*x| return x.render(tokens, stream), | |
| 182 | .ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream), | |
| 183 | .ExpectedCall => |*x| return x.render(tokens, stream), | |
| 184 | .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream), | |
| 185 | .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream), | |
| 186 | .ExtraAlignQualifier => |*x| return x.render(tokens, stream), | |
| 187 | .ExtraConstQualifier => |*x| return x.render(tokens, stream), | |
| 188 | .ExtraVolatileQualifier => |*x| return x.render(tokens, stream), | |
| 189 | .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream), | |
| 190 | .ExpectedTypeExpr => |*x| return x.render(tokens, stream), | |
| 191 | .ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream), | |
| 192 | .ExpectedParamType => |*x| return x.render(tokens, stream), | |
| 193 | .ExpectedExpr => |*x| return x.render(tokens, stream), | |
| 194 | .ExpectedPrimaryExpr => |*x| return x.render(tokens, stream), | |
| 195 | .ExpectedToken => |*x| return x.render(tokens, stream), | |
| 196 | .ExpectedCommaOrEnd => |*x| return x.render(tokens, stream), | |
| 197 | .ExpectedParamList => |*x| return x.render(tokens, stream), | |
| 198 | .ExpectedPayload => |*x| return x.render(tokens, stream), | |
| 199 | .ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream), | |
| 200 | .ExpectedBlockOrExpression => |*x| return x.render(tokens, stream), | |
| 201 | .ExpectedExprOrAssignment => |*x| return x.render(tokens, stream), | |
| 202 | .ExpectedPrefixExpr => |*x| return x.render(tokens, stream), | |
| 203 | .ExpectedLoopExpr => |*x| return x.render(tokens, stream), | |
| 204 | .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), | |
| 205 | .ExpectedSuffixOp => |*x| return x.render(tokens, stream), | |
| 207 | 206 | } |
| 208 | 207 | } |
| 209 | 208 | |
| 210 | 209 | pub fn loc(self: *const Error) TokenIndex { |
| 211 | 210 | switch (self.*) { |
| 212 | // TODO https://github.com/ziglang/zig/issues/683 | |
| 213 | @TagType(Error).InvalidToken => |x| return x.token, | |
| 214 | @TagType(Error).ExpectedContainerMembers => |x| return x.token, | |
| 215 | @TagType(Error).ExpectedStringLiteral => |x| return x.token, | |
| 216 | @TagType(Error).ExpectedIntegerLiteral => |x| return x.token, | |
| 217 | @TagType(Error).ExpectedPubItem => |x| return x.token, | |
| 218 | @TagType(Error).ExpectedIdentifier => |x| return x.token, | |
| 219 | @TagType(Error).ExpectedStatement => |x| return x.token, | |
| 220 | @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, | |
| 221 | @TagType(Error).ExpectedVarDecl => |x| return x.token, | |
| 222 | @TagType(Error).ExpectedReturnType => |x| return x.token, | |
| 223 | @TagType(Error).ExpectedAggregateKw => |x| return x.token, | |
| 224 | @TagType(Error).UnattachedDocComment => |x| return x.token, | |
| 225 | @TagType(Error).ExpectedEqOrSemi => |x| return x.token, | |
| 226 | @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token, | |
| 227 | @TagType(Error).ExpectedSemiOrElse => |x| return x.token, | |
| 228 | @TagType(Error).ExpectedLabelOrLBrace => |x| return x.token, | |
| 229 | @TagType(Error).ExpectedLBrace => |x| return x.token, | |
| 230 | @TagType(Error).ExpectedColonOrRParen => |x| return x.token, | |
| 231 | @TagType(Error).ExpectedLabelable => |x| return x.token, | |
| 232 | @TagType(Error).ExpectedInlinable => |x| return x.token, | |
| 233 | @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token, | |
| 234 | @TagType(Error).ExpectedCall => |x| return x.node.firstToken(), | |
| 235 | @TagType(Error).ExpectedCallOrFnProto => |x| return x.node.firstToken(), | |
| 236 | @TagType(Error).ExpectedSliceOrRBracket => |x| return x.token, | |
| 237 | @TagType(Error).ExtraAlignQualifier => |x| return x.token, | |
| 238 | @TagType(Error).ExtraConstQualifier => |x| return x.token, | |
| 239 | @TagType(Error).ExtraVolatileQualifier => |x| return x.token, | |
| 240 | @TagType(Error).ExtraAllowZeroQualifier => |x| return x.token, | |
| 241 | @TagType(Error).ExpectedTypeExpr => |x| return x.token, | |
| 242 | @TagType(Error).ExpectedPrimaryTypeExpr => |x| return x.token, | |
| 243 | @TagType(Error).ExpectedParamType => |x| return x.token, | |
| 244 | @TagType(Error).ExpectedExpr => |x| return x.token, | |
| 245 | @TagType(Error).ExpectedPrimaryExpr => |x| return x.token, | |
| 246 | @TagType(Error).ExpectedToken => |x| return x.token, | |
| 247 | @TagType(Error).ExpectedCommaOrEnd => |x| return x.token, | |
| 248 | @TagType(Error).ExpectedParamList => |x| return x.token, | |
| 249 | @TagType(Error).ExpectedPayload => |x| return x.token, | |
| 250 | @TagType(Error).ExpectedBlockOrAssignment => |x| return x.token, | |
| 251 | @TagType(Error).ExpectedBlockOrExpression => |x| return x.token, | |
| 252 | @TagType(Error).ExpectedExprOrAssignment => |x| return x.token, | |
| 253 | @TagType(Error).ExpectedPrefixExpr => |x| return x.token, | |
| 254 | @TagType(Error).ExpectedLoopExpr => |x| return x.token, | |
| 255 | @TagType(Error).ExpectedDerefOrUnwrap => |x| return x.token, | |
| 256 | @TagType(Error).ExpectedSuffixOp => |x| return x.token, | |
| 211 | .InvalidToken => |x| return x.token, | |
| 212 | .ExpectedContainerMembers => |x| return x.token, | |
| 213 | .ExpectedStringLiteral => |x| return x.token, | |
| 214 | .ExpectedIntegerLiteral => |x| return x.token, | |
| 215 | .ExpectedPubItem => |x| return x.token, | |
| 216 | .ExpectedIdentifier => |x| return x.token, | |
| 217 | .ExpectedStatement => |x| return x.token, | |
| 218 | .ExpectedVarDeclOrFn => |x| return x.token, | |
| 219 | .ExpectedVarDecl => |x| return x.token, | |
| 220 | .ExpectedReturnType => |x| return x.token, | |
| 221 | .ExpectedAggregateKw => |x| return x.token, | |
| 222 | .UnattachedDocComment => |x| return x.token, | |
| 223 | .ExpectedEqOrSemi => |x| return x.token, | |
| 224 | .ExpectedSemiOrLBrace => |x| return x.token, | |
| 225 | .ExpectedSemiOrElse => |x| return x.token, | |
| 226 | .ExpectedLabelOrLBrace => |x| return x.token, | |
| 227 | .ExpectedLBrace => |x| return x.token, | |
| 228 | .ExpectedColonOrRParen => |x| return x.token, | |
| 229 | .ExpectedLabelable => |x| return x.token, | |
| 230 | .ExpectedInlinable => |x| return x.token, | |
| 231 | .ExpectedAsmOutputReturnOrType => |x| return x.token, | |
| 232 | .ExpectedCall => |x| return x.node.firstToken(), | |
| 233 | .ExpectedCallOrFnProto => |x| return x.node.firstToken(), | |
| 234 | .ExpectedSliceOrRBracket => |x| return x.token, | |
| 235 | .ExtraAlignQualifier => |x| return x.token, | |
| 236 | .ExtraConstQualifier => |x| return x.token, | |
| 237 | .ExtraVolatileQualifier => |x| return x.token, | |
| 238 | .ExtraAllowZeroQualifier => |x| return x.token, | |
| 239 | .ExpectedTypeExpr => |x| return x.token, | |
| 240 | .ExpectedPrimaryTypeExpr => |x| return x.token, | |
| 241 | .ExpectedParamType => |x| return x.token, | |
| 242 | .ExpectedExpr => |x| return x.token, | |
| 243 | .ExpectedPrimaryExpr => |x| return x.token, | |
| 244 | .ExpectedToken => |x| return x.token, | |
| 245 | .ExpectedCommaOrEnd => |x| return x.token, | |
| 246 | .ExpectedParamList => |x| return x.token, | |
| 247 | .ExpectedPayload => |x| return x.token, | |
| 248 | .ExpectedBlockOrAssignment => |x| return x.token, | |
| 249 | .ExpectedBlockOrExpression => |x| return x.token, | |
| 250 | .ExpectedExprOrAssignment => |x| return x.token, | |
| 251 | .ExpectedPrefixExpr => |x| return x.token, | |
| 252 | .ExpectedLoopExpr => |x| return x.token, | |
| 253 | .ExpectedDerefOrUnwrap => |x| return x.token, | |
| 254 | .ExpectedSuffixOp => |x| return x.token, | |
| 257 | 255 | } |
| 258 | 256 | } |
| 259 | 257 | |
| ... | ... | @@ -320,8 +318,19 @@ pub const Error = union(enum) { |
| 320 | 318 | expected_id: Token.Id, |
| 321 | 319 | |
| 322 | 320 | pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { |
| 323 | const token_name = @tagName(tokens.at(self.token).id); | |
| 324 | return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name); | |
| 321 | const found_token = tokens.at(self.token); | |
| 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 | 1717 | i -= 1; |
| 1709 | 1718 | |
| 1710 | 1719 | switch (self.op) { |
| 1711 | @TagType(Op).Call => |*call_info| { | |
| 1720 | .Call => |*call_info| { | |
| 1712 | 1721 | if (i < call_info.params.len) return call_info.params.at(i).*; |
| 1713 | 1722 | i -= call_info.params.len; |
| 1714 | 1723 | }, |
| 1715 | Op.ArrayAccess => |index_expr| { | |
| 1724 | .ArrayAccess => |index_expr| { | |
| 1716 | 1725 | if (i < 1) return index_expr; |
| 1717 | 1726 | i -= 1; |
| 1718 | 1727 | }, |
| 1719 | @TagType(Op).Slice => |range| { | |
| 1728 | .Slice => |range| { | |
| 1720 | 1729 | if (i < 1) return range.start; |
| 1721 | 1730 | i -= 1; |
| 1722 | 1731 | |
| ... | ... | @@ -1725,16 +1734,16 @@ pub const Node = struct { |
| 1725 | 1734 | i -= 1; |
| 1726 | 1735 | } |
| 1727 | 1736 | }, |
| 1728 | Op.ArrayInitializer => |*exprs| { | |
| 1737 | .ArrayInitializer => |*exprs| { | |
| 1729 | 1738 | if (i < exprs.len) return exprs.at(i).*; |
| 1730 | 1739 | i -= exprs.len; |
| 1731 | 1740 | }, |
| 1732 | Op.StructInitializer => |*fields| { | |
| 1741 | .StructInitializer => |*fields| { | |
| 1733 | 1742 | if (i < fields.len) return fields.at(i).*; |
| 1734 | 1743 | i -= fields.len; |
| 1735 | 1744 | }, |
| 1736 | Op.UnwrapOptional, | |
| 1737 | Op.Deref, | |
| 1745 | .UnwrapOptional, | |
| 1746 | .Deref, | |
| 1738 | 1747 | => {}, |
| 1739 | 1748 | } |
| 1740 | 1749 | |
| ... | ... | @@ -1743,7 +1752,7 @@ pub const Node = struct { |
| 1743 | 1752 | |
| 1744 | 1753 | pub fn firstToken(self: *const SuffixOp) TokenIndex { |
| 1745 | 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 | 1756 | else => {}, |
| 1748 | 1757 | } |
| 1749 | 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 | 774 | arena, |
| 775 | 775 | it, |
| 776 | 776 | tree, |
| 777 | SimpleBinOpParseFn(.Keyword_and, Node.InfixOp.Op.BoolAnd), | |
| 777 | SimpleBinOpParseFn(.Keyword_and, .BoolAnd), | |
| 778 | 778 | parseCompareExpr, |
| 779 | 779 | .Infinitely, |
| 780 | 780 | ); |
std/zig/parser_test.zig+26| ... | ... | @@ -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 | 2296 | const std = @import("std"); |
| 2271 | 2297 | const mem = std.mem; |
| 2272 | 2298 | const warn = std.debug.warn; |
std/zig/render.zig+7-1| ... | ... | @@ -2020,7 +2020,13 @@ fn renderTokenOffset( |
| 2020 | 2020 | |
| 2021 | 2021 | const after_comment_token = tree.tokens.at(token_index + offset); |
| 2022 | 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 | 2030 | else => indent, |
| 2025 | 2031 | }; |
| 2026 | 2032 | try stream.writeByteNTimes(' ', next_line_indent); |
std/zig/tokenizer.zig+6| ... | ... | @@ -77,6 +77,7 @@ pub const Token = struct { |
| 77 | 77 | |
| 78 | 78 | pub const Id = enum { |
| 79 | 79 | Invalid, |
| 80 | Invalid_ampersands, | |
| 80 | 81 | Identifier, |
| 81 | 82 | StringLiteral, |
| 82 | 83 | MultilineStringLiteralLine, |
| ... | ... | @@ -484,6 +485,11 @@ pub const Tokenizer = struct { |
| 484 | 485 | }, |
| 485 | 486 | |
| 486 | 487 | State.Ampersand => switch (c) { |
| 488 | '&' => { | |
| 489 | result.id = Token.Id.Invalid_ampersands; | |
| 490 | self.index += 1; | |
| 491 | break; | |
| 492 | }, | |
| 487 | 493 | '=' => { |
| 488 | 494 | result.id = Token.Id.AmpersandEqual; |
| 489 | 495 | self.index += 1; |
test/compile_errors.zig+9-9| ... | ... | @@ -201,7 +201,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 201 | 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 | 207 | cases.add( |
| ... | ... | @@ -234,7 +234,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 234 | 234 | |
| 235 | 235 | cases.add( |
| 236 | 236 | "usingnamespace with wrong type", |
| 237 | \\use void; | |
| 237 | \\usingnamespace void; | |
| 238 | 238 | , |
| 239 | 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 | 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 | 2746 | cases.add( |
| ... | ... | @@ -2750,7 +2750,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2750 | 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 | 2756 | cases.add( |
| ... | ... | @@ -2820,7 +2820,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2820 | 2820 | \\} |
| 2821 | 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 | 2826 | cases.add( |
| ... | ... | @@ -3883,7 +3883,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3883 | 3883 | \\ |
| 3884 | 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 | 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 | 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 | 4139 | cases.add( |
| ... | ... | @@ -4143,7 +4143,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4143 | 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 | 4149 | cases.add( |
| ... | ... | @@ -4291,7 +4291,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4291 | 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 | 4297 | cases.add( |
test/stage1/behavior.zig+1| ... | ... | @@ -93,6 +93,7 @@ comptime { |
| 93 | 93 | _ = @import("behavior/undefined.zig"); |
| 94 | 94 | _ = @import("behavior/underscore.zig"); |
| 95 | 95 | _ = @import("behavior/union.zig"); |
| 96 | _ = @import("behavior/usingnamespace.zig"); | |
| 96 | 97 | _ = @import("behavior/var_args.zig"); |
| 97 | 98 | _ = @import("behavior/vector.zig"); |
| 98 | 99 | _ = @import("behavior/void.zig"); |
test/stage1/behavior/atomics.zig+31| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 3 | 4 | const builtin = @import("builtin"); |
| 4 | 5 | const AtomicRmwOp = builtin.AtomicRmwOp; |
| 5 | 6 | const AtomicOrder = builtin.AtomicOrder; |
| ... | ... | @@ -69,3 +70,33 @@ test "cmpxchg with ptr" { |
| 69 | 70 | expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); |
| 70 | 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 | 1 | const std = @import("std"); |
| 2 | 2 | const expect = std.testing.expect; |
| 3 | const expectEqual = std.testing.expectEqual; | |
| 3 | 4 | const builtin = @import("builtin"); |
| 4 | 5 | |
| 5 | 6 | test "compile time recursion" { |
| ... | ... | @@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" { |
| 794 | 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 | 228 | S.entry(); |
| 229 | 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 | 74 | S.doTheTest(); |
| 75 | 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 | 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 | 1817 | /////////////// Cases for only stage1 because stage2 behavior is better //////////////// |
| 1784 | 1818 | cases.addC("Parameterless function prototypes", |
| 1785 | 1819 | \\void foo() {} |