authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-13 13:03:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:15-07:00
logbc79328dcf3a8653e26c7fe7b4cd8fc7fff6c421
tree69d95c3550b5c820a5115543ca1e6d4a4c33c253
parent8e6d46bca593088af7c7ec078f5534631e2a937d

fix endianness when using test-runner in qemu


1 files changed, 63 insertions(+), 12 deletions(-)

lib/std/zig/Server.zig+63-12
...@@ -105,13 +105,17 @@ pub fn receiveMessage(s: *Server) !InMessage.Header {...@@ -105,13 +105,17 @@ pub fn receiveMessage(s: *Server) !InMessage.Header {
105 assert(fifo.readableLength() == buf.len);105 assert(fifo.readableLength() == buf.len);
106 if (buf.len >= @sizeOf(Header)) {106 if (buf.len >= @sizeOf(Header)) {
107 const header = @ptrCast(*align(1) const Header, buf[0..@sizeOf(Header)]);107 const header = @ptrCast(*align(1) const Header, buf[0..@sizeOf(Header)]);
108 const bytes_len = bswap(header.bytes_len);
109 const tag = bswap(header.tag);
108110
109 if (buf.len - @sizeOf(Header) >= header.bytes_len) {111 if (buf.len - @sizeOf(Header) >= bytes_len) {
110 const result = header.*;
111 fifo.discard(@sizeOf(Header));112 fifo.discard(@sizeOf(Header));
112 return result;113 return .{
114 .tag = tag,
115 .bytes_len = bytes_len,
116 };
113 } else {117 } else {
114 const needed = header.bytes_len - (buf.len - @sizeOf(Header));118 const needed = bytes_len - (buf.len - @sizeOf(Header));
115 const write_buffer = try fifo.writableWithSize(needed);119 const write_buffer = try fifo.writableWithSize(needed);
116 const amt = try s.in.read(write_buffer);120 const amt = try s.in.read(write_buffer);
117 fifo.update(amt);121 fifo.update(amt);
...@@ -130,7 +134,7 @@ pub fn receiveBody_u32(s: *Server) !u32 {...@@ -130,7 +134,7 @@ pub fn receiveBody_u32(s: *Server) !u32 {
130 const buf = fifo.readableSlice(0);134 const buf = fifo.readableSlice(0);
131 const result = @ptrCast(*align(1) const u32, buf[0..4]).*;135 const result = @ptrCast(*align(1) const u32, buf[0..4]).*;
132 fifo.discard(4);136 fifo.discard(4);
133 return result;137 return bswap(result);
134}138}
135139
136pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void {140pub fn serveStringMessage(s: *Server, tag: OutMessage.Tag, msg: []const u8) !void {
...@@ -146,8 +150,9 @@ pub fn serveMessage(...@@ -146,8 +150,9 @@ pub fn serveMessage(
146 bufs: []const []const u8,150 bufs: []const []const u8,
147) !void {151) !void {
148 var iovecs: [10]std.os.iovec_const = undefined;152 var iovecs: [10]std.os.iovec_const = undefined;
153 const header_le = bswap(header);
149 iovecs[0] = .{154 iovecs[0] = .{
150 .iov_base = @ptrCast([*]const u8, &header),155 .iov_base = @ptrCast([*]const u8, &header_le),
151 .iov_len = @sizeOf(OutMessage.Header),156 .iov_len = @sizeOf(OutMessage.Header),
152 };157 };
153 for (bufs, iovecs[1 .. bufs.len + 1]) |buf, *iovec| {158 for (bufs, iovecs[1 .. bufs.len + 1]) |buf, *iovec| {
...@@ -177,11 +182,12 @@ pub fn serveTestResults(...@@ -177,11 +182,12 @@ pub fn serveTestResults(
177 s: *Server,182 s: *Server,
178 msg: OutMessage.TestResults,183 msg: OutMessage.TestResults,
179) !void {184) !void {
185 const msg_le = bswap(msg);
180 try s.serveMessage(.{186 try s.serveMessage(.{
181 .tag = .test_results,187 .tag = .test_results,
182 .bytes_len = @intCast(u32, @sizeOf(OutMessage.TestResults)),188 .bytes_len = @intCast(u32, @sizeOf(OutMessage.TestResults)),
183 }, &.{189 }, &.{
184 std.mem.asBytes(&msg),190 std.mem.asBytes(&msg_le),
185 });191 });
186}192}
187193
...@@ -204,19 +210,31 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {...@@ -204,19 +210,31 @@ pub fn serveErrorBundle(s: *Server, error_bundle: std.zig.ErrorBundle) !void {
204}210}
205211
206pub const TestMetadata = struct {212pub const TestMetadata = struct {
207 names: []const u32,213 names: []u32,
208 async_frame_sizes: []const u32,214 async_frame_sizes: []u32,
209 expected_panic_msgs: []const u32,215 expected_panic_msgs: []u32,
210 string_bytes: []const u8,216 string_bytes: []const u8,
211};217};
212218
213pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {219pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
214 const header: OutMessage.TestMetadata = .{220 const header: OutMessage.TestMetadata = .{
215 .tests_len = @intCast(u32, test_metadata.names.len),221 .tests_len = bswap(@intCast(u32, test_metadata.names.len)),
216 .string_bytes_len = @intCast(u32, test_metadata.string_bytes.len),222 .string_bytes_len = bswap(@intCast(u32, test_metadata.string_bytes.len)),
217 };223 };
218 const bytes_len = @sizeOf(OutMessage.TestMetadata) +224 const bytes_len = @sizeOf(OutMessage.TestMetadata) +
219 3 * 4 * test_metadata.names.len + test_metadata.string_bytes.len;225 3 * 4 * test_metadata.names.len + test_metadata.string_bytes.len;
226
227 if (need_bswap) {
228 bswap_u32_array(test_metadata.names);
229 bswap_u32_array(test_metadata.async_frame_sizes);
230 bswap_u32_array(test_metadata.expected_panic_msgs);
231 }
232 defer if (need_bswap) {
233 bswap_u32_array(test_metadata.names);
234 bswap_u32_array(test_metadata.async_frame_sizes);
235 bswap_u32_array(test_metadata.expected_panic_msgs);
236 };
237
220 return s.serveMessage(.{238 return s.serveMessage(.{
221 .tag = .test_metadata,239 .tag = .test_metadata,
222 .bytes_len = @intCast(u32, bytes_len),240 .bytes_len = @intCast(u32, bytes_len),
...@@ -230,10 +248,43 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {...@@ -230,10 +248,43 @@ pub fn serveTestMetadata(s: *Server, test_metadata: TestMetadata) !void {
230 });248 });
231}249}
232250
251fn bswap(x: anytype) @TypeOf(x) {
252 if (!need_bswap) return x;
253
254 const T = @TypeOf(x);
255 switch (@typeInfo(T)) {
256 .Enum => return @intToEnum(T, @byteSwap(@enumToInt(x))),
257 .Int => return @byteSwap(x),
258 .Struct => |info| switch (info.layout) {
259 .Extern => {
260 var result: T = undefined;
261 inline for (info.fields) |field| {
262 @field(result, field.name) = bswap(@field(x, field.name));
263 }
264 return result;
265 },
266 .Packed => {
267 const I = info.backing_integer.?;
268 return @bitCast(T, @byteSwap(@bitCast(I, x)));
269 },
270 .Auto => @compileError("auto layout struct"),
271 },
272 else => @compileError("bswap on type " ++ @typeName(T)),
273 }
274}
275
276fn bswap_u32_array(slice: []u32) void {
277 comptime assert(need_bswap);
278 for (slice) |*elem| elem.* = @byteSwap(elem.*);
279}
280
233const OutMessage = std.zig.Server.Message;281const OutMessage = std.zig.Server.Message;
234const InMessage = std.zig.Client.Message;282const InMessage = std.zig.Client.Message;
235283
236const Server = @This();284const Server = @This();
285const builtin = @import("builtin");
237const std = @import("std");286const std = @import("std");
238const Allocator = std.mem.Allocator;287const Allocator = std.mem.Allocator;
239const assert = std.debug.assert;288const assert = std.debug.assert;
289const native_endian = builtin.target.cpu.arch.endian();
290const need_bswap = native_endian != .Little;