authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-03 12:39:15-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-03 12:39:15-04:00
log63ebd9d12e48765514777418e12f55576ff63509
tree05f40973b86f91bffd6458247bd9cd2c3d66b72d
parenta2e1be0346c364c4327dc2b81bbcdeca12414dab
parent5687323cd2a759dfdf9533e46e3de8cddb1b55b7
signature Commit is signed but in an unrecognized format.

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


45 files changed, 1354 insertions(+), 725 deletions(-)

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