| author | |
| committer | |
| log | 3f4d0ecd7e5a57b425b1cd99139145e7e509c3c6 |
| tree | 76d1d16a397e44c04167456116d6d3cc91f0b994 |
| parent | 9462852433a815496e0edf5d5b2e00726f5ea072 |
| parent | 0ac1b83885c7f2a97a8ac25657afcb5c9b80afb4 |
10 files changed, 202 insertions(+), 63 deletions(-)
doc/docgen.zig+16-13| ... | @@ -689,7 +689,10 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { | ... | @@ -689,7 +689,10 @@ fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 { |
| 689 | fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void { | 689 | fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var, zig_exe: []const u8) !void { |
| 690 | var code_progress_index: usize = 0; | 690 | var code_progress_index: usize = 0; |
| 691 | 691 | ||
| 692 | const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, zig_exe)); | 692 | var env_map = try os.getEnvMap(allocator); |
| 693 | try env_map.set("ZIG_DEBUG_COLOR", "1"); | ||
| 694 | |||
| 695 | const builtin_code = try escapeHtml(allocator, try getBuiltinCode(allocator, &env_map, zig_exe)); | ||
| 693 | 696 | ||
| 694 | for (toc.nodes) |node| { | 697 | for (toc.nodes) |node| { |
| 695 | switch (node) { | 698 | switch (node) { |
| ... | @@ -778,12 +781,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -778,12 +781,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 778 | try build_args.append("c"); | 781 | try build_args.append("c"); |
| 779 | try out.print(" --library c"); | 782 | try out.print(" --library c"); |
| 780 | } | 783 | } |
| 781 | _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); | 784 | _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); |
| 782 | 785 | ||
| 783 | const run_args = [][]const u8{tmp_bin_file_name}; | 786 | const run_args = [][]const u8{tmp_bin_file_name}; |
| 784 | 787 | ||
| 785 | const result = if (expected_outcome == ExpectedOutcome.Fail) blk: { | 788 | const result = if (expected_outcome == ExpectedOutcome.Fail) blk: { |
| 786 | const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size); | 789 | const result = try os.ChildProcess.exec(allocator, run_args, null, &env_map, max_doc_file_size); |
| 787 | switch (result.term) { | 790 | switch (result.term) { |
| 788 | os.ChildProcess.Term.Exited => |exit_code| { | 791 | os.ChildProcess.Term.Exited => |exit_code| { |
| 789 | if (exit_code == 0) { | 792 | if (exit_code == 0) { |
| ... | @@ -799,7 +802,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -799,7 +802,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 799 | } | 802 | } |
| 800 | break :blk result; | 803 | break :blk result; |
| 801 | } else blk: { | 804 | } else blk: { |
| 802 | break :blk exec(allocator, run_args) catch return parseError(tokenizer, code.source_token, "example crashed"); | 805 | break :blk exec(allocator, &env_map, run_args) catch return parseError(tokenizer, code.source_token, "example crashed"); |
| 803 | }; | 806 | }; |
| 804 | 807 | ||
| 805 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | 808 | const escaped_stderr = try escapeHtml(allocator, result.stderr); |
| ... | @@ -845,7 +848,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -845,7 +848,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 845 | "msvc", | 848 | "msvc", |
| 846 | }); | 849 | }); |
| 847 | } | 850 | } |
| 848 | const result = exec(allocator, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed"); | 851 | const result = exec(allocator, &env_map, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed"); |
| 849 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | 852 | const escaped_stderr = try escapeHtml(allocator, result.stderr); |
| 850 | const escaped_stdout = try escapeHtml(allocator, result.stdout); | 853 | const escaped_stdout = try escapeHtml(allocator, result.stdout); |
| 851 | try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout); | 854 | try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout); |
| ... | @@ -877,7 +880,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -877,7 +880,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 877 | try out.print(" --release-small"); | 880 | try out.print(" --release-small"); |
| 878 | }, | 881 | }, |
| 879 | } | 882 | } |
| 880 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size); | 883 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, &env_map, max_doc_file_size); |
| 881 | switch (result.term) { | 884 | switch (result.term) { |
| 882 | os.ChildProcess.Term.Exited => |exit_code| { | 885 | os.ChildProcess.Term.Exited => |exit_code| { |
| 883 | if (exit_code == 0) { | 886 | if (exit_code == 0) { |
| ... | @@ -923,7 +926,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -923,7 +926,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 923 | builtin.Mode.ReleaseSmall => try test_args.append("--release-small"), | 926 | builtin.Mode.ReleaseSmall => try test_args.append("--release-small"), |
| 924 | } | 927 | } |
| 925 | 928 | ||
| 926 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size); | 929 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, &env_map, max_doc_file_size); |
| 927 | switch (result.term) { | 930 | switch (result.term) { |
| 928 | os.ChildProcess.Term.Exited => |exit_code| { | 931 | os.ChildProcess.Term.Exited => |exit_code| { |
| 929 | if (exit_code == 0) { | 932 | if (exit_code == 0) { |
| ... | @@ -1000,7 +1003,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -1000,7 +1003,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1000 | } | 1003 | } |
| 1001 | 1004 | ||
| 1002 | if (maybe_error_match) |error_match| { | 1005 | if (maybe_error_match) |error_match| { |
| 1003 | const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, null, max_doc_file_size); | 1006 | const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, &env_map, max_doc_file_size); |
| 1004 | switch (result.term) { | 1007 | switch (result.term) { |
| 1005 | os.ChildProcess.Term.Exited => |exit_code| { | 1008 | os.ChildProcess.Term.Exited => |exit_code| { |
| 1006 | if (exit_code == 0) { | 1009 | if (exit_code == 0) { |
| ... | @@ -1032,7 +1035,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -1032,7 +1035,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1032 | try out.print("</code></pre>\n"); | 1035 | try out.print("</code></pre>\n"); |
| 1033 | } | 1036 | } |
| 1034 | } else { | 1037 | } else { |
| 1035 | _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); | 1038 | _ = exec(allocator, &env_map, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile"); |
| 1036 | } | 1039 | } |
| 1037 | if (!code.is_inline) { | 1040 | if (!code.is_inline) { |
| 1038 | try out.print("</code></pre>\n"); | 1041 | try out.print("</code></pre>\n"); |
| ... | @@ -1045,8 +1048,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var | ... | @@ -1045,8 +1048,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var |
| 1045 | } | 1048 | } |
| 1046 | } | 1049 | } |
| 1047 | 1050 | ||
| 1048 | fn exec(allocator: *mem.Allocator, args: []const []const u8) !os.ChildProcess.ExecResult { | 1051 | fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u8) !os.ChildProcess.ExecResult { |
| 1049 | const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size); | 1052 | const result = try os.ChildProcess.exec(allocator, args, null, env_map, max_doc_file_size); |
| 1050 | switch (result.term) { | 1053 | switch (result.term) { |
| 1051 | os.ChildProcess.Term.Exited => |exit_code| { | 1054 | os.ChildProcess.Term.Exited => |exit_code| { |
| 1052 | if (exit_code != 0) { | 1055 | if (exit_code != 0) { |
| ... | @@ -1070,8 +1073,8 @@ fn exec(allocator: *mem.Allocator, args: []const []const u8) !os.ChildProcess.Ex | ... | @@ -1070,8 +1073,8 @@ fn exec(allocator: *mem.Allocator, args: []const []const u8) !os.ChildProcess.Ex |
| 1070 | return result; | 1073 | return result; |
| 1071 | } | 1074 | } |
| 1072 | 1075 | ||
| 1073 | fn getBuiltinCode(allocator: *mem.Allocator, zig_exe: []const u8) ![]const u8 { | 1076 | fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 { |
| 1074 | const result = try exec(allocator, []const []const u8{ | 1077 | const result = try exec(allocator, env_map, []const []const u8{ |
| 1075 | zig_exe, | 1078 | zig_exe, |
| 1076 | "builtin", | 1079 | "builtin", |
| 1077 | }); | 1080 | }); |
doc/langref.html.in+51-3| ... | @@ -6649,12 +6649,60 @@ pub fn main() void { | ... | @@ -6649,12 +6649,60 @@ pub fn main() void { |
| 6649 | {#header_close#} | 6649 | {#header_close#} |
| 6650 | 6650 | ||
| 6651 | {#header_open|Invalid Error Set Cast#} | 6651 | {#header_open|Invalid Error Set Cast#} |
| 6652 | <p>TODO</p> | 6652 | <p>At compile-time:</p> |
| 6653 | {#code_begin|test_err|error.B not a member of error set 'Set2'#} | ||
| 6654 | const Set1 = error{ | ||
| 6655 | A, | ||
| 6656 | B, | ||
| 6657 | }; | ||
| 6658 | const Set2 = error{ | ||
| 6659 | A, | ||
| 6660 | C, | ||
| 6661 | }; | ||
| 6662 | comptime { | ||
| 6663 | _ = @errSetCast(Set2, Set1.B); | ||
| 6664 | } | ||
| 6665 | {#code_end#} | ||
| 6666 | <p>At runtime:</p> | ||
| 6667 | {#code_begin|exe_err#} | ||
| 6668 | const Set1 = error{ | ||
| 6669 | A, | ||
| 6670 | B, | ||
| 6671 | }; | ||
| 6672 | const Set2 = error{ | ||
| 6673 | A, | ||
| 6674 | C, | ||
| 6675 | }; | ||
| 6676 | pub fn main() void { | ||
| 6677 | _ = foo(Set1.B); | ||
| 6678 | } | ||
| 6679 | fn foo(set1: Set1) Set2 { | ||
| 6680 | return @errSetCast(Set2, set1); | ||
| 6681 | } | ||
| 6682 | {#code_end#} | ||
| 6653 | {#header_close#} | 6683 | {#header_close#} |
| 6654 | 6684 | ||
| 6655 | {#header_open|Incorrect Pointer Alignment#} | 6685 | {#header_open|Incorrect Pointer Alignment#} |
| 6656 | <p>TODO</p> | 6686 | <p>At compile-time:</p> |
| 6657 | 6687 | {#code_begin|test_err|pointer address 0x1 is not aligned to 4 bytes#} | |
| 6688 | comptime { | ||
| 6689 | const ptr = @intToPtr(*i32, 0x1); | ||
| 6690 | const aligned = @alignCast(4, ptr); | ||
| 6691 | } | ||
| 6692 | {#code_end#} | ||
| 6693 | <p>At runtime:</p> | ||
| 6694 | {#code_begin|exe_err#} | ||
| 6695 | pub fn main() !void { | ||
| 6696 | var array align(4) = []u32{ 0x11111111, 0x11111111 }; | ||
| 6697 | const bytes = @sliceToBytes(array[0..]); | ||
| 6698 | if (foo(bytes) != 0x11111111) return error.Wrong; | ||
| 6699 | } | ||
| 6700 | fn foo(bytes: []u8) u32 { | ||
| 6701 | const slice4 = bytes[1..5]; | ||
| 6702 | const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); | ||
| 6703 | return int_slice[0]; | ||
| 6704 | } | ||
| 6705 | {#code_end#} | ||
| 6658 | {#header_close#} | 6706 | {#header_close#} |
| 6659 | {#header_open|Wrong Union Field Access#} | 6707 | {#header_open|Wrong Union Field Access#} |
| 6660 | <p>TODO</p> | 6708 | <p>TODO</p> |
src/ir.cpp+15| ... | @@ -19370,6 +19370,15 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 | ... | @@ -19370,6 +19370,15 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 19370 | if (!val) | 19370 | if (!val) |
| 19371 | return ira->codegen->invalid_instruction; | 19371 | return ira->codegen->invalid_instruction; |
| 19372 | 19372 | ||
| 19373 | if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && | ||
| 19374 | val->data.x_ptr.data.hard_coded_addr.addr % align_bytes != 0) | ||
| 19375 | { | ||
| 19376 | ir_add_error(ira, target, | ||
| 19377 | buf_sprintf("pointer address 0x%" ZIG_PRI_x64 " is not aligned to %" PRIu32 " bytes", | ||
| 19378 | val->data.x_ptr.data.hard_coded_addr.addr, align_bytes)); | ||
| 19379 | return ira->codegen->invalid_instruction; | ||
| 19380 | } | ||
| 19381 | |||
| 19373 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); | 19382 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); |
| 19374 | copy_const_val(&result->value, val, false); | 19383 | copy_const_val(&result->value, val, false); |
| 19375 | result->value.type = result_type; | 19384 | result->value.type = result_type; |
| ... | @@ -19796,6 +19805,12 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr | ... | @@ -19796,6 +19805,12 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr |
| 19796 | return ira->codegen->builtin_types.entry_invalid; | 19805 | return ira->codegen->builtin_types.entry_invalid; |
| 19797 | } | 19806 | } |
| 19798 | 19807 | ||
| 19808 | if (!type_has_bits(target->value.type)) { | ||
| 19809 | ir_add_error(ira, target, | ||
| 19810 | buf_sprintf("pointer to size 0 type has no address")); | ||
| 19811 | return ira->codegen->builtin_types.entry_invalid; | ||
| 19812 | } | ||
| 19813 | |||
| 19799 | if (instr_is_comptime(target)) { | 19814 | if (instr_is_comptime(target)) { |
| 19800 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); | 19815 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 19801 | if (!val) | 19816 | if (!val) |
std/build.zig+18| ... | @@ -814,6 +814,7 @@ pub const LibExeObjStep = struct { | ... | @@ -814,6 +814,7 @@ pub const LibExeObjStep = struct { |
| 814 | out_h_filename: []const u8, | 814 | out_h_filename: []const u8, |
| 815 | assembly_files: ArrayList([]const u8), | 815 | assembly_files: ArrayList([]const u8), |
| 816 | packages: ArrayList(Pkg), | 816 | packages: ArrayList(Pkg), |
| 817 | build_options_contents: std.Buffer, | ||
| 817 | 818 | ||
| 818 | // C only stuff | 819 | // C only stuff |
| 819 | source_files: ArrayList([]const u8), | 820 | source_files: ArrayList([]const u8), |
| ... | @@ -905,6 +906,7 @@ pub const LibExeObjStep = struct { | ... | @@ -905,6 +906,7 @@ pub const LibExeObjStep = struct { |
| 905 | .lib_paths = ArrayList([]const u8).init(builder.allocator), | 906 | .lib_paths = ArrayList([]const u8).init(builder.allocator), |
| 906 | .object_src = undefined, | 907 | .object_src = undefined, |
| 907 | .disable_libc = true, | 908 | .disable_libc = true, |
| 909 | .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, | ||
| 908 | }; | 910 | }; |
| 909 | self.computeOutFileNames(); | 911 | self.computeOutFileNames(); |
| 910 | return self; | 912 | return self; |
| ... | @@ -945,6 +947,7 @@ pub const LibExeObjStep = struct { | ... | @@ -945,6 +947,7 @@ pub const LibExeObjStep = struct { |
| 945 | .out_h_filename = undefined, | 947 | .out_h_filename = undefined, |
| 946 | .assembly_files = undefined, | 948 | .assembly_files = undefined, |
| 947 | .packages = undefined, | 949 | .packages = undefined, |
| 950 | .build_options_contents = undefined, | ||
| 948 | }; | 951 | }; |
| 949 | self.computeOutFileNames(); | 952 | self.computeOutFileNames(); |
| 950 | return self; | 953 | return self; |
| ... | @@ -1096,6 +1099,12 @@ pub const LibExeObjStep = struct { | ... | @@ -1096,6 +1099,12 @@ pub const LibExeObjStep = struct { |
| 1096 | self.include_dirs.append(self.builder.cache_root) catch unreachable; | 1099 | self.include_dirs.append(self.builder.cache_root) catch unreachable; |
| 1097 | } | 1100 | } |
| 1098 | 1101 | ||
| 1102 | pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void { | ||
| 1103 | assert(self.is_zig); | ||
| 1104 | const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream; | ||
| 1105 | out.print("pub const {} = {};\n", name, value) catch unreachable; | ||
| 1106 | } | ||
| 1107 | |||
| 1099 | pub fn addIncludeDir(self: *LibExeObjStep, path: []const u8) void { | 1108 | pub fn addIncludeDir(self: *LibExeObjStep, path: []const u8) void { |
| 1100 | self.include_dirs.append(path) catch unreachable; | 1109 | self.include_dirs.append(path) catch unreachable; |
| 1101 | } | 1110 | } |
| ... | @@ -1155,6 +1164,15 @@ pub const LibExeObjStep = struct { | ... | @@ -1155,6 +1164,15 @@ pub const LibExeObjStep = struct { |
| 1155 | zig_args.append(builder.pathFromRoot(root_src)) catch unreachable; | 1164 | zig_args.append(builder.pathFromRoot(root_src)) catch unreachable; |
| 1156 | } | 1165 | } |
| 1157 | 1166 | ||
| 1167 | if (self.build_options_contents.len() > 0) { | ||
| 1168 | const build_options_file = try os.path.join(builder.allocator, builder.cache_root, builder.fmt("{}_build_options.zig", self.name)); | ||
| 1169 | try std.io.writeFile(builder.allocator, build_options_file, self.build_options_contents.toSliceConst()); | ||
| 1170 | try zig_args.append("--pkg-begin"); | ||
| 1171 | try zig_args.append("build_options"); | ||
| 1172 | try zig_args.append(builder.pathFromRoot(build_options_file)); | ||
| 1173 | try zig_args.append("--pkg-end"); | ||
| 1174 | } | ||
| 1175 | |||
| 1158 | for (self.object_files.toSliceConst()) |object_file| { | 1176 | for (self.object_files.toSliceConst()) |object_file| { |
| 1159 | zig_args.append("--object") catch unreachable; | 1177 | zig_args.append("--object") catch unreachable; |
| 1160 | zig_args.append(builder.pathFromRoot(object_file)) catch unreachable; | 1178 | zig_args.append(builder.pathFromRoot(object_file)) catch unreachable; |
std/debug/index.zig+50-23| ... | @@ -10,6 +10,7 @@ const ArrayList = std.ArrayList; | ... | @@ -10,6 +10,7 @@ const ArrayList = std.ArrayList; |
| 10 | const builtin = @import("builtin"); | 10 | const builtin = @import("builtin"); |
| 11 | 11 | ||
| 12 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; | 12 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; |
| 13 | pub const failing_allocator = FailingAllocator.init(global_allocator, 0); | ||
| 13 | 14 | ||
| 14 | pub const runtime_safety = switch (builtin.mode) { | 15 | pub const runtime_safety = switch (builtin.mode) { |
| 15 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => true, | 16 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => true, |
| ... | @@ -49,6 +50,12 @@ pub fn getSelfDebugInfo() !*ElfStackTrace { | ... | @@ -49,6 +50,12 @@ pub fn getSelfDebugInfo() !*ElfStackTrace { |
| 49 | } | 50 | } |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 53 | fn wantTtyColor() bool { | ||
| 54 | var bytes: [128]u8 = undefined; | ||
| 55 | const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; | ||
| 56 | return if (std.os.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| true else |_| stderr_file.isTty(); | ||
| 57 | } | ||
| 58 | |||
| 52 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. | 59 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. |
| 53 | pub fn dumpCurrentStackTrace(start_addr: ?usize) void { | 60 | pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 54 | const stderr = getStderrStream() catch return; | 61 | const stderr = getStderrStream() catch return; |
| ... | @@ -56,7 +63,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { | ... | @@ -56,7 +63,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |
| 56 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; | 63 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 57 | return; | 64 | return; |
| 58 | }; | 65 | }; |
| 59 | writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty(), start_addr) catch |err| { | 66 | writeCurrentStackTrace(stderr, getDebugInfoAllocator(), debug_info, wantTtyColor(), start_addr) catch |err| { |
| 60 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | 67 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 61 | return; | 68 | return; |
| 62 | }; | 69 | }; |
| ... | @@ -69,7 +76,7 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { | ... | @@ -69,7 +76,7 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void { |
| 69 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; | 76 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 70 | return; | 77 | return; |
| 71 | }; | 78 | }; |
| 72 | writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, stderr_file.isTty()) catch |err| { | 79 | writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, wantTtyColor()) catch |err| { |
| 73 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | 80 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 74 | return; | 81 | return; |
| 75 | }; | 82 | }; |
| ... | @@ -161,7 +168,7 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, | ... | @@ -161,7 +168,7 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, |
| 161 | frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; | 168 | frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; |
| 162 | }) { | 169 | }) { |
| 163 | const return_address = stack_trace.instruction_addresses[frame_index]; | 170 | const return_address = stack_trace.instruction_addresses[frame_index]; |
| 164 | try printSourceAtAddress(debug_info, out_stream, return_address); | 171 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); |
| 165 | } | 172 | } |
| 166 | } | 173 | } |
| 167 | 174 | ||
| ... | @@ -194,13 +201,11 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_ | ... | @@ -194,13 +201,11 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: *mem.Allocator, debug_ |
| 194 | } | 201 | } |
| 195 | }, | 202 | }, |
| 196 | } | 203 | } |
| 197 | try printSourceAtAddress(debug_info, out_stream, return_address); | 204 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); |
| 198 | } | 205 | } |
| 199 | } | 206 | } |
| 200 | 207 | ||
| 201 | fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: usize) !void { | 208 | fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: usize, tty_color: bool) !void { |
| 202 | const ptr_hex = "0x{x}"; | ||
| 203 | |||
| 204 | switch (builtin.os) { | 209 | switch (builtin.os) { |
| 205 | builtin.Os.windows => return error.UnsupportedDebugInfo, | 210 | builtin.Os.windows => return error.UnsupportedDebugInfo, |
| 206 | builtin.Os.macosx => { | 211 | builtin.Os.macosx => { |
| ... | @@ -214,36 +219,58 @@ fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: us | ... | @@ -214,36 +219,58 @@ fn printSourceAtAddress(debug_info: *ElfStackTrace, out_stream: var, address: us |
| 214 | .address = address, | 219 | .address = address, |
| 215 | }; | 220 | }; |
| 216 | const symbol = debug_info.symbol_table.search(address) orelse &unknown; | 221 | const symbol = debug_info.symbol_table.search(address) orelse &unknown; |
| 217 | try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n", symbol.name, address); | 222 | try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ DIM ++ "0x{x}" ++ " in ??? (???)" ++ RESET ++ "\n", symbol.name, address); |
| 218 | }, | 223 | }, |
| 219 | else => { | 224 | else => { |
| 220 | const compile_unit = findCompileUnit(debug_info, address) catch { | 225 | const compile_unit = findCompileUnit(debug_info, address) catch { |
| 221 | try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", address); | 226 | if (tty_color) { |
| 227 | try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n ???\n\n", address); | ||
| 228 | } else { | ||
| 229 | try out_stream.print("???:?:?: 0x{x} in ??? (???)\n ???\n\n", address); | ||
| 230 | } | ||
| 222 | return; | 231 | return; |
| 223 | }; | 232 | }; |
| 224 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); | 233 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); |
| 225 | if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { | 234 | if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { |
| 226 | defer line_info.deinit(); | 235 | defer line_info.deinit(); |
| 227 | try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", line_info.file_name, line_info.line, line_info.column, address, compile_unit_name); | 236 | if (tty_color) { |
| 228 | if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) { | 237 | try out_stream.print( |
| 229 | if (line_info.column == 0) { | 238 | WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ "0x{x} in ??? ({})" ++ RESET ++ "\n", |
| 230 | try out_stream.write("\n"); | 239 | line_info.file_name, |
| 231 | } else { | 240 | line_info.line, |
| 232 | { | 241 | line_info.column, |
| 233 | var col_i: usize = 1; | 242 | address, |
| 234 | while (col_i < line_info.column) : (col_i += 1) { | 243 | compile_unit_name, |
| 235 | try out_stream.writeByte(' '); | 244 | ); |
| 245 | if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) { | ||
| 246 | if (line_info.column == 0) { | ||
| 247 | try out_stream.write("\n"); | ||
| 248 | } else { | ||
| 249 | { | ||
| 250 | var col_i: usize = 1; | ||
| 251 | while (col_i < line_info.column) : (col_i += 1) { | ||
| 252 | try out_stream.writeByte(' '); | ||
| 253 | } | ||
| 236 | } | 254 | } |
| 255 | try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | ||
| 237 | } | 256 | } |
| 238 | try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | 257 | } else |err| switch (err) { |
| 258 | error.EndOfFile => {}, | ||
| 259 | else => return err, | ||
| 239 | } | 260 | } |
| 240 | } else |err| switch (err) { | 261 | } else { |
| 241 | error.EndOfFile => {}, | 262 | try out_stream.print( |
| 242 | else => return err, | 263 | "{}:{}:{}: 0x{x} in ??? ({})\n", |
| 264 | line_info.file_name, | ||
| 265 | line_info.line, | ||
| 266 | line_info.column, | ||
| 267 | address, | ||
| 268 | compile_unit_name, | ||
| 269 | ); | ||
| 243 | } | 270 | } |
| 244 | } else |err| switch (err) { | 271 | } else |err| switch (err) { |
| 245 | error.MissingDebugInfo, error.InvalidDebugInfo => { | 272 | error.MissingDebugInfo, error.InvalidDebugInfo => { |
| 246 | try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name); | 273 | try out_stream.print("0x{x} in ??? ({})\n", address, compile_unit_name); |
| 247 | }, | 274 | }, |
| 248 | else => return err, | 275 | else => return err, |
| 249 | } | 276 | } |
std/hash_map.zig+10-10| ... | @@ -259,14 +259,14 @@ test "basic hash map usage" { | ... | @@ -259,14 +259,14 @@ test "basic hash map usage" { |
| 259 | var map = HashMap(i32, i32, hash_i32, eql_i32).init(&direct_allocator.allocator); | 259 | var map = HashMap(i32, i32, hash_i32, eql_i32).init(&direct_allocator.allocator); |
| 260 | defer map.deinit(); | 260 | defer map.deinit(); |
| 261 | 261 | ||
| 262 | assert((map.put(1, 11) catch unreachable) == null); | 262 | assert((try map.put(1, 11)) == null); |
| 263 | assert((map.put(2, 22) catch unreachable) == null); | 263 | assert((try map.put(2, 22)) == null); |
| 264 | assert((map.put(3, 33) catch unreachable) == null); | 264 | assert((try map.put(3, 33)) == null); |
| 265 | assert((map.put(4, 44) catch unreachable) == null); | 265 | assert((try map.put(4, 44)) == null); |
| 266 | assert((map.put(5, 55) catch unreachable) == null); | 266 | assert((try map.put(5, 55)) == null); |
| 267 | 267 | ||
| 268 | assert((map.put(5, 66) catch unreachable).? == 55); | 268 | assert((try map.put(5, 66)).? == 55); |
| 269 | assert((map.put(5, 55) catch unreachable).? == 66); | 269 | assert((try map.put(5, 55)).? == 66); |
| 270 | 270 | ||
| 271 | assert(map.contains(2)); | 271 | assert(map.contains(2)); |
| 272 | assert(map.get(2).?.value == 22); | 272 | assert(map.get(2).?.value == 22); |
| ... | @@ -282,9 +282,9 @@ test "iterator hash map" { | ... | @@ -282,9 +282,9 @@ test "iterator hash map" { |
| 282 | var reset_map = HashMap(i32, i32, hash_i32, eql_i32).init(&direct_allocator.allocator); | 282 | var reset_map = HashMap(i32, i32, hash_i32, eql_i32).init(&direct_allocator.allocator); |
| 283 | defer reset_map.deinit(); | 283 | defer reset_map.deinit(); |
| 284 | 284 | ||
| 285 | assert((reset_map.put(1, 11) catch unreachable) == null); | 285 | assert((try reset_map.put(1, 11)) == null); |
| 286 | assert((reset_map.put(2, 22) catch unreachable) == null); | 286 | assert((try reset_map.put(2, 22)) == null); |
| 287 | assert((reset_map.put(3, 33) catch unreachable) == null); | 287 | assert((try reset_map.put(3, 33)) == null); |
| 288 | 288 | ||
| 289 | var keys = []i32{ | 289 | var keys = []i32{ |
| 290 | 1, | 290 | 1, |
std/os/index.zig+11-3| ... | @@ -553,8 +553,13 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { | ... | @@ -553,8 +553,13 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 553 | return null; | 553 | return null; |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | pub const GetEnvVarOwnedError = error{ | ||
| 557 | OutOfMemory, | ||
| 558 | EnvironmentVariableNotFound, | ||
| 559 | }; | ||
| 560 | |||
| 556 | /// Caller must free returned memory. | 561 | /// Caller must free returned memory. |
| 557 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) ![]u8 { | 562 | pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 { |
| 558 | if (is_windows) { | 563 | if (is_windows) { |
| 559 | const key_with_null = try cstr.addNullByte(allocator, key); | 564 | const key_with_null = try cstr.addNullByte(allocator, key); |
| 560 | defer allocator.free(key_with_null); | 565 | defer allocator.free(key_with_null); |
| ... | @@ -563,14 +568,17 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) ![]u8 { | ... | @@ -563,14 +568,17 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) ![]u8 { |
| 563 | errdefer allocator.free(buf); | 568 | errdefer allocator.free(buf); |
| 564 | 569 | ||
| 565 | while (true) { | 570 | while (true) { |
| 566 | const windows_buf_len = try math.cast(windows.DWORD, buf.len); | 571 | const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory; |
| 567 | const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len); | 572 | const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len); |
| 568 | 573 | ||
| 569 | if (result == 0) { | 574 | if (result == 0) { |
| 570 | const err = windows.GetLastError(); | 575 | const err = windows.GetLastError(); |
| 571 | return switch (err) { | 576 | return switch (err) { |
| 572 | windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound, | 577 | windows.ERROR.ENVVAR_NOT_FOUND => error.EnvironmentVariableNotFound, |
| 573 | else => unexpectedErrorWindows(err), | 578 | else => { |
| 579 | _ = unexpectedErrorWindows(err); | ||
| 580 | return error.EnvironmentVariableNotFound; | ||
| 581 | }, | ||
| 574 | }; | 582 | }; |
| 575 | } | 583 | } |
| 576 | 584 |
std/special/build_runner.zig+6-3| ... | @@ -122,10 +122,13 @@ pub fn main() !void { | ... | @@ -122,10 +122,13 @@ pub fn main() !void { |
| 122 | return usageAndErr(&builder, true, try stderr_stream); | 122 | return usageAndErr(&builder, true, try stderr_stream); |
| 123 | 123 | ||
| 124 | builder.make(targets.toSliceConst()) catch |err| { | 124 | builder.make(targets.toSliceConst()) catch |err| { |
| 125 | if (err == error.InvalidStepName) { | 125 | switch (err) { |
| 126 | return usageAndErr(&builder, true, try stderr_stream); | 126 | error.InvalidStepName => { |
| 127 | return usageAndErr(&builder, true, try stderr_stream); | ||
| 128 | }, | ||
| 129 | error.UncleanExit => os.exit(1), | ||
| 130 | else => return err, | ||
| 127 | } | 131 | } |
| 128 | return err; | ||
| 129 | }; | 132 | }; |
| 130 | } | 133 | } |
| 131 | 134 |
std/zig/bench.zig+6-8| ... | @@ -19,20 +19,18 @@ pub fn main() !void { | ... | @@ -19,20 +19,18 @@ pub fn main() !void { |
| 19 | } | 19 | } |
| 20 | const end = timer.read(); | 20 | const end = timer.read(); |
| 21 | memory_used /= iterations; | 21 | memory_used /= iterations; |
| 22 | const elapsed_s = f64(end - start) / std.os.time.ns_per_s; | 22 | const elapsed_s = @intToFloat(f64, end - start) / std.os.time.ns_per_s; |
| 23 | const bytes_per_sec = f64(source.len * iterations) / elapsed_s; | 23 | const bytes_per_sec = @intToFloat(f64, source.len * iterations) / elapsed_s; |
| 24 | const mb_per_sec = bytes_per_sec / (1024 * 1024); | 24 | const mb_per_sec = bytes_per_sec / (1024 * 1024); |
| 25 | 25 | ||
| 26 | var stdout_file = try std.io.getStdOut(); | 26 | var stdout_file = try std.io.getStdOut(); |
| 27 | const stdout = *std.io.FileOutStream.init(*stdout_file).stream; | 27 | const stdout = &std.io.FileOutStream.init(&stdout_file).stream; |
| 28 | try stdout.print("{.3} MB/s, {} KB used \n", mb_per_sec, memory_used / 1024); | 28 | try stdout.print("{.3} MiB/s, {} KiB used \n", mb_per_sec, memory_used / 1024); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | fn testOnce() usize { | 31 | fn testOnce() usize { |
| 32 | var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); | 32 | var fixed_buf_alloc = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 33 | var allocator = *fixed_buf_alloc.allocator; | 33 | var allocator = &fixed_buf_alloc.allocator; |
| 34 | var tokenizer = Tokenizer.init(source); | 34 | _ = std.zig.parse(allocator, source) catch @panic("parse failure"); |
| 35 | var parser = Parser.init(*tokenizer, allocator, "(memory buffer)"); | ||
| 36 | _ = parser.parse() catch @panic("parse failure"); | ||
| 37 | return fixed_buf_alloc.end_index; | 35 | return fixed_buf_alloc.end_index; |
| 38 | } | 36 | } |
test/compile_errors.zig+19| ... | @@ -1,6 +1,25 @@ | ... | @@ -1,6 +1,25 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.add( | ||
| 5 | "bad @alignCast at comptime", | ||
| 6 | \\comptime { | ||
| 7 | \\ const ptr = @intToPtr(*i32, 0x1); | ||
| 8 | \\ const aligned = @alignCast(4, ptr); | ||
| 9 | \\} | ||
| 10 | , | ||
| 11 | ".tmp_source.zig:3:35: error: pointer address 0x1 is not aligned to 4 bytes", | ||
| 12 | ); | ||
| 13 | |||
| 14 | cases.add( | ||
| 15 | "@ptrToInt on *void", | ||
| 16 | \\export fn entry() bool { | ||
| 17 | \\ return @ptrToInt(&{}) == @ptrToInt(&{}); | ||
| 18 | \\} | ||
| 19 | , | ||
| 20 | ".tmp_source.zig:2:23: error: pointer to size 0 type has no address", | ||
| 21 | ); | ||
| 22 | |||
| 4 | cases.add( | 23 | cases.add( |
| 5 | "@popCount - non-integer", | 24 | "@popCount - non-integer", |
| 6 | \\export fn entry(x: f32) u32 { | 25 | \\export fn entry(x: f32) u32 { |