Skip to content

Commit c17e186

Browse files
authored
Merge pull request #25495 from kcbanner/fixup_translate_c
Add error bundle support to `translate-c`, unify `cmdTranslateC` and `cImport`
2 parents 66193e7 + ed6d9e2 commit c17e186

File tree

11 files changed

+407
-290
lines changed

11 files changed

+407
-290
lines changed

lib/compiler/resinator/main.zig

Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const cvtres = @import("cvtres.zig");
1313
const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage;
1414
const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
1515
const aro = @import("aro");
16+
const compiler_util = @import("../util.zig");
1617

1718
pub fn main() !void {
1819
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
@@ -671,7 +672,11 @@ const ErrorHandler = union(enum) {
671672
) !void {
672673
switch (self.*) {
673674
.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+
);
675680
defer error_bundle.deinit(allocator);
676681

677682
try server.serveErrorBundle(error_bundle);
@@ -753,7 +758,7 @@ fn cliDiagnosticsToErrorBundle(
753758
switch (err_details.type) {
754759
.err => {
755760
if (cur_err) |err| {
756-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
761+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
757762
}
758763
cur_err = .{
759764
.msg = try bundle.addString(err_details.msg.items),
@@ -771,7 +776,7 @@ fn cliDiagnosticsToErrorBundle(
771776
}
772777
}
773778
if (cur_err) |err| {
774-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
779+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
775780
}
776781

777782
return try bundle.toOwnedBundle("");
@@ -840,7 +845,7 @@ fn diagnosticsToErrorBundle(
840845
switch (err_details.type) {
841846
.err => {
842847
if (cur_err) |err| {
843-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
848+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
844849
}
845850
cur_err = .{
846851
.msg = try bundle.addString(msg_buf.written()),
@@ -859,20 +864,12 @@ fn diagnosticsToErrorBundle(
859864
}
860865
}
861866
if (cur_err) |err| {
862-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
867+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
863868
}
864869

865870
return try bundle.toOwnedBundle("");
866871
}
867872

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-
876873
fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
877874
@branchHint(.cold);
878875
var bundle: ErrorBundle.Wip = undefined;
@@ -883,75 +880,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con
883880
});
884881
return try bundle.toOwnedBundle("");
885882
}
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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -345,20 +345,7 @@ fn buildWasmBinary(
345345
}
346346
},
347347
.error_bundle => {
348-
const EbHdr = std.zig.Server.Message.ErrorBundle;
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-
};
348+
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
362349
},
363350
.emit_digest => {
364351
const EmitDigest = std.zig.Server.Message.EmitDigest;

lib/compiler/translate-c/main.zig

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const assert = std.debug.assert;
33
const mem = std.mem;
44
const process = std.process;
55
const aro = @import("aro");
6+
const compiler_util = @import("../util.zig");
67
const Translator = @import("Translator.zig");
78

89
const fast_exit = @import("builtin").mode != .Debug;
@@ -13,24 +14,33 @@ pub fn main() u8 {
1314
const gpa = general_purpose_allocator.allocator();
1415
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);
1718
defer arena_instance.deinit();
1819
const arena = arena_instance.allocator();
1920

20-
const args = process.argsAlloc(arena) catch {
21+
var args = process.argsAlloc(arena) catch {
2122
std.debug.print("ran out of memory allocating arguments\n", .{});
2223
if (fast_exit) process.exit(1);
2324
return 1;
2425
};
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+
2632
var stderr_buf: [1024]u8 = undefined;
2733
var stderr = std.fs.File.stderr().writer(&stderr_buf);
28-
var diagnostics: aro.Diagnostics = .{
29-
.output = .{ .to_writer = .{
34+
var diagnostics: aro.Diagnostics = switch (zig_integration) {
35+
false => .{ .output = .{ .to_writer = .{
3036
.color = .detect(stderr.file),
3137
.writer = &stderr.interface,
32-
} },
38+
} } },
39+
true => .{ .output = .{ .to_list = .{
40+
.arena = .init(gpa),
41+
} } },
3342
};
43+
defer diagnostics.deinit();
3444

3545
var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) {
3646
error.OutOfMemory => {
@@ -47,13 +57,22 @@ pub fn main() u8 {
4757
var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } };
4858
defer toolchain.deinit();
4959

50-
translate(&driver, &toolchain, args) catch |err| switch (err) {
60+
translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) {
5161
error.OutOfMemory => {
5262
std.debug.print("ran out of memory translating\n", .{});
5363
if (fast_exit) process.exit(1);
5464
return 1;
5565
},
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 {
5776
if (fast_exit) process.exit(1);
5877
return 1;
5978
},
@@ -63,10 +82,27 @@ pub fn main() u8 {
6382
return 1;
6483
},
6584
};
85+
86+
assert(comp.diagnostics.errors == 0 or !zig_integration);
6687
if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0));
6788
return @intFromBool(comp.diagnostics.errors != 0);
6889
}
6990

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+
70106
pub const usage =
71107
\\Usage {s}: [options] file [CC options]
72108
\\
@@ -79,7 +115,7 @@ pub const usage =
79115
\\
80116
;
81117

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 {
83119
const gpa = d.comp.gpa;
84120

85121
const aro_args = args: {
@@ -99,6 +135,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
99135
try stdout.interface.writeAll("0.0.0-dev\n");
100136
try stdout.interface.flush();
101137
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", .{});
102141
} else {
103142
i += 1;
104143
}
@@ -116,6 +155,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
116155
return d.fatal("user provided macro source exceeded max size", .{});
117156
}
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+
119166
const content = try macro_buf.toOwnedSlice(gpa);
120167
errdefer gpa.free(content);
121168

@@ -160,7 +207,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
160207
defer c_tree.deinit();
161208

162209
if (d.diagnostics.errors != 0) {
163-
if (fast_exit) process.exit(1);
210+
if (fast_exit and !zig_integration) process.exit(1);
164211
return error.FatalError;
165212
}
166213

@@ -212,7 +259,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
212259
if (out_writer.err) |write_err|
213260
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);
216263
}
217264

218265
test {

0 commit comments

Comments
 (0)