authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-10 21:07:20-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-10-10 21:07:20-07:00
logc17e18647bf55bae38a1837a6afb19b0f2393892
tree43b31a86060f36ab3a40baab8fc4834317794619
parent66193e72d3deeac4f78bc8d81f42a7d9b243fa58
parented6d9e2a9d6a25d511cbaa4c7ee34083223460ae
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #25495 from kcbanner/fixup_translate_c

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");
13const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage;13const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage;
14const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;14const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
15const aro = @import("aro");15const aro = @import("aro");
16const compiler_util = @import("../util.zig");
1617
17pub fn main() !void {18pub 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);
676681
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 }
776781
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 }
864869
865 return try bundle.toOwnedBundle("");870 return try bundle.toOwnedBundle("");
866}871}
867872
868fn 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
876fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {873fn 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
887fn 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;
3const mem = std.mem;3const mem = std.mem;
4const process = std.process;4const process = std.process;
5const aro = @import("aro");5const aro = @import("aro");
6const compiler_util = @import("../util.zig");
6const Translator = @import("Translator.zig");7const Translator = @import("Translator.zig");
78
8const fast_exit = @import("builtin").mode != .Debug;9const 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();
1516
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();
1920
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 };
2526
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();
3444
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();
4959
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}
6990
91fn 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
70pub const usage =106pub 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;
81117
82fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {118fn 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;
84120
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 }
118157
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);
121168
...@@ -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();
161208
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 }
166213
...@@ -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) });
214261
215 if (fast_exit) process.exit(0);262 if (fast_exit and !zig_integration) process.exit(0);
216}263}
217264
218test {265test {
lib/compiler/util.zig created+82
...@@ -0,0 +1,82 @@
1//! Utilities shared between compiler sub-commands
2const std = @import("std");
3const aro = @import("aro");
4const ErrorBundle = std.zig.ErrorBundle;
5
6pub 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 }
418418
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}
233233
234pub 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
234pub const TestMetadata = struct {256pub 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}
56415641
5642pub const CImportResult = struct {5642pub 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};
56515652
5652/// Caller owns returned memory.5653pub fn translateC(
5653pub 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);
56605667
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 };
56635686
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 };
56665694
5667 man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects5695 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" });
56695699
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) });
56745704
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);
56795717
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);
56815724
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 }
56855730
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);
56885733
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 });
56935736
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 };
56985743
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 }
57105752
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;
57145782
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);
57175785
5718 break :digest .{ bin_digest, false };5786 return .{
5787 .digest = bin_digest,
5788 .cache_hit = false,
5789 .errors = ErrorBundle.empty,
5719 };5790 };
5791}
57205792
5721 if (man.have_exclusive_lock) {5793/// Caller owns returned memory.
5794pub 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 is5831 // 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 but5832 // 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 update5833 // 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 }
57305839
5731 return .{5840 return result;
5732 .digest = digest,
5733 .cache_hit = is_hit,
5734 .errors = std.zig.ErrorBundle.empty,
5735 };
5736}5841}
57375842
5738fn workerUpdateCObject(5843fn 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 is6727 // 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 messages6733 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}
66746767
6675pub 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.
6719fn addCommonCCArgs(6769fn 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();
40774077
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();
40814081
...@@ -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 }
41054110
...@@ -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;
45204523
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];
45234526
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();
45264532
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 };
45354538
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,
45404543 } else result: {
4541 try translateC(comp.gpa, arena, argv.items, prog_node, null);4544 const result = try comp.translateC(
45424545 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}
45614593
4562pub fn translateC(4594pub fn translateC(
tools/incr-check.zig+1-14
...@@ -259,20 +259,7 @@ const Eval = struct {...@@ -259,20 +259,7 @@ const Eval = struct {
259259
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) {