mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 08:33:15 +00:00
Merge pull request #13054 from Luukdegram/wasm-producer
wasm-linker: generate 'producers' section
This commit is contained in:
commit
fa9327ac05
@ -644,6 +644,8 @@ const WasmDumper = struct {
|
||||
|
||||
if (mem.eql(u8, name, "name")) {
|
||||
try parseDumpNames(reader, writer, data);
|
||||
} else if (mem.eql(u8, name, "producers")) {
|
||||
try parseDumpProducers(reader, writer, data);
|
||||
}
|
||||
// TODO: Implement parsing and dumping other custom sections (such as relocations)
|
||||
},
|
||||
@ -863,4 +865,38 @@ const WasmDumper = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parseDumpProducers(reader: anytype, writer: anytype, data: []const u8) !void {
|
||||
const field_count = try std.leb.readULEB128(u32, reader);
|
||||
try writer.print("fields {d}\n", .{field_count});
|
||||
var current_field: u32 = 0;
|
||||
while (current_field < field_count) : (current_field += 1) {
|
||||
const field_name_length = try std.leb.readULEB128(u32, reader);
|
||||
const field_name = data[reader.context.pos..][0..field_name_length];
|
||||
reader.context.pos += field_name_length;
|
||||
|
||||
const value_count = try std.leb.readULEB128(u32, reader);
|
||||
try writer.print(
|
||||
\\field_name {s}
|
||||
\\values {d}
|
||||
, .{ field_name, value_count });
|
||||
try writer.writeByte('\n');
|
||||
var current_value: u32 = 0;
|
||||
while (current_value < value_count) : (current_value += 1) {
|
||||
const value_length = try std.leb.readULEB128(u32, reader);
|
||||
const value = data[reader.context.pos..][0..value_length];
|
||||
reader.context.pos += value_length;
|
||||
|
||||
const version_length = try std.leb.readULEB128(u32, reader);
|
||||
const version = data[reader.context.pos..][0..version_length];
|
||||
reader.context.pos += version_length;
|
||||
|
||||
try writer.print(
|
||||
\\value_name {s}
|
||||
\\version {s}
|
||||
, .{ value, version });
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -2556,6 +2556,10 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
|
||||
}
|
||||
} else if (!wasm.base.options.strip) {
|
||||
try wasm.emitNameSection(&binary_bytes, arena);
|
||||
}
|
||||
|
||||
if (!wasm.base.options.strip) {
|
||||
if (wasm.dwarf) |*dwarf| {
|
||||
const mod = wasm.base.options.module.?;
|
||||
try dwarf.writeDbgAbbrev(&wasm.base);
|
||||
@ -2597,7 +2601,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
debug_bytes.clearRetainingCapacity();
|
||||
}
|
||||
}
|
||||
try wasm.emitNameSection(&binary_bytes, arena);
|
||||
|
||||
try emitProducerSection(&binary_bytes);
|
||||
}
|
||||
|
||||
// Only when writing all sections executed properly we write the magic
|
||||
@ -2631,6 +2636,65 @@ fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []
|
||||
);
|
||||
}
|
||||
|
||||
fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void {
|
||||
const header_offset = try reserveCustomSectionHeader(binary_bytes);
|
||||
|
||||
const writer = binary_bytes.writer();
|
||||
const producers = "producers";
|
||||
try leb.writeULEB128(writer, @intCast(u32, producers.len));
|
||||
try writer.writeAll(producers);
|
||||
|
||||
try leb.writeULEB128(writer, @as(u32, 2)); // 2 fields: Language + processed-by
|
||||
|
||||
// used for the Zig version
|
||||
var version_buf: [100]u8 = undefined;
|
||||
const version = try std.fmt.bufPrint(&version_buf, "{}", .{build_options.semver});
|
||||
|
||||
// language field
|
||||
{
|
||||
const language = "language";
|
||||
try leb.writeULEB128(writer, @intCast(u32, language.len));
|
||||
try writer.writeAll(language);
|
||||
|
||||
// field_value_count (TODO: Parse object files for producer sections to detect their language)
|
||||
try leb.writeULEB128(writer, @as(u32, 1));
|
||||
|
||||
// versioned name
|
||||
{
|
||||
try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig"
|
||||
try writer.writeAll("Zig");
|
||||
|
||||
try leb.writeULEB128(writer, @intCast(u32, version.len));
|
||||
try writer.writeAll(version);
|
||||
}
|
||||
}
|
||||
|
||||
// processed-by field
|
||||
{
|
||||
const processed_by = "processed-by";
|
||||
try leb.writeULEB128(writer, @intCast(u32, processed_by.len));
|
||||
try writer.writeAll(processed_by);
|
||||
|
||||
// field_value_count (TODO: Parse object files for producer sections to detect other used tools)
|
||||
try leb.writeULEB128(writer, @as(u32, 1));
|
||||
|
||||
// versioned name
|
||||
{
|
||||
try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig"
|
||||
try writer.writeAll("Zig");
|
||||
|
||||
try leb.writeULEB128(writer, @intCast(u32, version.len));
|
||||
try writer.writeAll(version);
|
||||
}
|
||||
}
|
||||
|
||||
try writeCustomSectionHeader(
|
||||
binary_bytes.items,
|
||||
header_offset,
|
||||
@intCast(u32, binary_bytes.items.len - header_offset - 6),
|
||||
);
|
||||
}
|
||||
|
||||
fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
|
||||
const Name = struct {
|
||||
index: u32,
|
||||
|
||||
@ -34,7 +34,7 @@ fn addWasmCases(cases: *tests.StandaloneContext) void {
|
||||
});
|
||||
|
||||
cases.addBuildFile("test/link/wasm/bss/build.zig", .{
|
||||
.build_modes = true,
|
||||
.build_modes = false,
|
||||
.requires_stage2 = true,
|
||||
});
|
||||
|
||||
@ -44,6 +44,11 @@ fn addWasmCases(cases: *tests.StandaloneContext) void {
|
||||
.use_emulation = true,
|
||||
});
|
||||
|
||||
cases.addBuildFile("test/link/wasm/producers/build.zig", .{
|
||||
.build_modes = true,
|
||||
.requires_stage2 = true,
|
||||
});
|
||||
|
||||
cases.addBuildFile("test/link/wasm/segments/build.zig", .{
|
||||
.build_modes = true,
|
||||
.requires_stage2 = true,
|
||||
|
||||
36
test/link/wasm/producers/build.zig
Normal file
36
test/link/wasm/producers/build.zig
Normal file
@ -0,0 +1,36 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
lib.use_llvm = false;
|
||||
lib.use_stage1 = false;
|
||||
lib.use_lld = false;
|
||||
lib.install();
|
||||
|
||||
const zig_version = builtin.zig_version;
|
||||
var version_buf: [100]u8 = undefined;
|
||||
const version_fmt = std.fmt.bufPrint(&version_buf, "version {}", .{zig_version}) catch unreachable;
|
||||
|
||||
const check_lib = lib.checkObject(.wasm);
|
||||
check_lib.checkStart("name producers");
|
||||
check_lib.checkNext("fields 2");
|
||||
check_lib.checkNext("field_name language");
|
||||
check_lib.checkNext("values 1");
|
||||
check_lib.checkNext("value_name Zig");
|
||||
check_lib.checkNext(version_fmt);
|
||||
check_lib.checkNext("field_name processed-by");
|
||||
check_lib.checkNext("values 1");
|
||||
check_lib.checkNext("value_name Zig");
|
||||
check_lib.checkNext(version_fmt);
|
||||
|
||||
test_step.dependOn(&check_lib.step);
|
||||
}
|
||||
1
test/link/wasm/producers/lib.zig
Normal file
1
test/link/wasm/producers/lib.zig
Normal file
@ -0,0 +1 @@
|
||||
export fn foo() void {}
|
||||
Loading…
x
Reference in New Issue
Block a user