authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-30 16:51:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-01 12:05:20-07:00
log16d3f7b2fa7461643e85a9a52dcd2bf9c01caa1e
tree2350b2bf2b52345e3647a85330176680d28ecafc
parentfa5011aa3166ace57a1c02158b04e8025900bb56

std.Build.Step.CheckObject: fix parseDumpNames

This function incorrectly assumed that module name subsections, function name subsections, and local name subsections are encoded the same, however according to [the specification](https://webassembly.github.io/spec/core/appendix/custom.html) they are encoded differently. This commit adds support for parsing module name subsections correctly, which started appearing after upgrading to LLVM 18.

1 files changed, 57 insertions(+), 31 deletions(-)

lib/std/Build/Step/CheckObject.zig+57-31
......@@ -2475,12 +2475,12 @@ const WasmDumper = struct {
24752475 try writer.print("params {d}\n", .{params});
24762476 var index: u32 = 0;
24772477 while (index < params) : (index += 1) {
2478 try parseDumpType(step, std.wasm.Valtype, reader, writer);
2478 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
24792479 } else index = 0;
24802480 const returns = try std.leb.readULEB128(u32, reader);
24812481 try writer.print("returns {d}\n", .{returns});
24822482 while (index < returns) : (index += 1) {
2483 try parseDumpType(step, std.wasm.Valtype, reader, writer);
2483 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
24842484 }
24852485 }
24862486 },
......@@ -2512,11 +2512,11 @@ const WasmDumper = struct {
25122512 try parseDumpLimits(reader, writer);
25132513 },
25142514 .global => {
2515 try parseDumpType(step, std.wasm.Valtype, reader, writer);
2515 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
25162516 try writer.print("mutable {}\n", .{0x01 == try std.leb.readULEB128(u32, reader)});
25172517 },
25182518 .table => {
2519 try parseDumpType(step, std.wasm.RefType, reader, writer);
2519 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);
25202520 try parseDumpLimits(reader, writer);
25212521 },
25222522 }
......@@ -2531,7 +2531,7 @@ const WasmDumper = struct {
25312531 .table => {
25322532 var i: u32 = 0;
25332533 while (i < entries) : (i += 1) {
2534 try parseDumpType(step, std.wasm.RefType, reader, writer);
2534 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);
25352535 try parseDumpLimits(reader, writer);
25362536 }
25372537 },
......@@ -2544,7 +2544,7 @@ const WasmDumper = struct {
25442544 .global => {
25452545 var i: u32 = 0;
25462546 while (i < entries) : (i += 1) {
2547 try parseDumpType(step, std.wasm.Valtype, reader, writer);
2547 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);
25482548 try writer.print("mutable {}\n", .{0x01 == try std.leb.readULEB128(u1, reader)});
25492549 try parseDumpInit(step, reader, writer);
25502550 }
......@@ -2605,12 +2605,13 @@ const WasmDumper = struct {
26052605 }
26062606 }
26072607
2608 fn parseDumpType(step: *Step, comptime WasmType: type, reader: anytype, writer: anytype) !void {
2609 const type_byte = try reader.readByte();
2610 const valtype = std.meta.intToEnum(WasmType, type_byte) catch {
2611 return step.fail("Invalid wasm type value '{d}'", .{type_byte});
2608 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, writer: anytype) !E {
2609 const byte = try reader.readByte();
2610 const tag = std.meta.intToEnum(E, byte) catch {
2611 return step.fail("invalid wasm type value '{d}'", .{byte});
26122612 };
2613 try writer.print("type {s}\n", .{@tagName(valtype)});
2613 try writer.print("type {s}\n", .{@tagName(tag)});
2614 return tag;
26142615 }
26152616
26162617 fn parseDumpLimits(reader: anytype, writer: anytype) !void {
......@@ -2642,29 +2643,54 @@ const WasmDumper = struct {
26422643 }
26432644 }
26442645
2646 /// https://webassembly.github.io/spec/core/appendix/custom.html
26452647 fn parseDumpNames(step: *Step, reader: anytype, writer: anytype, data: []const u8) !void {
26462648 while (reader.context.pos < data.len) {
2647 try parseDumpType(step, std.wasm.NameSubsection, reader, writer);
2648 const size = try std.leb.readULEB128(u32, reader);
2649 const entries = try std.leb.readULEB128(u32, reader);
2650 try writer.print(
2651 \\size {d}
2652 \\names {d}
2653 , .{ size, entries });
2654 try writer.writeByte('\n');
2655 var i: u32 = 0;
2656 while (i < entries) : (i += 1) {
2657 const index = try std.leb.readULEB128(u32, reader);
2658 const name_len = try std.leb.readULEB128(u32, reader);
2659 const pos = reader.context.pos;
2660 const name = data[pos..][0..name_len];
2661 reader.context.pos += name_len;
2649 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, writer)) {
2650 // The module name subsection ... consists of a single name
2651 // that is assigned to the module itself.
2652 .module => {
2653 const size = try std.leb.readULEB128(u32, reader);
2654 const name_len = try std.leb.readULEB128(u32, reader);
2655 if (size != name_len + 1) return error.BadSubsectionSize;
2656 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2657 try writer.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});
2658 reader.context.pos += name_len;
2659 },
26622660
2663 try writer.print(
2664 \\index {d}
2665 \\name {s}
2666 , .{ index, name });
2667 try writer.writeByte('\n');
2661 // The function name subsection ... consists of a name map
2662 // assigning function names to function indices.
2663 .function, .global, .data_segment => {
2664 const size = try std.leb.readULEB128(u32, reader);
2665 const entries = try std.leb.readULEB128(u32, reader);
2666 try writer.print(
2667 \\size {d}
2668 \\names {d}
2669 \\
2670 , .{ size, entries });
2671 for (0..entries) |_| {
2672 const index = try std.leb.readULEB128(u32, reader);
2673 const name_len = try std.leb.readULEB128(u32, reader);
2674 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2675 const name = data[reader.context.pos..][0..name_len];
2676 reader.context.pos += name.len;
2677
2678 try writer.print(
2679 \\index {d}
2680 \\name {s}
2681 \\
2682 , .{ index, name });
2683 }
2684 },
2685
2686 // The local name subsection ... consists of an indirect name
2687 // map assigning local names to local indices grouped by
2688 // function indices.
2689 .local => {
2690 return step.fail("TODO implement parseDumpNames for local subsections", .{});
2691 },
2692
2693 else => |t| return step.fail("invalid subsection type: {s}", .{@tagName(t)}),
26682694 }
26692695 }
26702696 }