diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-10-23 20:02:25 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-10-25 20:48:09 +0200 |
| commit | 3d1d19f3877190db42544acf9e0ed26784ba82ba (patch) | |
| tree | 71d7f6ac0907474f3bca919863aa41f84afade2e /src | |
| parent | 2f41109cc445c450029ea81c0da6873f32fa0981 (diff) | |
| download | zig-3d1d19f3877190db42544acf9e0ed26784ba82ba.tar.gz zig-3d1d19f3877190db42544acf9e0ed26784ba82ba.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Wasm.zig | 18 | ||||
| -rw-r--r-- | src/link/Wasm/types.zig | 24 |
2 files changed, 32 insertions, 10 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index da9a878720..4b6895c4e5 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -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(); diff --git a/src/link/Wasm/types.zig b/src/link/Wasm/types.zig index 5e071c2f20..1b6df86d37 100644 --- a/src/link/Wasm/types.zig +++ b/src/link/Wasm/types.zig @@ -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 }, }); |
