Skip to content

Commit 4aa4d80

Browse files
committed
- Rework translate-c to integrate with the build system (by outputing error bundles on stdout) via --zig-integration
- Revive some of the removed cache integration logic in `cmdTranslateC` now that `translate-c` can return error bundles - Fixup inconsistent path separators (on Windows) when building the aro include path - Move some error bundle logic from resinator into aro.Diagnostics - Add `ErrorBundle.addRootErrorMessageWithNotes` (extracted from resinator)
1 parent 328ae41 commit 4aa4d80

File tree

6 files changed

+275
-131
lines changed

6 files changed

+275
-131
lines changed

lib/compiler/aro/aro/Diagnostics.zig

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,79 @@ fn addMessage(d: *Diagnostics, msg: Message) Compilation.Error!void {
562562
},
563563
}
564564
}
565+
566+
const ErrorBundle = std.zig.ErrorBundle;
567+
568+
pub fn toErrorBundle(
569+
d: *const Diagnostics,
570+
gpa: std.mem.Allocator,
571+
fail_msg: ?[]const u8,
572+
) !ErrorBundle {
573+
@branchHint(.cold);
574+
575+
var bundle: ErrorBundle.Wip = undefined;
576+
try bundle.init(gpa);
577+
errdefer bundle.deinit();
578+
579+
if (fail_msg) |msg| {
580+
try bundle.addRootErrorMessage(.{
581+
.msg = try bundle.addString(msg),
582+
});
583+
}
584+
585+
var cur_err: ?ErrorBundle.ErrorMessage = null;
586+
var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty;
587+
defer cur_notes.deinit(gpa);
588+
for (d.output.to_list.messages.items) |msg| {
589+
switch (msg.kind) {
590+
// Clear the current error so that notes don't bleed into unassociated errors
591+
.off, .warning => {
592+
cur_err = null;
593+
continue;
594+
},
595+
.note => if (cur_err == null) continue,
596+
.@"fatal error", .@"error" => {},
597+
}
598+
599+
const src_loc = src_loc: {
600+
if (msg.location) |location| {
601+
break :src_loc try bundle.addSourceLocation(.{
602+
.src_path = try bundle.addString(location.path),
603+
.line = location.line_no - 1, // 1-based -> 0-based
604+
.column = location.col - 1, // 1-based -> 0-based
605+
.span_start = location.width,
606+
.span_main = location.width,
607+
.span_end = location.width,
608+
.source_line = try bundle.addString(location.line),
609+
});
610+
}
611+
break :src_loc ErrorBundle.SourceLocationIndex.none;
612+
};
613+
614+
switch (msg.kind) {
615+
.@"fatal error", .@"error" => {
616+
if (cur_err) |err| {
617+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
618+
}
619+
cur_err = .{
620+
.msg = try bundle.addString(msg.text),
621+
.src_loc = src_loc,
622+
};
623+
cur_notes.clearRetainingCapacity();
624+
},
625+
.note => {
626+
cur_err.?.notes_len += 1;
627+
try cur_notes.append(gpa, .{
628+
.msg = try bundle.addString(msg.text),
629+
.src_loc = src_loc,
630+
});
631+
},
632+
.off, .warning => unreachable,
633+
}
634+
}
635+
if (cur_err) |err| {
636+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
637+
}
638+
639+
return try bundle.toOwnedBundle("");
640+
}

lib/compiler/resinator/main.zig

Lines changed: 5 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ const ErrorHandler = union(enum) {
671671
) !void {
672672
switch (self.*) {
673673
.server => |*server| {
674-
var error_bundle = try aroDiagnosticsToErrorBundle(allocator, fail_msg, comp);
674+
var error_bundle = try comp.diagnostics.toErrorBundle(allocator, fail_msg);
675675
defer error_bundle.deinit(allocator);
676676

677677
try server.serveErrorBundle(error_bundle);
@@ -753,7 +753,7 @@ fn cliDiagnosticsToErrorBundle(
753753
switch (err_details.type) {
754754
.err => {
755755
if (cur_err) |err| {
756-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
756+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
757757
}
758758
cur_err = .{
759759
.msg = try bundle.addString(err_details.msg.items),
@@ -771,7 +771,7 @@ fn cliDiagnosticsToErrorBundle(
771771
}
772772
}
773773
if (cur_err) |err| {
774-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
774+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
775775
}
776776

777777
return try bundle.toOwnedBundle("");
@@ -840,7 +840,7 @@ fn diagnosticsToErrorBundle(
840840
switch (err_details.type) {
841841
.err => {
842842
if (cur_err) |err| {
843-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
843+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
844844
}
845845
cur_err = .{
846846
.msg = try bundle.addString(msg_buf.written()),
@@ -859,20 +859,12 @@ fn diagnosticsToErrorBundle(
859859
}
860860
}
861861
if (cur_err) |err| {
862-
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
862+
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
863863
}
864864

865865
return try bundle.toOwnedBundle("");
866866
}
867867

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-
876868
fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
877869
@branchHint(.cold);
878870
var bundle: ErrorBundle.Wip = undefined;
@@ -883,75 +875,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con
883875
});
884876
return try bundle.toOwnedBundle("");
885877
}
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/translate-c/main.zig

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,33 @@ pub fn main() u8 {
1313
const gpa = general_purpose_allocator.allocator();
1414
defer _ = general_purpose_allocator.deinit();
1515

16-
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
16+
var arena_instance = std.heap.ArenaAllocator.init(gpa);
1717
defer arena_instance.deinit();
1818
const arena = arena_instance.allocator();
1919

20-
const args = process.argsAlloc(arena) catch {
20+
var args = process.argsAlloc(arena) catch {
2121
std.debug.print("ran out of memory allocating arguments\n", .{});
2222
if (fast_exit) process.exit(1);
2323
return 1;
2424
};
2525

26+
var zig_integration = false;
27+
if (args.len > 1 and std.mem.eql(u8, args[1], "--zig-integration")) {
28+
zig_integration = true;
29+
}
30+
2631
var stderr_buf: [1024]u8 = undefined;
2732
var stderr = std.fs.File.stderr().writer(&stderr_buf);
28-
var diagnostics: aro.Diagnostics = .{
29-
.output = .{ .to_writer = .{
33+
var diagnostics: aro.Diagnostics = switch (zig_integration) {
34+
false => .{ .output = .{ .to_writer = .{
3035
.color = .detect(stderr.file),
3136
.writer = &stderr.interface,
32-
} },
37+
} } },
38+
true => .{ .output = .{ .to_list = .{
39+
.arena = .init(gpa),
40+
} } },
3341
};
42+
defer diagnostics.deinit();
3443

3544
var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) {
3645
error.OutOfMemory => {
@@ -47,13 +56,22 @@ pub fn main() u8 {
4756
var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } };
4857
defer toolchain.deinit();
4958

50-
translate(&driver, &toolchain, args) catch |err| switch (err) {
59+
translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) {
5160
error.OutOfMemory => {
5261
std.debug.print("ran out of memory translating\n", .{});
5362
if (fast_exit) process.exit(1);
5463
return 1;
5564
},
56-
error.FatalError => {
65+
error.FatalError => if (zig_integration) {
66+
serveErrorBundle(arena, &diagnostics) catch |bundle_err| {
67+
std.debug.print("unable to serve error bundle: {}\n", .{bundle_err});
68+
if (fast_exit) process.exit(1);
69+
return 1;
70+
};
71+
72+
if (fast_exit) process.exit(0);
73+
return 0;
74+
} else {
5775
if (fast_exit) process.exit(1);
5876
return 1;
5977
},
@@ -63,10 +81,23 @@ pub fn main() u8 {
6381
return 1;
6482
},
6583
};
84+
85+
assert(comp.diagnostics.errors == 0 or !zig_integration);
6686
if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0));
6787
return @intFromBool(comp.diagnostics.errors != 0);
6888
}
6989

90+
fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostics) !void {
91+
const error_bundle = try diagnostics.toErrorBundle(arena, "failed during translation");
92+
var stdout_buffer: [1024]u8 = undefined;
93+
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
94+
var server: std.zig.Server = .{
95+
.out = &stdout_writer.interface,
96+
.in = undefined,
97+
};
98+
try server.serveErrorBundle(error_bundle);
99+
}
100+
70101
pub const usage =
71102
\\Usage {s}: [options] file [CC options]
72103
\\
@@ -79,7 +110,7 @@ pub const usage =
79110
\\
80111
;
81112

82-
fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
113+
fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void {
83114
const gpa = d.comp.gpa;
84115

85116
const aro_args = args: {
@@ -99,6 +130,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
99130
try stdout.interface.writeAll("0.0.0-dev\n");
100131
try stdout.interface.flush();
101132
return;
133+
} else if (mem.eql(u8, arg, "--zig-integration")) {
134+
if (i != 1 or !zig_integration)
135+
return d.fatal("--zig-integration must be the first argument", .{});
102136
} else {
103137
i += 1;
104138
}
@@ -116,6 +150,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
116150
return d.fatal("user provided macro source exceeded max size", .{});
117151
}
118152

153+
const has_output_file = if (d.output_name) |path|
154+
!std.mem.eql(u8, path, "-")
155+
else
156+
false;
157+
if (zig_integration and !has_output_file) {
158+
return d.fatal("--zig-integration requires specifying an output file", .{});
159+
}
160+
119161
const content = try macro_buf.toOwnedSlice(gpa);
120162
errdefer gpa.free(content);
121163

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

162204
if (d.diagnostics.errors != 0) {
163-
if (fast_exit) process.exit(1);
205+
if (fast_exit and !zig_integration) process.exit(1);
164206
return error.FatalError;
165207
}
166208

@@ -212,7 +254,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
212254
if (out_writer.err) |write_err|
213255
return d.fatal("failed to write result to '{s}': {s}", .{ out_file_path, aro.Driver.errorDescription(write_err) });
214256

215-
if (fast_exit) process.exit(0);
257+
if (fast_exit and !zig_integration) process.exit(0);
216258
}
217259

218260
test {

lib/std/zig/ErrorBundle.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,18 @@ pub const Wip = struct {
416416
wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em));
417417
}
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+
419431
pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) Allocator.Error!MessageIndex {
420432
return @enumFromInt(try addExtra(wip, em));
421433
}

src/Compilation.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,7 +3398,7 @@ fn flush(
33983398
/// Linker backends which do not have this requirement can fall back to the simple
33993399
/// implementation at the bottom of this function.
34003400
/// This function is only called when CacheMode is `whole`.
3401-
fn renameTmpIntoCache(
3401+
pub fn renameTmpIntoCache(
34023402
cache_directory: Cache.Directory,
34033403
tmp_dir_sub_path: []const u8,
34043404
o_sub_path: []const u8,
@@ -6684,7 +6684,7 @@ pub fn addTranslateCCArgs(
66846684

66856685
try argv.appendSlice(&.{ "-x", "c" });
66866686

6687-
const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"});
6687+
const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" });
66886688
try argv.appendSlice(&.{ "-isystem", resource_path });
66896689

66906690
try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro);

0 commit comments

Comments
 (0)