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()
209209 else()
210210 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Wno-comment")
211211 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")
213213 endif()
214214 endif()
215215 set_target_properties(embedded_lld_lib PROPERTIES
......@@ -511,19 +511,23 @@ set(OPTIMIZED_C_FLAGS "-std=c99 -O3")
511511
512512set(EXE_LDFLAGS " ")
513513if(MSVC)
514 set(EXE_LDFLAGS "/STACK:16777216")
514 set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216")
515515elseif(MINGW)
516516 set(EXE_LDFLAGS "${EXE_LDFLAGS} -Wl,--stack,16777216")
517517endif()
518518
519519if(ZIG_STATIC)
520520 if(APPLE)
521 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++")
521 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++")
522522 elseif(MINGW)
523 set(EXE_LDFLAGS "-static-libgcc -static-libstdc++ -Wl,-Bstatic,--whole-archive -lwinpthread -lz3 -lz -lgomp -Wl,--no-whole-archive")
524 else()
525 set(EXE_LDFLAGS "-static")
523 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static-libgcc -static-libstdc++ -Wl,-Bstatic, -lwinpthread -lz3 -lz -lgomp")
524 elseif(NOT MSVC)
525 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static")
526526 endif()
527else()
528 if(MINGW)
529 set(EXE_LDFLAGS "${EXE_LDFLAGS} -lz3")
530 endif()
527531endif()
528532
529533if(ZIG_TEST_COVERAGE)
......@@ -559,11 +563,6 @@ if(NOT MSVC)
559563 target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
560564endif()
561565
562if(MINGW)
563 find_library(Z3_LIBRARIES NAMES z3 z3.dll)
564 target_link_libraries(compiler LINK_PUBLIC ${Z3_LIBRARIES})
565endif()
566
567566if(ZIG_DIA_GUIDS_LIB)
568567 target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
569568endif()
doc/docgen.zig+118-118
......@@ -742,101 +742,101 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
742742 const token = tokenizer.next();
743743 try writeEscaped(out, src[index..token.start]);
744744 switch (token.id) {
745 std.zig.Token.Id.Eof => break,
746
747 std.zig.Token.Id.Keyword_align,
748 std.zig.Token.Id.Keyword_and,
749 std.zig.Token.Id.Keyword_asm,
750 std.zig.Token.Id.Keyword_async,
751 std.zig.Token.Id.Keyword_await,
752 std.zig.Token.Id.Keyword_break,
753 std.zig.Token.Id.Keyword_cancel,
754 std.zig.Token.Id.Keyword_catch,
755 std.zig.Token.Id.Keyword_comptime,
756 std.zig.Token.Id.Keyword_const,
757 std.zig.Token.Id.Keyword_continue,
758 std.zig.Token.Id.Keyword_defer,
759 std.zig.Token.Id.Keyword_else,
760 std.zig.Token.Id.Keyword_enum,
761 std.zig.Token.Id.Keyword_errdefer,
762 std.zig.Token.Id.Keyword_error,
763 std.zig.Token.Id.Keyword_export,
764 std.zig.Token.Id.Keyword_extern,
765 std.zig.Token.Id.Keyword_for,
766 std.zig.Token.Id.Keyword_if,
767 std.zig.Token.Id.Keyword_inline,
768 std.zig.Token.Id.Keyword_nakedcc,
769 std.zig.Token.Id.Keyword_noalias,
770 std.zig.Token.Id.Keyword_or,
771 std.zig.Token.Id.Keyword_orelse,
772 std.zig.Token.Id.Keyword_packed,
773 std.zig.Token.Id.Keyword_promise,
774 std.zig.Token.Id.Keyword_pub,
775 std.zig.Token.Id.Keyword_resume,
776 std.zig.Token.Id.Keyword_return,
777 std.zig.Token.Id.Keyword_linksection,
778 std.zig.Token.Id.Keyword_stdcallcc,
779 std.zig.Token.Id.Keyword_struct,
780 std.zig.Token.Id.Keyword_suspend,
781 std.zig.Token.Id.Keyword_switch,
782 std.zig.Token.Id.Keyword_test,
783 std.zig.Token.Id.Keyword_threadlocal,
784 std.zig.Token.Id.Keyword_try,
785 std.zig.Token.Id.Keyword_union,
786 std.zig.Token.Id.Keyword_unreachable,
787 std.zig.Token.Id.Keyword_usingnamespace,
788 std.zig.Token.Id.Keyword_var,
789 std.zig.Token.Id.Keyword_volatile,
790 std.zig.Token.Id.Keyword_allowzero,
791 std.zig.Token.Id.Keyword_while,
745 .Eof => break,
746
747 .Keyword_align,
748 .Keyword_and,
749 .Keyword_asm,
750 .Keyword_async,
751 .Keyword_await,
752 .Keyword_break,
753 .Keyword_cancel,
754 .Keyword_catch,
755 .Keyword_comptime,
756 .Keyword_const,
757 .Keyword_continue,
758 .Keyword_defer,
759 .Keyword_else,
760 .Keyword_enum,
761 .Keyword_errdefer,
762 .Keyword_error,
763 .Keyword_export,
764 .Keyword_extern,
765 .Keyword_for,
766 .Keyword_if,
767 .Keyword_inline,
768 .Keyword_nakedcc,
769 .Keyword_noalias,
770 .Keyword_or,
771 .Keyword_orelse,
772 .Keyword_packed,
773 .Keyword_promise,
774 .Keyword_pub,
775 .Keyword_resume,
776 .Keyword_return,
777 .Keyword_linksection,
778 .Keyword_stdcallcc,
779 .Keyword_struct,
780 .Keyword_suspend,
781 .Keyword_switch,
782 .Keyword_test,
783 .Keyword_threadlocal,
784 .Keyword_try,
785 .Keyword_union,
786 .Keyword_unreachable,
787 .Keyword_usingnamespace,
788 .Keyword_var,
789 .Keyword_volatile,
790 .Keyword_allowzero,
791 .Keyword_while,
792792 => {
793793 try out.write("<span class=\"tok-kw\">");
794794 try writeEscaped(out, src[token.start..token.end]);
795795 try out.write("</span>");
796796 },
797797
798 std.zig.Token.Id.Keyword_fn => {
798 .Keyword_fn => {
799799 try out.write("<span class=\"tok-kw\">");
800800 try writeEscaped(out, src[token.start..token.end]);
801801 try out.write("</span>");
802802 next_tok_is_fn = true;
803803 },
804804
805 std.zig.Token.Id.Keyword_undefined,
806 std.zig.Token.Id.Keyword_null,
807 std.zig.Token.Id.Keyword_true,
808 std.zig.Token.Id.Keyword_false,
805 .Keyword_undefined,
806 .Keyword_null,
807 .Keyword_true,
808 .Keyword_false,
809809 => {
810810 try out.write("<span class=\"tok-null\">");
811811 try writeEscaped(out, src[token.start..token.end]);
812812 try out.write("</span>");
813813 },
814814
815 std.zig.Token.Id.StringLiteral,
816 std.zig.Token.Id.MultilineStringLiteralLine,
817 std.zig.Token.Id.CharLiteral,
815 .StringLiteral,
816 .MultilineStringLiteralLine,
817 .CharLiteral,
818818 => {
819819 try out.write("<span class=\"tok-str\">");
820820 try writeEscaped(out, src[token.start..token.end]);
821821 try out.write("</span>");
822822 },
823823
824 std.zig.Token.Id.Builtin => {
824 .Builtin => {
825825 try out.write("<span class=\"tok-builtin\">");
826826 try writeEscaped(out, src[token.start..token.end]);
827827 try out.write("</span>");
828828 },
829829
830 std.zig.Token.Id.LineComment,
831 std.zig.Token.Id.DocComment,
832 std.zig.Token.Id.ShebangLine,
830 .LineComment,
831 .DocComment,
832 .ShebangLine,
833833 => {
834834 try out.write("<span class=\"tok-comment\">");
835835 try writeEscaped(out, src[token.start..token.end]);
836836 try out.write("</span>");
837837 },
838838
839 std.zig.Token.Id.Identifier => {
839 .Identifier => {
840840 if (prev_tok_was_fn) {
841841 try out.write("<span class=\"tok-fn\">");
842842 try writeEscaped(out, src[token.start..token.end]);
......@@ -864,72 +864,72 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
864864 }
865865 },
866866
867 std.zig.Token.Id.IntegerLiteral,
868 std.zig.Token.Id.FloatLiteral,
867 .IntegerLiteral,
868 .FloatLiteral,
869869 => {
870870 try out.write("<span class=\"tok-number\">");
871871 try writeEscaped(out, src[token.start..token.end]);
872872 try out.write("</span>");
873873 },
874874
875 std.zig.Token.Id.Bang,
876 std.zig.Token.Id.Pipe,
877 std.zig.Token.Id.PipePipe,
878 std.zig.Token.Id.PipeEqual,
879 std.zig.Token.Id.Equal,
880 std.zig.Token.Id.EqualEqual,
881 std.zig.Token.Id.EqualAngleBracketRight,
882 std.zig.Token.Id.BangEqual,
883 std.zig.Token.Id.LParen,
884 std.zig.Token.Id.RParen,
885 std.zig.Token.Id.Semicolon,
886 std.zig.Token.Id.Percent,
887 std.zig.Token.Id.PercentEqual,
888 std.zig.Token.Id.LBrace,
889 std.zig.Token.Id.RBrace,
890 std.zig.Token.Id.LBracket,
891 std.zig.Token.Id.RBracket,
892 std.zig.Token.Id.Period,
893 std.zig.Token.Id.Ellipsis2,
894 std.zig.Token.Id.Ellipsis3,
895 std.zig.Token.Id.Caret,
896 std.zig.Token.Id.CaretEqual,
897 std.zig.Token.Id.Plus,
898 std.zig.Token.Id.PlusPlus,
899 std.zig.Token.Id.PlusEqual,
900 std.zig.Token.Id.PlusPercent,
901 std.zig.Token.Id.PlusPercentEqual,
902 std.zig.Token.Id.Minus,
903 std.zig.Token.Id.MinusEqual,
904 std.zig.Token.Id.MinusPercent,
905 std.zig.Token.Id.MinusPercentEqual,
906 std.zig.Token.Id.Asterisk,
907 std.zig.Token.Id.AsteriskEqual,
908 std.zig.Token.Id.AsteriskAsterisk,
909 std.zig.Token.Id.AsteriskPercent,
910 std.zig.Token.Id.AsteriskPercentEqual,
911 std.zig.Token.Id.Arrow,
912 std.zig.Token.Id.Colon,
913 std.zig.Token.Id.Slash,
914 std.zig.Token.Id.SlashEqual,
915 std.zig.Token.Id.Comma,
916 std.zig.Token.Id.Ampersand,
917 std.zig.Token.Id.AmpersandEqual,
918 std.zig.Token.Id.QuestionMark,
919 std.zig.Token.Id.AngleBracketLeft,
920 std.zig.Token.Id.AngleBracketLeftEqual,
921 std.zig.Token.Id.AngleBracketAngleBracketLeft,
922 std.zig.Token.Id.AngleBracketAngleBracketLeftEqual,
923 std.zig.Token.Id.AngleBracketRight,
924 std.zig.Token.Id.AngleBracketRightEqual,
925 std.zig.Token.Id.AngleBracketAngleBracketRight,
926 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
927 std.zig.Token.Id.Tilde,
928 std.zig.Token.Id.BracketStarBracket,
929 std.zig.Token.Id.BracketStarCBracket,
875 .Bang,
876 .Pipe,
877 .PipePipe,
878 .PipeEqual,
879 .Equal,
880 .EqualEqual,
881 .EqualAngleBracketRight,
882 .BangEqual,
883 .LParen,
884 .RParen,
885 .Semicolon,
886 .Percent,
887 .PercentEqual,
888 .LBrace,
889 .RBrace,
890 .LBracket,
891 .RBracket,
892 .Period,
893 .Ellipsis2,
894 .Ellipsis3,
895 .Caret,
896 .CaretEqual,
897 .Plus,
898 .PlusPlus,
899 .PlusEqual,
900 .PlusPercent,
901 .PlusPercentEqual,
902 .Minus,
903 .MinusEqual,
904 .MinusPercent,
905 .MinusPercentEqual,
906 .Asterisk,
907 .AsteriskEqual,
908 .AsteriskAsterisk,
909 .AsteriskPercent,
910 .AsteriskPercentEqual,
911 .Arrow,
912 .Colon,
913 .Slash,
914 .SlashEqual,
915 .Comma,
916 .Ampersand,
917 .AmpersandEqual,
918 .QuestionMark,
919 .AngleBracketLeft,
920 .AngleBracketLeftEqual,
921 .AngleBracketAngleBracketLeft,
922 .AngleBracketAngleBracketLeftEqual,
923 .AngleBracketRight,
924 .AngleBracketRightEqual,
925 .AngleBracketAngleBracketRight,
926 .AngleBracketAngleBracketRightEqual,
927 .Tilde,
928 .BracketStarBracket,
929 .BracketStarCBracket,
930930 => try writeEscaped(out, src[token.start..token.end]),
931931
932 std.zig.Token.Id.Invalid => return parseError(
932 .Invalid, .Invalid_ampersands => return parseError(
933933 docgen_tokenizer,
934934 source_token,
935935 "syntax error",
doc/langref.html.in+16
......@@ -6330,6 +6330,22 @@ comptime {
63306330 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
63316331 we can remove this restriction
63326332 </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>
63336349 {#header_close#}
63346350 {#header_open|@bitCast#}
63356351 <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
src/all_types.hpp+11-7
......@@ -366,6 +366,7 @@ enum TldId {
366366 TldIdFn,
367367 TldIdContainer,
368368 TldIdCompTime,
369 TldIdUsingNamespace,
369370};
370371
371372enum TldResolution {
......@@ -413,6 +414,12 @@ struct TldCompTime {
413414 Tld base;
414415};
415416
417struct TldUsingNamespace {
418 Tld base;
419
420 ConstExprValue *using_namespace_value;
421};
422
416423struct TypeEnumField {
417424 Buf *name;
418425 BigInt value;
......@@ -453,7 +460,7 @@ enum NodeType {
453460 NodeTypeFieldAccessExpr,
454461 NodeTypePtrDeref,
455462 NodeTypeUnwrapOptional,
456 NodeTypeUse,
463 NodeTypeUsingNamespace,
457464 NodeTypeBoolLiteral,
458465 NodeTypeNullLiteral,
459466 NodeTypeUndefinedLiteral,
......@@ -715,9 +722,6 @@ struct AstNodeArrayType {
715722struct AstNodeUsingNamespace {
716723 VisibMod visib_mod;
717724 AstNode *expr;
718
719 TldResolution resolution;
720 ConstExprValue *using_namespace_value;
721725};
722726
723727struct AstNodeIfBoolExpr {
......@@ -1745,8 +1749,6 @@ struct CodeGen {
17451749
17461750 ZigList<Tld *> resolve_queue;
17471751 size_t resolve_queue_index;
1748 ZigList<AstNode *> use_queue;
1749 size_t use_queue_index;
17501752 ZigList<TimeEvent> timing_events;
17511753 ZigList<AstNode *> tld_ref_source_node_stack;
17521754 ZigList<ZigFn *> inline_fns;
......@@ -2005,7 +2007,7 @@ struct ScopeDecls {
20052007 Scope base;
20062008
20072009 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> decl_table;
2008 ZigList<AstNode *> use_decls;
2010 ZigList<TldUsingNamespace *> use_decls;
20092011 AstNode *safety_set_node;
20102012 AstNode *fast_math_set_node;
20112013 ZigType *import;
......@@ -2541,6 +2543,7 @@ struct IrInstructionLoadPtrGen {
25412543struct IrInstructionStorePtr {
25422544 IrInstruction base;
25432545
2546 bool allow_write_through_const;
25442547 IrInstruction *ptr;
25452548 IrInstruction *value;
25462549};
......@@ -3705,6 +3708,7 @@ enum ResultLocId {
37053708struct ResultLoc {
37063709 ResultLocId id;
37073710 bool written;
3711 bool allow_write_through_const;
37083712 IrInstruction *resolved_loc; // result ptr
37093713 IrInstruction *source_instruction;
37103714 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
2828static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type);
2929static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
3030static 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
3234static bool is_top_level_struct(ZigType *import) {
3335 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) {
28542856 add_node_error(g, tld->source_node, buf_sprintf("non-extern function has no body"));
28552857 return;
28562858 }
2859 } else if (tld->id == TldIdUsingNamespace) {
2860 g->resolve_queue.append(tld);
28572861 }
28582862 if (is_export) {
28592863 g->resolve_queue.append(tld);
......@@ -2867,7 +2871,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
28672871 }
28682872 }
28692873
2870 {
2874 if (tld->name != nullptr) {
28712875 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
28722876 if (entry) {
28732877 Tld *other_tld = entry->value;
......@@ -2875,9 +2879,7 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
28752879 add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition is here"));
28762880 return;
28772881 }
2878 }
28792882
2880 {
28812883 ZigType *type;
28822884 if (get_primitive_type(g, tld->name, &type) != ErrorPrimitiveTypeNotFound) {
28832885 add_node_error(g, tld->source_node,
......@@ -2977,12 +2979,14 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
29772979
29782980 break;
29792981 }
2980 case NodeTypeUse:
2981 {
2982 g->use_queue.append(node);
2983 decls_scope->use_decls.append(node);
2984 break;
2985 }
2982 case NodeTypeUsingNamespace: {
2983 VisibMod visib_mod = node->data.using_namespace.visib_mod;
2984 TldUsingNamespace *tld_using_namespace = allocate<TldUsingNamespace>(1);
2985 init_tld(&tld_using_namespace->base, TldIdUsingNamespace, nullptr, visib_mod, node, &decls_scope->base);
2986 add_top_level_decl(g, decls_scope, &tld_using_namespace->base);
2987 decls_scope->use_decls.append(tld_using_namespace);
2988 break;
2989 }
29862990 case NodeTypeTestDecl:
29872991 preview_test_decl(g, node, decls_scope);
29882992 break;
......@@ -3266,6 +3270,118 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
32663270 g->global_vars.append(tld_var);
32673271}
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
32693385void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
32703386 if (tld->resolution != TldResolutionUnresolved)
32713387 return;
......@@ -3299,6 +3415,14 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
32993415 resolve_decl_comptime(g, tld_comptime);
33003416 break;
33013417 }
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 }
33023426 }
33033427
33043428 tld->resolution = TldResolutionOk;
......@@ -3308,10 +3432,10 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) {
33083432Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name) {
33093433 // resolve all the using_namespace decls
33103434 for (size_t i = 0; i < decls_scope->use_decls.length; i += 1) {
3311 AstNode *use_decl_node = decls_scope->use_decls.at(i);
3312 if (use_decl_node->data.using_namespace.resolution == TldResolutionUnresolved) {
3313 preview_use_decl(g, use_decl_node, decls_scope);
3314 resolve_use_decl(g, use_decl_node, decls_scope);
3435 TldUsingNamespace *tld_using_namespace = decls_scope->use_decls.at(i);
3436 if (tld_using_namespace->base.resolution == TldResolutionUnresolved) {
3437 preview_use_decl(g, tld_using_namespace, decls_scope);
3438 resolve_use_decl(g, tld_using_namespace, decls_scope);
33153439 }
33163440 }
33173441
......@@ -3752,110 +3876,6 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
37523876 analyze_fn_ir(g, fn_table_entry, return_type_node);
37533877}
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
38593879ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Buf *source_code,
38603880 SourceKind source_kind)
38613881{
......@@ -3975,18 +3995,8 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
39753995
39763996void semantic_analyze(CodeGen *g) {
39773997 while (g->resolve_queue_index < g->resolve_queue.length ||
3978 g->fn_defs_index < g->fn_defs.length ||
3979 g->use_queue_index < g->use_queue.length)
3998 g->fn_defs_index < g->fn_defs.length)
39803999 {
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 }
39904000 for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) {
39914001 Tld *tld = g->resolve_queue.at(g->resolve_queue_index);
39924002 AstNode *source_node = nullptr;
src/analyze.hpp-2
......@@ -86,8 +86,6 @@ bool is_array_ref(ZigType *type_entry);
8686bool is_container_ref(ZigType *type_entry);
8787bool is_valid_vector_elem_type(ZigType *elem_type);
8888void 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);
9189ZigFn *scope_fn_entry(Scope *scope);
9290ZigPackage *scope_package(Scope *scope);
9391ZigType *get_scope_import(Scope *scope);
src/ast_render.cpp+20-13
......@@ -193,8 +193,8 @@ static const char *node_type_str(NodeType node_type) {
193193 return "Symbol";
194194 case NodeTypePrefixOpExpr:
195195 return "PrefixOpExpr";
196 case NodeTypeUse:
197 return "Use";
196 case NodeTypeUsingNamespace:
197 return "UsingNamespace";
198198 case NodeTypeBoolLiteral:
199199 return "BoolLiteral";
200200 case NodeTypeNullLiteral:
......@@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) {
319319}
320320
321321static bool is_printable(uint8_t c) {
322 if (c == 0) {
323 return false;
324 }
322325 static const uint8_t printables[] =
323326 " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:";
324327 for (size_t i = 0; i < array_length(printables); i += 1) {
......@@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) {
337340 buf_append_str(dest, "\\\"");
338341 } else if (c == '\\') {
339342 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");
346343 } else if (c == '\n') {
347344 buf_append_str(dest, "\\n");
348345 } else if (c == '\r') {
349346 buf_append_str(dest, "\\r");
350347 } else if (c == '\t') {
351348 buf_append_str(dest, "\\t");
352 } else if (c == '\v') {
353 buf_append_str(dest, "\\v");
354349 } else if (is_printable(c)) {
355350 buf_append_char(dest, c);
356351 } else {
......@@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
630625 case NodeTypeCharLiteral:
631626 {
632627 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)) {
634641 fprintf(ar->f, "'%c'", c);
635642 } else {
636643 fprintf(ar->f, "'\\x%02x'", (int)c);
......@@ -791,7 +798,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
791798 AstNode *decls_node = node->data.container_decl.decls.at(decl_i);
792799 render_node_grouped(ar, decls_node);
793800
794 if (decls_node->type == NodeTypeUse ||
801 if (decls_node->type == NodeTypeUsingNamespace ||
795802 decls_node->type == NodeTypeVariableDeclaration ||
796803 decls_node->type == NodeTypeFnProto)
797804 {
......@@ -1170,7 +1177,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
11701177 case NodeTypeParamDecl:
11711178 case NodeTypeTestDecl:
11721179 case NodeTypeStructField:
1173 case NodeTypeUse:
1180 case NodeTypeUsingNamespace:
11741181 zig_panic("TODO more ast rendering");
11751182 }
11761183}
src/codegen.cpp+154-139
......@@ -89,126 +89,6 @@ static const char *symbols_that_llvm_depends_on[] = {
8989 // TODO probably all of compiler-rt needs to go here
9090};
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
21292void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
21393 g->clang_argv = args;
21494 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
233113 g->version_patch = patch;
234114}
235115
236void codegen_set_is_test(CodeGen *g, bool is_test_build) {
237 g->is_test_build = is_test_build;
238}
239
240116void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
241117 g->emit_file_type = emit_file_type;
242118}
......@@ -4582,8 +4458,14 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
45824458 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, "");
45834459 }
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
45854466 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
45884470 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
45894471 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
54865368 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
54875369 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc,
54885370 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);
54905373 return result_loc;
54915374}
54925375
......@@ -5499,7 +5382,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab
54995382 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
55005383 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
55015384 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, "");
55035389}
55045390
55055391static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
......@@ -7994,6 +7880,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
79947880 return contents;
79957881}
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
79977891static Error define_builtin_compile_vars(CodeGen *g) {
79987892 if (g->std_package == nullptr)
79997893 return ErrorNone;
......@@ -8078,8 +7972,16 @@ static Error define_builtin_compile_vars(CodeGen *g) {
80787972 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
80797973 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
80807974 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
8081 g->std_package->package_table.put(buf_create_from_str("root"),
8082 g->is_test_build ? g->test_runner_package : g->root_package);
7975 ZigPackage *root_pkg;
7976 if (g->is_test_build) {
7977 if (g->test_runner_package == nullptr) {
7978 g->test_runner_package = create_test_runner_pkg(g);
7979 }
7980 root_pkg = g->test_runner_package;
7981 } else {
7982 root_pkg = g->root_package;
7983 }
7984 g->std_package->package_table.put(buf_create_from_str("root"), root_pkg);
80837985 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents,
80847986 SourceKindPkgMain);
80857987
......@@ -8586,14 +8488,6 @@ static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) {
85868488 return package;
85878489}
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
85978491static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
85988492 Error err;
85998493
......@@ -8643,7 +8537,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
86438537 ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true);
86448538
86458539 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);
86478541 g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig");
86488542}
86498543
......@@ -9757,7 +9651,8 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
97579651 ZigLibCInstallation *libc)
97589652{
97599653 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);
97619656 child_gen->disable_gen_h = true;
97629657 child_gen->want_stack_check = WantStackCheckDisabled;
97639658 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
97849679 return child_gen;
97859680}
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 @@
1818
1919CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
2020 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
2323CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
2424 ZigLibCInstallation *libc);
2525
2626void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2727void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
28void codegen_set_is_test(CodeGen *codegen, bool is_test);
2928void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
3029
3130void 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_
189189static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr,
190190 ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime);
191191static 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);
193194static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
194195 IrInstruction *base_ptr, bool safety_check_on, bool initializing);
195196static 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
197198static IrInstruction *ir_analyze_unwrap_err_code(IrAnalyze *ira, IrInstruction *source_instr,
198199 IrInstruction *base_ptr, bool initializing);
199200static 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);
201202static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNode *source_node,
202203 IrInstruction *union_type, IrInstruction *field_name, AstNode *expr_node,
203204 LVal lval, ResultLoc *parent_result_loc);
......@@ -1612,7 +1613,7 @@ static IrInstruction *ir_build_unreachable(IrBuilder *irb, Scope *scope, AstNode
16121613 return &unreachable_instruction->base;
16131614}
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,
16161617 IrInstruction *ptr, IrInstruction *value)
16171618{
16181619 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 *
16241625 ir_ref_instruction(ptr, irb->current_basic_block);
16251626 ir_ref_instruction(value, irb->current_basic_block);
16261627
1627 return &instruction->base;
1628 return instruction;
16281629}
16291630
16301631static 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
40014002
40024003static IrInstruction *ir_gen_assign(IrBuilder *irb, Scope *scope, AstNode *node) {
40034004 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)
40074017 return irb->codegen->invalid_instruction;
40084018
4009 ir_build_store_ptr(irb, scope, node, lvalue, rvalue);
40104019 return ir_build_const_void(irb, scope, node);
40114020}
40124021
......@@ -6042,6 +6051,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
60426051 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
60436052 result_loc_inst->base.id = ResultLocIdInstruction;
60446053 result_loc_inst->base.source_instruction = field_ptr;
6054 result_loc_inst->base.allow_write_through_const = true;
60456055 ir_ref_instruction(field_ptr, irb->current_basic_block);
60466056 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
60806090 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
60816091 result_loc_inst->base.id = ResultLocIdInstruction;
60826092 result_loc_inst->base.source_instruction = elem_ptr;
6093 result_loc_inst->base.allow_write_through_const = true;
60836094 ir_ref_instruction(elem_ptr, irb->current_basic_block);
60846095 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
66376648
66386649 ir_set_cursor_at_end_and_append_block(irb, continue_block);
66396650 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;
66416652 ir_build_br(irb, child_scope, node, cond_block, is_comptime);
66426653
66436654 IrInstruction *else_result = nullptr;
......@@ -8430,7 +8441,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
84308441 switch (node->type) {
84318442 case NodeTypeStructValueField:
84328443 case NodeTypeParamDecl:
8433 case NodeTypeUse:
8444 case NodeTypeUsingNamespace:
84348445 case NodeTypeSwitchProng:
84358446 case NodeTypeSwitchRange:
84368447 case NodeTypeStructField:
......@@ -11155,7 +11166,8 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
1115511166 }
1115611167
1115711168 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);
1115911171 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1116011172 return result_loc_inst;
1116111173 }
......@@ -11615,7 +11627,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
1161511627 }
1161611628 IrInstruction *result_loc_inst = nullptr;
1161711629 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);
1161911631 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1162011632 return result_loc_inst;
1162111633 }
......@@ -11658,7 +11670,7 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
1165811670 IrInstruction *result_loc_inst;
1165911671 if (handle_is_ptr(wanted_type)) {
1166011672 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);
1166211674 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1166311675 return result_loc_inst;
1166411676 }
......@@ -11743,7 +11755,7 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
1174311755 IrInstruction *result_loc_inst;
1174411756 if (handle_is_ptr(wanted_type)) {
1174511757 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);
1174711759 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1174811760 return result_loc_inst;
1174911761 }
......@@ -11816,7 +11828,8 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
1181611828
1181711829 IrInstruction *result_loc;
1181811830 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);
1182011833 } else {
1182111834 result_loc = nullptr;
1182211835 }
......@@ -11860,7 +11873,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
1186011873 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
1186111874
1186211875 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);
1186411878 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1186511879 return result_loc_inst;
1186611880 }
......@@ -12516,7 +12530,8 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
1251612530 if (result_loc == nullptr) {
1251712531 result_loc = no_result_loc();
1251812532 }
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);
1252012535 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1252112536 return result_loc_inst;
1252212537 }
......@@ -13097,7 +13112,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1309713112 IrInstruction *result_loc_inst;
1309813113 if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
1309913114 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);
1310113117 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1310213118 return result_loc_inst;
1310313119 }
......@@ -14597,7 +14613,7 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1459714613 for (uint64_t x = 0; x < mult_amt; x += 1) {
1459814614 for (uint64_t y = 0; y < old_array_len; y += 1) {
1459914615 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);
1460114617 i += 1;
1460214618 }
1460314619 }
......@@ -14834,7 +14850,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
1483414850 // instruction.
1483514851 assert(deref->value.special != ConstValSpecialRuntime);
1483614852 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);
1483814854 }
1483914855
1484014856 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
1535215368
1535315369 if (peer_parent->peers.length == 1) {
1535415370 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);
1535615372 result_peer->suspend_pos.basic_block_index = SIZE_MAX;
1535715373 result_peer->suspend_pos.instruction_index = SIZE_MAX;
1535815374 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
1537215388 if (peer_parent->skipped) {
1537315389 if (non_null_comptime) {
1537415390 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);
1537615392 }
1537715393 return nullptr;
1537815394 }
......@@ -15390,7 +15406,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1539015406 }
1539115407
1539215408 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);
1539415410 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
1539515411 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
1539615412 {
......@@ -15440,7 +15456,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1544015456 }
1544115457
1544215458 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);
1544415460 if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
1544515461 parent_result_loc->value.type->id == ZigTypeIdUnreachable)
1544615462 {
......@@ -15469,8 +15485,15 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1546915485
1547015486static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_source_instr,
1547115487 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)
1547315489{
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 }
1547415497 IrInstruction *result_loc = ir_resolve_result_raw(ira, suspend_source_instr, result_loc_pass1, value_type,
1547515498 value, force_runtime, non_null_comptime);
1547615499 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
1552515548 if (type_is_invalid(implicit_elem_type))
1552615549 return ira->codegen->invalid_instruction;
1552715550 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);
1552915552 if (result_loc != nullptr)
1553015553 return result_loc;
1553115554
......@@ -15534,7 +15557,7 @@ static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrIn
1553415557 instruction->result_loc->id == ResultLocIdReturn)
1553515558 {
1553615559 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);
1553815561 if (result_loc != nullptr &&
1553915562 (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
1554015563 {
......@@ -15623,7 +15646,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
1562315646 ZigType *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
1562415647
1562515648 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);
1562715650 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
1562815651 return result_loc;
1562915652 }
......@@ -15841,7 +15864,7 @@ no_mem_slot:
1584115864}
1584215865
1584315866static 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)
1584515868{
1584615869 assert(ptr->value.type->id == ZigTypeIdPointer);
1584715870
......@@ -15857,7 +15880,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1585715880
1585815881 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) {
1586115884 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
1586215885 return ira->codegen->invalid_instruction;
1586315886 }
......@@ -15936,10 +15959,9 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
1593615959 break;
1593715960 }
1593815961
15939 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
15940 ptr, value);
15941 result->value.type = ira->codegen->builtin_types.entry_void;
15942 return result;
15962 IrInstructionStorePtr *store_ptr = ir_build_store_ptr(&ira->new_irb, source_instr->scope,
15963 source_instr->source_node, ptr, value);
15964 return &store_ptr->base;
1594315965}
1594415966
1594515967static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
......@@ -16382,7 +16404,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1638216404 IrInstruction *result_loc;
1638316405 if (handle_is_ptr(impl_fn_type_id->return_type)) {
1638416406 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);
1638616408 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) ||
1638716409 instr_is_unreachable(result_loc)))
1638816410 {
......@@ -16504,7 +16526,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1650416526 IrInstruction *result_loc;
1650516527 if (handle_is_ptr(return_type)) {
1650616528 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);
1650816530 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
1650916531 return result_loc;
1651016532 }
......@@ -17020,7 +17042,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1702017042
1702117043 // In case resolving the parent activates a suspend, do it now
1702217044 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);
1702417046 if (parent_result_loc != nullptr &&
1702517047 (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
1702617048 {
......@@ -17477,6 +17499,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1747717499 return result;
1747817500 } else if (is_slice(array_type)) {
1747917501 ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index];
17502 ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base);
1748017503 if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
1748117504 IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
1748217505 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
1766317686 return ira->codegen->invalid_instruction;
1766417687 if (type_is_invalid(struct_val->type))
1766517688 return ira->codegen->invalid_instruction;
17666 if (struct_val->special == ConstValSpecialUndef && initializing) {
17689 if (initializing && struct_val->special == ConstValSpecialUndef) {
1766717690 struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count);
1766817691 struct_val->special = ConstValSpecialStatic;
1766917692 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_
1784717870 switch (tld->id) {
1784817871 case TldIdContainer:
1784917872 case TldIdCompTime:
17873 case TldIdUsingNamespace:
1785017874 zig_unreachable();
1785117875 case TldIdVar:
1785217876 {
......@@ -18260,7 +18284,7 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc
1826018284 if (type_is_invalid(value->value.type))
1826118285 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);
1826418288}
1826518289
1826618290static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
......@@ -18763,7 +18787,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
1876318787 if (optional_val == nullptr)
1876418788 return ira->codegen->invalid_instruction;
1876518789
18766 if (initializing && optional_val->special == ConstValSpecialUndef) {
18790 if (initializing) {
1876718791 switch (type_has_one_possible_value(ira->codegen, child_type)) {
1876818792 case OnePossibleValueInvalid:
1876918793 return ira->codegen->invalid_instruction;
......@@ -19668,7 +19692,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1966819692
1966919693 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, instruction, field, result_loc,
1967019694 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);
1967219696 if (instr_is_comptime(field_ptr) && field_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1967319697 const_ptrs.append(field_ptr);
1967419698 } else {
......@@ -19685,7 +19709,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1968519709 IrInstruction *field_result_loc = const_ptrs.at(i);
1968619710 IrInstruction *deref = ir_get_deref(ira, field_result_loc, field_result_loc, nullptr);
1968719711 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);
1968919713 }
1969019714 }
1969119715 }
......@@ -19812,7 +19836,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1981219836 assert(elem_result_loc->value.special == ConstValSpecialStatic);
1981319837 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
1981419838 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);
1981619840 }
1981719841 }
1981819842 }
......@@ -21531,7 +21555,7 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
2153121555 IrInstruction *result_loc;
2153221556 if (handle_is_ptr(result_type)) {
2153321557 result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
21534 result_type, nullptr, true, false);
21558 result_type, nullptr, true, false, true);
2153521559 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
2153621560 return result_loc;
2153721561 }
......@@ -21788,7 +21812,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
2178821812 }
2178921813
2179021814 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);
2179221816 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) {
2179321817 return result_loc;
2179421818 }
......@@ -21865,7 +21889,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
2186521889 }
2186621890
2186721891 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);
2186921893 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
2187021894 return result_loc;
2187121895 }
......@@ -22607,7 +22631,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
2260722631 }
2260822632
2260922633 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);
2261122635 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
2261222636 return result_loc;
2261322637 }
......@@ -23259,7 +23283,7 @@ static IrInstruction *ir_analyze_unwrap_error_payload(IrAnalyze *ira, IrInstruct
2325923283 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
2326023284 if (err_union_val == nullptr)
2326123285 return ira->codegen->invalid_instruction;
23262 if (err_union_val->special == ConstValSpecialUndef && initializing) {
23286 if (initializing && err_union_val->special == ConstValSpecialUndef) {
2326323287 ConstExprValue *vals = create_const_vals(2);
2326423288 ConstExprValue *err_set_val = &vals[0];
2326523289 ConstExprValue *payload_val = &vals[1];
......@@ -24734,10 +24758,11 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
2473424758 operand_type->data.integral.bit_count));
2473524759 return ira->codegen->builtin_types.entry_invalid;
2473624760 }
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) {
2473824763 ir_add_error(ira, op,
24739 buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
24740 operand_type->data.integral.bit_count));
24764 buf_sprintf("expected %" PRIu32 "-bit integer type or smaller, found %" PRIu32 "-bit integer type",
24765 max_atomic_bits, operand_type->data.integral.bit_count));
2474124766 return ira->codegen->builtin_types.entry_invalid;
2474224767 }
2474324768 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
2538625411
2538725412 bool was_written = instruction->result_loc->written;
2538825413 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);
2539025415 if (result_loc != nullptr) {
2539125416 if (type_is_invalid(result_loc->value.type))
2539225417 return ira->codegen->invalid_instruction;
......@@ -25394,7 +25419,8 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct
2539425419 return result_loc;
2539525420
2539625421 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);
2539825424 if (type_is_invalid(store_ptr->value.type)) {
2539925425 return ira->codegen->invalid_instruction;
2540025426 }
......@@ -25418,7 +25444,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInst
2541825444 return operand;
2541925445
2542025446 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);
2542225448 if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)))
2542325449 return result_loc;
2542425450
src/main.cpp+3-4
......@@ -583,7 +583,7 @@ int main(int argc, char **argv) {
583583 }
584584
585585 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);
587587 g->valgrind_support = valgrind_support;
588588 g->enable_time_report = timing_info;
589589 codegen_set_out_name(g, buf_create_from_str("build"));
......@@ -1011,7 +1011,7 @@ int main(int argc, char **argv) {
10111011 }
10121012 case CmdBuiltin: {
10131013 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);
10151015 codegen_set_strip(g, strip);
10161016 for (size_t i = 0; i < link_libs.length; i += 1) {
10171017 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) {
11151115 cache_dir_buf = buf_create_from_str(cache_dir);
11161116 }
11171117 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);
11191119 if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
11201120 g->valgrind_support = valgrind_support;
11211121 g->want_pic = want_pic;
......@@ -1125,7 +1125,6 @@ int main(int argc, char **argv) {
11251125 g->enable_time_report = timing_info;
11261126 codegen_set_out_name(g, buf_out_name);
11271127 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
1128 codegen_set_is_test(g, cmd == CmdTest);
11291128 g->want_single_threaded = want_single_threaded;
11301129 codegen_set_linker_script(g, linker_script);
11311130 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) {
676676 AstNode *expr = ast_expect(pc, ast_parse_expr);
677677 expect_token(pc, TokenIdSemicolon);
678678
679 AstNode *res = ast_create_node(pc, NodeTypeUse, usingnamespace);
679 AstNode *res = ast_create_node(pc, NodeTypeUsingNamespace, usingnamespace);
680680 res->data.using_namespace.visib_mod = visib_mod;
681681 res->data.using_namespace.expr = expr;
682682 return res;
......@@ -2938,7 +2938,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
29382938 case NodeTypeUnwrapOptional:
29392939 visit_field(&node->data.unwrap_optional.expr, visit, context);
29402940 break;
2941 case NodeTypeUse:
2941 case NodeTypeUsingNamespace:
29422942 visit_field(&node->data.using_namespace.expr, visit, context);
29432943 break;
29442944 case NodeTypeBoolLiteral:
src/target.cpp+67-1
......@@ -878,6 +878,72 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
878878 zig_unreachable();
879879}
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
881947uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
882948 switch (target->os) {
883949 case OsFreestanding:
......@@ -1524,9 +1590,9 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
15241590 case OsKFreeBSD:
15251591 case OsNetBSD:
15261592 case OsHurd:
1527 case OsWindows:
15281593 return ZigLLVM_GNU;
15291594 case OsUefi:
1595 case OsWindows:
15301596 return ZigLLVM_MSVC;
15311597 case OsLinux:
15321598 case OsWASI:
src/target.hpp+1
......@@ -195,6 +195,7 @@ const char *target_arch_musl_name(ZigLLVM_ArchType arch);
195195bool target_supports_libunwind(const ZigTarget *target);
196196
197197uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
198uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch);
198199
199200size_t target_libc_count(void);
200201void target_libc_enum(size_t index, ZigTarget *out_target);
src/util.hpp+1-1
......@@ -43,7 +43,7 @@ ATTRIBUTE_NORETURN
4343ATTRIBUTE_PRINTF(1, 2)
4444void zig_panic(const char *format, ...);
4545
46#ifdef WIN32
46#ifdef _WIN32
4747#define __func__ __FUNCTION__
4848#endif
4949
src/zig_clang.h+1-1
......@@ -50,7 +50,7 @@ enum ZigClangAPValueKind {
5050struct ZigClangAPValue {
5151 enum ZigClangAPValueKind Kind;
5252 // experimentally-derived size of clang::APValue::DataType
53#if defined(WIN32) && defined(_MSC_VER)
53#if defined(_WIN32) && defined(_MSC_VER)
5454 char Data[52];
5555#else
5656 char Data[68];
std/build.zig+47-28
......@@ -41,9 +41,11 @@ pub const Builder = struct {
4141 env_map: *BufMap,
4242 top_level_steps: ArrayList(*TopLevelStep),
4343 install_prefix: ?[]const u8,
44 search_prefixes: ArrayList([]const u8),
44 dest_dir: ?[]const u8,
4545 lib_dir: ?[]const u8,
4646 exe_dir: ?[]const u8,
47 install_path: []const u8,
48 search_prefixes: ArrayList([]const u8),
4749 installed_files: ArrayList(InstalledFile),
4850 build_root: []const u8,
4951 cache_root: []const u8,
......@@ -125,10 +127,11 @@ pub const Builder = struct {
125127 .top_level_steps = ArrayList(*TopLevelStep).init(allocator),
126128 .default_step = undefined,
127129 .env_map = env_map,
128 .install_prefix = null,
129130 .search_prefixes = ArrayList([]const u8).init(allocator),
131 .install_prefix = null,
130132 .lib_dir = null,
131133 .exe_dir = null,
134 .dest_dir = env_map.get("DESTDIR"),
132135 .installed_files = ArrayList(InstalledFile).init(allocator),
133136 .install_tls = TopLevelStep{
134137 .step = Step.initNoOp("install", allocator),
......@@ -142,6 +145,7 @@ pub const Builder = struct {
142145 .is_release = false,
143146 .override_std_dir = null,
144147 .override_lib_dir = null,
148 .install_path = undefined,
145149 };
146150 try self.top_level_steps.append(&self.install_tls);
147151 try self.top_level_steps.append(&self.uninstall_tls);
......@@ -164,14 +168,19 @@ pub const Builder = struct {
164168 }
165169
166170 fn resolveInstallPrefix(self: *Builder) void {
167 const prefix = if (self.install_prefix) |prefix| prefix else blk: {
168 const prefix = self.cache_root;
169 self.install_prefix = prefix;
170 break :blk prefix;
171 };
172
173 self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "lib" }) catch unreachable;
174 self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ prefix, "bin" }) catch unreachable;
171 if (self.dest_dir) |dest_dir| {
172 const install_prefix = self.install_prefix orelse "/usr";
173 self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable;
174 } else {
175 const install_prefix = self.install_prefix orelse blk: {
176 const p = self.cache_root;
177 self.install_prefix = p;
178 break :blk p;
179 };
180 self.install_path = install_prefix;
181 }
182 self.lib_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "lib" }) catch unreachable;
183 self.exe_dir = fs.path.join(self.allocator, [_][]const u8{ self.install_path, "bin" }) catch unreachable;
175184 }
176185
177186 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
......@@ -796,11 +805,7 @@ pub const Builder = struct {
796805 return name;
797806 }
798807 const full_path = try fs.path.join(self.allocator, [_][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) });
799 if (fs.path.real(self.allocator, full_path)) |real_path| {
800 return real_path;
801 } else |_| {
802 continue;
803 }
808 return fs.realpathAlloc(self.allocator, full_path) catch continue;
804809 }
805810 }
806811 if (self.env_map.get("PATH")) |PATH| {
......@@ -808,14 +813,10 @@ pub const Builder = struct {
808813 if (fs.path.isAbsolute(name)) {
809814 return name;
810815 }
811 var it = mem.tokenize(PATH, []u8{fs.path.delimiter});
816 var it = mem.tokenize(PATH, [_]u8{fs.path.delimiter});
812817 while (it.next()) |path| {
813818 const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
814 if (fs.path.real(self.allocator, full_path)) |real_path| {
815 return real_path;
816 } else |_| {
817 continue;
818 }
819 return fs.realpathAlloc(self.allocator, full_path) catch continue;
819820 }
820821 }
821822 }
......@@ -825,11 +826,7 @@ pub const Builder = struct {
825826 }
826827 for (paths) |path| {
827828 const full_path = try fs.path.join(self.allocator, [_][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
828 if (fs.path.real(self.allocator, full_path)) |real_path| {
829 return real_path;
830 } else |_| {
831 continue;
832 }
829 return fs.realpathAlloc(self.allocator, full_path) catch continue;
833830 }
834831 }
835832 return error.FileNotFound;
......@@ -884,7 +881,7 @@ pub const Builder = struct {
884881
885882 fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
886883 const base_dir = switch (dir) {
887 .Prefix => self.install_prefix.?,
884 .Prefix => self.install_path,
888885 .Bin => self.exe_dir.?,
889886 .Lib => self.lib_dir.?,
890887 };
......@@ -895,6 +892,15 @@ pub const Builder = struct {
895892 }
896893};
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
898904pub const Version = struct {
899905 major: u32,
900906 minor: u32,
......@@ -1113,6 +1119,9 @@ pub const Target = union(enum) {
11131119 }
11141120
11151121 pub fn libPrefix(self: Target) []const u8 {
1122 if (self.isWasm()) {
1123 return "";
1124 }
11161125 switch (self.getAbi()) {
11171126 .msvc => return "",
11181127 else => return "lib",
......@@ -1255,6 +1264,8 @@ pub const LibExeObjStep = struct {
12551264 libc_file: ?[]const u8 = null,
12561265 target_glibc: ?Version = null,
12571266
1267 valgrind_support: ?bool = null,
1268
12581269 const LinkObject = union(enum) {
12591270 StaticPath: []const u8,
12601271 OtherStep: *LibExeObjStep,
......@@ -1791,7 +1802,7 @@ pub const LibExeObjStep = struct {
17911802 try zig_args.append("--bundle-compiler-rt");
17921803 }
17931804 if (self.disable_stack_probing) {
1794 try zig_args.append("--disable-stack-probing");
1805 try zig_args.append("-fno-stack-check");
17951806 }
17961807
17971808 switch (self.target) {
......@@ -1882,6 +1893,14 @@ pub const LibExeObjStep = struct {
18821893 try zig_args.append("--system-linker-hack");
18831894 }
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
18851904 if (self.override_std_dir) |dir| {
18861905 try zig_args.append("--override-std-dir");
18871906 try zig_args.append(builder.pathFromRoot(dir));
std/coff.zig+46-6
......@@ -19,6 +19,7 @@ const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
1919const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
2020
2121const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
22const IMAGE_DEBUG_TYPE_CODEVIEW = 2;
2223const DEBUG_DIRECTORY = 6;
2324
2425pub const CoffError = error{
......@@ -28,6 +29,7 @@ pub const CoffError = error{
2829 MissingCoffSection,
2930};
3031
32// Official documentation of the format: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
3133pub const Coff = struct {
3234 in_file: File,
3335 allocator: *mem.Allocator,
......@@ -120,16 +122,43 @@ pub const Coff = struct {
120122
121123 pub fn getPdbPath(self: *Coff, buffer: []u8) !usize {
122124 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 the
126 // debug_directory.
126 const header = blk: {
127 if (self.getSection(".buildid")) |section| {
128 break :blk section.header;
129 } else if (self.getSection(".rdata")) |section| {
130 break :blk section.header;
131 } else {
132 return error.MissingCoffSection;
133 }
134 };
135
127136 const debug_dir = &self.pe_header.data_directory[DEBUG_DIRECTORY];
128137 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
131139 var file_stream = self.in_file.inStream();
132140 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
134163 var cv_signature: [4]u8 = undefined; // CodeView signature
135164 try in.readNoEof(cv_signature[0..]);
......@@ -141,7 +170,7 @@ pub const Coff = struct {
141170
142171 // Finally read the null-terminated string.
143172 var byte = try in.readByte();
144 var i: usize = 0;
173 i = 0;
145174 while (byte != 0 and i < buffer.len) : (i += 1) {
146175 buffer[i] = byte;
147176 byte = try in.readByte();
......@@ -170,7 +199,7 @@ pub const Coff = struct {
170199 try self.sections.append(Section{
171200 .header = SectionHeader{
172201 .name = name,
173 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
202 .misc = SectionHeader.Misc{ .virtual_size = try in.readIntLittle(u32) },
174203 .virtual_address = try in.readIntLittle(u32),
175204 .size_of_raw_data = try in.readIntLittle(u32),
176205 .pointer_to_raw_data = try in.readIntLittle(u32),
......@@ -214,6 +243,17 @@ const OptionalHeader = struct {
214243 data_directory: [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]DataDirectory,
215244};
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
217257pub const Section = struct {
218258 header: SectionHeader,
219259};
std/debug.zig+54-21
......@@ -12,6 +12,7 @@ const coff = std.coff;
1212const pdb = std.pdb;
1313const ArrayList = std.ArrayList;
1414const builtin = @import("builtin");
15const root = @import("root");
1516const maxInt = std.math.maxInt;
1617const File = std.fs.File;
1718const windows = std.os.windows;
......@@ -217,6 +218,12 @@ var panicking: u8 = 0; // TODO make this a bool
217218pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn {
218219 @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
220227 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
221228 // Panicked during a panic.
222229
......@@ -368,7 +375,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
368375 const obj_basename = fs.path.basename(mod.obj_file_name);
369376
370377 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) {
372379 const prefix = @ptrCast(*pdb.RecordPrefix, &mod.symbols[symbol_i]);
373380 if (prefix.RecordLen < 2)
374381 return error.InvalidDebugInfo;
......@@ -851,8 +858,10 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
851858 const age = try pdb_stream.stream.readIntLittle(u32);
852859 var guid: [16]u8 = undefined;
853860 try pdb_stream.stream.readNoEof(guid[0..]);
861 if (version != 20000404) // VC70, only value observed by LLVM team
862 return error.UnknownPDBVersion;
854863 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
855 return error.InvalidDebugInfo;
864 return error.PDBMismatch;
856865 // We validated the executable and pdb match.
857866
858867 const string_table_index = str_tab_index: {
......@@ -896,13 +905,18 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
896905 return error.MissingDebugInfo;
897906 };
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;
900909 di.pdb.dbi = di.pdb.getStream(pdb.StreamType.Dbi) orelse return error.MissingDebugInfo;
901910
902911 const dbi = di.pdb.dbi;
903912
904913 // Dbi Header
905914 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
906920 const mod_info_size = dbi_stream_header.ModInfoSize;
907921 const section_contrib_size = dbi_stream_header.SectionContributionSize;
908922
......@@ -2312,39 +2326,58 @@ fn getDebugInfoAllocator() *mem.Allocator {
23122326
23132327/// Whether or not the current target can print useful debug information when a segfault occurs.
23142328pub 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
23162342/// Attaches a global SIGSEGV handler which calls @panic("segmentation fault");
23172343pub fn attachSegfaultHandler() void {
23182344 if (!have_segfault_handling_support) {
23192345 @compileError("segfault handler not supported for this target");
23202346 }
2321 switch (builtin.os) {
2322 .linux => {
2323 var act = os.Sigaction{
2324 .sigaction = handleSegfaultLinux,
2325 .mask = os.empty_sigset,
2326 .flags = (os.SA_SIGINFO | os.SA_RESTART | os.SA_RESETHAND),
2327 };
2328
2329 os.sigaction(os.SIGSEGV, &act, null);
2330 },
2331 .windows => {
2332 _ = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
2333 },
2334 else => unreachable,
2347 if (windows.is_the_target) {
2348 windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
2349 return;
23352350 }
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);
23362358}
23372359
2338extern fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: *const c_void) noreturn {
2339 // Reset to the default handler so that if a segfault happens in this handler it will crash
2340 // the process. Also when this handler returns, the original instruction will be repeated
2341 // and the resulting segfault will crash the process rather than continually dump stack traces.
2360fn resetSegfaultHandler() void {
2361 if (windows.is_the_target) {
2362 if (windows_segfault_handle) |handle| {
2363 assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
2364 windows_segfault_handle = null;
2365 }
2366 return;
2367 }
23422368 var act = os.Sigaction{
23432369 .sigaction = os.SIG_DFL,
23442370 .mask = os.empty_sigset,
23452371 .flags = 0,
23462372 };
23472373 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
23492382 const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
23502383 const ip = @intCast(usize, ctx.mcontext.gregs[os.REG_RIP]);
std/fmt.zig+20-1
......@@ -374,9 +374,10 @@ pub fn formatType(
374374 return output(context, "{ ... }");
375375 }
376376 comptime var field_i = 0;
377 try output(context, "{");
377378 inline while (field_i < @memberCount(T)) : (field_i += 1) {
378379 if (field_i == 0) {
379 try output(context, "{ .");
380 try output(context, " .");
380381 } else {
381382 try output(context, ", .");
382383 }
......@@ -425,6 +426,9 @@ pub fn formatType(
425426 if (info.child == u8) {
426427 return formatText(value, fmt, options, context, Errors, output);
427428 }
429 if (value.len == 0) {
430 return format(context, Errors, output, "[0]{}", @typeName(T.Child));
431 }
428432 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
429433 },
430434 .Fn => {
......@@ -1439,6 +1443,21 @@ test "struct.self-referential" {
14391443 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", inst);
14401444}
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
14421461test "bytes.hex" {
14431462 const some_bytes = "\xCA\xFE\xBA\xBE";
14441463 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", some_bytes);
std/os.zig+21
......@@ -133,6 +133,11 @@ fn getRandomBytesDevURandom(buf: []u8) !void {
133133 const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
134134 defer close(fd);
135135
136 const st = try fstat(fd);
137 if (!S_ISCHR(st.mode)) {
138 return error.NoDevice;
139 }
140
136141 const stream = &std.fs.File.openHandle(fd).inStream().stream;
137142 stream.readNoEof(buf) catch return error.Unexpected;
138143}
......@@ -2053,6 +2058,22 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
20532058 }
20542059}
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
20562077pub const PipeError = error{
20572078 SystemFdQuotaExceeded,
20582079 ProcessFdQuotaExceeded,
std/os/bits/darwin.zig+59
......@@ -1116,3 +1116,62 @@ pub const stack_t = extern struct {
11161116 ss_size: isize,
11171117 ss_flags: i32,
11181118};
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 {
876876 ss_size: isize,
877877 ss_flags: i32,
878878};
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) {
55 else => false,
66};
77pub 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");
22const builtin = @import("builtin");
33pub const is_the_target = builtin.os == .freebsd;
44pub usingnamespace std.c;
5pub usingnamespace @import("bits.zig");
\ No newline at end of file
std/os/windows/kernel32.zig+1
......@@ -1,6 +1,7 @@
11usingnamespace @import("bits.zig");
22
33pub 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
56pub extern "kernel32" stdcallcc fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) BOOL;
67
std/pdb.zig+73-44
......@@ -499,45 +499,78 @@ const Msf = struct {
499499
500500 const superblock = try in.readStruct(SuperBlock);
501501
502 // Sanity checks
502503 if (!mem.eql(u8, superblock.FileMagic, SuperBlock.file_magic))
503504 return error.InvalidDebugInfo;
504
505 if (superblock.FreeBlockMapBlock != 1 and superblock.FreeBlockMapBlock != 2)
506 return error.InvalidDebugInfo;
507 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())
508 return error.InvalidDebugInfo;
505509 switch (superblock.BlockSize) {
506510 // llvm only supports 4096 but we can handle any of these values
507511 512, 1024, 2048, 4096 => {},
508512 else => return error.InvalidDebugInfo,
509513 }
510514
511 if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos())
512 return error.InvalidDebugInfo;
515 const dir_block_count = blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize);
516 if (dir_block_count > superblock.BlockSize / @sizeOf(u32))
517 return error.UnhandledBigDirectoryStream; // cf. BlockMapAddr comment.
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(
515525 superblock.BlockSize,
516 blockCountFromSize(superblock.NumDirectoryBytes, superblock.BlockSize),
517 superblock.BlockSize * superblock.BlockMapAddr,
518526 file,
519 allocator,
527 dir_blocks,
520528 );
521529
530 const begin = self.directory.pos;
522531 const stream_count = try self.directory.stream.readIntLittle(u32);
523
524532 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| {
526540 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);
528542 }
529543
530544 self.streams = try allocator.alloc(MsfStream, stream_count);
531545 for (self.streams) |*stream, i| {
532 stream.* = try MsfStream.init(
533 superblock.BlockSize,
534 stream_sizes[i],
535 // MsfStream.init expects the file to be at the part where it reads [N]u32
536 try file.getPos(),
537 file,
538 allocator,
539 );
546 const size = stream_sizes[i];
547 if (size == 0) {
548 stream.* = MsfStream{
549 .blocks = [_]u32{},
550 };
551 } else {
552 var blocks = try allocator.alloc(u32, size);
553 var j: u32 = 0;
554 while (j < size) : (j += 1) {
555 const block_id = try self.directory.stream.readIntLittle(u32);
556 const n = (block_id % superblock.BlockSize);
557 // 0 is for SuperBlock, 1 and 2 for FPMs.
558 if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > try file.getEndPos())
559 return error.InvalidBlockIndex;
560 blocks[j] = block_id;
561 }
562
563 stream.* = MsfStream.init(
564 superblock.BlockSize,
565 file,
566 blocks,
567 );
568 }
540569 }
570
571 const end = self.directory.pos;
572 if (end - begin != superblock.NumDirectoryBytes)
573 return error.InvalidStreamDirectory;
541574 }
542575};
543576
......@@ -574,7 +607,6 @@ const SuperBlock = packed struct {
574607 NumDirectoryBytes: u32,
575608
576609 Unknown: u32,
577
578610 /// The index of a block within the MSF file. At this block is an array of
579611 /// ulittle32_t’s listing the blocks that the stream directory resides on.
580612 /// For large MSF files, the stream directory (which describes the block
......@@ -584,45 +616,41 @@ const SuperBlock = packed struct {
584616 /// and the stream directory itself can be stitched together accordingly.
585617 /// The number of ulittle32_t’s in this array is given by
586618 /// 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.
587625 BlockMapAddr: u32,
588626};
589627
590628const MsfStream = struct {
591 in_file: File,
592 pos: u64,
593 blocks: []u32,
594 block_size: u32,
629 in_file: File = undefined,
630 pos: u64 = undefined,
631 blocks: []u32 = undefined,
632 block_size: u32 = undefined,
595633
596634 /// Implementation of InStream trait for Pdb.MsfStream
597 stream: Stream,
635 stream: Stream = undefined,
598636
599637 pub const Error = @typeOf(read).ReturnType.ErrorSet;
600638 pub const Stream = io.InStream(Error);
601639
602 fn init(block_size: u32, block_count: u32, pos: u64, file: File, allocator: *mem.Allocator) !MsfStream {
603 var stream = MsfStream{
640 fn init(block_size: u32, file: File, blocks: []u32) MsfStream {
641 const stream = MsfStream{
604642 .in_file = file,
605643 .pos = 0,
606 .blocks = try allocator.alloc(u32, block_count),
644 .blocks = blocks,
607645 .block_size = block_size,
608646 .stream = Stream{ .readFn = readFn },
609647 };
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
620649 return stream;
621650 }
622651
623652 fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 {
624653 var list = ArrayList(u8).init(allocator);
625 defer list.deinit();
626654 while (true) {
627655 const byte = try self.stream.readByte();
628656 if (byte == 0) {
......@@ -642,11 +670,12 @@ const MsfStream = struct {
642670 const in = &file_stream.stream;
643671
644672 var size: usize = 0;
645 for (buffer) |*byte| {
646 byte.* = try in.readByte();
647
648 offset += 1;
649 size += 1;
673 var rem_buffer = buffer;
674 while (size < buffer.len) {
675 const size_to_read = math.min(self.block_size - offset, rem_buffer.len);
676 size += try in.read(rem_buffer[0..size_to_read]);
677 rem_buffer = buffer[size..];
678 offset += size_to_read;
650679
651680 // If we're at the end of a block, go to the next one.
652681 if (offset == self.block_size) {
......@@ -657,8 +686,8 @@ const MsfStream = struct {
657686 }
658687 }
659688
660 self.pos += size;
661 return size;
689 self.pos += buffer.len;
690 return buffer.len;
662691 }
663692
664693 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
146146 error.Unexpected => return error.EnvironmentVariableNotFound,
147147 else => |e| return e,
148148 };
149
150149 if (result > buf.len) {
151150 buf = try allocator.realloc(buf, result);
152151 continue;
153152 }
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) {
156155 error.DanglingSurrogateHalf => return error.InvalidUtf8,
157156 error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
158157 error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
std/rb.zig+51-3
......@@ -93,7 +93,8 @@ pub const Node = struct {
9393 comptime {
9494 assert(@alignOf(*Node) >= 2);
9595 }
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);
9798 }
9899
99100 fn setColor(node: *Node, color: Color) void {
......@@ -233,10 +234,13 @@ pub const Tree = struct {
233234 return null;
234235 }
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.
236241 pub fn lookup(tree: *Tree, key: *Node) ?*Node {
237 var parent: *Node = undefined;
242 var parent: ?*Node = undefined;
238243 var is_left: bool = undefined;
239
240244 return doLookup(key, tree, &parent, &is_left);
241245 }
242246
......@@ -544,3 +548,47 @@ test "rb" {
544548 num = testGetNumber(num.node.next().?);
545549 }
546550}
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;
7777pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type {
7878 return struct {
7979 const Self = @This();
80 const prealloc_exp = blk: {
81 // we don't use the prealloc_exp constant when prealloc_item_count is 0.
82 assert(prealloc_item_count != 0);
83 assert(std.math.isPowerOfTwo(prealloc_item_count));
80 const ShelfIndex = std.math.Log2Int(usize);
8481
85 const value = std.math.log2_int(usize, prealloc_item_count);
86 break :blk @typeOf(1)(value);
82 const prealloc_exp: ShelfIndex = blk: {
83 // we don't use the prealloc_exp constant when prealloc_item_count is 0
84 // but lazy-init may still be triggered by other code so supply a value
85 if (prealloc_item_count == 0) {
86 break :blk 0;
87 } else {
88 assert(std.math.isPowerOfTwo(prealloc_item_count));
89 const value = std.math.log2_int(usize, prealloc_item_count);
90 break :blk value;
91 }
8792 };
88 const ShelfIndex = std.math.Log2Int(usize);
8993
9094 prealloc_segment: [prealloc_item_count]T,
9195 dynamic_segments: [][*]T,
......@@ -157,11 +161,12 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
157161
158162 /// Grows or shrinks capacity to match usage.
159163 pub fn setCapacity(self: *Self, new_capacity: usize) !void {
160 if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) {
161 return self.shrinkCapacity(new_capacity);
162 } else {
163 return self.growCapacity(new_capacity);
164 if (prealloc_item_count != 0) {
165 if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) {
166 return self.shrinkCapacity(new_capacity);
167 }
164168 }
169 return self.growCapacity(new_capacity);
165170 }
166171
167172 /// Only grows capacity, or retains current capacity
......@@ -399,4 +404,6 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
399404 testing.expect(item == i);
400405 list.shrinkCapacity(list.len);
401406 }
407
408 try list.setCapacity(0);
402409}
std/special/start.zig+6-16
......@@ -24,16 +24,6 @@ comptime {
2424 }
2525}
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
3727extern fn wasm_freestanding_start() void {
3828 _ = callMain();
3929}
......@@ -45,13 +35,13 @@ nakedcc fn _start() noreturn {
4535
4636 switch (builtin.arch) {
4737 .x86_64 => {
48 argc_ptr = asm ("lea (%%rsp), %[argc]"
49 : [argc] "=r" (-> [*]usize)
38 argc_ptr = asm (""
39 : [argc] "={rsp}" (-> [*]usize)
5040 );
5141 },
5242 .i386 => {
53 argc_ptr = asm ("lea (%%esp), %[argc]"
54 : [argc] "=r" (-> [*]usize)
43 argc_ptr = asm (""
44 : [argc] "={esp}" (-> [*]usize)
5545 );
5646 },
5747 .aarch64, .aarch64_be => {
......@@ -77,7 +67,7 @@ extern fn WinMainCRTStartup() noreturn {
7767 _ = @import("start_windows_tls.zig");
7868 }
7969
80 enableSegfaultHandler();
70 std.debug.maybeEnableSegfaultHandler();
8171
8272 std.os.windows.kernel32.ExitProcess(callMain());
8373}
......@@ -118,7 +108,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
118108 std.os.argv = argv[0..argc];
119109 std.os.environ = envp;
120110
121 enableSegfaultHandler();
111 std.debug.maybeEnableSegfaultHandler();
122112
123113 return callMain();
124114}
std/std.zig+1
......@@ -105,6 +105,7 @@ test "std" {
105105 _ = @import("packed_int_array.zig");
106106 _ = @import("priority_queue.zig");
107107 _ = @import("rand.zig");
108 _ = @import("rb.zig");
108109 _ = @import("sort.zig");
109110 _ = @import("testing.zig");
110111 _ = @import("thread.zig");
std/zig/ast.zig+109-100
......@@ -159,101 +159,99 @@ pub const Error = union(enum) {
159159
160160 pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void {
161161 switch (self.*) {
162 // TODO https://github.com/ziglang/zig/issues/683
163 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
164 @TagType(Error).ExpectedContainerMembers => |*x| return x.render(tokens, stream),
165 @TagType(Error).ExpectedStringLiteral => |*x| return x.render(tokens, stream),
166 @TagType(Error).ExpectedIntegerLiteral => |*x| return x.render(tokens, stream),
167 @TagType(Error).ExpectedPubItem => |*x| return x.render(tokens, stream),
168 @TagType(Error).ExpectedIdentifier => |*x| return x.render(tokens, stream),
169 @TagType(Error).ExpectedStatement => |*x| return x.render(tokens, stream),
170 @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
171 @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream),
172 @TagType(Error).ExpectedReturnType => |*x| return x.render(tokens, stream),
173 @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
174 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
175 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
176 @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
177 @TagType(Error).ExpectedSemiOrElse => |*x| return x.render(tokens, stream),
178 @TagType(Error).ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream),
179 @TagType(Error).ExpectedLBrace => |*x| return x.render(tokens, stream),
180 @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
181 @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),
182 @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),
183 @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
184 @TagType(Error).ExpectedCall => |*x| return x.render(tokens, stream),
185 @TagType(Error).ExpectedCallOrFnProto => |*x| return x.render(tokens, stream),
186 @TagType(Error).ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream),
187 @TagType(Error).ExtraAlignQualifier => |*x| return x.render(tokens, stream),
188 @TagType(Error).ExtraConstQualifier => |*x| return x.render(tokens, stream),
189 @TagType(Error).ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
190 @TagType(Error).ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
191 @TagType(Error).ExpectedTypeExpr => |*x| return x.render(tokens, stream),
192 @TagType(Error).ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream),
193 @TagType(Error).ExpectedParamType => |*x| return x.render(tokens, stream),
194 @TagType(Error).ExpectedExpr => |*x| return x.render(tokens, stream),
195 @TagType(Error).ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),
196 @TagType(Error).ExpectedToken => |*x| return x.render(tokens, stream),
197 @TagType(Error).ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),
198 @TagType(Error).ExpectedParamList => |*x| return x.render(tokens, stream),
199 @TagType(Error).ExpectedPayload => |*x| return x.render(tokens, stream),
200 @TagType(Error).ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream),
201 @TagType(Error).ExpectedBlockOrExpression => |*x| return x.render(tokens, stream),
202 @TagType(Error).ExpectedExprOrAssignment => |*x| return x.render(tokens, stream),
203 @TagType(Error).ExpectedPrefixExpr => |*x| return x.render(tokens, stream),
204 @TagType(Error).ExpectedLoopExpr => |*x| return x.render(tokens, stream),
205 @TagType(Error).ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
206 @TagType(Error).ExpectedSuffixOp => |*x| return x.render(tokens, stream),
162 .InvalidToken => |*x| return x.render(tokens, stream),
163 .ExpectedContainerMembers => |*x| return x.render(tokens, stream),
164 .ExpectedStringLiteral => |*x| return x.render(tokens, stream),
165 .ExpectedIntegerLiteral => |*x| return x.render(tokens, stream),
166 .ExpectedPubItem => |*x| return x.render(tokens, stream),
167 .ExpectedIdentifier => |*x| return x.render(tokens, stream),
168 .ExpectedStatement => |*x| return x.render(tokens, stream),
169 .ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
170 .ExpectedVarDecl => |*x| return x.render(tokens, stream),
171 .ExpectedReturnType => |*x| return x.render(tokens, stream),
172 .ExpectedAggregateKw => |*x| return x.render(tokens, stream),
173 .UnattachedDocComment => |*x| return x.render(tokens, stream),
174 .ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
175 .ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
176 .ExpectedSemiOrElse => |*x| return x.render(tokens, stream),
177 .ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream),
178 .ExpectedLBrace => |*x| return x.render(tokens, stream),
179 .ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
180 .ExpectedLabelable => |*x| return x.render(tokens, stream),
181 .ExpectedInlinable => |*x| return x.render(tokens, stream),
182 .ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
183 .ExpectedCall => |*x| return x.render(tokens, stream),
184 .ExpectedCallOrFnProto => |*x| return x.render(tokens, stream),
185 .ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream),
186 .ExtraAlignQualifier => |*x| return x.render(tokens, stream),
187 .ExtraConstQualifier => |*x| return x.render(tokens, stream),
188 .ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
189 .ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
190 .ExpectedTypeExpr => |*x| return x.render(tokens, stream),
191 .ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream),
192 .ExpectedParamType => |*x| return x.render(tokens, stream),
193 .ExpectedExpr => |*x| return x.render(tokens, stream),
194 .ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),
195 .ExpectedToken => |*x| return x.render(tokens, stream),
196 .ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),
197 .ExpectedParamList => |*x| return x.render(tokens, stream),
198 .ExpectedPayload => |*x| return x.render(tokens, stream),
199 .ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream),
200 .ExpectedBlockOrExpression => |*x| return x.render(tokens, stream),
201 .ExpectedExprOrAssignment => |*x| return x.render(tokens, stream),
202 .ExpectedPrefixExpr => |*x| return x.render(tokens, stream),
203 .ExpectedLoopExpr => |*x| return x.render(tokens, stream),
204 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
205 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),
207206 }
208207 }
209208
210209 pub fn loc(self: *const Error) TokenIndex {
211210 switch (self.*) {
212 // TODO https://github.com/ziglang/zig/issues/683
213 @TagType(Error).InvalidToken => |x| return x.token,
214 @TagType(Error).ExpectedContainerMembers => |x| return x.token,
215 @TagType(Error).ExpectedStringLiteral => |x| return x.token,
216 @TagType(Error).ExpectedIntegerLiteral => |x| return x.token,
217 @TagType(Error).ExpectedPubItem => |x| return x.token,
218 @TagType(Error).ExpectedIdentifier => |x| return x.token,
219 @TagType(Error).ExpectedStatement => |x| return x.token,
220 @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
221 @TagType(Error).ExpectedVarDecl => |x| return x.token,
222 @TagType(Error).ExpectedReturnType => |x| return x.token,
223 @TagType(Error).ExpectedAggregateKw => |x| return x.token,
224 @TagType(Error).UnattachedDocComment => |x| return x.token,
225 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
226 @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,
227 @TagType(Error).ExpectedSemiOrElse => |x| return x.token,
228 @TagType(Error).ExpectedLabelOrLBrace => |x| return x.token,
229 @TagType(Error).ExpectedLBrace => |x| return x.token,
230 @TagType(Error).ExpectedColonOrRParen => |x| return x.token,
231 @TagType(Error).ExpectedLabelable => |x| return x.token,
232 @TagType(Error).ExpectedInlinable => |x| return x.token,
233 @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,
234 @TagType(Error).ExpectedCall => |x| return x.node.firstToken(),
235 @TagType(Error).ExpectedCallOrFnProto => |x| return x.node.firstToken(),
236 @TagType(Error).ExpectedSliceOrRBracket => |x| return x.token,
237 @TagType(Error).ExtraAlignQualifier => |x| return x.token,
238 @TagType(Error).ExtraConstQualifier => |x| return x.token,
239 @TagType(Error).ExtraVolatileQualifier => |x| return x.token,
240 @TagType(Error).ExtraAllowZeroQualifier => |x| return x.token,
241 @TagType(Error).ExpectedTypeExpr => |x| return x.token,
242 @TagType(Error).ExpectedPrimaryTypeExpr => |x| return x.token,
243 @TagType(Error).ExpectedParamType => |x| return x.token,
244 @TagType(Error).ExpectedExpr => |x| return x.token,
245 @TagType(Error).ExpectedPrimaryExpr => |x| return x.token,
246 @TagType(Error).ExpectedToken => |x| return x.token,
247 @TagType(Error).ExpectedCommaOrEnd => |x| return x.token,
248 @TagType(Error).ExpectedParamList => |x| return x.token,
249 @TagType(Error).ExpectedPayload => |x| return x.token,
250 @TagType(Error).ExpectedBlockOrAssignment => |x| return x.token,
251 @TagType(Error).ExpectedBlockOrExpression => |x| return x.token,
252 @TagType(Error).ExpectedExprOrAssignment => |x| return x.token,
253 @TagType(Error).ExpectedPrefixExpr => |x| return x.token,
254 @TagType(Error).ExpectedLoopExpr => |x| return x.token,
255 @TagType(Error).ExpectedDerefOrUnwrap => |x| return x.token,
256 @TagType(Error).ExpectedSuffixOp => |x| return x.token,
211 .InvalidToken => |x| return x.token,
212 .ExpectedContainerMembers => |x| return x.token,
213 .ExpectedStringLiteral => |x| return x.token,
214 .ExpectedIntegerLiteral => |x| return x.token,
215 .ExpectedPubItem => |x| return x.token,
216 .ExpectedIdentifier => |x| return x.token,
217 .ExpectedStatement => |x| return x.token,
218 .ExpectedVarDeclOrFn => |x| return x.token,
219 .ExpectedVarDecl => |x| return x.token,
220 .ExpectedReturnType => |x| return x.token,
221 .ExpectedAggregateKw => |x| return x.token,
222 .UnattachedDocComment => |x| return x.token,
223 .ExpectedEqOrSemi => |x| return x.token,
224 .ExpectedSemiOrLBrace => |x| return x.token,
225 .ExpectedSemiOrElse => |x| return x.token,
226 .ExpectedLabelOrLBrace => |x| return x.token,
227 .ExpectedLBrace => |x| return x.token,
228 .ExpectedColonOrRParen => |x| return x.token,
229 .ExpectedLabelable => |x| return x.token,
230 .ExpectedInlinable => |x| return x.token,
231 .ExpectedAsmOutputReturnOrType => |x| return x.token,
232 .ExpectedCall => |x| return x.node.firstToken(),
233 .ExpectedCallOrFnProto => |x| return x.node.firstToken(),
234 .ExpectedSliceOrRBracket => |x| return x.token,
235 .ExtraAlignQualifier => |x| return x.token,
236 .ExtraConstQualifier => |x| return x.token,
237 .ExtraVolatileQualifier => |x| return x.token,
238 .ExtraAllowZeroQualifier => |x| return x.token,
239 .ExpectedTypeExpr => |x| return x.token,
240 .ExpectedPrimaryTypeExpr => |x| return x.token,
241 .ExpectedParamType => |x| return x.token,
242 .ExpectedExpr => |x| return x.token,
243 .ExpectedPrimaryExpr => |x| return x.token,
244 .ExpectedToken => |x| return x.token,
245 .ExpectedCommaOrEnd => |x| return x.token,
246 .ExpectedParamList => |x| return x.token,
247 .ExpectedPayload => |x| return x.token,
248 .ExpectedBlockOrAssignment => |x| return x.token,
249 .ExpectedBlockOrExpression => |x| return x.token,
250 .ExpectedExprOrAssignment => |x| return x.token,
251 .ExpectedPrefixExpr => |x| return x.token,
252 .ExpectedLoopExpr => |x| return x.token,
253 .ExpectedDerefOrUnwrap => |x| return x.token,
254 .ExpectedSuffixOp => |x| return x.token,
257255 }
258256 }
259257
......@@ -320,8 +318,19 @@ pub const Error = union(enum) {
320318 expected_id: Token.Id,
321319
322320 pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void {
323 const token_name = @tagName(tokens.at(self.token).id);
324 return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name);
321 const found_token = tokens.at(self.token);
322 switch (found_token.id) {
323 .Invalid_ampersands => {
324 return stream.print("`&&` is invalid. Note that `and` is boolean AND.");
325 },
326 .Invalid => {
327 return stream.print("expected {}, found invalid bytes", @tagName(self.expected_id));
328 },
329 else => {
330 const token_name = @tagName(found_token.id);
331 return stream.print("expected {}, found {}", @tagName(self.expected_id), token_name);
332 },
333 }
325334 }
326335 };
327336
......@@ -1708,15 +1717,15 @@ pub const Node = struct {
17081717 i -= 1;
17091718
17101719 switch (self.op) {
1711 @TagType(Op).Call => |*call_info| {
1720 .Call => |*call_info| {
17121721 if (i < call_info.params.len) return call_info.params.at(i).*;
17131722 i -= call_info.params.len;
17141723 },
1715 Op.ArrayAccess => |index_expr| {
1724 .ArrayAccess => |index_expr| {
17161725 if (i < 1) return index_expr;
17171726 i -= 1;
17181727 },
1719 @TagType(Op).Slice => |range| {
1728 .Slice => |range| {
17201729 if (i < 1) return range.start;
17211730 i -= 1;
17221731
......@@ -1725,16 +1734,16 @@ pub const Node = struct {
17251734 i -= 1;
17261735 }
17271736 },
1728 Op.ArrayInitializer => |*exprs| {
1737 .ArrayInitializer => |*exprs| {
17291738 if (i < exprs.len) return exprs.at(i).*;
17301739 i -= exprs.len;
17311740 },
1732 Op.StructInitializer => |*fields| {
1741 .StructInitializer => |*fields| {
17331742 if (i < fields.len) return fields.at(i).*;
17341743 i -= fields.len;
17351744 },
1736 Op.UnwrapOptional,
1737 Op.Deref,
1745 .UnwrapOptional,
1746 .Deref,
17381747 => {},
17391748 }
17401749
......@@ -1743,7 +1752,7 @@ pub const Node = struct {
17431752
17441753 pub fn firstToken(self: *const SuffixOp) TokenIndex {
17451754 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(),
17471756 else => {},
17481757 }
17491758 return self.lhs.firstToken();
std/zig/parse.zig+1-1
......@@ -774,7 +774,7 @@ fn parseBoolAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
774774 arena,
775775 it,
776776 tree,
777 SimpleBinOpParseFn(.Keyword_and, Node.InfixOp.Op.BoolAnd),
777 SimpleBinOpParseFn(.Keyword_and, .BoolAnd),
778778 parseCompareExpr,
779779 .Infinitely,
780780 );
std/zig/parser_test.zig+26
......@@ -2267,6 +2267,32 @@ test "zig fmt: file ends with struct field" {
22672267 );
22682268}
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
22702296const std = @import("std");
22712297const mem = std.mem;
22722298const warn = std.debug.warn;
std/zig/render.zig+7-1
......@@ -2020,7 +2020,13 @@ fn renderTokenOffset(
20202020
20212021 const after_comment_token = tree.tokens.at(token_index + offset);
20222022 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 },
20242030 else => indent,
20252031 };
20262032 try stream.writeByteNTimes(' ', next_line_indent);
std/zig/tokenizer.zig+6
......@@ -77,6 +77,7 @@ pub const Token = struct {
7777
7878 pub const Id = enum {
7979 Invalid,
80 Invalid_ampersands,
8081 Identifier,
8182 StringLiteral,
8283 MultilineStringLiteralLine,
......@@ -484,6 +485,11 @@ pub const Tokenizer = struct {
484485 },
485486
486487 State.Ampersand => switch (c) {
488 '&' => {
489 result.id = Token.Id.Invalid_ampersands;
490 self.index += 1;
491 break;
492 },
487493 '=' => {
488494 result.id = Token.Id.AmpersandEqual;
489495 self.index += 1;
test/compile_errors.zig+9-9
......@@ -201,7 +201,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
201201 \\ return error.OutOfMemory;
202202 \\}
203203 ,
204 "tmp.zig:2:7: error: error is discarded",
204 "tmp.zig:2:12: error: error is discarded",
205205 );
206206
207207 cases.add(
......@@ -234,7 +234,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
234234
235235 cases.add(
236236 "usingnamespace with wrong type",
237 \\use void;
237 \\usingnamespace void;
238238 ,
239239 "tmp.zig:1:1: error: expected struct, enum, or union; found 'void'",
240240 );
......@@ -2740,7 +2740,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27402740 \\ 3 = 3;
27412741 \\}
27422742 ,
2743 "tmp.zig:2:7: error: cannot assign to constant",
2743 "tmp.zig:2:9: error: cannot assign to constant",
27442744 );
27452745
27462746 cases.add(
......@@ -2750,7 +2750,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27502750 \\ a = 4;
27512751 \\}
27522752 ,
2753 "tmp.zig:3:7: error: cannot assign to constant",
2753 "tmp.zig:3:9: error: cannot assign to constant",
27542754 );
27552755
27562756 cases.add(
......@@ -2820,7 +2820,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28202820 \\}
28212821 \\export fn entry() void { f(); }
28222822 ,
2823 "tmp.zig:3:7: error: cannot assign to constant",
2823 "tmp.zig:3:9: error: cannot assign to constant",
28242824 );
28252825
28262826 cases.add(
......@@ -3883,7 +3883,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
38833883 \\
38843884 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
38853885 ,
3886 "tmp.zig:6:24: error: unable to evaluate constant expression",
3886 "tmp.zig:6:26: error: unable to evaluate constant expression",
38873887 "tmp.zig:4:17: note: called from here",
38883888 );
38893889
......@@ -4133,7 +4133,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
41334133 \\ cstr[0] = 'W';
41344134 \\}
41354135 ,
4136 "tmp.zig:3:11: error: cannot assign to constant",
4136 "tmp.zig:3:13: error: cannot assign to constant",
41374137 );
41384138
41394139 cases.add(
......@@ -4143,7 +4143,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
41434143 \\ cstr[0] = 'W';
41444144 \\}
41454145 ,
4146 "tmp.zig:3:11: error: cannot assign to constant",
4146 "tmp.zig:3:13: error: cannot assign to constant",
41474147 );
41484148
41494149 cases.add(
......@@ -4291,7 +4291,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
42914291 \\ f.field = 0;
42924292 \\}
42934293 ,
4294 "tmp.zig:6:13: error: cannot assign to constant",
4294 "tmp.zig:6:15: error: cannot assign to constant",
42954295 );
42964296
42974297 cases.add(
test/stage1/behavior.zig+1
......@@ -93,6 +93,7 @@ comptime {
9393 _ = @import("behavior/undefined.zig");
9494 _ = @import("behavior/underscore.zig");
9595 _ = @import("behavior/union.zig");
96 _ = @import("behavior/usingnamespace.zig");
9697 _ = @import("behavior/var_args.zig");
9798 _ = @import("behavior/vector.zig");
9899 _ = @import("behavior/void.zig");
test/stage1/behavior/atomics.zig+31
......@@ -1,5 +1,6 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
34const builtin = @import("builtin");
45const AtomicRmwOp = builtin.AtomicRmwOp;
56const AtomicOrder = builtin.AtomicOrder;
......@@ -69,3 +70,33 @@ test "cmpxchg with ptr" {
6970 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
7071 expect(x == &data2);
7172}
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 @@
11const std = @import("std");
22const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
34const builtin = @import("builtin");
45
56test "compile time recursion" {
......@@ -794,3 +795,12 @@ test "no undeclared identifier error in unanalyzed branches" {
794795 lol_this_doesnt_exist = nonsense;
795796 }
796797}
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" {
228228 S.entry();
229229 comptime S.entry();
230230}
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" {
7474 S.doTheTest();
7575 comptime S.doTheTest();
7676}
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 {
17801780 \\}
17811781 );
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
17831817 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
17841818 cases.addC("Parameterless function prototypes",
17851819 \\void foo() {}