authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-26 23:30:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-28 18:30:57-07:00
log9860dd475ab754f85f2f8c96039255bda8721002
treef1f309035fe51e724bbc6e28b28f986cfda55d4d
parent8f4cb4614fa7fe275dff360e9f281cb43b99261a

std: delete most remaining uses of GenericWriter


9 files changed, 116 insertions(+), 666 deletions(-)

lib/std/Io.zig-42
...@@ -144,48 +144,6 @@ pub fn GenericReader(...@@ -144,48 +144,6 @@ pub fn GenericReader(
144 return @errorCast(self.any().readAllAlloc(allocator, max_size));144 return @errorCast(self.any().readAllAlloc(allocator, max_size));
145 }145 }
146146
147 pub inline fn readUntilDelimiterAlloc(
148 self: Self,
149 allocator: Allocator,
150 delimiter: u8,
151 max_size: usize,
152 ) (NoEofError || Allocator.Error || error{StreamTooLong})![]u8 {
153 return @errorCast(self.any().readUntilDelimiterAlloc(
154 allocator,
155 delimiter,
156 max_size,
157 ));
158 }
159
160 pub inline fn readUntilDelimiter(
161 self: Self,
162 buf: []u8,
163 delimiter: u8,
164 ) (NoEofError || error{StreamTooLong})![]u8 {
165 return @errorCast(self.any().readUntilDelimiter(buf, delimiter));
166 }
167
168 pub inline fn readUntilDelimiterOrEofAlloc(
169 self: Self,
170 allocator: Allocator,
171 delimiter: u8,
172 max_size: usize,
173 ) (Error || Allocator.Error || error{StreamTooLong})!?[]u8 {
174 return @errorCast(self.any().readUntilDelimiterOrEofAlloc(
175 allocator,
176 delimiter,
177 max_size,
178 ));
179 }
180
181 pub inline fn readUntilDelimiterOrEof(
182 self: Self,
183 buf: []u8,
184 delimiter: u8,
185 ) (Error || error{StreamTooLong})!?[]u8 {
186 return @errorCast(self.any().readUntilDelimiterOrEof(buf, delimiter));
187 }
188
189 pub inline fn streamUntilDelimiter(147 pub inline fn streamUntilDelimiter(
190 self: Self,148 self: Self,
191 writer: anytype,149 writer: anytype,
lib/std/Io/DeprecatedReader.zig-4
...@@ -290,7 +290,3 @@ const mem = std.mem;...@@ -290,7 +290,3 @@ const mem = std.mem;
290const testing = std.testing;290const testing = std.testing;
291const native_endian = @import("builtin").target.cpu.arch.endian();291const native_endian = @import("builtin").target.cpu.arch.endian();
292const Alignment = std.mem.Alignment;292const Alignment = std.mem.Alignment;
293
294test {
295 _ = @import("Reader/test.zig");
296}
lib/std/Io/Reader/test.zig deleted-351
...@@ -1,351 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const testing = std.testing;
4
5test "Reader" {
6 var buf = "a\x02".*;
7 var fis = std.io.fixedBufferStream(&buf);
8 const reader = fis.reader();
9 try testing.expect((try reader.readByte()) == 'a');
10 try testing.expect((try reader.readEnum(enum(u8) {
11 a = 0,
12 b = 99,
13 c = 2,
14 d = 3,
15 }, builtin.cpu.arch.endian())) == .c);
16 try testing.expectError(error.EndOfStream, reader.readByte());
17}
18
19test "isBytes" {
20 var fis = std.io.fixedBufferStream("foobar");
21 const reader = fis.reader();
22 try testing.expectEqual(true, try reader.isBytes("foo"));
23 try testing.expectEqual(false, try reader.isBytes("qux"));
24}
25
26test "skipBytes" {
27 var fis = std.io.fixedBufferStream("foobar");
28 const reader = fis.reader();
29 try reader.skipBytes(3, .{});
30 try testing.expect(try reader.isBytes("bar"));
31 try reader.skipBytes(0, .{});
32 try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{}));
33}
34
35test "readUntilDelimiterArrayList returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
36 const a = std.testing.allocator;
37 var list = std.array_list.Managed(u8).init(a);
38 defer list.deinit();
39
40 var fis = std.io.fixedBufferStream("0000\n1234\n");
41 const reader = fis.reader();
42
43 try reader.readUntilDelimiterArrayList(&list, '\n', 5);
44 try std.testing.expectEqualStrings("0000", list.items);
45 try reader.readUntilDelimiterArrayList(&list, '\n', 5);
46 try std.testing.expectEqualStrings("1234", list.items);
47 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
48}
49
50test "readUntilDelimiterArrayList returns an empty ArrayList" {
51 const a = std.testing.allocator;
52 var list = std.array_list.Managed(u8).init(a);
53 defer list.deinit();
54
55 var fis = std.io.fixedBufferStream("\n");
56 const reader = fis.reader();
57
58 try reader.readUntilDelimiterArrayList(&list, '\n', 5);
59 try std.testing.expectEqualStrings("", list.items);
60}
61
62test "readUntilDelimiterArrayList returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
63 const a = std.testing.allocator;
64 var list = std.array_list.Managed(u8).init(a);
65 defer list.deinit();
66
67 var fis = std.io.fixedBufferStream("1234567\n");
68 const reader = fis.reader();
69
70 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5));
71 try std.testing.expectEqualStrings("12345", list.items);
72 try reader.readUntilDelimiterArrayList(&list, '\n', 5);
73 try std.testing.expectEqualStrings("67", list.items);
74}
75
76test "readUntilDelimiterArrayList returns EndOfStream" {
77 const a = std.testing.allocator;
78 var list = std.array_list.Managed(u8).init(a);
79 defer list.deinit();
80
81 var fis = std.io.fixedBufferStream("1234");
82 const reader = fis.reader();
83
84 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
85 try std.testing.expectEqualStrings("1234", list.items);
86}
87
88test "readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
89 const a = std.testing.allocator;
90
91 var fis = std.io.fixedBufferStream("0000\n1234\n");
92 const reader = fis.reader();
93
94 {
95 const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
96 defer a.free(result);
97 try std.testing.expectEqualStrings("0000", result);
98 }
99
100 {
101 const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
102 defer a.free(result);
103 try std.testing.expectEqualStrings("1234", result);
104 }
105
106 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
107}
108
109test "readUntilDelimiterAlloc returns an empty ArrayList" {
110 const a = std.testing.allocator;
111
112 var fis = std.io.fixedBufferStream("\n");
113 const reader = fis.reader();
114
115 {
116 const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
117 defer a.free(result);
118 try std.testing.expectEqualStrings("", result);
119 }
120}
121
122test "readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
123 const a = std.testing.allocator;
124
125 var fis = std.io.fixedBufferStream("1234567\n");
126 const reader = fis.reader();
127
128 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5));
129
130 const result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
131 defer a.free(result);
132 try std.testing.expectEqualStrings("67", result);
133}
134
135test "readUntilDelimiterAlloc returns EndOfStream" {
136 const a = std.testing.allocator;
137
138 var fis = std.io.fixedBufferStream("1234");
139 const reader = fis.reader();
140
141 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
142}
143
144test "readUntilDelimiter returns bytes read until the delimiter" {
145 var buf: [5]u8 = undefined;
146 var fis = std.io.fixedBufferStream("0000\n1234\n");
147 const reader = fis.reader();
148 try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n'));
149 try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
150}
151
152test "readUntilDelimiter returns an empty string" {
153 var buf: [5]u8 = undefined;
154 var fis = std.io.fixedBufferStream("\n");
155 const reader = fis.reader();
156 try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
157}
158
159test "readUntilDelimiter returns StreamTooLong, then an empty string" {
160 var buf: [5]u8 = undefined;
161 var fis = std.io.fixedBufferStream("12345\n");
162 const reader = fis.reader();
163 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
164 try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
165}
166
167test "readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" {
168 var buf: [5]u8 = undefined;
169 var fis = std.io.fixedBufferStream("1234567\n");
170 const reader = fis.reader();
171 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
172 try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n'));
173}
174
175test "readUntilDelimiter returns EndOfStream" {
176 {
177 var buf: [5]u8 = undefined;
178 var fis = std.io.fixedBufferStream("");
179 const reader = fis.reader();
180 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
181 }
182 {
183 var buf: [5]u8 = undefined;
184 var fis = std.io.fixedBufferStream("1234");
185 const reader = fis.reader();
186 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
187 }
188}
189
190test "readUntilDelimiter returns bytes read until delimiter, then EndOfStream" {
191 var buf: [5]u8 = undefined;
192 var fis = std.io.fixedBufferStream("1234\n");
193 const reader = fis.reader();
194 try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
195 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
196}
197
198test "readUntilDelimiter returns StreamTooLong, then EndOfStream" {
199 var buf: [5]u8 = undefined;
200 var fis = std.io.fixedBufferStream("12345");
201 const reader = fis.reader();
202 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
203 try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
204}
205
206test "readUntilDelimiter writes all bytes read to the output buffer" {
207 var buf: [5]u8 = undefined;
208 var fis = std.io.fixedBufferStream("0000\n12345");
209 const reader = fis.reader();
210 _ = try reader.readUntilDelimiter(&buf, '\n');
211 try std.testing.expectEqualStrings("0000\n", &buf);
212 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
213 try std.testing.expectEqualStrings("12345", &buf);
214}
215
216test "readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
217 const a = std.testing.allocator;
218
219 var fis = std.io.fixedBufferStream("0000\n1234\n");
220 const reader = fis.reader();
221
222 {
223 const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
224 defer a.free(result);
225 try std.testing.expectEqualStrings("0000", result);
226 }
227
228 {
229 const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
230 defer a.free(result);
231 try std.testing.expectEqualStrings("1234", result);
232 }
233
234 try std.testing.expect((try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)) == null);
235}
236
237test "readUntilDelimiterOrEofAlloc returns an empty ArrayList" {
238 const a = std.testing.allocator;
239
240 var fis = std.io.fixedBufferStream("\n");
241 const reader = fis.reader();
242
243 {
244 const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
245 defer a.free(result);
246 try std.testing.expectEqualStrings("", result);
247 }
248}
249
250test "readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
251 const a = std.testing.allocator;
252
253 var fis = std.io.fixedBufferStream("1234567\n");
254 const reader = fis.reader();
255
256 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5));
257
258 const result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
259 defer a.free(result);
260 try std.testing.expectEqualStrings("67", result);
261}
262
263test "readUntilDelimiterOrEof returns bytes read until the delimiter" {
264 var buf: [5]u8 = undefined;
265 var fis = std.io.fixedBufferStream("0000\n1234\n");
266 const reader = fis.reader();
267 try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
268 try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
269}
270
271test "readUntilDelimiterOrEof returns an empty string" {
272 var buf: [5]u8 = undefined;
273 var fis = std.io.fixedBufferStream("\n");
274 const reader = fis.reader();
275 try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
276}
277
278test "readUntilDelimiterOrEof returns StreamTooLong, then an empty string" {
279 var buf: [5]u8 = undefined;
280 var fis = std.io.fixedBufferStream("12345\n");
281 const reader = fis.reader();
282 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
283 try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
284}
285
286test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" {
287 var buf: [5]u8 = undefined;
288 var fis = std.io.fixedBufferStream("1234567\n");
289 const reader = fis.reader();
290 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
291 try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
292}
293
294test "readUntilDelimiterOrEof returns null" {
295 var buf: [5]u8 = undefined;
296 var fis = std.io.fixedBufferStream("");
297 const reader = fis.reader();
298 try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
299}
300
301test "readUntilDelimiterOrEof returns bytes read until delimiter, then null" {
302 var buf: [5]u8 = undefined;
303 var fis = std.io.fixedBufferStream("1234\n");
304 const reader = fis.reader();
305 try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
306 try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
307}
308
309test "readUntilDelimiterOrEof returns bytes read until end-of-stream" {
310 var buf: [5]u8 = undefined;
311 var fis = std.io.fixedBufferStream("1234");
312 const reader = fis.reader();
313 try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
314}
315
316test "readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" {
317 var buf: [5]u8 = undefined;
318 var fis = std.io.fixedBufferStream("1234567");
319 const reader = fis.reader();
320 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
321 try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
322}
323
324test "readUntilDelimiterOrEof writes all bytes read to the output buffer" {
325 var buf: [5]u8 = undefined;
326 var fis = std.io.fixedBufferStream("0000\n12345");
327 const reader = fis.reader();
328 _ = try reader.readUntilDelimiterOrEof(&buf, '\n');
329 try std.testing.expectEqualStrings("0000\n", &buf);
330 try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
331 try std.testing.expectEqualStrings("12345", &buf);
332}
333
334test "streamUntilDelimiter writes all bytes without delimiter to the output" {
335 const input_string = "some_string_with_delimiter!";
336 var input_fbs = std.io.fixedBufferStream(input_string);
337 const reader = input_fbs.reader();
338
339 var output: [input_string.len]u8 = undefined;
340 var output_fbs = std.io.fixedBufferStream(&output);
341 const writer = output_fbs.writer();
342
343 try reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len);
344 try std.testing.expectEqualStrings("some_string_with_delimiter", output_fbs.getWritten());
345 try std.testing.expectError(error.EndOfStream, reader.streamUntilDelimiter(writer, '!', input_fbs.buffer.len));
346
347 input_fbs.reset();
348 output_fbs.reset();
349
350 try std.testing.expectError(error.StreamTooLong, reader.streamUntilDelimiter(writer, '!', 5));
351}
lib/std/Thread.zig+1-1
...@@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {...@@ -167,7 +167,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
167 const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });167 const file = try std.fs.cwd().openFile(path, .{ .mode = .write_only });
168 defer file.close();168 defer file.close();
169169
170 try file.deprecatedWriter().writeAll(name);170 try file.writeAll(name);
171 return;171 return;
172 },172 },
173 .windows => {173 .windows => {
lib/std/array_list.zig-54
...@@ -2041,60 +2041,6 @@ test "Managed(T) of struct T" {...@@ -2041,60 +2041,6 @@ test "Managed(T) of struct T" {
2041 }2041 }
2042}2042}
20432043
2044test "Managed(u8) implements writer" {
2045 const a = testing.allocator;
2046
2047 {
2048 var buffer = Managed(u8).init(a);
2049 defer buffer.deinit();
2050
2051 const x: i32 = 42;
2052 const y: i32 = 1234;
2053 try buffer.writer().print("x: {}\ny: {}\n", .{ x, y });
2054
2055 try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
2056 }
2057 {
2058 var list = AlignedManaged(u8, .@"2").init(a);
2059 defer list.deinit();
2060
2061 const writer = list.writer();
2062 try writer.writeAll("a");
2063 try writer.writeAll("bc");
2064 try writer.writeAll("d");
2065 try writer.writeAll("efg");
2066
2067 try testing.expectEqualSlices(u8, list.items, "abcdefg");
2068 }
2069}
2070
2071test "ArrayList(u8) implements writer" {
2072 const a = testing.allocator;
2073
2074 {
2075 var buffer: ArrayList(u8) = .empty;
2076 defer buffer.deinit(a);
2077
2078 const x: i32 = 42;
2079 const y: i32 = 1234;
2080 try buffer.writer(a).print("x: {}\ny: {}\n", .{ x, y });
2081
2082 try testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
2083 }
2084 {
2085 var list: Aligned(u8, .@"2") = .empty;
2086 defer list.deinit(a);
2087
2088 const writer = list.writer(a);
2089 try writer.writeAll("a");
2090 try writer.writeAll("bc");
2091 try writer.writeAll("d");
2092 try writer.writeAll("efg");
2093
2094 try testing.expectEqualSlices(u8, list.items, "abcdefg");
2095 }
2096}
2097
2098test "shrink still sets length when resizing is disabled" {2044test "shrink still sets length when resizing is disabled" {
2099 var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 });2045 var failing_allocator = testing.FailingAllocator.init(testing.allocator, .{ .resize_fail_index = 0 });
2100 const a = failing_allocator.allocator();2046 const a = failing_allocator.allocator();
lib/std/crypto/scrypt.zig+12-9
...@@ -304,31 +304,34 @@ const crypt_format = struct {...@@ -304,31 +304,34 @@ const crypt_format = struct {
304304
305 /// Serialize parameters into a string in modular crypt format.305 /// Serialize parameters into a string in modular crypt format.
306 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {306 pub fn serialize(params: anytype, str: []u8) EncodingError![]const u8 {
307 var buf = io.fixedBufferStream(str);307 var w: std.Io.Writer = .fixed(str);
308 try serializeTo(params, buf.writer());308 serializeTo(params, &w) catch |err| switch (err) {
309 return buf.getWritten();309 error.WriteFailed => return error.NoSpaceLeft,
310 else => |e| return e,
311 };
312 return w.buffered();
310 }313 }
311314
312 /// Compute the number of bytes required to serialize `params`315 /// Compute the number of bytes required to serialize `params`
313 pub fn calcSize(params: anytype) usize {316 pub fn calcSize(params: anytype) usize {
314 var trash: [128]u8 = undefined;317 var trash: [128]u8 = undefined;
315 var d: std.Io.Writer.Discarding = .init(&trash);318 var d: std.Io.Writer.Discarding = .init(&trash);
316 serializeTo(params, &d) catch unreachable;319 serializeTo(params, &d.writer) catch unreachable;
317 return @intCast(d.fullCount());320 return @intCast(d.fullCount());
318 }321 }
319322
320 fn serializeTo(params: anytype, out: anytype) !void {323 fn serializeTo(params: anytype, w: *std.Io.Writer) !void {
321 var header: [14]u8 = undefined;324 var header: [14]u8 = undefined;
322 header[0..3].* = prefix.*;325 header[0..3].* = prefix.*;
323 Codec.intEncode(header[3..4], params.ln);326 Codec.intEncode(header[3..4], params.ln);
324 Codec.intEncode(header[4..9], params.r);327 Codec.intEncode(header[4..9], params.r);
325 Codec.intEncode(header[9..14], params.p);328 Codec.intEncode(header[9..14], params.p);
326 try out.writeAll(&header);329 try w.writeAll(&header);
327 try out.writeAll(params.salt);330 try w.writeAll(params.salt);
328 try out.writeAll("$");331 try w.writeAll("$");
329 var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined;332 var buf: [@TypeOf(params.hash).max_encoded_length]u8 = undefined;
330 const hash_str = try params.hash.toB64(&buf);333 const hash_str = try params.hash.toB64(&buf);
331 try out.writeAll(hash_str);334 try w.writeAll(hash_str);
332 }335 }
333336
334 /// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet,337 /// Custom codec that maps 6 bits into 8 like regular Base64, but uses its own alphabet,
lib/std/debug/Dwarf/expression.zig+101-100
...@@ -8,6 +8,8 @@ const OP = std.dwarf.OP;...@@ -8,6 +8,8 @@ const OP = std.dwarf.OP;
8const abi = std.debug.Dwarf.abi;8const abi = std.debug.Dwarf.abi;
9const mem = std.mem;9const mem = std.mem;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const testing = std.testing;
12const Writer = std.Io.Writer;
1113
12/// Expressions can be evaluated in different contexts, each requiring its own set of inputs.14/// Expressions can be evaluated in different contexts, each requiring its own set of inputs.
13/// Callers should specify all the fields relevant to their context. If a field is required15/// Callers should specify all the fields relevant to their context. If a field is required
...@@ -782,7 +784,7 @@ pub fn Builder(comptime options: Options) type {...@@ -782,7 +784,7 @@ pub fn Builder(comptime options: Options) type {
782784
783 return struct {785 return struct {
784 /// Zero-operand instructions786 /// Zero-operand instructions
785 pub fn writeOpcode(writer: anytype, comptime opcode: u8) !void {787 pub fn writeOpcode(writer: *Writer, comptime opcode: u8) !void {
786 if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;788 if (options.call_frame_context and !comptime isOpcodeValidInCFA(opcode)) return error.InvalidCFAOpcode;
787 switch (opcode) {789 switch (opcode) {
788 OP.dup,790 OP.dup,
...@@ -823,14 +825,14 @@ pub fn Builder(comptime options: Options) type {...@@ -823,14 +825,14 @@ pub fn Builder(comptime options: Options) type {
823 }825 }
824826
825 // 2.5.1.1: Literal Encodings827 // 2.5.1.1: Literal Encodings
826 pub fn writeLiteral(writer: anytype, literal: u8) !void {828 pub fn writeLiteral(writer: *Writer, literal: u8) !void {
827 switch (literal) {829 switch (literal) {
828 0...31 => |n| try writer.writeByte(n + OP.lit0),830 0...31 => |n| try writer.writeByte(n + OP.lit0),
829 else => return error.InvalidLiteral,831 else => return error.InvalidLiteral,
830 }832 }
831 }833 }
832834
833 pub fn writeConst(writer: anytype, comptime T: type, value: T) !void {835 pub fn writeConst(writer: *Writer, comptime T: type, value: T) !void {
834 if (@typeInfo(T) != .int) @compileError("Constants must be integers");836 if (@typeInfo(T) != .int) @compileError("Constants must be integers");
835837
836 switch (T) {838 switch (T) {
...@@ -852,7 +854,7 @@ pub fn Builder(comptime options: Options) type {...@@ -852,7 +854,7 @@ pub fn Builder(comptime options: Options) type {
852 else => switch (@typeInfo(T).int.signedness) {854 else => switch (@typeInfo(T).int.signedness) {
853 .unsigned => {855 .unsigned => {
854 try writer.writeByte(OP.constu);856 try writer.writeByte(OP.constu);
855 try leb.writeUleb128(writer, value);857 try writer.writeUleb128(value);
856 },858 },
857 .signed => {859 .signed => {
858 try writer.writeByte(OP.consts);860 try writer.writeByte(OP.consts);
...@@ -862,105 +864,105 @@ pub fn Builder(comptime options: Options) type {...@@ -862,105 +864,105 @@ pub fn Builder(comptime options: Options) type {
862 }864 }
863 }865 }
864866
865 pub fn writeConstx(writer: anytype, debug_addr_offset: anytype) !void {867 pub fn writeConstx(writer: *Writer, debug_addr_offset: anytype) !void {
866 try writer.writeByte(OP.constx);868 try writer.writeByte(OP.constx);
867 try leb.writeUleb128(writer, debug_addr_offset);869 try writer.writeUleb128(debug_addr_offset);
868 }870 }
869871
870 pub fn writeConstType(writer: anytype, die_offset: anytype, value_bytes: []const u8) !void {872 pub fn writeConstType(writer: *Writer, die_offset: anytype, value_bytes: []const u8) !void {
871 if (options.call_frame_context) return error.InvalidCFAOpcode;873 if (options.call_frame_context) return error.InvalidCFAOpcode;
872 if (value_bytes.len > 0xff) return error.InvalidTypeLength;874 if (value_bytes.len > 0xff) return error.InvalidTypeLength;
873 try writer.writeByte(OP.const_type);875 try writer.writeByte(OP.const_type);
874 try leb.writeUleb128(writer, die_offset);876 try writer.writeUleb128(die_offset);
875 try writer.writeByte(@intCast(value_bytes.len));877 try writer.writeByte(@intCast(value_bytes.len));
876 try writer.writeAll(value_bytes);878 try writer.writeAll(value_bytes);
877 }879 }
878880
879 pub fn writeAddr(writer: anytype, value: addr_type) !void {881 pub fn writeAddr(writer: *Writer, value: addr_type) !void {
880 try writer.writeByte(OP.addr);882 try writer.writeByte(OP.addr);
881 try writer.writeInt(addr_type, value, options.endian);883 try writer.writeInt(addr_type, value, options.endian);
882 }884 }
883885
884 pub fn writeAddrx(writer: anytype, debug_addr_offset: anytype) !void {886 pub fn writeAddrx(writer: *Writer, debug_addr_offset: anytype) !void {
885 if (options.call_frame_context) return error.InvalidCFAOpcode;887 if (options.call_frame_context) return error.InvalidCFAOpcode;
886 try writer.writeByte(OP.addrx);888 try writer.writeByte(OP.addrx);
887 try leb.writeUleb128(writer, debug_addr_offset);889 try writer.writeUleb128(debug_addr_offset);
888 }890 }
889891
890 // 2.5.1.2: Register Values892 // 2.5.1.2: Register Values
891 pub fn writeFbreg(writer: anytype, offset: anytype) !void {893 pub fn writeFbreg(writer: *Writer, offset: anytype) !void {
892 try writer.writeByte(OP.fbreg);894 try writer.writeByte(OP.fbreg);
893 try leb.writeIleb128(writer, offset);895 try leb.writeIleb128(writer, offset);
894 }896 }
895897
896 pub fn writeBreg(writer: anytype, register: u8, offset: anytype) !void {898 pub fn writeBreg(writer: *Writer, register: u8, offset: anytype) !void {
897 if (register > 31) return error.InvalidRegister;899 if (register > 31) return error.InvalidRegister;
898 try writer.writeByte(OP.breg0 + register);900 try writer.writeByte(OP.breg0 + register);
899 try leb.writeIleb128(writer, offset);901 try leb.writeIleb128(writer, offset);
900 }902 }
901903
902 pub fn writeBregx(writer: anytype, register: anytype, offset: anytype) !void {904 pub fn writeBregx(writer: *Writer, register: anytype, offset: anytype) !void {
903 try writer.writeByte(OP.bregx);905 try writer.writeByte(OP.bregx);
904 try leb.writeUleb128(writer, register);906 try writer.writeUleb128(register);
905 try leb.writeIleb128(writer, offset);907 try leb.writeIleb128(writer, offset);
906 }908 }
907909
908 pub fn writeRegvalType(writer: anytype, register: anytype, offset: anytype) !void {910 pub fn writeRegvalType(writer: *Writer, register: anytype, offset: anytype) !void {
909 if (options.call_frame_context) return error.InvalidCFAOpcode;911 if (options.call_frame_context) return error.InvalidCFAOpcode;
910 try writer.writeByte(OP.regval_type);912 try writer.writeByte(OP.regval_type);
911 try leb.writeUleb128(writer, register);913 try writer.writeUleb128(register);
912 try leb.writeUleb128(writer, offset);914 try writer.writeUleb128(offset);
913 }915 }
914916
915 // 2.5.1.3: Stack Operations917 // 2.5.1.3: Stack Operations
916 pub fn writePick(writer: anytype, index: u8) !void {918 pub fn writePick(writer: *Writer, index: u8) !void {
917 try writer.writeByte(OP.pick);919 try writer.writeByte(OP.pick);
918 try writer.writeByte(index);920 try writer.writeByte(index);
919 }921 }
920922
921 pub fn writeDerefSize(writer: anytype, size: u8) !void {923 pub fn writeDerefSize(writer: *Writer, size: u8) !void {
922 try writer.writeByte(OP.deref_size);924 try writer.writeByte(OP.deref_size);
923 try writer.writeByte(size);925 try writer.writeByte(size);
924 }926 }
925927
926 pub fn writeXDerefSize(writer: anytype, size: u8) !void {928 pub fn writeXDerefSize(writer: *Writer, size: u8) !void {
927 try writer.writeByte(OP.xderef_size);929 try writer.writeByte(OP.xderef_size);
928 try writer.writeByte(size);930 try writer.writeByte(size);
929 }931 }
930932
931 pub fn writeDerefType(writer: anytype, size: u8, die_offset: anytype) !void {933 pub fn writeDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
932 if (options.call_frame_context) return error.InvalidCFAOpcode;934 if (options.call_frame_context) return error.InvalidCFAOpcode;
933 try writer.writeByte(OP.deref_type);935 try writer.writeByte(OP.deref_type);
934 try writer.writeByte(size);936 try writer.writeByte(size);
935 try leb.writeUleb128(writer, die_offset);937 try writer.writeUleb128(die_offset);
936 }938 }
937939
938 pub fn writeXDerefType(writer: anytype, size: u8, die_offset: anytype) !void {940 pub fn writeXDerefType(writer: *Writer, size: u8, die_offset: anytype) !void {
939 try writer.writeByte(OP.xderef_type);941 try writer.writeByte(OP.xderef_type);
940 try writer.writeByte(size);942 try writer.writeByte(size);
941 try leb.writeUleb128(writer, die_offset);943 try writer.writeUleb128(die_offset);
942 }944 }
943945
944 // 2.5.1.4: Arithmetic and Logical Operations946 // 2.5.1.4: Arithmetic and Logical Operations
945947
946 pub fn writePlusUconst(writer: anytype, uint_value: anytype) !void {948 pub fn writePlusUconst(writer: *Writer, uint_value: anytype) !void {
947 try writer.writeByte(OP.plus_uconst);949 try writer.writeByte(OP.plus_uconst);
948 try leb.writeUleb128(writer, uint_value);950 try writer.writeUleb128(uint_value);
949 }951 }
950952
951 // 2.5.1.5: Control Flow Operations953 // 2.5.1.5: Control Flow Operations
952954
953 pub fn writeSkip(writer: anytype, offset: i16) !void {955 pub fn writeSkip(writer: *Writer, offset: i16) !void {
954 try writer.writeByte(OP.skip);956 try writer.writeByte(OP.skip);
955 try writer.writeInt(i16, offset, options.endian);957 try writer.writeInt(i16, offset, options.endian);
956 }958 }
957959
958 pub fn writeBra(writer: anytype, offset: i16) !void {960 pub fn writeBra(writer: *Writer, offset: i16) !void {
959 try writer.writeByte(OP.bra);961 try writer.writeByte(OP.bra);
960 try writer.writeInt(i16, offset, options.endian);962 try writer.writeInt(i16, offset, options.endian);
961 }963 }
962964
963 pub fn writeCall(writer: anytype, comptime T: type, offset: T) !void {965 pub fn writeCall(writer: *Writer, comptime T: type, offset: T) !void {
964 if (options.call_frame_context) return error.InvalidCFAOpcode;966 if (options.call_frame_context) return error.InvalidCFAOpcode;
965 switch (T) {967 switch (T) {
966 u16 => try writer.writeByte(OP.call2),968 u16 => try writer.writeByte(OP.call2),
...@@ -971,45 +973,45 @@ pub fn Builder(comptime options: Options) type {...@@ -971,45 +973,45 @@ pub fn Builder(comptime options: Options) type {
971 try writer.writeInt(T, offset, options.endian);973 try writer.writeInt(T, offset, options.endian);
972 }974 }
973975
974 pub fn writeCallRef(writer: anytype, comptime is_64: bool, value: if (is_64) u64 else u32) !void {976 pub fn writeCallRef(writer: *Writer, comptime is_64: bool, value: if (is_64) u64 else u32) !void {
975 if (options.call_frame_context) return error.InvalidCFAOpcode;977 if (options.call_frame_context) return error.InvalidCFAOpcode;
976 try writer.writeByte(OP.call_ref);978 try writer.writeByte(OP.call_ref);
977 try writer.writeInt(if (is_64) u64 else u32, value, options.endian);979 try writer.writeInt(if (is_64) u64 else u32, value, options.endian);
978 }980 }
979981
980 pub fn writeConvert(writer: anytype, die_offset: anytype) !void {982 pub fn writeConvert(writer: *Writer, die_offset: anytype) !void {
981 if (options.call_frame_context) return error.InvalidCFAOpcode;983 if (options.call_frame_context) return error.InvalidCFAOpcode;
982 try writer.writeByte(OP.convert);984 try writer.writeByte(OP.convert);
983 try leb.writeUleb128(writer, die_offset);985 try writer.writeUleb128(die_offset);
984 }986 }
985987
986 pub fn writeReinterpret(writer: anytype, die_offset: anytype) !void {988 pub fn writeReinterpret(writer: *Writer, die_offset: anytype) !void {
987 if (options.call_frame_context) return error.InvalidCFAOpcode;989 if (options.call_frame_context) return error.InvalidCFAOpcode;
988 try writer.writeByte(OP.reinterpret);990 try writer.writeByte(OP.reinterpret);
989 try leb.writeUleb128(writer, die_offset);991 try writer.writeUleb128(die_offset);
990 }992 }
991993
992 // 2.5.1.7: Special Operations994 // 2.5.1.7: Special Operations
993995
994 pub fn writeEntryValue(writer: anytype, expression: []const u8) !void {996 pub fn writeEntryValue(writer: *Writer, expression: []const u8) !void {
995 try writer.writeByte(OP.entry_value);997 try writer.writeByte(OP.entry_value);
996 try leb.writeUleb128(writer, expression.len);998 try writer.writeUleb128(expression.len);
997 try writer.writeAll(expression);999 try writer.writeAll(expression);
998 }1000 }
9991001
1000 // 2.6: Location Descriptions1002 // 2.6: Location Descriptions
1001 pub fn writeReg(writer: anytype, register: u8) !void {1003 pub fn writeReg(writer: *Writer, register: u8) !void {
1002 try writer.writeByte(OP.reg0 + register);1004 try writer.writeByte(OP.reg0 + register);
1003 }1005 }
10041006
1005 pub fn writeRegx(writer: anytype, register: anytype) !void {1007 pub fn writeRegx(writer: *Writer, register: anytype) !void {
1006 try writer.writeByte(OP.regx);1008 try writer.writeByte(OP.regx);
1007 try leb.writeUleb128(writer, register);1009 try writer.writeUleb128(register);
1008 }1010 }
10091011
1010 pub fn writeImplicitValue(writer: anytype, value_bytes: []const u8) !void {1012 pub fn writeImplicitValue(writer: *Writer, value_bytes: []const u8) !void {
1011 try writer.writeByte(OP.implicit_value);1013 try writer.writeByte(OP.implicit_value);
1012 try leb.writeUleb128(writer, value_bytes.len);1014 try writer.writeUleb128(value_bytes.len);
1013 try writer.writeAll(value_bytes);1015 try writer.writeAll(value_bytes);
1014 }1016 }
1015 };1017 };
...@@ -1042,8 +1044,7 @@ fn isOpcodeRegisterLocation(opcode: u8) bool {...@@ -1042,8 +1044,7 @@ fn isOpcodeRegisterLocation(opcode: u8) bool {
1042 };1044 };
1043}1045}
10441046
1045const testing = std.testing;1047test "basics" {
1046test "DWARF expressions" {
1047 const allocator = std.testing.allocator;1048 const allocator = std.testing.allocator;
10481049
1049 const options = Options{};1050 const options = Options{};
...@@ -1052,10 +1053,10 @@ test "DWARF expressions" {...@@ -1052,10 +1053,10 @@ test "DWARF expressions" {
10521053
1053 const b = Builder(options);1054 const b = Builder(options);
10541055
1055 var program = std.array_list.Managed(u8).init(allocator);1056 var program: std.Io.Writer.Allocating = .init(allocator);
1056 defer program.deinit();1057 defer program.deinit();
10571058
1058 const writer = program.writer();1059 const writer = &program.writer;
10591060
1060 // Literals1061 // Literals
1061 {1062 {
...@@ -1064,7 +1065,7 @@ test "DWARF expressions" {...@@ -1064,7 +1065,7 @@ test "DWARF expressions" {
1064 try b.writeLiteral(writer, @intCast(i));1065 try b.writeLiteral(writer, @intCast(i));
1065 }1066 }
10661067
1067 _ = try stack_machine.run(program.items, allocator, context, 0);1068 _ = try stack_machine.run(program.written(), allocator, context, 0);
10681069
1069 for (0..32) |i| {1070 for (0..32) |i| {
1070 const expected = 31 - i;1071 const expected = 31 - i;
...@@ -1108,16 +1109,16 @@ test "DWARF expressions" {...@@ -1108,16 +1109,16 @@ test "DWARF expressions" {
1108 var mock_compile_unit: std.debug.Dwarf.CompileUnit = undefined;1109 var mock_compile_unit: std.debug.Dwarf.CompileUnit = undefined;
1109 mock_compile_unit.addr_base = 1;1110 mock_compile_unit.addr_base = 1;
11101111
1111 var mock_debug_addr = std.array_list.Managed(u8).init(allocator);1112 var mock_debug_addr: std.Io.Writer.Allocating = .init(allocator);
1112 defer mock_debug_addr.deinit();1113 defer mock_debug_addr.deinit();
11131114
1114 try mock_debug_addr.writer().writeInt(u16, 0, native_endian);1115 try mock_debug_addr.writer.writeInt(u16, 0, native_endian);
1115 try mock_debug_addr.writer().writeInt(usize, input[11], native_endian);1116 try mock_debug_addr.writer.writeInt(usize, input[11], native_endian);
1116 try mock_debug_addr.writer().writeInt(usize, input[12], native_endian);1117 try mock_debug_addr.writer.writeInt(usize, input[12], native_endian);
11171118
1118 const context = Context{1119 const context: Context = .{
1119 .compile_unit = &mock_compile_unit,1120 .compile_unit = &mock_compile_unit,
1120 .debug_addr = mock_debug_addr.items,1121 .debug_addr = mock_debug_addr.written(),
1121 };1122 };
11221123
1123 try b.writeConstx(writer, @as(usize, 1));1124 try b.writeConstx(writer, @as(usize, 1));
...@@ -1127,7 +1128,7 @@ test "DWARF expressions" {...@@ -1127,7 +1128,7 @@ test "DWARF expressions" {
1127 const type_bytes: []const u8 = &.{ 1, 2, 3, 4 };1128 const type_bytes: []const u8 = &.{ 1, 2, 3, 4 };
1128 try b.writeConstType(writer, die_offset, type_bytes);1129 try b.writeConstType(writer, die_offset, type_bytes);
11291130
1130 _ = try stack_machine.run(program.items, allocator, context, 0);1131 _ = try stack_machine.run(program.written(), allocator, context, 0);
11311132
1132 const const_type = stack_machine.stack.pop().?.const_type;1133 const const_type = stack_machine.stack.pop().?.const_type;
1133 try testing.expectEqual(die_offset, const_type.type_offset);1134 try testing.expectEqual(die_offset, const_type.type_offset);
...@@ -1185,7 +1186,7 @@ test "DWARF expressions" {...@@ -1185,7 +1186,7 @@ test "DWARF expressions" {
1185 try b.writeBregx(writer, abi.ipRegNum(native_arch).?, @as(usize, 300));1186 try b.writeBregx(writer, abi.ipRegNum(native_arch).?, @as(usize, 300));
1186 try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400));1187 try b.writeRegvalType(writer, @as(u8, 0), @as(usize, 400));
11871188
1188 _ = try stack_machine.run(program.items, allocator, context, 0);1189 _ = try stack_machine.run(program.written(), allocator, context, 0);
11891190
1190 const regval_type = stack_machine.stack.pop().?.regval_type;1191 const regval_type = stack_machine.stack.pop().?.regval_type;
1191 try testing.expectEqual(@as(usize, 400), regval_type.type_offset);1192 try testing.expectEqual(@as(usize, 400), regval_type.type_offset);
...@@ -1214,7 +1215,7 @@ test "DWARF expressions" {...@@ -1214,7 +1215,7 @@ test "DWARF expressions" {
1214 program.clearRetainingCapacity();1215 program.clearRetainingCapacity();
1215 try b.writeConst(writer, u8, 1);1216 try b.writeConst(writer, u8, 1);
1216 try b.writeOpcode(writer, OP.dup);1217 try b.writeOpcode(writer, OP.dup);
1217 _ = try stack_machine.run(program.items, allocator, context, null);1218 _ = try stack_machine.run(program.written(), allocator, context, null);
1218 try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);1219 try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);
1219 try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);1220 try testing.expectEqual(@as(usize, 1), stack_machine.stack.pop().?.generic);
12201221
...@@ -1222,7 +1223,7 @@ test "DWARF expressions" {...@@ -1222,7 +1223,7 @@ test "DWARF expressions" {
1222 program.clearRetainingCapacity();1223 program.clearRetainingCapacity();
1223 try b.writeConst(writer, u8, 1);1224 try b.writeConst(writer, u8, 1);
1224 try b.writeOpcode(writer, OP.drop);1225 try b.writeOpcode(writer, OP.drop);
1225 _ = try stack_machine.run(program.items, allocator, context, null);1226 _ = try stack_machine.run(program.written(), allocator, context, null);
1226 try testing.expect(stack_machine.stack.pop() == null);1227 try testing.expect(stack_machine.stack.pop() == null);
12271228
1228 stack_machine.reset();1229 stack_machine.reset();
...@@ -1231,7 +1232,7 @@ test "DWARF expressions" {...@@ -1231,7 +1232,7 @@ test "DWARF expressions" {
1231 try b.writeConst(writer, u8, 5);1232 try b.writeConst(writer, u8, 5);
1232 try b.writeConst(writer, u8, 6);1233 try b.writeConst(writer, u8, 6);
1233 try b.writePick(writer, 2);1234 try b.writePick(writer, 2);
1234 _ = try stack_machine.run(program.items, allocator, context, null);1235 _ = try stack_machine.run(program.written(), allocator, context, null);
1235 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);1236 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
12361237
1237 stack_machine.reset();1238 stack_machine.reset();
...@@ -1240,7 +1241,7 @@ test "DWARF expressions" {...@@ -1240,7 +1241,7 @@ test "DWARF expressions" {
1240 try b.writeConst(writer, u8, 5);1241 try b.writeConst(writer, u8, 5);
1241 try b.writeConst(writer, u8, 6);1242 try b.writeConst(writer, u8, 6);
1242 try b.writeOpcode(writer, OP.over);1243 try b.writeOpcode(writer, OP.over);
1243 _ = try stack_machine.run(program.items, allocator, context, null);1244 _ = try stack_machine.run(program.written(), allocator, context, null);
1244 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);1245 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
12451246
1246 stack_machine.reset();1247 stack_machine.reset();
...@@ -1248,7 +1249,7 @@ test "DWARF expressions" {...@@ -1248,7 +1249,7 @@ test "DWARF expressions" {
1248 try b.writeConst(writer, u8, 5);1249 try b.writeConst(writer, u8, 5);
1249 try b.writeConst(writer, u8, 6);1250 try b.writeConst(writer, u8, 6);
1250 try b.writeOpcode(writer, OP.swap);1251 try b.writeOpcode(writer, OP.swap);
1251 _ = try stack_machine.run(program.items, allocator, context, null);1252 _ = try stack_machine.run(program.written(), allocator, context, null);
1252 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);1253 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
1253 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);1254 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
12541255
...@@ -1258,7 +1259,7 @@ test "DWARF expressions" {...@@ -1258,7 +1259,7 @@ test "DWARF expressions" {
1258 try b.writeConst(writer, u8, 5);1259 try b.writeConst(writer, u8, 5);
1259 try b.writeConst(writer, u8, 6);1260 try b.writeConst(writer, u8, 6);
1260 try b.writeOpcode(writer, OP.rot);1261 try b.writeOpcode(writer, OP.rot);
1261 _ = try stack_machine.run(program.items, allocator, context, null);1262 _ = try stack_machine.run(program.written(), allocator, context, null);
1262 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);1263 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
1263 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);1264 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
1264 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);1265 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
...@@ -1269,7 +1270,7 @@ test "DWARF expressions" {...@@ -1269,7 +1270,7 @@ test "DWARF expressions" {
1269 program.clearRetainingCapacity();1270 program.clearRetainingCapacity();
1270 try b.writeAddr(writer, @intFromPtr(&deref_target));1271 try b.writeAddr(writer, @intFromPtr(&deref_target));
1271 try b.writeOpcode(writer, OP.deref);1272 try b.writeOpcode(writer, OP.deref);
1272 _ = try stack_machine.run(program.items, allocator, context, null);1273 _ = try stack_machine.run(program.written(), allocator, context, null);
1273 try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);1274 try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);
12741275
1275 stack_machine.reset();1276 stack_machine.reset();
...@@ -1277,14 +1278,14 @@ test "DWARF expressions" {...@@ -1277,14 +1278,14 @@ test "DWARF expressions" {
1277 try b.writeLiteral(writer, 0);1278 try b.writeLiteral(writer, 0);
1278 try b.writeAddr(writer, @intFromPtr(&deref_target));1279 try b.writeAddr(writer, @intFromPtr(&deref_target));
1279 try b.writeOpcode(writer, OP.xderef);1280 try b.writeOpcode(writer, OP.xderef);
1280 _ = try stack_machine.run(program.items, allocator, context, null);1281 _ = try stack_machine.run(program.written(), allocator, context, null);
1281 try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);1282 try testing.expectEqual(deref_target, stack_machine.stack.pop().?.generic);
12821283
1283 stack_machine.reset();1284 stack_machine.reset();
1284 program.clearRetainingCapacity();1285 program.clearRetainingCapacity();
1285 try b.writeAddr(writer, @intFromPtr(&deref_target));1286 try b.writeAddr(writer, @intFromPtr(&deref_target));
1286 try b.writeDerefSize(writer, 1);1287 try b.writeDerefSize(writer, 1);
1287 _ = try stack_machine.run(program.items, allocator, context, null);1288 _ = try stack_machine.run(program.written(), allocator, context, null);
1288 try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);1289 try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);
12891290
1290 stack_machine.reset();1291 stack_machine.reset();
...@@ -1292,7 +1293,7 @@ test "DWARF expressions" {...@@ -1292,7 +1293,7 @@ test "DWARF expressions" {
1292 try b.writeLiteral(writer, 0);1293 try b.writeLiteral(writer, 0);
1293 try b.writeAddr(writer, @intFromPtr(&deref_target));1294 try b.writeAddr(writer, @intFromPtr(&deref_target));
1294 try b.writeXDerefSize(writer, 1);1295 try b.writeXDerefSize(writer, 1);
1295 _ = try stack_machine.run(program.items, allocator, context, null);1296 _ = try stack_machine.run(program.written(), allocator, context, null);
1296 try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);1297 try testing.expectEqual(@as(usize, @as(*const u8, @ptrCast(&deref_target)).*), stack_machine.stack.pop().?.generic);
12971298
1298 const type_offset: usize = @truncate(0xaabbaabb_aabbaabb);1299 const type_offset: usize = @truncate(0xaabbaabb_aabbaabb);
...@@ -1301,7 +1302,7 @@ test "DWARF expressions" {...@@ -1301,7 +1302,7 @@ test "DWARF expressions" {
1301 program.clearRetainingCapacity();1302 program.clearRetainingCapacity();
1302 try b.writeAddr(writer, @intFromPtr(&deref_target));1303 try b.writeAddr(writer, @intFromPtr(&deref_target));
1303 try b.writeDerefType(writer, 1, type_offset);1304 try b.writeDerefType(writer, 1, type_offset);
1304 _ = try stack_machine.run(program.items, allocator, context, null);1305 _ = try stack_machine.run(program.written(), allocator, context, null);
1305 const deref_type = stack_machine.stack.pop().?.regval_type;1306 const deref_type = stack_machine.stack.pop().?.regval_type;
1306 try testing.expectEqual(type_offset, deref_type.type_offset);1307 try testing.expectEqual(type_offset, deref_type.type_offset);
1307 try testing.expectEqual(@as(u8, 1), deref_type.type_size);1308 try testing.expectEqual(@as(u8, 1), deref_type.type_size);
...@@ -1312,7 +1313,7 @@ test "DWARF expressions" {...@@ -1312,7 +1313,7 @@ test "DWARF expressions" {
1312 try b.writeLiteral(writer, 0);1313 try b.writeLiteral(writer, 0);
1313 try b.writeAddr(writer, @intFromPtr(&deref_target));1314 try b.writeAddr(writer, @intFromPtr(&deref_target));
1314 try b.writeXDerefType(writer, 1, type_offset);1315 try b.writeXDerefType(writer, 1, type_offset);
1315 _ = try stack_machine.run(program.items, allocator, context, null);1316 _ = try stack_machine.run(program.written(), allocator, context, null);
1316 const xderef_type = stack_machine.stack.pop().?.regval_type;1317 const xderef_type = stack_machine.stack.pop().?.regval_type;
1317 try testing.expectEqual(type_offset, xderef_type.type_offset);1318 try testing.expectEqual(type_offset, xderef_type.type_offset);
1318 try testing.expectEqual(@as(u8, 1), xderef_type.type_size);1319 try testing.expectEqual(@as(u8, 1), xderef_type.type_size);
...@@ -1323,7 +1324,7 @@ test "DWARF expressions" {...@@ -1323,7 +1324,7 @@ test "DWARF expressions" {
1323 stack_machine.reset();1324 stack_machine.reset();
1324 program.clearRetainingCapacity();1325 program.clearRetainingCapacity();
1325 try b.writeOpcode(writer, OP.push_object_address);1326 try b.writeOpcode(writer, OP.push_object_address);
1326 _ = try stack_machine.run(program.items, allocator, context, null);1327 _ = try stack_machine.run(program.written(), allocator, context, null);
1327 try testing.expectEqual(@as(usize, @intFromPtr(context.object_address.?)), stack_machine.stack.pop().?.generic);1328 try testing.expectEqual(@as(usize, @intFromPtr(context.object_address.?)), stack_machine.stack.pop().?.generic);
13281329
1329 // TODO: Test OP.form_tls_address1330 // TODO: Test OP.form_tls_address
...@@ -1333,7 +1334,7 @@ test "DWARF expressions" {...@@ -1333,7 +1334,7 @@ test "DWARF expressions" {
1333 stack_machine.reset();1334 stack_machine.reset();
1334 program.clearRetainingCapacity();1335 program.clearRetainingCapacity();
1335 try b.writeOpcode(writer, OP.call_frame_cfa);1336 try b.writeOpcode(writer, OP.call_frame_cfa);
1336 _ = try stack_machine.run(program.items, allocator, context, null);1337 _ = try stack_machine.run(program.written(), allocator, context, null);
1337 try testing.expectEqual(context.cfa.?, stack_machine.stack.pop().?.generic);1338 try testing.expectEqual(context.cfa.?, stack_machine.stack.pop().?.generic);
1338 }1339 }
13391340
...@@ -1345,7 +1346,7 @@ test "DWARF expressions" {...@@ -1345,7 +1346,7 @@ test "DWARF expressions" {
1345 program.clearRetainingCapacity();1346 program.clearRetainingCapacity();
1346 try b.writeConst(writer, i16, -4096);1347 try b.writeConst(writer, i16, -4096);
1347 try b.writeOpcode(writer, OP.abs);1348 try b.writeOpcode(writer, OP.abs);
1348 _ = try stack_machine.run(program.items, allocator, context, null);1349 _ = try stack_machine.run(program.written(), allocator, context, null);
1349 try testing.expectEqual(@as(usize, 4096), stack_machine.stack.pop().?.generic);1350 try testing.expectEqual(@as(usize, 4096), stack_machine.stack.pop().?.generic);
13501351
1351 stack_machine.reset();1352 stack_machine.reset();
...@@ -1353,7 +1354,7 @@ test "DWARF expressions" {...@@ -1353,7 +1354,7 @@ test "DWARF expressions" {
1353 try b.writeConst(writer, u16, 0xff0f);1354 try b.writeConst(writer, u16, 0xff0f);
1354 try b.writeConst(writer, u16, 0xf0ff);1355 try b.writeConst(writer, u16, 0xf0ff);
1355 try b.writeOpcode(writer, OP.@"and");1356 try b.writeOpcode(writer, OP.@"and");
1356 _ = try stack_machine.run(program.items, allocator, context, null);1357 _ = try stack_machine.run(program.written(), allocator, context, null);
1357 try testing.expectEqual(@as(usize, 0xf00f), stack_machine.stack.pop().?.generic);1358 try testing.expectEqual(@as(usize, 0xf00f), stack_machine.stack.pop().?.generic);
13581359
1359 stack_machine.reset();1360 stack_machine.reset();
...@@ -1361,7 +1362,7 @@ test "DWARF expressions" {...@@ -1361,7 +1362,7 @@ test "DWARF expressions" {
1361 try b.writeConst(writer, i16, -404);1362 try b.writeConst(writer, i16, -404);
1362 try b.writeConst(writer, i16, 100);1363 try b.writeConst(writer, i16, 100);
1363 try b.writeOpcode(writer, OP.div);1364 try b.writeOpcode(writer, OP.div);
1364 _ = try stack_machine.run(program.items, allocator, context, null);1365 _ = try stack_machine.run(program.written(), allocator, context, null);
1365 try testing.expectEqual(@as(isize, -404 / 100), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));1366 try testing.expectEqual(@as(isize, -404 / 100), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));
13661367
1367 stack_machine.reset();1368 stack_machine.reset();
...@@ -1369,7 +1370,7 @@ test "DWARF expressions" {...@@ -1369,7 +1370,7 @@ test "DWARF expressions" {
1369 try b.writeConst(writer, u16, 200);1370 try b.writeConst(writer, u16, 200);
1370 try b.writeConst(writer, u16, 50);1371 try b.writeConst(writer, u16, 50);
1371 try b.writeOpcode(writer, OP.minus);1372 try b.writeOpcode(writer, OP.minus);
1372 _ = try stack_machine.run(program.items, allocator, context, null);1373 _ = try stack_machine.run(program.written(), allocator, context, null);
1373 try testing.expectEqual(@as(usize, 150), stack_machine.stack.pop().?.generic);1374 try testing.expectEqual(@as(usize, 150), stack_machine.stack.pop().?.generic);
13741375
1375 stack_machine.reset();1376 stack_machine.reset();
...@@ -1377,7 +1378,7 @@ test "DWARF expressions" {...@@ -1377,7 +1378,7 @@ test "DWARF expressions" {
1377 try b.writeConst(writer, u16, 123);1378 try b.writeConst(writer, u16, 123);
1378 try b.writeConst(writer, u16, 100);1379 try b.writeConst(writer, u16, 100);
1379 try b.writeOpcode(writer, OP.mod);1380 try b.writeOpcode(writer, OP.mod);
1380 _ = try stack_machine.run(program.items, allocator, context, null);1381 _ = try stack_machine.run(program.written(), allocator, context, null);
1381 try testing.expectEqual(@as(usize, 23), stack_machine.stack.pop().?.generic);1382 try testing.expectEqual(@as(usize, 23), stack_machine.stack.pop().?.generic);
13821383
1383 stack_machine.reset();1384 stack_machine.reset();
...@@ -1385,7 +1386,7 @@ test "DWARF expressions" {...@@ -1385,7 +1386,7 @@ test "DWARF expressions" {
1385 try b.writeConst(writer, u16, 0xff);1386 try b.writeConst(writer, u16, 0xff);
1386 try b.writeConst(writer, u16, 0xee);1387 try b.writeConst(writer, u16, 0xee);
1387 try b.writeOpcode(writer, OP.mul);1388 try b.writeOpcode(writer, OP.mul);
1388 _ = try stack_machine.run(program.items, allocator, context, null);1389 _ = try stack_machine.run(program.written(), allocator, context, null);
1389 try testing.expectEqual(@as(usize, 0xed12), stack_machine.stack.pop().?.generic);1390 try testing.expectEqual(@as(usize, 0xed12), stack_machine.stack.pop().?.generic);
13901391
1391 stack_machine.reset();1392 stack_machine.reset();
...@@ -1394,7 +1395,7 @@ test "DWARF expressions" {...@@ -1394,7 +1395,7 @@ test "DWARF expressions" {
1394 try b.writeOpcode(writer, OP.neg);1395 try b.writeOpcode(writer, OP.neg);
1395 try b.writeConst(writer, i16, -6);1396 try b.writeConst(writer, i16, -6);
1396 try b.writeOpcode(writer, OP.neg);1397 try b.writeOpcode(writer, OP.neg);
1397 _ = try stack_machine.run(program.items, allocator, context, null);1398 _ = try stack_machine.run(program.written(), allocator, context, null);
1398 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);1399 try testing.expectEqual(@as(usize, 6), stack_machine.stack.pop().?.generic);
1399 try testing.expectEqual(@as(isize, -5), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));1400 try testing.expectEqual(@as(isize, -5), @as(isize, @bitCast(stack_machine.stack.pop().?.generic)));
14001401
...@@ -1402,7 +1403,7 @@ test "DWARF expressions" {...@@ -1402,7 +1403,7 @@ test "DWARF expressions" {
1402 program.clearRetainingCapacity();1403 program.clearRetainingCapacity();
1403 try b.writeConst(writer, u16, 0xff0f);1404 try b.writeConst(writer, u16, 0xff0f);
1404 try b.writeOpcode(writer, OP.not);1405 try b.writeOpcode(writer, OP.not);
1405 _ = try stack_machine.run(program.items, allocator, context, null);1406 _ = try stack_machine.run(program.written(), allocator, context, null);
1406 try testing.expectEqual(~@as(usize, 0xff0f), stack_machine.stack.pop().?.generic);1407 try testing.expectEqual(~@as(usize, 0xff0f), stack_machine.stack.pop().?.generic);
14071408
1408 stack_machine.reset();1409 stack_machine.reset();
...@@ -1410,7 +1411,7 @@ test "DWARF expressions" {...@@ -1410,7 +1411,7 @@ test "DWARF expressions" {
1410 try b.writeConst(writer, u16, 0xff0f);1411 try b.writeConst(writer, u16, 0xff0f);
1411 try b.writeConst(writer, u16, 0xf0ff);1412 try b.writeConst(writer, u16, 0xf0ff);
1412 try b.writeOpcode(writer, OP.@"or");1413 try b.writeOpcode(writer, OP.@"or");
1413 _ = try stack_machine.run(program.items, allocator, context, null);1414 _ = try stack_machine.run(program.written(), allocator, context, null);
1414 try testing.expectEqual(@as(usize, 0xffff), stack_machine.stack.pop().?.generic);1415 try testing.expectEqual(@as(usize, 0xffff), stack_machine.stack.pop().?.generic);
14151416
1416 stack_machine.reset();1417 stack_machine.reset();
...@@ -1418,14 +1419,14 @@ test "DWARF expressions" {...@@ -1418,14 +1419,14 @@ test "DWARF expressions" {
1418 try b.writeConst(writer, i16, 402);1419 try b.writeConst(writer, i16, 402);
1419 try b.writeConst(writer, i16, 100);1420 try b.writeConst(writer, i16, 100);
1420 try b.writeOpcode(writer, OP.plus);1421 try b.writeOpcode(writer, OP.plus);
1421 _ = try stack_machine.run(program.items, allocator, context, null);1422 _ = try stack_machine.run(program.written(), allocator, context, null);
1422 try testing.expectEqual(@as(usize, 502), stack_machine.stack.pop().?.generic);1423 try testing.expectEqual(@as(usize, 502), stack_machine.stack.pop().?.generic);
14231424
1424 stack_machine.reset();1425 stack_machine.reset();
1425 program.clearRetainingCapacity();1426 program.clearRetainingCapacity();
1426 try b.writeConst(writer, u16, 4096);1427 try b.writeConst(writer, u16, 4096);
1427 try b.writePlusUconst(writer, @as(usize, 8192));1428 try b.writePlusUconst(writer, @as(usize, 8192));
1428 _ = try stack_machine.run(program.items, allocator, context, null);1429 _ = try stack_machine.run(program.written(), allocator, context, null);
1429 try testing.expectEqual(@as(usize, 4096 + 8192), stack_machine.stack.pop().?.generic);1430 try testing.expectEqual(@as(usize, 4096 + 8192), stack_machine.stack.pop().?.generic);
14301431
1431 stack_machine.reset();1432 stack_machine.reset();
...@@ -1433,7 +1434,7 @@ test "DWARF expressions" {...@@ -1433,7 +1434,7 @@ test "DWARF expressions" {
1433 try b.writeConst(writer, u16, 0xfff);1434 try b.writeConst(writer, u16, 0xfff);
1434 try b.writeConst(writer, u16, 1);1435 try b.writeConst(writer, u16, 1);
1435 try b.writeOpcode(writer, OP.shl);1436 try b.writeOpcode(writer, OP.shl);
1436 _ = try stack_machine.run(program.items, allocator, context, null);1437 _ = try stack_machine.run(program.written(), allocator, context, null);
1437 try testing.expectEqual(@as(usize, 0xfff << 1), stack_machine.stack.pop().?.generic);1438 try testing.expectEqual(@as(usize, 0xfff << 1), stack_machine.stack.pop().?.generic);
14381439
1439 stack_machine.reset();1440 stack_machine.reset();
...@@ -1441,7 +1442,7 @@ test "DWARF expressions" {...@@ -1441,7 +1442,7 @@ test "DWARF expressions" {
1441 try b.writeConst(writer, u16, 0xfff);1442 try b.writeConst(writer, u16, 0xfff);
1442 try b.writeConst(writer, u16, 1);1443 try b.writeConst(writer, u16, 1);
1443 try b.writeOpcode(writer, OP.shr);1444 try b.writeOpcode(writer, OP.shr);
1444 _ = try stack_machine.run(program.items, allocator, context, null);1445 _ = try stack_machine.run(program.written(), allocator, context, null);
1445 try testing.expectEqual(@as(usize, 0xfff >> 1), stack_machine.stack.pop().?.generic);1446 try testing.expectEqual(@as(usize, 0xfff >> 1), stack_machine.stack.pop().?.generic);
14461447
1447 stack_machine.reset();1448 stack_machine.reset();
...@@ -1449,7 +1450,7 @@ test "DWARF expressions" {...@@ -1449,7 +1450,7 @@ test "DWARF expressions" {
1449 try b.writeConst(writer, u16, 0xfff);1450 try b.writeConst(writer, u16, 0xfff);
1450 try b.writeConst(writer, u16, 1);1451 try b.writeConst(writer, u16, 1);
1451 try b.writeOpcode(writer, OP.shr);1452 try b.writeOpcode(writer, OP.shr);
1452 _ = try stack_machine.run(program.items, allocator, context, null);1453 _ = try stack_machine.run(program.written(), allocator, context, null);
1453 try testing.expectEqual(@as(usize, @bitCast(@as(isize, 0xfff) >> 1)), stack_machine.stack.pop().?.generic);1454 try testing.expectEqual(@as(usize, @bitCast(@as(isize, 0xfff) >> 1)), stack_machine.stack.pop().?.generic);
14541455
1455 stack_machine.reset();1456 stack_machine.reset();
...@@ -1457,7 +1458,7 @@ test "DWARF expressions" {...@@ -1457,7 +1458,7 @@ test "DWARF expressions" {
1457 try b.writeConst(writer, u16, 0xf0ff);1458 try b.writeConst(writer, u16, 0xf0ff);
1458 try b.writeConst(writer, u16, 0xff0f);1459 try b.writeConst(writer, u16, 0xff0f);
1459 try b.writeOpcode(writer, OP.xor);1460 try b.writeOpcode(writer, OP.xor);
1460 _ = try stack_machine.run(program.items, allocator, context, null);1461 _ = try stack_machine.run(program.written(), allocator, context, null);
1461 try testing.expectEqual(@as(usize, 0x0ff0), stack_machine.stack.pop().?.generic);1462 try testing.expectEqual(@as(usize, 0x0ff0), stack_machine.stack.pop().?.generic);
1462 }1463 }
14631464
...@@ -1486,7 +1487,7 @@ test "DWARF expressions" {...@@ -1486,7 +1487,7 @@ test "DWARF expressions" {
1486 try b.writeConst(writer, u16, 1);1487 try b.writeConst(writer, u16, 1);
1487 try b.writeConst(writer, u16, 0);1488 try b.writeConst(writer, u16, 0);
1488 try b.writeOpcode(writer, e[0]);1489 try b.writeOpcode(writer, e[0]);
1489 _ = try stack_machine.run(program.items, allocator, context, null);1490 _ = try stack_machine.run(program.written(), allocator, context, null);
1490 try testing.expectEqual(@as(usize, e[3]), stack_machine.stack.pop().?.generic);1491 try testing.expectEqual(@as(usize, e[3]), stack_machine.stack.pop().?.generic);
1491 try testing.expectEqual(@as(usize, e[2]), stack_machine.stack.pop().?.generic);1492 try testing.expectEqual(@as(usize, e[2]), stack_machine.stack.pop().?.generic);
1492 try testing.expectEqual(@as(usize, e[1]), stack_machine.stack.pop().?.generic);1493 try testing.expectEqual(@as(usize, e[1]), stack_machine.stack.pop().?.generic);
...@@ -1497,7 +1498,7 @@ test "DWARF expressions" {...@@ -1497,7 +1498,7 @@ test "DWARF expressions" {
1497 try b.writeLiteral(writer, 2);1498 try b.writeLiteral(writer, 2);
1498 try b.writeSkip(writer, 1);1499 try b.writeSkip(writer, 1);
1499 try b.writeLiteral(writer, 3);1500 try b.writeLiteral(writer, 3);
1500 _ = try stack_machine.run(program.items, allocator, context, null);1501 _ = try stack_machine.run(program.written(), allocator, context, null);
1501 try testing.expectEqual(@as(usize, 2), stack_machine.stack.pop().?.generic);1502 try testing.expectEqual(@as(usize, 2), stack_machine.stack.pop().?.generic);
15021503
1503 stack_machine.reset();1504 stack_machine.reset();
...@@ -1509,7 +1510,7 @@ test "DWARF expressions" {...@@ -1509,7 +1510,7 @@ test "DWARF expressions" {
1509 try b.writeBra(writer, 1);1510 try b.writeBra(writer, 1);
1510 try b.writeLiteral(writer, 4);1511 try b.writeLiteral(writer, 4);
1511 try b.writeLiteral(writer, 5);1512 try b.writeLiteral(writer, 5);
1512 _ = try stack_machine.run(program.items, allocator, context, null);1513 _ = try stack_machine.run(program.written(), allocator, context, null);
1513 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);1514 try testing.expectEqual(@as(usize, 5), stack_machine.stack.pop().?.generic);
1514 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);1515 try testing.expectEqual(@as(usize, 4), stack_machine.stack.pop().?.generic);
1515 try testing.expect(stack_machine.stack.pop() == null);1516 try testing.expect(stack_machine.stack.pop() == null);
...@@ -1535,7 +1536,7 @@ test "DWARF expressions" {...@@ -1535,7 +1536,7 @@ test "DWARF expressions" {
1535 program.clearRetainingCapacity();1536 program.clearRetainingCapacity();
1536 try b.writeConstType(writer, @as(usize, 0), &value_bytes);1537 try b.writeConstType(writer, @as(usize, 0), &value_bytes);
1537 try b.writeConvert(writer, @as(usize, 0));1538 try b.writeConvert(writer, @as(usize, 0));
1538 _ = try stack_machine.run(program.items, allocator, context, null);1539 _ = try stack_machine.run(program.written(), allocator, context, null);
1539 try testing.expectEqual(value, stack_machine.stack.pop().?.generic);1540 try testing.expectEqual(value, stack_machine.stack.pop().?.generic);
15401541
1541 // Reinterpret to generic type1542 // Reinterpret to generic type
...@@ -1543,7 +1544,7 @@ test "DWARF expressions" {...@@ -1543,7 +1544,7 @@ test "DWARF expressions" {
1543 program.clearRetainingCapacity();1544 program.clearRetainingCapacity();
1544 try b.writeConstType(writer, @as(usize, 0), &value_bytes);1545 try b.writeConstType(writer, @as(usize, 0), &value_bytes);
1545 try b.writeReinterpret(writer, @as(usize, 0));1546 try b.writeReinterpret(writer, @as(usize, 0));
1546 _ = try stack_machine.run(program.items, allocator, context, null);1547 _ = try stack_machine.run(program.written(), allocator, context, null);
1547 try testing.expectEqual(value, stack_machine.stack.pop().?.generic);1548 try testing.expectEqual(value, stack_machine.stack.pop().?.generic);
15481549
1549 // Reinterpret to new type1550 // Reinterpret to new type
...@@ -1553,7 +1554,7 @@ test "DWARF expressions" {...@@ -1553,7 +1554,7 @@ test "DWARF expressions" {
1553 program.clearRetainingCapacity();1554 program.clearRetainingCapacity();
1554 try b.writeConstType(writer, @as(usize, 0), &value_bytes);1555 try b.writeConstType(writer, @as(usize, 0), &value_bytes);
1555 try b.writeReinterpret(writer, die_offset);1556 try b.writeReinterpret(writer, die_offset);
1556 _ = try stack_machine.run(program.items, allocator, context, null);1557 _ = try stack_machine.run(program.written(), allocator, context, null);
1557 const const_type = stack_machine.stack.pop().?.const_type;1558 const const_type = stack_machine.stack.pop().?.const_type;
1558 try testing.expectEqual(die_offset, const_type.type_offset);1559 try testing.expectEqual(die_offset, const_type.type_offset);
15591560
...@@ -1561,7 +1562,7 @@ test "DWARF expressions" {...@@ -1561,7 +1562,7 @@ test "DWARF expressions" {
1561 program.clearRetainingCapacity();1562 program.clearRetainingCapacity();
1562 try b.writeLiteral(writer, 0);1563 try b.writeLiteral(writer, 0);
1563 try b.writeReinterpret(writer, die_offset);1564 try b.writeReinterpret(writer, die_offset);
1564 _ = try stack_machine.run(program.items, allocator, context, null);1565 _ = try stack_machine.run(program.written(), allocator, context, null);
1565 const regval_type = stack_machine.stack.pop().?.regval_type;1566 const regval_type = stack_machine.stack.pop().?.regval_type;
1566 try testing.expectEqual(die_offset, regval_type.type_offset);1567 try testing.expectEqual(die_offset, regval_type.type_offset);
1567 }1568 }
...@@ -1573,20 +1574,20 @@ test "DWARF expressions" {...@@ -1573,20 +1574,20 @@ test "DWARF expressions" {
1573 stack_machine.reset();1574 stack_machine.reset();
1574 program.clearRetainingCapacity();1575 program.clearRetainingCapacity();
1575 try b.writeOpcode(writer, OP.nop);1576 try b.writeOpcode(writer, OP.nop);
1576 _ = try stack_machine.run(program.items, allocator, context, null);1577 _ = try stack_machine.run(program.written(), allocator, context, null);
1577 try testing.expect(stack_machine.stack.pop() == null);1578 try testing.expect(stack_machine.stack.pop() == null);
15781579
1579 // Sub-expression1580 // Sub-expression
1580 {1581 {
1581 var sub_program = std.array_list.Managed(u8).init(allocator);1582 var sub_program: std.Io.Writer.Allocating = .init(allocator);
1582 defer sub_program.deinit();1583 defer sub_program.deinit();
1583 const sub_writer = sub_program.writer();1584 const sub_writer = &sub_program.writer;
1584 try b.writeLiteral(sub_writer, 3);1585 try b.writeLiteral(sub_writer, 3);
15851586
1586 stack_machine.reset();1587 stack_machine.reset();
1587 program.clearRetainingCapacity();1588 program.clearRetainingCapacity();
1588 try b.writeEntryValue(writer, sub_program.items);1589 try b.writeEntryValue(writer, sub_program.written());
1589 _ = try stack_machine.run(program.items, allocator, context, null);1590 _ = try stack_machine.run(program.written(), allocator, context, null);
1590 try testing.expectEqual(@as(usize, 3), stack_machine.stack.pop().?.generic);1591 try testing.expectEqual(@as(usize, 3), stack_machine.stack.pop().?.generic);
1591 }1592 }
15921593
...@@ -1605,15 +1606,15 @@ test "DWARF expressions" {...@@ -1605,15 +1606,15 @@ test "DWARF expressions" {
1605 if (abi.regBytes(&thread_context, 0, reg_context)) |reg_bytes| {1606 if (abi.regBytes(&thread_context, 0, reg_context)) |reg_bytes| {
1606 mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);1607 mem.writeInt(usize, reg_bytes[0..@sizeOf(usize)], 0xee, native_endian);
16071608
1608 var sub_program = std.array_list.Managed(u8).init(allocator);1609 var sub_program: std.Io.Writer.Allocating = .init(allocator);
1609 defer sub_program.deinit();1610 defer sub_program.deinit();
1610 const sub_writer = sub_program.writer();1611 const sub_writer = &sub_program.writer;
1611 try b.writeReg(sub_writer, 0);1612 try b.writeReg(sub_writer, 0);
16121613
1613 stack_machine.reset();1614 stack_machine.reset();
1614 program.clearRetainingCapacity();1615 program.clearRetainingCapacity();
1615 try b.writeEntryValue(writer, sub_program.items);1616 try b.writeEntryValue(writer, sub_program.written());
1616 _ = try stack_machine.run(program.items, allocator, context, null);1617 _ = try stack_machine.run(program.written(), allocator, context, null);
1617 try testing.expectEqual(@as(usize, 0xee), stack_machine.stack.pop().?.generic);1618 try testing.expectEqual(@as(usize, 0xee), stack_machine.stack.pop().?.generic);
1618 } else |err| {1619 } else |err| {
1619 switch (err) {1620 switch (err) {
lib/std/leb128.zig-103
...@@ -33,28 +33,6 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T {...@@ -33,28 +33,6 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T {
33 return @as(T, @truncate(value));33 return @as(T, @truncate(value));
34}34}
3535
36/// Write a single unsigned integer as unsigned LEB128 to the given writer.
37pub fn writeUleb128(writer: anytype, arg: anytype) !void {
38 const Arg = @TypeOf(arg);
39 const Int = switch (Arg) {
40 comptime_int => std.math.IntFittingRange(arg, arg),
41 else => Arg,
42 };
43 const Value = if (@typeInfo(Int).int.bits < 8) u8 else Int;
44 var value: Value = arg;
45
46 while (true) {
47 const byte: u8 = @truncate(value & 0x7f);
48 value >>= 7;
49 if (value == 0) {
50 try writer.writeByte(byte);
51 break;
52 } else {
53 try writer.writeByte(byte | 0x80);
54 }
55 }
56}
57
58/// Read a single signed LEB128 value from the given reader as type T,36/// Read a single signed LEB128 value from the given reader as type T,
59/// or error.Overflow if the value cannot fit.37/// or error.Overflow if the value cannot fit.
60pub fn readIleb128(comptime T: type, reader: anytype) !T {38pub fn readIleb128(comptime T: type, reader: anytype) !T {
...@@ -374,84 +352,3 @@ test "deserialize unsigned LEB128" {...@@ -374,84 +352,3 @@ test "deserialize unsigned LEB128" {
374 // Decode sequence of ULEB128 values352 // Decode sequence of ULEB128 values
375 try test_read_uleb128_seq(u64, 4, "\x81\x01\x3f\x80\x7f\x80\x80\x80\x00");353 try test_read_uleb128_seq(u64, 4, "\x81\x01\x3f\x80\x7f\x80\x80\x80\x00");
376}354}
377
378fn test_write_leb128(value: anytype) !void {
379 const T = @TypeOf(value);
380 const signedness = @typeInfo(T).int.signedness;
381 const t_signed = signedness == .signed;
382
383 const writeStream = if (t_signed) writeIleb128 else writeUleb128;
384 const readStream = if (t_signed) readIleb128 else readUleb128;
385
386 // decode to a larger bit size too, to ensure sign extension
387 // is working as expected
388 const larger_type_bits = ((@typeInfo(T).int.bits + 8) / 8) * 8;
389 const B = std.meta.Int(signedness, larger_type_bits);
390
391 const bytes_needed = bn: {
392 if (@typeInfo(T).int.bits <= 7) break :bn @as(u16, 1);
393
394 const unused_bits = if (value < 0) @clz(~value) else @clz(value);
395 const used_bits: u16 = (@typeInfo(T).int.bits - unused_bits) + @intFromBool(t_signed);
396 if (used_bits <= 7) break :bn @as(u16, 1);
397 break :bn ((used_bits + 6) / 7);
398 };
399
400 const max_groups = if (@typeInfo(T).int.bits == 0) 1 else (@typeInfo(T).int.bits + 6) / 7;
401
402 var buf: [max_groups]u8 = undefined;
403 var fbs = std.io.fixedBufferStream(&buf);
404
405 // stream write
406 try writeStream(fbs.writer(), value);
407 const w1_pos = fbs.pos;
408 try testing.expect(w1_pos == bytes_needed);
409
410 // stream read
411 fbs.pos = 0;
412 const sr = try readStream(T, fbs.reader());
413 try testing.expect(fbs.pos == w1_pos);
414 try testing.expect(sr == value);
415
416 // bigger type stream read
417 fbs.pos = 0;
418 const bsr = try readStream(B, fbs.reader());
419 try testing.expect(fbs.pos == w1_pos);
420 try testing.expect(bsr == value);
421}
422
423test "serialize unsigned LEB128" {
424 if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest;
425
426 const max_bits = 18;
427
428 comptime var t = 0;
429 inline while (t <= max_bits) : (t += 1) {
430 const T = std.meta.Int(.unsigned, t);
431 const min = std.math.minInt(T);
432 const max = std.math.maxInt(T);
433 var i = @as(std.meta.Int(.unsigned, @typeInfo(T).int.bits + 1), min);
434
435 while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i)));
436 }
437}
438
439test "serialize signed LEB128" {
440 if (builtin.cpu.arch == .x86 and builtin.abi == .musl and builtin.link_mode == .dynamic) return error.SkipZigTest;
441
442 // explicitly test i0 because starting `t` at 0
443 // will break the while loop
444 try test_write_leb128(@as(i0, 0));
445
446 const max_bits = 18;
447
448 comptime var t = 1;
449 inline while (t <= max_bits) : (t += 1) {
450 const T = std.meta.Int(.signed, t);
451 const min = std.math.minInt(T);
452 const max = std.math.maxInt(T);
453 var i = @as(std.meta.Int(.signed, @typeInfo(T).int.bits + 1), min);
454
455 while (i <= max) : (i += 1) try test_write_leb128(@as(T, @intCast(i)));
456 }
457}
lib/std/posix/test.zig+2-2
...@@ -683,11 +683,11 @@ test "mmap" {...@@ -683,11 +683,11 @@ test "mmap" {
683 const file = try tmp.dir.createFile(test_out_file, .{});683 const file = try tmp.dir.createFile(test_out_file, .{});
684 defer file.close();684 defer file.close();
685685
686 const stream = file.deprecatedWriter();686 var stream = file.writer(&.{});
687687
688 var i: u32 = 0;688 var i: u32 = 0;
689 while (i < alloc_size / @sizeOf(u32)) : (i += 1) {689 while (i < alloc_size / @sizeOf(u32)) : (i += 1) {
690 try stream.writeInt(u32, i, .little);690 try stream.interface.writeInt(u32, i, .little);
691 }691 }
692 }692 }
693693