| author | |
| committer | |
| log | c17e18647bf55bae38a1837a6afb19b0f2393892 |
| tree | 43b31a86060f36ab3a40baab8fc4834317794619 |
| parent | 66193e72d3deeac4f78bc8d81f42a7d9b243fa58 |
| parent | ed6d9e2a9d6a25d511cbaa4c7ee34083223460ae |
| signature |
Add error bundle support to `translate-c`, unify `cmdTranslateC` and `cImport`11 files changed, 407 insertions(+), 290 deletions(-)
lib/compiler/resinator/main.zig+10-85| ... | @@ -13,6 +13,7 @@ const cvtres = @import("cvtres.zig"); | ... | @@ -13,6 +13,7 @@ const cvtres = @import("cvtres.zig"); |
| 13 | const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage; | 13 | const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage; |
| 14 | const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; | 14 | const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType; |
| 15 | const aro = @import("aro"); | 15 | const aro = @import("aro"); |
| 16 | const compiler_util = @import("../util.zig"); | ||
| 16 | 17 | ||
| 17 | pub fn main() !void { | 18 | pub fn main() !void { |
| 18 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; | 19 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; |
| ... | @@ -671,7 +672,11 @@ const ErrorHandler = union(enum) { | ... | @@ -671,7 +672,11 @@ const ErrorHandler = union(enum) { |
| 671 | ) !void { | 672 | ) !void { |
| 672 | switch (self.*) { | 673 | switch (self.*) { |
| 673 | .server => |*server| { | 674 | .server => |*server| { |
| 674 | var error_bundle = try aroDiagnosticsToErrorBundle(allocator, fail_msg, comp); | 675 | var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle( |
| 676 | comp.diagnostics, | ||
| 677 | allocator, | ||
| 678 | fail_msg, | ||
| 679 | ); | ||
| 675 | defer error_bundle.deinit(allocator); | 680 | defer error_bundle.deinit(allocator); |
| 676 | 681 | ||
| 677 | try server.serveErrorBundle(error_bundle); | 682 | try server.serveErrorBundle(error_bundle); |
| ... | @@ -753,7 +758,7 @@ fn cliDiagnosticsToErrorBundle( | ... | @@ -753,7 +758,7 @@ fn cliDiagnosticsToErrorBundle( |
| 753 | switch (err_details.type) { | 758 | switch (err_details.type) { |
| 754 | .err => { | 759 | .err => { |
| 755 | if (cur_err) |err| { | 760 | if (cur_err) |err| { |
| 756 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | 761 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 757 | } | 762 | } |
| 758 | cur_err = .{ | 763 | cur_err = .{ |
| 759 | .msg = try bundle.addString(err_details.msg.items), | 764 | .msg = try bundle.addString(err_details.msg.items), |
| ... | @@ -771,7 +776,7 @@ fn cliDiagnosticsToErrorBundle( | ... | @@ -771,7 +776,7 @@ fn cliDiagnosticsToErrorBundle( |
| 771 | } | 776 | } |
| 772 | } | 777 | } |
| 773 | if (cur_err) |err| { | 778 | if (cur_err) |err| { |
| 774 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | 779 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 775 | } | 780 | } |
| 776 | 781 | ||
| 777 | return try bundle.toOwnedBundle(""); | 782 | return try bundle.toOwnedBundle(""); |
| ... | @@ -840,7 +845,7 @@ fn diagnosticsToErrorBundle( | ... | @@ -840,7 +845,7 @@ fn diagnosticsToErrorBundle( |
| 840 | switch (err_details.type) { | 845 | switch (err_details.type) { |
| 841 | .err => { | 846 | .err => { |
| 842 | if (cur_err) |err| { | 847 | if (cur_err) |err| { |
| 843 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | 848 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 844 | } | 849 | } |
| 845 | cur_err = .{ | 850 | cur_err = .{ |
| 846 | .msg = try bundle.addString(msg_buf.written()), | 851 | .msg = try bundle.addString(msg_buf.written()), |
| ... | @@ -859,20 +864,12 @@ fn diagnosticsToErrorBundle( | ... | @@ -859,20 +864,12 @@ fn diagnosticsToErrorBundle( |
| 859 | } | 864 | } |
| 860 | } | 865 | } |
| 861 | if (cur_err) |err| { | 866 | if (cur_err) |err| { |
| 862 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | 867 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); |
| 863 | } | 868 | } |
| 864 | 869 | ||
| 865 | return try bundle.toOwnedBundle(""); | 870 | return try bundle.toOwnedBundle(""); |
| 866 | } | 871 | } |
| 867 | 872 | ||
| 868 | fn flushErrorMessageIntoBundle(wip: *ErrorBundle.Wip, msg: ErrorBundle.ErrorMessage, notes: []const ErrorBundle.ErrorMessage) !void { | ||
| 869 | try wip.addRootErrorMessage(msg); | ||
| 870 | const notes_start = try wip.reserveNotes(@intCast(notes.len)); | ||
| 871 | for (notes_start.., notes) |i, note| { | ||
| 872 | wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note)); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle { | 873 | fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle { |
| 877 | @branchHint(.cold); | 874 | @branchHint(.cold); |
| 878 | var bundle: ErrorBundle.Wip = undefined; | 875 | var bundle: ErrorBundle.Wip = undefined; |
| ... | @@ -883,75 +880,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con | ... | @@ -883,75 +880,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con |
| 883 | }); | 880 | }); |
| 884 | return try bundle.toOwnedBundle(""); | 881 | return try bundle.toOwnedBundle(""); |
| 885 | } | 882 | } |
| 886 | |||
| 887 | fn aroDiagnosticsToErrorBundle( | ||
| 888 | gpa: std.mem.Allocator, | ||
| 889 | fail_msg: []const u8, | ||
| 890 | comp: *aro.Compilation, | ||
| 891 | ) !ErrorBundle { | ||
| 892 | @branchHint(.cold); | ||
| 893 | |||
| 894 | var bundle: ErrorBundle.Wip = undefined; | ||
| 895 | try bundle.init(gpa); | ||
| 896 | errdefer bundle.deinit(); | ||
| 897 | |||
| 898 | try bundle.addRootErrorMessage(.{ | ||
| 899 | .msg = try bundle.addString(fail_msg), | ||
| 900 | }); | ||
| 901 | |||
| 902 | var cur_err: ?ErrorBundle.ErrorMessage = null; | ||
| 903 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | ||
| 904 | defer cur_notes.deinit(gpa); | ||
| 905 | for (comp.diagnostics.output.to_list.messages.items) |msg| { | ||
| 906 | switch (msg.kind) { | ||
| 907 | // Clear the current error so that notes don't bleed into unassociated errors | ||
| 908 | .off, .warning => { | ||
| 909 | cur_err = null; | ||
| 910 | continue; | ||
| 911 | }, | ||
| 912 | .note => if (cur_err == null) continue, | ||
| 913 | .@"fatal error", .@"error" => {}, | ||
| 914 | } | ||
| 915 | |||
| 916 | const src_loc = src_loc: { | ||
| 917 | if (msg.location) |location| { | ||
| 918 | break :src_loc try bundle.addSourceLocation(.{ | ||
| 919 | .src_path = try bundle.addString(location.path), | ||
| 920 | .line = location.line_no - 1, // 1-based -> 0-based | ||
| 921 | .column = location.col - 1, // 1-based -> 0-based | ||
| 922 | .span_start = location.width, | ||
| 923 | .span_main = location.width, | ||
| 924 | .span_end = location.width, | ||
| 925 | .source_line = try bundle.addString(location.line), | ||
| 926 | }); | ||
| 927 | } | ||
| 928 | break :src_loc ErrorBundle.SourceLocationIndex.none; | ||
| 929 | }; | ||
| 930 | |||
| 931 | switch (msg.kind) { | ||
| 932 | .@"fatal error", .@"error" => { | ||
| 933 | if (cur_err) |err| { | ||
| 934 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | ||
| 935 | } | ||
| 936 | cur_err = .{ | ||
| 937 | .msg = try bundle.addString(msg.text), | ||
| 938 | .src_loc = src_loc, | ||
| 939 | }; | ||
| 940 | cur_notes.clearRetainingCapacity(); | ||
| 941 | }, | ||
| 942 | .note => { | ||
| 943 | cur_err.?.notes_len += 1; | ||
| 944 | try cur_notes.append(gpa, .{ | ||
| 945 | .msg = try bundle.addString(msg.text), | ||
| 946 | .src_loc = src_loc, | ||
| 947 | }); | ||
| 948 | }, | ||
| 949 | .off, .warning => unreachable, | ||
| 950 | } | ||
| 951 | } | ||
| 952 | if (cur_err) |err| { | ||
| 953 | try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items); | ||
| 954 | } | ||
| 955 | |||
| 956 | return try bundle.toOwnedBundle(""); | ||
| 957 | } |
lib/compiler/std-docs.zig+1-14| ... | @@ -345,20 +345,7 @@ fn buildWasmBinary( | ... | @@ -345,20 +345,7 @@ fn buildWasmBinary( |
| 345 | } | 345 | } |
| 346 | }, | 346 | }, |
| 347 | .error_bundle => { | 347 | .error_bundle => { |
| 348 | const EbHdr = std.zig.Server.Message.ErrorBundle; | 348 | result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 349 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | ||
| 350 | const extra_bytes = | ||
| 351 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 352 | const string_bytes = | ||
| 353 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 354 | // TODO: use @ptrCast when the compiler supports it | ||
| 355 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | ||
| 356 | const extra_array = try arena.alloc(u32, unaligned_extra.len); | ||
| 357 | @memcpy(extra_array, unaligned_extra); | ||
| 358 | result_error_bundle = .{ | ||
| 359 | .string_bytes = try arena.dupe(u8, string_bytes), | ||
| 360 | .extra = extra_array, | ||
| 361 | }; | ||
| 362 | }, | 349 | }, |
| 363 | .emit_digest => { | 350 | .emit_digest => { |
| 364 | const EmitDigest = std.zig.Server.Message.EmitDigest; | 351 | const EmitDigest = std.zig.Server.Message.EmitDigest; |
lib/compiler/translate-c/main.zig+57-10| ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; | ... | @@ -3,6 +3,7 @@ const assert = std.debug.assert; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const process = std.process; | 4 | const process = std.process; |
| 5 | const aro = @import("aro"); | 5 | const aro = @import("aro"); |
| 6 | const compiler_util = @import("../util.zig"); | ||
| 6 | const Translator = @import("Translator.zig"); | 7 | const Translator = @import("Translator.zig"); |
| 7 | 8 | ||
| 8 | const fast_exit = @import("builtin").mode != .Debug; | 9 | const fast_exit = @import("builtin").mode != .Debug; |
| ... | @@ -13,24 +14,33 @@ pub fn main() u8 { | ... | @@ -13,24 +14,33 @@ pub fn main() u8 { |
| 13 | const gpa = general_purpose_allocator.allocator(); | 14 | const gpa = general_purpose_allocator.allocator(); |
| 14 | defer _ = general_purpose_allocator.deinit(); | 15 | defer _ = general_purpose_allocator.deinit(); |
| 15 | 16 | ||
| 16 | var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); | 17 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| 17 | defer arena_instance.deinit(); | 18 | defer arena_instance.deinit(); |
| 18 | const arena = arena_instance.allocator(); | 19 | const arena = arena_instance.allocator(); |
| 19 | 20 | ||
| 20 | const args = process.argsAlloc(arena) catch { | 21 | var args = process.argsAlloc(arena) catch { |
| 21 | std.debug.print("ran out of memory allocating arguments\n", .{}); | 22 | std.debug.print("ran out of memory allocating arguments\n", .{}); |
| 22 | if (fast_exit) process.exit(1); | 23 | if (fast_exit) process.exit(1); |
| 23 | return 1; | 24 | return 1; |
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 27 | var zig_integration = false; | ||
| 28 | if (args.len > 1 and std.mem.eql(u8, args[1], "--zig-integration")) { | ||
| 29 | zig_integration = true; | ||
| 30 | } | ||
| 31 | |||
| 26 | var stderr_buf: [1024]u8 = undefined; | 32 | var stderr_buf: [1024]u8 = undefined; |
| 27 | var stderr = std.fs.File.stderr().writer(&stderr_buf); | 33 | var stderr = std.fs.File.stderr().writer(&stderr_buf); |
| 28 | var diagnostics: aro.Diagnostics = .{ | 34 | var diagnostics: aro.Diagnostics = switch (zig_integration) { |
| 29 | .output = .{ .to_writer = .{ | 35 | false => .{ .output = .{ .to_writer = .{ |
| 30 | .color = .detect(stderr.file), | 36 | .color = .detect(stderr.file), |
| 31 | .writer = &stderr.interface, | 37 | .writer = &stderr.interface, |
| 32 | } }, | 38 | } } }, |
| 39 | true => .{ .output = .{ .to_list = .{ | ||
| 40 | .arena = .init(gpa), | ||
| 41 | } } }, | ||
| 33 | }; | 42 | }; |
| 43 | defer diagnostics.deinit(); | ||
| 34 | 44 | ||
| 35 | var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) { | 45 | var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) { |
| 36 | error.OutOfMemory => { | 46 | error.OutOfMemory => { |
| ... | @@ -47,13 +57,22 @@ pub fn main() u8 { | ... | @@ -47,13 +57,22 @@ pub fn main() u8 { |
| 47 | var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } }; | 57 | var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } }; |
| 48 | defer toolchain.deinit(); | 58 | defer toolchain.deinit(); |
| 49 | 59 | ||
| 50 | translate(&driver, &toolchain, args) catch |err| switch (err) { | 60 | translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) { |
| 51 | error.OutOfMemory => { | 61 | error.OutOfMemory => { |
| 52 | std.debug.print("ran out of memory translating\n", .{}); | 62 | std.debug.print("ran out of memory translating\n", .{}); |
| 53 | if (fast_exit) process.exit(1); | 63 | if (fast_exit) process.exit(1); |
| 54 | return 1; | 64 | return 1; |
| 55 | }, | 65 | }, |
| 56 | error.FatalError => { | 66 | error.FatalError => if (zig_integration) { |
| 67 | serveErrorBundle(arena, &diagnostics) catch |bundle_err| { | ||
| 68 | std.debug.print("unable to serve error bundle: {}\n", .{bundle_err}); | ||
| 69 | if (fast_exit) process.exit(1); | ||
| 70 | return 1; | ||
| 71 | }; | ||
| 72 | |||
| 73 | if (fast_exit) process.exit(0); | ||
| 74 | return 0; | ||
| 75 | } else { | ||
| 57 | if (fast_exit) process.exit(1); | 76 | if (fast_exit) process.exit(1); |
| 58 | return 1; | 77 | return 1; |
| 59 | }, | 78 | }, |
| ... | @@ -63,10 +82,27 @@ pub fn main() u8 { | ... | @@ -63,10 +82,27 @@ pub fn main() u8 { |
| 63 | return 1; | 82 | return 1; |
| 64 | }, | 83 | }, |
| 65 | }; | 84 | }; |
| 85 | |||
| 86 | assert(comp.diagnostics.errors == 0 or !zig_integration); | ||
| 66 | if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0)); | 87 | if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0)); |
| 67 | return @intFromBool(comp.diagnostics.errors != 0); | 88 | return @intFromBool(comp.diagnostics.errors != 0); |
| 68 | } | 89 | } |
| 69 | 90 | ||
| 91 | fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostics) !void { | ||
| 92 | const error_bundle = try compiler_util.aroDiagnosticsToErrorBundle( | ||
| 93 | diagnostics, | ||
| 94 | arena, | ||
| 95 | "translation failure", | ||
| 96 | ); | ||
| 97 | var stdout_buffer: [1024]u8 = undefined; | ||
| 98 | var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer); | ||
| 99 | var server: std.zig.Server = .{ | ||
| 100 | .out = &stdout_writer.interface, | ||
| 101 | .in = undefined, | ||
| 102 | }; | ||
| 103 | try server.serveErrorBundle(error_bundle); | ||
| 104 | } | ||
| 105 | |||
| 70 | pub const usage = | 106 | pub const usage = |
| 71 | \\Usage {s}: [options] file [CC options] | 107 | \\Usage {s}: [options] file [CC options] |
| 72 | \\ | 108 | \\ |
| ... | @@ -79,7 +115,7 @@ pub const usage = | ... | @@ -79,7 +115,7 @@ pub const usage = |
| 79 | \\ | 115 | \\ |
| 80 | ; | 116 | ; |
| 81 | 117 | ||
| 82 | fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | 118 | fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void { |
| 83 | const gpa = d.comp.gpa; | 119 | const gpa = d.comp.gpa; |
| 84 | 120 | ||
| 85 | const aro_args = args: { | 121 | const aro_args = args: { |
| ... | @@ -99,6 +135,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | ... | @@ -99,6 +135,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 99 | try stdout.interface.writeAll("0.0.0-dev\n"); | 135 | try stdout.interface.writeAll("0.0.0-dev\n"); |
| 100 | try stdout.interface.flush(); | 136 | try stdout.interface.flush(); |
| 101 | return; | 137 | return; |
| 138 | } else if (mem.eql(u8, arg, "--zig-integration")) { | ||
| 139 | if (i != 1 or !zig_integration) | ||
| 140 | return d.fatal("--zig-integration must be the first argument", .{}); | ||
| 102 | } else { | 141 | } else { |
| 103 | i += 1; | 142 | i += 1; |
| 104 | } | 143 | } |
| ... | @@ -116,6 +155,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | ... | @@ -116,6 +155,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 116 | return d.fatal("user provided macro source exceeded max size", .{}); | 155 | return d.fatal("user provided macro source exceeded max size", .{}); |
| 117 | } | 156 | } |
| 118 | 157 | ||
| 158 | const has_output_file = if (d.output_name) |path| | ||
| 159 | !std.mem.eql(u8, path, "-") | ||
| 160 | else | ||
| 161 | false; | ||
| 162 | if (zig_integration and !has_output_file) { | ||
| 163 | return d.fatal("--zig-integration requires specifying an output file", .{}); | ||
| 164 | } | ||
| 165 | |||
| 119 | const content = try macro_buf.toOwnedSlice(gpa); | 166 | const content = try macro_buf.toOwnedSlice(gpa); |
| 120 | errdefer gpa.free(content); | 167 | errdefer gpa.free(content); |
| 121 | 168 | ||
| ... | @@ -160,7 +207,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | ... | @@ -160,7 +207,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 160 | defer c_tree.deinit(); | 207 | defer c_tree.deinit(); |
| 161 | 208 | ||
| 162 | if (d.diagnostics.errors != 0) { | 209 | if (d.diagnostics.errors != 0) { |
| 163 | if (fast_exit) process.exit(1); | 210 | if (fast_exit and !zig_integration) process.exit(1); |
| 164 | return error.FatalError; | 211 | return error.FatalError; |
| 165 | } | 212 | } |
| 166 | 213 | ||
| ... | @@ -212,7 +259,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { | ... | @@ -212,7 +259,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void { |
| 212 | if (out_writer.err) |write_err| | 259 | if (out_writer.err) |write_err| |
| 213 | return d.fatal("failed to write result to '{s}': {s}", .{ out_file_path, aro.Driver.errorDescription(write_err) }); | 260 | return d.fatal("failed to write result to '{s}': {s}", .{ out_file_path, aro.Driver.errorDescription(write_err) }); |
| 214 | 261 | ||
| 215 | if (fast_exit) process.exit(0); | 262 | if (fast_exit and !zig_integration) process.exit(0); |
| 216 | } | 263 | } |
| 217 | 264 | ||
| 218 | test { | 265 | test { |
lib/compiler/util.zig created+82| ... | @@ -0,0 +1,82 @@ | ||
| 1 | //! Utilities shared between compiler sub-commands | ||
| 2 | const std = @import("std"); | ||
| 3 | const aro = @import("aro"); | ||
| 4 | const ErrorBundle = std.zig.ErrorBundle; | ||
| 5 | |||
| 6 | pub fn aroDiagnosticsToErrorBundle( | ||
| 7 | d: *const aro.Diagnostics, | ||
| 8 | gpa: std.mem.Allocator, | ||
| 9 | fail_msg: ?[]const u8, | ||
| 10 | ) !ErrorBundle { | ||
| 11 | @branchHint(.cold); | ||
| 12 | |||
| 13 | var bundle: ErrorBundle.Wip = undefined; | ||
| 14 | try bundle.init(gpa); | ||
| 15 | errdefer bundle.deinit(); | ||
| 16 | |||
| 17 | if (fail_msg) |msg| { | ||
| 18 | try bundle.addRootErrorMessage(.{ | ||
| 19 | .msg = try bundle.addString(msg), | ||
| 20 | }); | ||
| 21 | } | ||
| 22 | |||
| 23 | var cur_err: ?ErrorBundle.ErrorMessage = null; | ||
| 24 | var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty; | ||
| 25 | defer cur_notes.deinit(gpa); | ||
| 26 | for (d.output.to_list.messages.items) |msg| { | ||
| 27 | switch (msg.kind) { | ||
| 28 | .off, .warning => { | ||
| 29 | // Emit any pending error and clear everything so that notes don't bleed into unassociated errors | ||
| 30 | if (cur_err) |err| { | ||
| 31 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | ||
| 32 | cur_err = null; | ||
| 33 | } | ||
| 34 | cur_notes.clearRetainingCapacity(); | ||
| 35 | continue; | ||
| 36 | }, | ||
| 37 | .note => if (cur_err == null) continue, | ||
| 38 | .@"fatal error", .@"error" => {}, | ||
| 39 | } | ||
| 40 | |||
| 41 | const src_loc = src_loc: { | ||
| 42 | if (msg.location) |location| { | ||
| 43 | break :src_loc try bundle.addSourceLocation(.{ | ||
| 44 | .src_path = try bundle.addString(location.path), | ||
| 45 | .line = location.line_no - 1, // 1-based -> 0-based | ||
| 46 | .column = location.col - 1, // 1-based -> 0-based | ||
| 47 | .span_start = location.width, | ||
| 48 | .span_main = location.width, | ||
| 49 | .span_end = location.width, | ||
| 50 | .source_line = try bundle.addString(location.line), | ||
| 51 | }); | ||
| 52 | } | ||
| 53 | break :src_loc ErrorBundle.SourceLocationIndex.none; | ||
| 54 | }; | ||
| 55 | |||
| 56 | switch (msg.kind) { | ||
| 57 | .@"fatal error", .@"error" => { | ||
| 58 | if (cur_err) |err| { | ||
| 59 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | ||
| 60 | } | ||
| 61 | cur_err = .{ | ||
| 62 | .msg = try bundle.addString(msg.text), | ||
| 63 | .src_loc = src_loc, | ||
| 64 | }; | ||
| 65 | cur_notes.clearRetainingCapacity(); | ||
| 66 | }, | ||
| 67 | .note => { | ||
| 68 | cur_err.?.notes_len += 1; | ||
| 69 | try cur_notes.append(gpa, .{ | ||
| 70 | .msg = try bundle.addString(msg.text), | ||
| 71 | .src_loc = src_loc, | ||
| 72 | }); | ||
| 73 | }, | ||
| 74 | .off, .warning => unreachable, | ||
| 75 | } | ||
| 76 | } | ||
| 77 | if (cur_err) |err| { | ||
| 78 | try bundle.addRootErrorMessageWithNotes(err, cur_notes.items); | ||
| 79 | } | ||
| 80 | |||
| 81 | return try bundle.toOwnedBundle(""); | ||
| 82 | } | ||
lib/std/Build/Step.zig+1-16| ... | @@ -524,22 +524,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build. | ... | @@ -524,22 +524,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build. |
| 524 | } | 524 | } |
| 525 | }, | 525 | }, |
| 526 | .error_bundle => { | 526 | .error_bundle => { |
| 527 | const EbHdr = std.zig.Server.Message.ErrorBundle; | 527 | s.result_error_bundle = try std.zig.Server.allocErrorBundle(gpa, body); |
| 528 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | ||
| 529 | const extra_bytes = | ||
| 530 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 531 | const string_bytes = | ||
| 532 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 533 | // TODO: use @ptrCast when the compiler supports it | ||
| 534 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | ||
| 535 | { | ||
| 536 | s.result_error_bundle = .{ .string_bytes = &.{}, .extra = &.{} }; | ||
| 537 | errdefer s.result_error_bundle.deinit(gpa); | ||
| 538 | s.result_error_bundle.string_bytes = try gpa.dupe(u8, string_bytes); | ||
| 539 | const extra = try gpa.alloc(u32, unaligned_extra.len); | ||
| 540 | @memcpy(extra, unaligned_extra); | ||
| 541 | s.result_error_bundle.extra = extra; | ||
| 542 | } | ||
| 543 | // This message indicates the end of the update. | 528 | // This message indicates the end of the update. |
| 544 | if (watch) break :poll; | 529 | if (watch) break :poll; |
| 545 | }, | 530 | }, |
lib/std/Build/WebServer.zig+1-13| ... | @@ -595,19 +595,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim | ... | @@ -595,19 +595,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim |
| 595 | } | 595 | } |
| 596 | }, | 596 | }, |
| 597 | .error_bundle => { | 597 | .error_bundle => { |
| 598 | const EbHdr = std.zig.Server.Message.ErrorBundle; | 598 | result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 599 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | ||
| 600 | const extra_bytes = | ||
| 601 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 602 | const string_bytes = | ||
| 603 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 604 | const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes); | ||
| 605 | const extra_array = try arena.alloc(u32, unaligned_extra.len); | ||
| 606 | @memcpy(extra_array, unaligned_extra); | ||
| 607 | result_error_bundle = .{ | ||
| 608 | .string_bytes = try arena.dupe(u8, string_bytes), | ||
| 609 | .extra = extra_array, | ||
| 610 | }; | ||
| 611 | }, | 599 | }, |
| 612 | .emit_digest => { | 600 | .emit_digest => { |
| 613 | const EmitDigest = std.zig.Server.Message.EmitDigest; | 601 | const EmitDigest = std.zig.Server.Message.EmitDigest; |
lib/std/zig/ErrorBundle.zig+12| ... | @@ -416,6 +416,18 @@ pub const Wip = struct { | ... | @@ -416,6 +416,18 @@ pub const Wip = struct { |
| 416 | wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em)); | 416 | wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em)); |
| 417 | } | 417 | } |
| 418 | 418 | ||
| 419 | pub fn addRootErrorMessageWithNotes( | ||
| 420 | wip: *Wip, | ||
| 421 | msg: ErrorMessage, | ||
| 422 | notes: []const ErrorMessage, | ||
| 423 | ) !void { | ||
| 424 | try wip.addRootErrorMessage(msg); | ||
| 425 | const notes_start = try wip.reserveNotes(@intCast(notes.len)); | ||
| 426 | for (notes_start.., notes) |i, note| { | ||
| 427 | wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note)); | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 419 | pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) Allocator.Error!MessageIndex { | 431 | pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) Allocator.Error!MessageIndex { |
| 420 | return @enumFromInt(try addExtra(wip, em)); | 432 | return @enumFromInt(try addExtra(wip, em)); |
| 421 | } | 433 | } |
lib/std/zig/Server.zig+22| ... | @@ -231,6 +231,28 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void { | ... | @@ -231,6 +231,28 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void { |
| 231 | try s.out.flush(); | 231 | try s.out.flush(); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | pub fn allocErrorBundle(allocator: std.mem.Allocator, body: []const u8) !std.zig.ErrorBundle { | ||
| 235 | const eb_hdr = @as(*align(1) const OutMessage.ErrorBundle, @ptrCast(body)); | ||
| 236 | const extra_bytes = | ||
| 237 | body[@sizeOf(OutMessage.ErrorBundle)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 238 | const string_bytes = | ||
| 239 | body[@sizeOf(OutMessage.ErrorBundle) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 240 | const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes); | ||
| 241 | |||
| 242 | var error_bundle: std.zig.ErrorBundle = .{ | ||
| 243 | .string_bytes = &.{}, | ||
| 244 | .extra = &.{}, | ||
| 245 | }; | ||
| 246 | errdefer error_bundle.deinit(allocator); | ||
| 247 | |||
| 248 | error_bundle.string_bytes = try allocator.dupe(u8, string_bytes); | ||
| 249 | const extra = try allocator.alloc(u32, unaligned_extra.len); | ||
| 250 | @memcpy(extra, unaligned_extra); | ||
| 251 | error_bundle.extra = extra; | ||
| 252 | |||
| 253 | return error_bundle; | ||
| 254 | } | ||
| 255 | |||
| 234 | pub const TestMetadata = struct { | 256 | pub const TestMetadata = struct { |
| 235 | names: []const u32, | 257 | names: []const u32, |
| 236 | expected_panic_msgs: []const u32, | 258 | expected_panic_msgs: []const u32, |
src/Compilation.zig+153-103| ... | @@ -5640,6 +5640,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest | ... | @@ -5640,6 +5640,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest |
| 5640 | } | 5640 | } |
| 5641 | 5641 | ||
| 5642 | pub const CImportResult = struct { | 5642 | pub const CImportResult = struct { |
| 5643 | // Only valid if `errors` is not empty | ||
| 5643 | digest: [Cache.bin_digest_len]u8, | 5644 | digest: [Cache.bin_digest_len]u8, |
| 5644 | cache_hit: bool, | 5645 | cache_hit: bool, |
| 5645 | errors: std.zig.ErrorBundle, | 5646 | errors: std.zig.ErrorBundle, |
| ... | @@ -5649,76 +5650,184 @@ pub const CImportResult = struct { | ... | @@ -5649,76 +5650,184 @@ pub const CImportResult = struct { |
| 5649 | } | 5650 | } |
| 5650 | }; | 5651 | }; |
| 5651 | 5652 | ||
| 5652 | /// Caller owns returned memory. | 5653 | pub fn translateC( |
| 5653 | pub fn cImport( | ||
| 5654 | comp: *Compilation, | 5654 | comp: *Compilation, |
| 5655 | c_src: []const u8, | 5655 | arena: Allocator, |
| 5656 | man: *Cache.Manifest, | ||
| 5657 | ext: FileExt, | ||
| 5658 | source: union(enum) { | ||
| 5659 | path: []const u8, | ||
| 5660 | c_src: []const u8, | ||
| 5661 | }, | ||
| 5662 | translated_basename: []const u8, | ||
| 5656 | owner_mod: *Package.Module, | 5663 | owner_mod: *Package.Module, |
| 5657 | prog_node: std.Progress.Node, | 5664 | prog_node: std.Progress.Node, |
| 5658 | ) !CImportResult { | 5665 | ) !CImportResult { |
| 5659 | dev.check(.translate_c_command); | 5666 | dev.check(.translate_c_command); |
| 5660 | 5667 | ||
| 5661 | const cimport_basename = "cimport.h"; | 5668 | const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); |
| 5662 | const translated_basename = "cimport.zig"; | 5669 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; |
| 5670 | const cache_dir = comp.dirs.local_cache.handle; | ||
| 5671 | var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{}); | ||
| 5672 | defer cache_tmp_dir.close(); | ||
| 5673 | |||
| 5674 | const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); | ||
| 5675 | const source_path = switch (source) { | ||
| 5676 | .c_src => |c_src| path: { | ||
| 5677 | const cimport_basename = "cimport.h"; | ||
| 5678 | const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename; | ||
| 5679 | const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path}); | ||
| 5680 | if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path}); | ||
| 5681 | try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src }); | ||
| 5682 | break :path out_h_path; | ||
| 5683 | }, | ||
| 5684 | .path => |p| p, | ||
| 5685 | }; | ||
| 5663 | 5686 | ||
| 5664 | var man = comp.obtainCObjectCacheManifest(owner_mod); | 5687 | const out_dep_path: ?[]const u8 = blk: { |
| 5665 | defer man.deinit(); | 5688 | if (comp.disable_c_depfile) break :blk null; |
| 5689 | const c_src_basename = fs.path.basename(source_path); | ||
| 5690 | const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename}); | ||
| 5691 | const out_dep_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, dep_basename }); | ||
| 5692 | break :blk out_dep_path; | ||
| 5693 | }; | ||
| 5666 | 5694 | ||
| 5667 | man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects | 5695 | var argv = std.array_list.Managed([]const u8).init(arena); |
| 5668 | man.hash.addBytes(c_src); | 5696 | { |
| 5697 | const target = &owner_mod.resolved_target.result; | ||
| 5698 | try argv.appendSlice(&.{ "--zig-integration", "-x", "c" }); | ||
| 5669 | 5699 | ||
| 5670 | const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: { | 5700 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" }); |
| 5671 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | 5701 | try argv.appendSlice(&.{ "-isystem", resource_path }); |
| 5672 | defer arena_allocator.deinit(); | 5702 | try comp.addCommonCCArgs(arena, &argv, ext, out_dep_path, owner_mod, .aro); |
| 5673 | const arena = arena_allocator.allocator(); | 5703 | try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) }); |
| 5674 | 5704 | ||
| 5675 | const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); | 5705 | const mcpu = mcpu: { |
| 5676 | const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; | 5706 | var buf: std.ArrayListUnmanaged(u8) = .empty; |
| 5677 | const cache_dir = comp.dirs.local_cache.handle; | 5707 | defer buf.deinit(comp.gpa); |
| 5678 | const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename; | 5708 | |
| 5709 | try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name}); | ||
| 5710 | |||
| 5711 | // TODO better serialization https://github.com/ziglang/zig/issues/4584 | ||
| 5712 | const all_features_list = target.cpu.arch.allFeaturesList(); | ||
| 5713 | try argv.ensureUnusedCapacity(all_features_list.len * 4); | ||
| 5714 | for (all_features_list, 0..) |feature, index_usize| { | ||
| 5715 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); | ||
| 5716 | const is_enabled = target.cpu.features.isEnabled(index); | ||
| 5679 | 5717 | ||
| 5680 | try cache_dir.makePath(tmp_sub_path); | 5718 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; |
| 5719 | try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name }); | ||
| 5720 | } | ||
| 5721 | break :mcpu try buf.toOwnedSlice(arena); | ||
| 5722 | }; | ||
| 5723 | try argv.append(mcpu); | ||
| 5681 | 5724 | ||
| 5682 | const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path}); | 5725 | try argv.appendSlice(comp.global_cc_argv); |
| 5683 | const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); | 5726 | try argv.appendSlice(owner_mod.cc_argv); |
| 5684 | const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path}); | 5727 | try argv.appendSlice(&.{ source_path, "-o", translated_path }); |
| 5728 | if (comp.verbose_cimport) dump_argv(argv.items); | ||
| 5729 | } | ||
| 5685 | 5730 | ||
| 5686 | if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path}); | 5731 | var stdout: []u8 = undefined; |
| 5687 | try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src }); | 5732 | try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout); |
| 5688 | 5733 | ||
| 5689 | var argv = std.array_list.Managed([]const u8).init(comp.gpa); | 5734 | if (out_dep_path) |dep_file_path| add_deps: { |
| 5690 | defer argv.deinit(); | 5735 | if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_file_path}); |
| 5691 | try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod); | ||
| 5692 | try argv.appendSlice(&.{ out_h_path, "-o", translated_path }); | ||
| 5693 | 5736 | ||
| 5694 | if (comp.verbose_cc) dump_argv(argv.items); | 5737 | const dep_basename = fs.path.basename(dep_file_path); |
| 5695 | var stdout: []u8 = undefined; | 5738 | // Add the files depended on to the cache system, if a dep file was emitted |
| 5696 | try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout); | 5739 | man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) { |
| 5697 | if (comp.verbose_cimport and stdout.len != 0) log.info("unexpected stdout: {s}", .{stdout}); | 5740 | error.FileNotFound => break :add_deps, |
| 5741 | else => |e| return e, | ||
| 5742 | }; | ||
| 5698 | 5743 | ||
| 5699 | const dep_sub_path = out_h_sub_path ++ ".d"; | ||
| 5700 | if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_sub_path}); | ||
| 5701 | try man.addDepFilePost(cache_dir, dep_sub_path); | ||
| 5702 | switch (comp.cache_use) { | 5744 | switch (comp.cache_use) { |
| 5703 | .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { | 5745 | .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { |
| 5704 | whole.cache_manifest_mutex.lock(); | 5746 | whole.cache_manifest_mutex.lock(); |
| 5705 | defer whole.cache_manifest_mutex.unlock(); | 5747 | defer whole.cache_manifest_mutex.unlock(); |
| 5706 | try whole_cache_manifest.addDepFilePost(cache_dir, dep_sub_path); | 5748 | try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename); |
| 5707 | }, | 5749 | }, |
| 5708 | .incremental, .none => {}, | 5750 | .incremental, .none => {}, |
| 5709 | } | 5751 | } |
| 5710 | 5752 | ||
| 5711 | const bin_digest = man.finalBin(); | 5753 | // Just to save disk space, we delete the file because it is never needed again. |
| 5712 | const hex_digest = Cache.binToHex(bin_digest); | 5754 | cache_tmp_dir.deleteFile(dep_basename) catch |err| { |
| 5713 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; | 5755 | log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); |
| 5756 | }; | ||
| 5757 | } | ||
| 5758 | |||
| 5759 | if (stdout.len > 0) { | ||
| 5760 | var reader: std.Io.Reader = .fixed(stdout); | ||
| 5761 | const MessageHeader = std.zig.Server.Message.Header; | ||
| 5762 | const header = reader.takeStruct(MessageHeader, .little) catch |err| | ||
| 5763 | fatal("unable to read translate-c MessageHeader: {s}", .{@errorName(err)}); | ||
| 5764 | const body = reader.take(header.bytes_len) catch |err| | ||
| 5765 | fatal("unable to read {}-byte translate-c message body: {s}", .{ header.bytes_len, @errorName(err) }); | ||
| 5766 | switch (header.tag) { | ||
| 5767 | .error_bundle => { | ||
| 5768 | const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body); | ||
| 5769 | return .{ | ||
| 5770 | .digest = undefined, | ||
| 5771 | .cache_hit = false, | ||
| 5772 | .errors = error_bundle, | ||
| 5773 | }; | ||
| 5774 | }, | ||
| 5775 | else => fatal("unexpected message type received from translate-c: {s}", .{@tagName(header.tag)}), | ||
| 5776 | } | ||
| 5777 | } | ||
| 5778 | |||
| 5779 | const bin_digest = man.finalBin(); | ||
| 5780 | const hex_digest = Cache.binToHex(bin_digest); | ||
| 5781 | const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; | ||
| 5714 | 5782 | ||
| 5715 | if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); | 5783 | if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); |
| 5716 | try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path); | 5784 | try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path); |
| 5717 | 5785 | ||
| 5718 | break :digest .{ bin_digest, false }; | 5786 | return .{ |
| 5787 | .digest = bin_digest, | ||
| 5788 | .cache_hit = false, | ||
| 5789 | .errors = ErrorBundle.empty, | ||
| 5719 | }; | 5790 | }; |
| 5791 | } | ||
| 5720 | 5792 | ||
| 5721 | if (man.have_exclusive_lock) { | 5793 | /// Caller owns returned memory. |
| 5794 | pub fn cImport( | ||
| 5795 | comp: *Compilation, | ||
| 5796 | c_src: []const u8, | ||
| 5797 | owner_mod: *Package.Module, | ||
| 5798 | prog_node: std.Progress.Node, | ||
| 5799 | ) !CImportResult { | ||
| 5800 | dev.check(.translate_c_command); | ||
| 5801 | |||
| 5802 | const translated_basename = "cimport.zig"; | ||
| 5803 | |||
| 5804 | var man = comp.obtainCObjectCacheManifest(owner_mod); | ||
| 5805 | defer man.deinit(); | ||
| 5806 | |||
| 5807 | man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish c-import from compiling C objects | ||
| 5808 | man.hash.addBytes(c_src); | ||
| 5809 | |||
| 5810 | const result: CImportResult = if (try man.hit()) .{ | ||
| 5811 | .digest = man.finalBin(), | ||
| 5812 | .cache_hit = true, | ||
| 5813 | .errors = ErrorBundle.empty, | ||
| 5814 | } else result: { | ||
| 5815 | var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); | ||
| 5816 | defer arena_allocator.deinit(); | ||
| 5817 | const arena = arena_allocator.allocator(); | ||
| 5818 | |||
| 5819 | break :result try comp.translateC( | ||
| 5820 | arena, | ||
| 5821 | &man, | ||
| 5822 | .c, | ||
| 5823 | .{ .c_src = c_src }, | ||
| 5824 | translated_basename, | ||
| 5825 | owner_mod, | ||
| 5826 | prog_node, | ||
| 5827 | ); | ||
| 5828 | }; | ||
| 5829 | |||
| 5830 | if (result.errors.errorMessageCount() == 0 and man.have_exclusive_lock) { | ||
| 5722 | // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is | 5831 | // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is |
| 5723 | // possible we had a hit and the manifest is dirty, for example if the file mtime changed but | 5832 | // possible we had a hit and the manifest is dirty, for example if the file mtime changed but |
| 5724 | // the contents were the same, we hit the cache but the manifest is dirty and we need to update | 5833 | // the contents were the same, we hit the cache but the manifest is dirty and we need to update |
| ... | @@ -5728,11 +5837,7 @@ pub fn cImport( | ... | @@ -5728,11 +5837,7 @@ pub fn cImport( |
| 5728 | }; | 5837 | }; |
| 5729 | } | 5838 | } |
| 5730 | 5839 | ||
| 5731 | return .{ | 5840 | return result; |
| 5732 | .digest = digest, | ||
| 5733 | .cache_hit = is_hit, | ||
| 5734 | .errors = std.zig.ErrorBundle.empty, | ||
| 5735 | }; | ||
| 5736 | } | 5841 | } |
| 5737 | 5842 | ||
| 5738 | fn workerUpdateCObject( | 5843 | fn workerUpdateCObject( |
| ... | @@ -6622,19 +6727,7 @@ fn spawnZigRc( | ... | @@ -6622,19 +6727,7 @@ fn spawnZigRc( |
| 6622 | // We expect exactly one ErrorBundle, and if any error_bundle header is | 6727 | // We expect exactly one ErrorBundle, and if any error_bundle header is |
| 6623 | // sent then it's a fatal error. | 6728 | // sent then it's a fatal error. |
| 6624 | .error_bundle => { | 6729 | .error_bundle => { |
| 6625 | const EbHdr = std.zig.Server.Message.ErrorBundle; | 6730 | const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body); |
| 6626 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | ||
| 6627 | const extra_bytes = | ||
| 6628 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 6629 | const string_bytes = | ||
| 6630 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 6631 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | ||
| 6632 | const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len); | ||
| 6633 | @memcpy(extra_array, unaligned_extra); | ||
| 6634 | const error_bundle = std.zig.ErrorBundle{ | ||
| 6635 | .string_bytes = try comp.gpa.dupe(u8, string_bytes), | ||
| 6636 | .extra = extra_array, | ||
| 6637 | }; | ||
| 6638 | return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle); | 6731 | return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle); |
| 6639 | }, | 6732 | }, |
| 6640 | else => {}, // ignore other messages | 6733 | else => {}, // ignore other messages |
| ... | @@ -6672,49 +6765,6 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error | ... | @@ -6672,49 +6765,6 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error |
| 6672 | } | 6765 | } |
| 6673 | } | 6766 | } |
| 6674 | 6767 | ||
| 6675 | pub fn addTranslateCCArgs( | ||
| 6676 | comp: *Compilation, | ||
| 6677 | arena: Allocator, | ||
| 6678 | argv: *std.array_list.Managed([]const u8), | ||
| 6679 | ext: FileExt, | ||
| 6680 | out_dep_path: ?[]const u8, | ||
| 6681 | owner_mod: *Package.Module, | ||
| 6682 | ) !void { | ||
| 6683 | const target = &owner_mod.resolved_target.result; | ||
| 6684 | |||
| 6685 | try argv.appendSlice(&.{ "-x", "c" }); | ||
| 6686 | |||
| 6687 | const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); | ||
| 6688 | try argv.appendSlice(&.{ "-isystem", resource_path }); | ||
| 6689 | |||
| 6690 | try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro); | ||
| 6691 | |||
| 6692 | try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) }); | ||
| 6693 | |||
| 6694 | const mcpu = mcpu: { | ||
| 6695 | var buf: std.ArrayListUnmanaged(u8) = .empty; | ||
| 6696 | defer buf.deinit(comp.gpa); | ||
| 6697 | |||
| 6698 | try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name}); | ||
| 6699 | |||
| 6700 | // TODO better serialization https://github.com/ziglang/zig/issues/4584 | ||
| 6701 | const all_features_list = target.cpu.arch.allFeaturesList(); | ||
| 6702 | try argv.ensureUnusedCapacity(all_features_list.len * 4); | ||
| 6703 | for (all_features_list, 0..) |feature, index_usize| { | ||
| 6704 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); | ||
| 6705 | const is_enabled = target.cpu.features.isEnabled(index); | ||
| 6706 | |||
| 6707 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; | ||
| 6708 | try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name }); | ||
| 6709 | } | ||
| 6710 | break :mcpu try buf.toOwnedSlice(arena); | ||
| 6711 | }; | ||
| 6712 | try argv.append(mcpu); | ||
| 6713 | |||
| 6714 | try argv.appendSlice(comp.global_cc_argv); | ||
| 6715 | try argv.appendSlice(owner_mod.cc_argv); | ||
| 6716 | } | ||
| 6717 | |||
| 6718 | /// Add common C compiler args between translate-c and C object compilation. | 6768 | /// Add common C compiler args between translate-c and C object compilation. |
| 6719 | fn addCommonCCArgs( | 6769 | fn addCommonCCArgs( |
| 6720 | comp: *const Compilation, | 6770 | comp: *const Compilation, |
src/main.zig+67-35| ... | @@ -4075,7 +4075,7 @@ fn serve( | ... | @@ -4075,7 +4075,7 @@ fn serve( |
| 4075 | while (true) { | 4075 | while (true) { |
| 4076 | const hdr = try server.receiveMessage(); | 4076 | const hdr = try server.receiveMessage(); |
| 4077 | 4077 | ||
| 4078 | // Lock the debug server while hanling the message. | 4078 | // Lock the debug server while handling the message. |
| 4079 | if (comp.debugIncremental()) ids.mutex.lock(); | 4079 | if (comp.debugIncremental()) ids.mutex.lock(); |
| 4080 | defer if (comp.debugIncremental()) ids.mutex.unlock(); | 4080 | defer if (comp.debugIncremental()) ids.mutex.unlock(); |
| 4081 | 4081 | ||
| ... | @@ -4092,7 +4092,11 @@ fn serve( | ... | @@ -4092,7 +4092,11 @@ fn serve( |
| 4092 | var output: Compilation.CImportResult = undefined; | 4092 | var output: Compilation.CImportResult = undefined; |
| 4093 | try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node); | 4093 | try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node); |
| 4094 | defer output.deinit(gpa); | 4094 | defer output.deinit(gpa); |
| 4095 | try server.serveStringMessage(.file_system_inputs, file_system_inputs.items); | 4095 | |
| 4096 | if (file_system_inputs.items.len != 0) { | ||
| 4097 | try server.serveStringMessage(.file_system_inputs, file_system_inputs.items); | ||
| 4098 | } | ||
| 4099 | |||
| 4096 | if (output.errors.errorMessageCount() != 0) { | 4100 | if (output.errors.errorMessageCount() != 0) { |
| 4097 | try server.serveErrorBundle(output.errors); | 4101 | try server.serveErrorBundle(output.errors); |
| 4098 | } else { | 4102 | } else { |
| ... | @@ -4100,6 +4104,7 @@ fn serve( | ... | @@ -4100,6 +4104,7 @@ fn serve( |
| 4100 | .flags = .{ .cache_hit = output.cache_hit }, | 4104 | .flags = .{ .cache_hit = output.cache_hit }, |
| 4101 | }); | 4105 | }); |
| 4102 | } | 4106 | } |
| 4107 | |||
| 4103 | continue; | 4108 | continue; |
| 4104 | } | 4109 | } |
| 4105 | 4110 | ||
| ... | @@ -4515,48 +4520,75 @@ fn cmdTranslateC( | ... | @@ -4515,48 +4520,75 @@ fn cmdTranslateC( |
| 4515 | prog_node: std.Progress.Node, | 4520 | prog_node: std.Progress.Node, |
| 4516 | ) !void { | 4521 | ) !void { |
| 4517 | dev.check(.translate_c_command); | 4522 | dev.check(.translate_c_command); |
| 4518 | _ = file_system_inputs; | ||
| 4519 | _ = fancy_output; | ||
| 4520 | 4523 | ||
| 4521 | assert(comp.c_source_files.len == 1); | 4524 | assert(comp.c_source_files.len == 1); |
| 4522 | const c_source_file = comp.c_source_files[0]; | 4525 | const c_source_file = comp.c_source_files[0]; |
| 4523 | 4526 | ||
| 4524 | var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); | 4527 | const translated_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name}); |
| 4525 | defer zig_cache_tmp_dir.close(); | 4528 | |
| 4529 | var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod); | ||
| 4530 | man.want_shared_lock = false; | ||
| 4531 | defer man.deinit(); | ||
| 4526 | 4532 | ||
| 4527 | const ext = Compilation.classifyFileExt(c_source_file.src_path); | 4533 | man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects |
| 4528 | const out_dep_path: ?[]const u8 = blk: { | 4534 | man.hash.add(comp.config.c_frontend); |
| 4529 | if (comp.disable_c_depfile) break :blk null; | 4535 | Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| { |
| 4530 | const c_src_basename = fs.path.basename(c_source_file.src_path); | 4536 | fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) }); |
| 4531 | const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename}); | ||
| 4532 | const out_dep_path = try comp.tmpFilePath(arena, dep_basename); | ||
| 4533 | break :blk out_dep_path; | ||
| 4534 | }; | 4537 | }; |
| 4535 | 4538 | ||
| 4536 | var argv = std.array_list.Managed([]const u8).init(arena); | 4539 | const result: Compilation.CImportResult = if (try man.hit()) .{ |
| 4537 | try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); | 4540 | .digest = man.finalBin(), |
| 4538 | try argv.append(c_source_file.src_path); | 4541 | .cache_hit = true, |
| 4539 | if (comp.verbose_cc) Compilation.dump_argv(argv.items); | 4542 | .errors = std.zig.ErrorBundle.empty, |
| 4540 | 4543 | } else result: { | |
| 4541 | try translateC(comp.gpa, arena, argv.items, prog_node, null); | 4544 | const result = try comp.translateC( |
| 4542 | 4545 | arena, | |
| 4543 | if (out_dep_path) |dep_file_path| { | 4546 | &man, |
| 4544 | const dep_basename = fs.path.basename(dep_file_path); | 4547 | Compilation.classifyFileExt(c_source_file.src_path), |
| 4545 | // Add the files depended on to the cache system. | 4548 | .{ .path = c_source_file.src_path }, |
| 4546 | //man.addDepFilePost(zig_cache_tmp_dir, dep_basename) catch |err| switch (err) { | 4549 | translated_basename, |
| 4547 | // error.FileNotFound => { | 4550 | comp.root_mod, |
| 4548 | // // Clang didn't emit the dep file; nothing to add to the manifest. | 4551 | prog_node, |
| 4549 | // break :add_deps; | 4552 | ); |
| 4550 | // }, | 4553 | |
| 4551 | // else => |e| return e, | 4554 | if (result.errors.errorMessageCount() != 0) { |
| 4552 | //}; | 4555 | if (fancy_output) |p| { |
| 4553 | // Just to save disk space, we delete the file because it is never needed again. | 4556 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); |
| 4554 | zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { | 4557 | p.* = result; |
| 4555 | warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); | 4558 | return; |
| 4559 | } else { | ||
| 4560 | const color: Color = .auto; | ||
| 4561 | result.errors.renderToStdErr(color.renderOptions()); | ||
| 4562 | process.exit(1); | ||
| 4563 | } | ||
| 4564 | } | ||
| 4565 | |||
| 4566 | man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err}); | ||
| 4567 | break :result result; | ||
| 4568 | }; | ||
| 4569 | |||
| 4570 | if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf); | ||
| 4571 | if (fancy_output) |p| { | ||
| 4572 | p.* = result; | ||
| 4573 | } else { | ||
| 4574 | const hex_digest = Cache.binToHex(result.digest); | ||
| 4575 | const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_basename }); | ||
| 4576 | const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| { | ||
| 4577 | const path = comp.dirs.local_cache.path orelse "."; | ||
| 4578 | fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ | ||
| 4579 | path, | ||
| 4580 | fs.path.sep_str, | ||
| 4581 | out_zig_path, | ||
| 4582 | @errorName(err), | ||
| 4583 | }); | ||
| 4556 | }; | 4584 | }; |
| 4585 | defer zig_file.close(); | ||
| 4586 | var stdout_writer = fs.File.stdout().writer(&stdout_buffer); | ||
| 4587 | var file_reader = zig_file.reader(&.{}); | ||
| 4588 | _ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited); | ||
| 4589 | try stdout_writer.interface.flush(); | ||
| 4590 | return cleanExit(); | ||
| 4557 | } | 4591 | } |
| 4558 | |||
| 4559 | return cleanExit(); | ||
| 4560 | } | 4592 | } |
| 4561 | 4593 | ||
| 4562 | pub fn translateC( | 4594 | pub fn translateC( |
tools/incr-check.zig+1-14| ... | @@ -259,20 +259,7 @@ const Eval = struct { | ... | @@ -259,20 +259,7 @@ const Eval = struct { |
| 259 | 259 | ||
| 260 | switch (header.tag) { | 260 | switch (header.tag) { |
| 261 | .error_bundle => { | 261 | .error_bundle => { |
| 262 | const EbHdr = std.zig.Server.Message.ErrorBundle; | 262 | const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body); |
| 263 | const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body)); | ||
| 264 | const extra_bytes = | ||
| 265 | body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len]; | ||
| 266 | const string_bytes = | ||
| 267 | body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len]; | ||
| 268 | // TODO: use @ptrCast when the compiler supports it | ||
| 269 | const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes); | ||
| 270 | const extra_array = try arena.alloc(u32, unaligned_extra.len); | ||
| 271 | @memcpy(extra_array, unaligned_extra); | ||
| 272 | const result_error_bundle: std.zig.ErrorBundle = .{ | ||
| 273 | .string_bytes = try arena.dupe(u8, string_bytes), | ||
| 274 | .extra = extra_array, | ||
| 275 | }; | ||
| 276 | if (stderr.bufferedLen() > 0) { | 263 | if (stderr.bufferedLen() > 0) { |
| 277 | const stderr_data = try poller.toOwnedSlice(.stderr); | 264 | const stderr_data = try poller.toOwnedSlice(.stderr); |
| 278 | if (eval.allow_stderr) { | 265 | if (eval.allow_stderr) { |