mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
wasm-linker: emit target_features section
When the result is not being stripped, we emit the `target_features` section based on all the used features. This includes features inferred from linked object files. Considering we know all possible features upfront, we can use an array and therefore do not have to dynamically allocate memory. Using this trick we can also easily order all features based the same ordering as found in `std.Target.wasm` which is the same ordering used by LLVM and the like.
This commit is contained in:
parent
85b669d497
commit
777bcbf968
@ -651,7 +651,12 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn validateFeatures(wasm: *const Wasm, arena: Allocator) !void {
|
||||
fn validateFeatures(
|
||||
wasm: *const Wasm,
|
||||
arena: Allocator,
|
||||
to_emit: *[@typeInfo(std.Target.wasm.Feature).Enum.fields.len]bool,
|
||||
emit_features_count: *u32,
|
||||
) !void {
|
||||
const cpu_features = wasm.base.options.target.cpu.features;
|
||||
const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects.
|
||||
var allowed = std.AutoHashMap(std.Target.wasm.Feature, void).init(arena);
|
||||
@ -755,6 +760,13 @@ fn validateFeatures(wasm: *const Wasm, arena: Allocator) !void {
|
||||
if (!valid_feature_set) {
|
||||
return error.InvalidFeatureSet;
|
||||
}
|
||||
|
||||
if (allowed.count() > 0) {
|
||||
emit_features_count.* = allowed.count();
|
||||
for (to_emit) |*feature_enabled, feature_index| {
|
||||
feature_enabled.* = allowed.contains(@intToEnum(std.Target.wasm.Feature, feature_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn checkUndefinedSymbols(wasm: *const Wasm) !void {
|
||||
@ -2264,7 +2276,9 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try wasm.resolveSymbolsInObject(@intCast(u16, object_index));
|
||||
}
|
||||
|
||||
try wasm.validateFeatures(arena);
|
||||
var emit_features_count: u32 = 0;
|
||||
var enabled_features: [@typeInfo(std.Target.wasm.Feature).Enum.fields.len]bool = undefined;
|
||||
try wasm.validateFeatures(arena, &enabled_features, &emit_features_count);
|
||||
try wasm.resolveSymbolsInArchives();
|
||||
try wasm.checkUndefinedSymbols();
|
||||
|
||||
@ -2710,6 +2724,9 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
|
||||
try emitProducerSection(&binary_bytes);
|
||||
if (emit_features_count > 0) {
|
||||
try emitFeaturesSection(&binary_bytes, &enabled_features, emit_features_count);
|
||||
}
|
||||
}
|
||||
|
||||
// Only when writing all sections executed properly we write the magic
|
||||
@ -2802,6 +2819,32 @@ fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void {
|
||||
);
|
||||
}
|
||||
|
||||
fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []const bool, features_count: u32) !void {
|
||||
const header_offset = try reserveCustomSectionHeader(binary_bytes);
|
||||
|
||||
const writer = binary_bytes.writer();
|
||||
const target_features = "target_features";
|
||||
try leb.writeULEB128(writer, @intCast(u32, target_features.len));
|
||||
try writer.writeAll(target_features);
|
||||
|
||||
try leb.writeULEB128(writer, features_count);
|
||||
for (enabled_features) |enabled, feature_index| {
|
||||
if (enabled) {
|
||||
const feature: types.Feature = .{ .prefix = .used, .tag = @intToEnum(types.Feature.Tag, feature_index) };
|
||||
try leb.writeULEB128(writer, @enumToInt(feature.prefix));
|
||||
const string = feature.toString();
|
||||
try leb.writeULEB128(writer, @intCast(u32, string.len));
|
||||
try writer.writeAll(string);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user