mirror of
https://github.com/ziglang/zig.git
synced 2024-12-12 22:25:21 +00:00
wasm-linker: seperate linker -and cpu features
The list of features a Wasm object/binary file can emit can differ from the list of cpu features. The reason for this is because the "target_features" section also contains linker features. An example of this is the "shared-mem" feature, which is a feature for the linker and not that of the cpu target as defined by LLVM.
This commit is contained in:
parent
2f41109cc4
commit
3d1d19f387
@ -654,15 +654,15 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
|
||||
fn validateFeatures(
|
||||
wasm: *const Wasm,
|
||||
arena: Allocator,
|
||||
to_emit: *[@typeInfo(std.Target.wasm.Feature).Enum.fields.len]bool,
|
||||
to_emit: *[@typeInfo(types.Feature.Tag).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);
|
||||
var used = std.AutoArrayHashMap(std.Target.wasm.Feature, []const u8).init(arena);
|
||||
var disallowed = std.AutoHashMap(std.Target.wasm.Feature, []const u8).init(arena);
|
||||
var required = std.AutoHashMap(std.Target.wasm.Feature, []const u8).init(arena);
|
||||
var allowed = std.AutoHashMap(types.Feature.Tag, void).init(arena);
|
||||
var used = std.AutoArrayHashMap(types.Feature.Tag, []const u8).init(arena);
|
||||
var disallowed = std.AutoHashMap(types.Feature.Tag, []const u8).init(arena);
|
||||
var required = std.AutoHashMap(types.Feature.Tag, []const u8).init(arena);
|
||||
|
||||
// when false, we fail linking. We only verify this after a loop to catch all invalid features.
|
||||
var valid_feature_set = true;
|
||||
@ -674,7 +674,7 @@ fn validateFeatures(
|
||||
// std.builtin.Type.EnumField
|
||||
inline for (@typeInfo(std.Target.wasm.Feature).Enum.fields) |feature_field| {
|
||||
if (cpu_features.isEnabled(feature_field.value)) {
|
||||
allowed.putAssumeCapacityNoClobber(@intToEnum(std.Target.wasm.Feature, feature_field.value), {});
|
||||
allowed.putAssumeCapacityNoClobber(@intToEnum(types.Feature.Tag, feature_field.value), {});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -730,7 +730,7 @@ fn validateFeatures(
|
||||
|
||||
// For each linked object, validate the required and disallowed features
|
||||
for (wasm.objects.items) |object| {
|
||||
var object_used_features = std.AutoHashMap(std.Target.wasm.Feature, void).init(arena);
|
||||
var object_used_features = std.AutoHashMap(types.Feature.Tag, void).init(arena);
|
||||
try object_used_features.ensureTotalCapacity(@intCast(u32, object.features.len));
|
||||
for (object.features) |feature| {
|
||||
if (feature.prefix == .disallowed) continue; // already defined in 'disallowed' set.
|
||||
@ -764,7 +764,7 @@ fn validateFeatures(
|
||||
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));
|
||||
feature_enabled.* = allowed.contains(@intToEnum(types.Feature.Tag, feature_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2277,7 +2277,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
|
||||
var emit_features_count: u32 = 0;
|
||||
var enabled_features: [@typeInfo(std.Target.wasm.Feature).Enum.fields.len]bool = undefined;
|
||||
var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined;
|
||||
try wasm.validateFeatures(arena, &enabled_features, &emit_features_count);
|
||||
try wasm.resolveSymbolsInArchives();
|
||||
try wasm.checkUndefinedSymbols();
|
||||
|
@ -183,7 +183,27 @@ pub const Feature = struct {
|
||||
/// Type of the feature, must be unique in the sequence of features.
|
||||
tag: Tag,
|
||||
|
||||
pub const Tag = std.Target.wasm.Feature;
|
||||
/// Unlike `std.Target.wasm.Feature` this also contains linker-features such as shared-mem
|
||||
pub const Tag = enum {
|
||||
atomics,
|
||||
bulk_memory,
|
||||
exception_handling,
|
||||
extended_const,
|
||||
multivalue,
|
||||
mutable_globals,
|
||||
nontrapping_fptoint,
|
||||
reference_types,
|
||||
relaxed_simd,
|
||||
sign_ext,
|
||||
simd128,
|
||||
tail_call,
|
||||
shared_mem,
|
||||
|
||||
/// From a given cpu feature, returns its linker feature
|
||||
pub fn fromCpuFeature(feature: std.Target.wasm.Feature) Tag {
|
||||
return @intToEnum(Tag, @enumToInt(feature));
|
||||
}
|
||||
};
|
||||
|
||||
pub const Prefix = enum(u8) {
|
||||
used = '+',
|
||||
@ -205,6 +225,7 @@ pub const Feature = struct {
|
||||
.sign_ext => "sign-ext",
|
||||
.simd128 => "simd128",
|
||||
.tail_call => "tail-call",
|
||||
.shared_mem => "shared-mem",
|
||||
};
|
||||
}
|
||||
|
||||
@ -228,4 +249,5 @@ pub const known_features = std.ComptimeStringMap(Feature.Tag, .{
|
||||
.{ "sign-ext", .sign_ext },
|
||||
.{ "simd128", .simd128 },
|
||||
.{ "tail-call", .tail_call },
|
||||
.{ "shared-mem", .shared_mem },
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user