mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Merge pull request #25495 from kcbanner/fixup_translate_c
Add error bundle support to `translate-c`, unify `cmdTranslateC` and `cImport`
This commit is contained in:
commit
c17e18647b
@ -13,6 +13,7 @@ const cvtres = @import("cvtres.zig");
|
||||
const hasDisjointCodePage = @import("disjoint_code_page.zig").hasDisjointCodePage;
|
||||
const fmtResourceType = @import("res.zig").NameOrOrdinal.fmtResourceType;
|
||||
const aro = @import("aro");
|
||||
const compiler_util = @import("../util.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
|
||||
@ -671,7 +672,11 @@ const ErrorHandler = union(enum) {
|
||||
) !void {
|
||||
switch (self.*) {
|
||||
.server => |*server| {
|
||||
var error_bundle = try aroDiagnosticsToErrorBundle(allocator, fail_msg, comp);
|
||||
var error_bundle = try compiler_util.aroDiagnosticsToErrorBundle(
|
||||
comp.diagnostics,
|
||||
allocator,
|
||||
fail_msg,
|
||||
);
|
||||
defer error_bundle.deinit(allocator);
|
||||
|
||||
try server.serveErrorBundle(error_bundle);
|
||||
@ -753,7 +758,7 @@ fn cliDiagnosticsToErrorBundle(
|
||||
switch (err_details.type) {
|
||||
.err => {
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
cur_err = .{
|
||||
.msg = try bundle.addString(err_details.msg.items),
|
||||
@ -771,7 +776,7 @@ fn cliDiagnosticsToErrorBundle(
|
||||
}
|
||||
}
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
|
||||
return try bundle.toOwnedBundle("");
|
||||
@ -840,7 +845,7 @@ fn diagnosticsToErrorBundle(
|
||||
switch (err_details.type) {
|
||||
.err => {
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
cur_err = .{
|
||||
.msg = try bundle.addString(msg_buf.written()),
|
||||
@ -859,20 +864,12 @@ fn diagnosticsToErrorBundle(
|
||||
}
|
||||
}
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
|
||||
return try bundle.toOwnedBundle("");
|
||||
}
|
||||
|
||||
fn flushErrorMessageIntoBundle(wip: *ErrorBundle.Wip, msg: ErrorBundle.ErrorMessage, notes: []const ErrorBundle.ErrorMessage) !void {
|
||||
try wip.addRootErrorMessage(msg);
|
||||
const notes_start = try wip.reserveNotes(@intCast(notes.len));
|
||||
for (notes_start.., notes) |i, note| {
|
||||
wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note));
|
||||
}
|
||||
}
|
||||
|
||||
fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []const u8, args: anytype) !ErrorBundle {
|
||||
@branchHint(.cold);
|
||||
var bundle: ErrorBundle.Wip = undefined;
|
||||
@ -883,75 +880,3 @@ fn errorStringToErrorBundle(allocator: std.mem.Allocator, comptime format: []con
|
||||
});
|
||||
return try bundle.toOwnedBundle("");
|
||||
}
|
||||
|
||||
fn aroDiagnosticsToErrorBundle(
|
||||
gpa: std.mem.Allocator,
|
||||
fail_msg: []const u8,
|
||||
comp: *aro.Compilation,
|
||||
) !ErrorBundle {
|
||||
@branchHint(.cold);
|
||||
|
||||
var bundle: ErrorBundle.Wip = undefined;
|
||||
try bundle.init(gpa);
|
||||
errdefer bundle.deinit();
|
||||
|
||||
try bundle.addRootErrorMessage(.{
|
||||
.msg = try bundle.addString(fail_msg),
|
||||
});
|
||||
|
||||
var cur_err: ?ErrorBundle.ErrorMessage = null;
|
||||
var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty;
|
||||
defer cur_notes.deinit(gpa);
|
||||
for (comp.diagnostics.output.to_list.messages.items) |msg| {
|
||||
switch (msg.kind) {
|
||||
// Clear the current error so that notes don't bleed into unassociated errors
|
||||
.off, .warning => {
|
||||
cur_err = null;
|
||||
continue;
|
||||
},
|
||||
.note => if (cur_err == null) continue,
|
||||
.@"fatal error", .@"error" => {},
|
||||
}
|
||||
|
||||
const src_loc = src_loc: {
|
||||
if (msg.location) |location| {
|
||||
break :src_loc try bundle.addSourceLocation(.{
|
||||
.src_path = try bundle.addString(location.path),
|
||||
.line = location.line_no - 1, // 1-based -> 0-based
|
||||
.column = location.col - 1, // 1-based -> 0-based
|
||||
.span_start = location.width,
|
||||
.span_main = location.width,
|
||||
.span_end = location.width,
|
||||
.source_line = try bundle.addString(location.line),
|
||||
});
|
||||
}
|
||||
break :src_loc ErrorBundle.SourceLocationIndex.none;
|
||||
};
|
||||
|
||||
switch (msg.kind) {
|
||||
.@"fatal error", .@"error" => {
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
}
|
||||
cur_err = .{
|
||||
.msg = try bundle.addString(msg.text),
|
||||
.src_loc = src_loc,
|
||||
};
|
||||
cur_notes.clearRetainingCapacity();
|
||||
},
|
||||
.note => {
|
||||
cur_err.?.notes_len += 1;
|
||||
try cur_notes.append(gpa, .{
|
||||
.msg = try bundle.addString(msg.text),
|
||||
.src_loc = src_loc,
|
||||
});
|
||||
},
|
||||
.off, .warning => unreachable,
|
||||
}
|
||||
}
|
||||
if (cur_err) |err| {
|
||||
try flushErrorMessageIntoBundle(&bundle, err, cur_notes.items);
|
||||
}
|
||||
|
||||
return try bundle.toOwnedBundle("");
|
||||
}
|
||||
|
||||
@ -345,20 +345,7 @@ fn buildWasmBinary(
|
||||
}
|
||||
},
|
||||
.error_bundle => {
|
||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
// TODO: use @ptrCast when the compiler supports it
|
||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra_array, unaligned_extra);
|
||||
result_error_bundle = .{
|
||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
||||
.extra = extra_array,
|
||||
};
|
||||
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||
},
|
||||
.emit_digest => {
|
||||
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
||||
|
||||
@ -3,6 +3,7 @@ const assert = std.debug.assert;
|
||||
const mem = std.mem;
|
||||
const process = std.process;
|
||||
const aro = @import("aro");
|
||||
const compiler_util = @import("../util.zig");
|
||||
const Translator = @import("Translator.zig");
|
||||
|
||||
const fast_exit = @import("builtin").mode != .Debug;
|
||||
@ -13,24 +14,33 @@ pub fn main() u8 {
|
||||
const gpa = general_purpose_allocator.allocator();
|
||||
defer _ = general_purpose_allocator.deinit();
|
||||
|
||||
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_instance.deinit();
|
||||
const arena = arena_instance.allocator();
|
||||
|
||||
const args = process.argsAlloc(arena) catch {
|
||||
var args = process.argsAlloc(arena) catch {
|
||||
std.debug.print("ran out of memory allocating arguments\n", .{});
|
||||
if (fast_exit) process.exit(1);
|
||||
return 1;
|
||||
};
|
||||
|
||||
var zig_integration = false;
|
||||
if (args.len > 1 and std.mem.eql(u8, args[1], "--zig-integration")) {
|
||||
zig_integration = true;
|
||||
}
|
||||
|
||||
var stderr_buf: [1024]u8 = undefined;
|
||||
var stderr = std.fs.File.stderr().writer(&stderr_buf);
|
||||
var diagnostics: aro.Diagnostics = .{
|
||||
.output = .{ .to_writer = .{
|
||||
var diagnostics: aro.Diagnostics = switch (zig_integration) {
|
||||
false => .{ .output = .{ .to_writer = .{
|
||||
.color = .detect(stderr.file),
|
||||
.writer = &stderr.interface,
|
||||
} },
|
||||
} } },
|
||||
true => .{ .output = .{ .to_list = .{
|
||||
.arena = .init(gpa),
|
||||
} } },
|
||||
};
|
||||
defer diagnostics.deinit();
|
||||
|
||||
var comp = aro.Compilation.initDefault(gpa, arena, &diagnostics, std.fs.cwd()) catch |err| switch (err) {
|
||||
error.OutOfMemory => {
|
||||
@ -47,13 +57,22 @@ pub fn main() u8 {
|
||||
var toolchain: aro.Toolchain = .{ .driver = &driver, .filesystem = .{ .real = comp.cwd } };
|
||||
defer toolchain.deinit();
|
||||
|
||||
translate(&driver, &toolchain, args) catch |err| switch (err) {
|
||||
translate(&driver, &toolchain, args, zig_integration) catch |err| switch (err) {
|
||||
error.OutOfMemory => {
|
||||
std.debug.print("ran out of memory translating\n", .{});
|
||||
if (fast_exit) process.exit(1);
|
||||
return 1;
|
||||
},
|
||||
error.FatalError => {
|
||||
error.FatalError => if (zig_integration) {
|
||||
serveErrorBundle(arena, &diagnostics) catch |bundle_err| {
|
||||
std.debug.print("unable to serve error bundle: {}\n", .{bundle_err});
|
||||
if (fast_exit) process.exit(1);
|
||||
return 1;
|
||||
};
|
||||
|
||||
if (fast_exit) process.exit(0);
|
||||
return 0;
|
||||
} else {
|
||||
if (fast_exit) process.exit(1);
|
||||
return 1;
|
||||
},
|
||||
@ -63,10 +82,27 @@ pub fn main() u8 {
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
|
||||
assert(comp.diagnostics.errors == 0 or !zig_integration);
|
||||
if (fast_exit) process.exit(@intFromBool(comp.diagnostics.errors != 0));
|
||||
return @intFromBool(comp.diagnostics.errors != 0);
|
||||
}
|
||||
|
||||
fn serveErrorBundle(arena: std.mem.Allocator, diagnostics: *const aro.Diagnostics) !void {
|
||||
const error_bundle = try compiler_util.aroDiagnosticsToErrorBundle(
|
||||
diagnostics,
|
||||
arena,
|
||||
"translation failure",
|
||||
);
|
||||
var stdout_buffer: [1024]u8 = undefined;
|
||||
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||
var server: std.zig.Server = .{
|
||||
.out = &stdout_writer.interface,
|
||||
.in = undefined,
|
||||
};
|
||||
try server.serveErrorBundle(error_bundle);
|
||||
}
|
||||
|
||||
pub const usage =
|
||||
\\Usage {s}: [options] file [CC options]
|
||||
\\
|
||||
@ -79,7 +115,7 @@ pub const usage =
|
||||
\\
|
||||
;
|
||||
|
||||
fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
|
||||
fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8, zig_integration: bool) !void {
|
||||
const gpa = d.comp.gpa;
|
||||
|
||||
const aro_args = args: {
|
||||
@ -99,6 +135,9 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
|
||||
try stdout.interface.writeAll("0.0.0-dev\n");
|
||||
try stdout.interface.flush();
|
||||
return;
|
||||
} else if (mem.eql(u8, arg, "--zig-integration")) {
|
||||
if (i != 1 or !zig_integration)
|
||||
return d.fatal("--zig-integration must be the first argument", .{});
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
@ -116,6 +155,14 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
|
||||
return d.fatal("user provided macro source exceeded max size", .{});
|
||||
}
|
||||
|
||||
const has_output_file = if (d.output_name) |path|
|
||||
!std.mem.eql(u8, path, "-")
|
||||
else
|
||||
false;
|
||||
if (zig_integration and !has_output_file) {
|
||||
return d.fatal("--zig-integration requires specifying an output file", .{});
|
||||
}
|
||||
|
||||
const content = try macro_buf.toOwnedSlice(gpa);
|
||||
errdefer gpa.free(content);
|
||||
|
||||
@ -160,7 +207,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
|
||||
defer c_tree.deinit();
|
||||
|
||||
if (d.diagnostics.errors != 0) {
|
||||
if (fast_exit) process.exit(1);
|
||||
if (fast_exit and !zig_integration) process.exit(1);
|
||||
return error.FatalError;
|
||||
}
|
||||
|
||||
@ -212,7 +259,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
|
||||
if (out_writer.err) |write_err|
|
||||
return d.fatal("failed to write result to '{s}': {s}", .{ out_file_path, aro.Driver.errorDescription(write_err) });
|
||||
|
||||
if (fast_exit) process.exit(0);
|
||||
if (fast_exit and !zig_integration) process.exit(0);
|
||||
}
|
||||
|
||||
test {
|
||||
|
||||
82
lib/compiler/util.zig
Normal file
82
lib/compiler/util.zig
Normal file
@ -0,0 +1,82 @@
|
||||
//! Utilities shared between compiler sub-commands
|
||||
const std = @import("std");
|
||||
const aro = @import("aro");
|
||||
const ErrorBundle = std.zig.ErrorBundle;
|
||||
|
||||
pub fn aroDiagnosticsToErrorBundle(
|
||||
d: *const aro.Diagnostics,
|
||||
gpa: std.mem.Allocator,
|
||||
fail_msg: ?[]const u8,
|
||||
) !ErrorBundle {
|
||||
@branchHint(.cold);
|
||||
|
||||
var bundle: ErrorBundle.Wip = undefined;
|
||||
try bundle.init(gpa);
|
||||
errdefer bundle.deinit();
|
||||
|
||||
if (fail_msg) |msg| {
|
||||
try bundle.addRootErrorMessage(.{
|
||||
.msg = try bundle.addString(msg),
|
||||
});
|
||||
}
|
||||
|
||||
var cur_err: ?ErrorBundle.ErrorMessage = null;
|
||||
var cur_notes: std.ArrayList(ErrorBundle.ErrorMessage) = .empty;
|
||||
defer cur_notes.deinit(gpa);
|
||||
for (d.output.to_list.messages.items) |msg| {
|
||||
switch (msg.kind) {
|
||||
.off, .warning => {
|
||||
// Emit any pending error and clear everything so that notes don't bleed into unassociated errors
|
||||
if (cur_err) |err| {
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
cur_err = null;
|
||||
}
|
||||
cur_notes.clearRetainingCapacity();
|
||||
continue;
|
||||
},
|
||||
.note => if (cur_err == null) continue,
|
||||
.@"fatal error", .@"error" => {},
|
||||
}
|
||||
|
||||
const src_loc = src_loc: {
|
||||
if (msg.location) |location| {
|
||||
break :src_loc try bundle.addSourceLocation(.{
|
||||
.src_path = try bundle.addString(location.path),
|
||||
.line = location.line_no - 1, // 1-based -> 0-based
|
||||
.column = location.col - 1, // 1-based -> 0-based
|
||||
.span_start = location.width,
|
||||
.span_main = location.width,
|
||||
.span_end = location.width,
|
||||
.source_line = try bundle.addString(location.line),
|
||||
});
|
||||
}
|
||||
break :src_loc ErrorBundle.SourceLocationIndex.none;
|
||||
};
|
||||
|
||||
switch (msg.kind) {
|
||||
.@"fatal error", .@"error" => {
|
||||
if (cur_err) |err| {
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
cur_err = .{
|
||||
.msg = try bundle.addString(msg.text),
|
||||
.src_loc = src_loc,
|
||||
};
|
||||
cur_notes.clearRetainingCapacity();
|
||||
},
|
||||
.note => {
|
||||
cur_err.?.notes_len += 1;
|
||||
try cur_notes.append(gpa, .{
|
||||
.msg = try bundle.addString(msg.text),
|
||||
.src_loc = src_loc,
|
||||
});
|
||||
},
|
||||
.off, .warning => unreachable,
|
||||
}
|
||||
}
|
||||
if (cur_err) |err| {
|
||||
try bundle.addRootErrorMessageWithNotes(err, cur_notes.items);
|
||||
}
|
||||
|
||||
return try bundle.toOwnedBundle("");
|
||||
}
|
||||
@ -524,22 +524,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool, web_server: ?*Build.
|
||||
}
|
||||
},
|
||||
.error_bundle => {
|
||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
// TODO: use @ptrCast when the compiler supports it
|
||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
||||
{
|
||||
s.result_error_bundle = .{ .string_bytes = &.{}, .extra = &.{} };
|
||||
errdefer s.result_error_bundle.deinit(gpa);
|
||||
s.result_error_bundle.string_bytes = try gpa.dupe(u8, string_bytes);
|
||||
const extra = try gpa.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra, unaligned_extra);
|
||||
s.result_error_bundle.extra = extra;
|
||||
}
|
||||
s.result_error_bundle = try std.zig.Server.allocErrorBundle(gpa, body);
|
||||
// This message indicates the end of the update.
|
||||
if (watch) break :poll;
|
||||
},
|
||||
|
||||
@ -595,19 +595,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
|
||||
}
|
||||
},
|
||||
.error_bundle => {
|
||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes);
|
||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra_array, unaligned_extra);
|
||||
result_error_bundle = .{
|
||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
||||
.extra = extra_array,
|
||||
};
|
||||
result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||
},
|
||||
.emit_digest => {
|
||||
const EmitDigest = std.zig.Server.Message.EmitDigest;
|
||||
|
||||
@ -416,6 +416,18 @@ pub const Wip = struct {
|
||||
wip.root_list.appendAssumeCapacity(try addErrorMessage(wip, em));
|
||||
}
|
||||
|
||||
pub fn addRootErrorMessageWithNotes(
|
||||
wip: *Wip,
|
||||
msg: ErrorMessage,
|
||||
notes: []const ErrorMessage,
|
||||
) !void {
|
||||
try wip.addRootErrorMessage(msg);
|
||||
const notes_start = try wip.reserveNotes(@intCast(notes.len));
|
||||
for (notes_start.., notes) |i, note| {
|
||||
wip.extra.items[i] = @intFromEnum(wip.addErrorMessageAssumeCapacity(note));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addErrorMessage(wip: *Wip, em: ErrorMessage) Allocator.Error!MessageIndex {
|
||||
return @enumFromInt(try addExtra(wip, em));
|
||||
}
|
||||
|
||||
@ -231,6 +231,28 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
|
||||
try s.out.flush();
|
||||
}
|
||||
|
||||
pub fn allocErrorBundle(allocator: std.mem.Allocator, body: []const u8) !std.zig.ErrorBundle {
|
||||
const eb_hdr = @as(*align(1) const OutMessage.ErrorBundle, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(OutMessage.ErrorBundle)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(OutMessage.ErrorBundle) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
const unaligned_extra: []align(1) const u32 = @ptrCast(extra_bytes);
|
||||
|
||||
var error_bundle: std.zig.ErrorBundle = .{
|
||||
.string_bytes = &.{},
|
||||
.extra = &.{},
|
||||
};
|
||||
errdefer error_bundle.deinit(allocator);
|
||||
|
||||
error_bundle.string_bytes = try allocator.dupe(u8, string_bytes);
|
||||
const extra = try allocator.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra, unaligned_extra);
|
||||
error_bundle.extra = extra;
|
||||
|
||||
return error_bundle;
|
||||
}
|
||||
|
||||
pub const TestMetadata = struct {
|
||||
names: []const u32,
|
||||
expected_panic_msgs: []const u32,
|
||||
|
||||
@ -5640,6 +5640,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest
|
||||
}
|
||||
|
||||
pub const CImportResult = struct {
|
||||
// Only valid if `errors` is not empty
|
||||
digest: [Cache.bin_digest_len]u8,
|
||||
cache_hit: bool,
|
||||
errors: std.zig.ErrorBundle,
|
||||
@ -5649,6 +5650,146 @@ pub const CImportResult = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn translateC(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
man: *Cache.Manifest,
|
||||
ext: FileExt,
|
||||
source: union(enum) {
|
||||
path: []const u8,
|
||||
c_src: []const u8,
|
||||
},
|
||||
translated_basename: []const u8,
|
||||
owner_mod: *Package.Module,
|
||||
prog_node: std.Progress.Node,
|
||||
) !CImportResult {
|
||||
dev.check(.translate_c_command);
|
||||
|
||||
const tmp_basename = std.fmt.hex(std.crypto.random.int(u64));
|
||||
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename;
|
||||
const cache_dir = comp.dirs.local_cache.handle;
|
||||
var cache_tmp_dir = try cache_dir.makeOpenPath(tmp_sub_path, .{});
|
||||
defer cache_tmp_dir.close();
|
||||
|
||||
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename });
|
||||
const source_path = switch (source) {
|
||||
.c_src => |c_src| path: {
|
||||
const cimport_basename = "cimport.h";
|
||||
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
|
||||
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path});
|
||||
if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path});
|
||||
try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src });
|
||||
break :path out_h_path;
|
||||
},
|
||||
.path => |p| p,
|
||||
};
|
||||
|
||||
const out_dep_path: ?[]const u8 = blk: {
|
||||
if (comp.disable_c_depfile) break :blk null;
|
||||
const c_src_basename = fs.path.basename(source_path);
|
||||
const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
|
||||
const out_dep_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, dep_basename });
|
||||
break :blk out_dep_path;
|
||||
};
|
||||
|
||||
var argv = std.array_list.Managed([]const u8).init(arena);
|
||||
{
|
||||
const target = &owner_mod.resolved_target.result;
|
||||
try argv.appendSlice(&.{ "--zig-integration", "-x", "c" });
|
||||
|
||||
const resource_path = try comp.dirs.zig_lib.join(arena, &.{ "compiler", "aro", "include" });
|
||||
try argv.appendSlice(&.{ "-isystem", resource_path });
|
||||
try comp.addCommonCCArgs(arena, &argv, ext, out_dep_path, owner_mod, .aro);
|
||||
try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) });
|
||||
|
||||
const mcpu = mcpu: {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||
defer buf.deinit(comp.gpa);
|
||||
|
||||
try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name});
|
||||
|
||||
// TODO better serialization https://github.com/ziglang/zig/issues/4584
|
||||
const all_features_list = target.cpu.arch.allFeaturesList();
|
||||
try argv.ensureUnusedCapacity(all_features_list.len * 4);
|
||||
for (all_features_list, 0..) |feature, index_usize| {
|
||||
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
||||
const is_enabled = target.cpu.features.isEnabled(index);
|
||||
|
||||
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
||||
try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
||||
}
|
||||
break :mcpu try buf.toOwnedSlice(arena);
|
||||
};
|
||||
try argv.append(mcpu);
|
||||
|
||||
try argv.appendSlice(comp.global_cc_argv);
|
||||
try argv.appendSlice(owner_mod.cc_argv);
|
||||
try argv.appendSlice(&.{ source_path, "-o", translated_path });
|
||||
if (comp.verbose_cimport) dump_argv(argv.items);
|
||||
}
|
||||
|
||||
var stdout: []u8 = undefined;
|
||||
try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout);
|
||||
|
||||
if (out_dep_path) |dep_file_path| add_deps: {
|
||||
if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_file_path});
|
||||
|
||||
const dep_basename = fs.path.basename(dep_file_path);
|
||||
// Add the files depended on to the cache system, if a dep file was emitted
|
||||
man.addDepFilePost(cache_tmp_dir, dep_basename) catch |err| switch (err) {
|
||||
error.FileNotFound => break :add_deps,
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
switch (comp.cache_use) {
|
||||
.whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
|
||||
whole.cache_manifest_mutex.lock();
|
||||
defer whole.cache_manifest_mutex.unlock();
|
||||
try whole_cache_manifest.addDepFilePost(cache_tmp_dir, dep_basename);
|
||||
},
|
||||
.incremental, .none => {},
|
||||
}
|
||||
|
||||
// Just to save disk space, we delete the file because it is never needed again.
|
||||
cache_tmp_dir.deleteFile(dep_basename) catch |err| {
|
||||
log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err });
|
||||
};
|
||||
}
|
||||
|
||||
if (stdout.len > 0) {
|
||||
var reader: std.Io.Reader = .fixed(stdout);
|
||||
const MessageHeader = std.zig.Server.Message.Header;
|
||||
const header = reader.takeStruct(MessageHeader, .little) catch |err|
|
||||
fatal("unable to read translate-c MessageHeader: {s}", .{@errorName(err)});
|
||||
const body = reader.take(header.bytes_len) catch |err|
|
||||
fatal("unable to read {}-byte translate-c message body: {s}", .{ header.bytes_len, @errorName(err) });
|
||||
switch (header.tag) {
|
||||
.error_bundle => {
|
||||
const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body);
|
||||
return .{
|
||||
.digest = undefined,
|
||||
.cache_hit = false,
|
||||
.errors = error_bundle,
|
||||
};
|
||||
},
|
||||
else => fatal("unexpected message type received from translate-c: {s}", .{@tagName(header.tag)}),
|
||||
}
|
||||
}
|
||||
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
|
||||
|
||||
if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path });
|
||||
try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path);
|
||||
|
||||
return .{
|
||||
.digest = bin_digest,
|
||||
.cache_hit = false,
|
||||
.errors = ErrorBundle.empty,
|
||||
};
|
||||
}
|
||||
|
||||
/// Caller owns returned memory.
|
||||
pub fn cImport(
|
||||
comp: *Compilation,
|
||||
@ -5658,67 +5799,35 @@ pub fn cImport(
|
||||
) !CImportResult {
|
||||
dev.check(.translate_c_command);
|
||||
|
||||
const cimport_basename = "cimport.h";
|
||||
const translated_basename = "cimport.zig";
|
||||
|
||||
var man = comp.obtainCObjectCacheManifest(owner_mod);
|
||||
defer man.deinit();
|
||||
|
||||
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects
|
||||
man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish c-import from compiling C objects
|
||||
man.hash.addBytes(c_src);
|
||||
|
||||
const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: {
|
||||
const result: CImportResult = if (try man.hit()) .{
|
||||
.digest = man.finalBin(),
|
||||
.cache_hit = true,
|
||||
.errors = ErrorBundle.empty,
|
||||
} else result: {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const tmp_basename = std.fmt.hex(std.crypto.random.int(u64));
|
||||
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename;
|
||||
const cache_dir = comp.dirs.local_cache.handle;
|
||||
const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename;
|
||||
|
||||
try cache_dir.makePath(tmp_sub_path);
|
||||
|
||||
const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path});
|
||||
const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename });
|
||||
const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path});
|
||||
|
||||
if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path});
|
||||
try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src });
|
||||
|
||||
var argv = std.array_list.Managed([]const u8).init(comp.gpa);
|
||||
defer argv.deinit();
|
||||
try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod);
|
||||
try argv.appendSlice(&.{ out_h_path, "-o", translated_path });
|
||||
|
||||
if (comp.verbose_cc) dump_argv(argv.items);
|
||||
var stdout: []u8 = undefined;
|
||||
try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout);
|
||||
if (comp.verbose_cimport and stdout.len != 0) log.info("unexpected stdout: {s}", .{stdout});
|
||||
|
||||
const dep_sub_path = out_h_sub_path ++ ".d";
|
||||
if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_sub_path});
|
||||
try man.addDepFilePost(cache_dir, dep_sub_path);
|
||||
switch (comp.cache_use) {
|
||||
.whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| {
|
||||
whole.cache_manifest_mutex.lock();
|
||||
defer whole.cache_manifest_mutex.unlock();
|
||||
try whole_cache_manifest.addDepFilePost(cache_dir, dep_sub_path);
|
||||
},
|
||||
.incremental, .none => {},
|
||||
}
|
||||
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest;
|
||||
|
||||
if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path });
|
||||
try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path);
|
||||
|
||||
break :digest .{ bin_digest, false };
|
||||
break :result try comp.translateC(
|
||||
arena,
|
||||
&man,
|
||||
.c,
|
||||
.{ .c_src = c_src },
|
||||
translated_basename,
|
||||
owner_mod,
|
||||
prog_node,
|
||||
);
|
||||
};
|
||||
|
||||
if (man.have_exclusive_lock) {
|
||||
if (result.errors.errorMessageCount() == 0 and man.have_exclusive_lock) {
|
||||
// Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is
|
||||
// possible we had a hit and the manifest is dirty, for example if the file mtime changed but
|
||||
// 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(
|
||||
};
|
||||
}
|
||||
|
||||
return .{
|
||||
.digest = digest,
|
||||
.cache_hit = is_hit,
|
||||
.errors = std.zig.ErrorBundle.empty,
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
fn workerUpdateCObject(
|
||||
@ -6622,19 +6727,7 @@ fn spawnZigRc(
|
||||
// We expect exactly one ErrorBundle, and if any error_bundle header is
|
||||
// sent then it's a fatal error.
|
||||
.error_bundle => {
|
||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
||||
const extra_array = try comp.gpa.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra_array, unaligned_extra);
|
||||
const error_bundle = std.zig.ErrorBundle{
|
||||
.string_bytes = try comp.gpa.dupe(u8, string_bytes),
|
||||
.extra = extra_array,
|
||||
};
|
||||
const error_bundle = try std.zig.Server.allocErrorBundle(comp.gpa, body);
|
||||
return comp.failWin32ResourceWithOwnedBundle(win32_resource, error_bundle);
|
||||
},
|
||||
else => {}, // ignore other messages
|
||||
@ -6672,49 +6765,6 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addTranslateCCArgs(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
argv: *std.array_list.Managed([]const u8),
|
||||
ext: FileExt,
|
||||
out_dep_path: ?[]const u8,
|
||||
owner_mod: *Package.Module,
|
||||
) !void {
|
||||
const target = &owner_mod.resolved_target.result;
|
||||
|
||||
try argv.appendSlice(&.{ "-x", "c" });
|
||||
|
||||
const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"});
|
||||
try argv.appendSlice(&.{ "-isystem", resource_path });
|
||||
|
||||
try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro);
|
||||
|
||||
try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) });
|
||||
|
||||
const mcpu = mcpu: {
|
||||
var buf: std.ArrayListUnmanaged(u8) = .empty;
|
||||
defer buf.deinit(comp.gpa);
|
||||
|
||||
try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name});
|
||||
|
||||
// TODO better serialization https://github.com/ziglang/zig/issues/4584
|
||||
const all_features_list = target.cpu.arch.allFeaturesList();
|
||||
try argv.ensureUnusedCapacity(all_features_list.len * 4);
|
||||
for (all_features_list, 0..) |feature, index_usize| {
|
||||
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
||||
const is_enabled = target.cpu.features.isEnabled(index);
|
||||
|
||||
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
||||
try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name });
|
||||
}
|
||||
break :mcpu try buf.toOwnedSlice(arena);
|
||||
};
|
||||
try argv.append(mcpu);
|
||||
|
||||
try argv.appendSlice(comp.global_cc_argv);
|
||||
try argv.appendSlice(owner_mod.cc_argv);
|
||||
}
|
||||
|
||||
/// Add common C compiler args between translate-c and C object compilation.
|
||||
fn addCommonCCArgs(
|
||||
comp: *const Compilation,
|
||||
|
||||
98
src/main.zig
98
src/main.zig
@ -4075,7 +4075,7 @@ fn serve(
|
||||
while (true) {
|
||||
const hdr = try server.receiveMessage();
|
||||
|
||||
// Lock the debug server while hanling the message.
|
||||
// Lock the debug server while handling the message.
|
||||
if (comp.debugIncremental()) ids.mutex.lock();
|
||||
defer if (comp.debugIncremental()) ids.mutex.unlock();
|
||||
|
||||
@ -4092,7 +4092,11 @@ fn serve(
|
||||
var output: Compilation.CImportResult = undefined;
|
||||
try cmdTranslateC(comp, arena, &output, file_system_inputs, main_progress_node);
|
||||
defer output.deinit(gpa);
|
||||
try server.serveStringMessage(.file_system_inputs, file_system_inputs.items);
|
||||
|
||||
if (file_system_inputs.items.len != 0) {
|
||||
try server.serveStringMessage(.file_system_inputs, file_system_inputs.items);
|
||||
}
|
||||
|
||||
if (output.errors.errorMessageCount() != 0) {
|
||||
try server.serveErrorBundle(output.errors);
|
||||
} else {
|
||||
@ -4100,6 +4104,7 @@ fn serve(
|
||||
.flags = .{ .cache_hit = output.cache_hit },
|
||||
});
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4515,48 +4520,75 @@ fn cmdTranslateC(
|
||||
prog_node: std.Progress.Node,
|
||||
) !void {
|
||||
dev.check(.translate_c_command);
|
||||
_ = file_system_inputs;
|
||||
_ = fancy_output;
|
||||
|
||||
assert(comp.c_source_files.len == 1);
|
||||
const c_source_file = comp.c_source_files[0];
|
||||
|
||||
var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{});
|
||||
defer zig_cache_tmp_dir.close();
|
||||
const translated_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{comp.root_name});
|
||||
|
||||
const ext = Compilation.classifyFileExt(c_source_file.src_path);
|
||||
const out_dep_path: ?[]const u8 = blk: {
|
||||
if (comp.disable_c_depfile) break :blk null;
|
||||
const c_src_basename = fs.path.basename(c_source_file.src_path);
|
||||
const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename});
|
||||
const out_dep_path = try comp.tmpFilePath(arena, dep_basename);
|
||||
break :blk out_dep_path;
|
||||
var man: Cache.Manifest = comp.obtainCObjectCacheManifest(comp.root_mod);
|
||||
man.want_shared_lock = false;
|
||||
defer man.deinit();
|
||||
|
||||
man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects
|
||||
man.hash.add(comp.config.c_frontend);
|
||||
Compilation.cache_helpers.hashCSource(&man, c_source_file) catch |err| {
|
||||
fatal("unable to process '{s}': {s}", .{ c_source_file.src_path, @errorName(err) });
|
||||
};
|
||||
|
||||
var argv = std.array_list.Managed([]const u8).init(arena);
|
||||
try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod);
|
||||
try argv.append(c_source_file.src_path);
|
||||
if (comp.verbose_cc) Compilation.dump_argv(argv.items);
|
||||
const result: Compilation.CImportResult = if (try man.hit()) .{
|
||||
.digest = man.finalBin(),
|
||||
.cache_hit = true,
|
||||
.errors = std.zig.ErrorBundle.empty,
|
||||
} else result: {
|
||||
const result = try comp.translateC(
|
||||
arena,
|
||||
&man,
|
||||
Compilation.classifyFileExt(c_source_file.src_path),
|
||||
.{ .path = c_source_file.src_path },
|
||||
translated_basename,
|
||||
comp.root_mod,
|
||||
prog_node,
|
||||
);
|
||||
|
||||
try translateC(comp.gpa, arena, argv.items, prog_node, null);
|
||||
if (result.errors.errorMessageCount() != 0) {
|
||||
if (fancy_output) |p| {
|
||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||
p.* = result;
|
||||
return;
|
||||
} else {
|
||||
const color: Color = .auto;
|
||||
result.errors.renderToStdErr(color.renderOptions());
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (out_dep_path) |dep_file_path| {
|
||||
const dep_basename = fs.path.basename(dep_file_path);
|
||||
// Add the files depended on to the cache system.
|
||||
//man.addDepFilePost(zig_cache_tmp_dir, dep_basename) catch |err| switch (err) {
|
||||
// error.FileNotFound => {
|
||||
// // Clang didn't emit the dep file; nothing to add to the manifest.
|
||||
// break :add_deps;
|
||||
// },
|
||||
// else => |e| return e,
|
||||
//};
|
||||
// Just to save disk space, we delete the file because it is never needed again.
|
||||
zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| {
|
||||
warn("failed to delete '{s}': {t}", .{ dep_file_path, err });
|
||||
man.writeManifest() catch |err| warn("failed to write cache manifest: {t}", .{err});
|
||||
break :result result;
|
||||
};
|
||||
|
||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||
if (fancy_output) |p| {
|
||||
p.* = result;
|
||||
} else {
|
||||
const hex_digest = Cache.binToHex(result.digest);
|
||||
const out_zig_path = try fs.path.join(arena, &.{ "o", &hex_digest, translated_basename });
|
||||
const zig_file = comp.dirs.local_cache.handle.openFile(out_zig_path, .{}) catch |err| {
|
||||
const path = comp.dirs.local_cache.path orelse ".";
|
||||
fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{
|
||||
path,
|
||||
fs.path.sep_str,
|
||||
out_zig_path,
|
||||
@errorName(err),
|
||||
});
|
||||
};
|
||||
defer zig_file.close();
|
||||
var stdout_writer = fs.File.stdout().writer(&stdout_buffer);
|
||||
var file_reader = zig_file.reader(&.{});
|
||||
_ = try stdout_writer.interface.sendFileAll(&file_reader, .unlimited);
|
||||
try stdout_writer.interface.flush();
|
||||
return cleanExit();
|
||||
}
|
||||
|
||||
return cleanExit();
|
||||
}
|
||||
|
||||
pub fn translateC(
|
||||
|
||||
@ -259,20 +259,7 @@ const Eval = struct {
|
||||
|
||||
switch (header.tag) {
|
||||
.error_bundle => {
|
||||
const EbHdr = std.zig.Server.Message.ErrorBundle;
|
||||
const eb_hdr = @as(*align(1) const EbHdr, @ptrCast(body));
|
||||
const extra_bytes =
|
||||
body[@sizeOf(EbHdr)..][0 .. @sizeOf(u32) * eb_hdr.extra_len];
|
||||
const string_bytes =
|
||||
body[@sizeOf(EbHdr) + extra_bytes.len ..][0..eb_hdr.string_bytes_len];
|
||||
// TODO: use @ptrCast when the compiler supports it
|
||||
const unaligned_extra = std.mem.bytesAsSlice(u32, extra_bytes);
|
||||
const extra_array = try arena.alloc(u32, unaligned_extra.len);
|
||||
@memcpy(extra_array, unaligned_extra);
|
||||
const result_error_bundle: std.zig.ErrorBundle = .{
|
||||
.string_bytes = try arena.dupe(u8, string_bytes),
|
||||
.extra = extra_array,
|
||||
};
|
||||
const result_error_bundle = try std.zig.Server.allocErrorBundle(arena, body);
|
||||
if (stderr.bufferedLen() > 0) {
|
||||
const stderr_data = try poller.toOwnedSlice(.stderr);
|
||||
if (eval.allow_stderr) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user