diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Wasm.zig | 41 | ||||
| -rw-r--r-- | src/link/Wasm/Object.zig | 4 | ||||
| -rw-r--r-- | src/link/Wasm/types.zig | 12 |
3 files changed, 47 insertions, 10 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 50846eecf1..5792e57b89 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -795,6 +795,8 @@ fn validateFeatures( // when false, we fail linking. We only verify this after a loop to catch all invalid features. var valid_feature_set = true; + // will be set to true when there's any TLS segment found in any of the object files + var has_tls = false; // When the user has given an explicit list of features to enable, // we extract them and insert each into the 'allowed' list. @@ -825,6 +827,12 @@ fn validateFeatures( }, } } + + for (object.segment_info) |segment| { + if (segment.isTLS()) { + has_tls = true; + } + } } // when we infer the features, we allow each feature found in the 'used' set @@ -836,7 +844,7 @@ fn validateFeatures( allowed[used_index] = is_enabled; emit_features_count.* += @boolToInt(is_enabled); } else if (is_enabled and !allowed[used_index]) { - log.err("feature '{s}' not allowed, but used by linked object", .{(@intToEnum(types.Feature.Tag, used_index)).toString()}); + log.err("feature '{}' not allowed, but used by linked object", .{@intToEnum(types.Feature.Tag, used_index)}); log.err(" defined in '{s}'", .{wasm.objects.items[used_set >> 1].name}); valid_feature_set = false; } @@ -846,6 +854,30 @@ fn validateFeatures( return error.InvalidFeatureSet; } + if (wasm.base.options.shared_memory) { + const disallowed_feature = disallowed[@enumToInt(types.Feature.Tag.shared_mem)]; + if (@truncate(u1, disallowed_feature) != 0) { + log.err( + "shared-memory is disallowed by '{s}' because it wasn't compiled with 'atomics' and 'bulk-memory' features enabled", + .{wasm.objects.items[disallowed_feature >> 1].name}, + ); + valid_feature_set = false; + } + + for ([_]types.Feature.Tag{ .atomics, .bulk_memory }) |feature| { + if (!allowed[@enumToInt(feature)]) { + log.err("feature '{}' is not used but is required for shared-memory", .{feature}); + } + } + } + + if (has_tls) { + for ([_]types.Feature.Tag{ .atomics, .bulk_memory }) |feature| { + if (!allowed[@enumToInt(feature)]) { + log.err("feature '{}' is not used but is required for thread-local storage", .{feature}); + } + } + } // For each linked object, validate the required and disallowed features for (wasm.objects.items) |object| { var object_used_features = [_]bool{false} ** known_features_count; @@ -854,7 +886,7 @@ fn validateFeatures( // from here a feature is always used const disallowed_feature = disallowed[@enumToInt(feature.tag)]; if (@truncate(u1, disallowed_feature) != 0) { - log.err("feature '{s}' is disallowed, but used by linked object", .{feature.tag.toString()}); + log.err("feature '{}' is disallowed, but used by linked object", .{feature.tag}); log.err(" disallowed by '{s}'", .{wasm.objects.items[disallowed_feature >> 1].name}); log.err(" used in '{s}'", .{object.name}); valid_feature_set = false; @@ -867,7 +899,7 @@ fn validateFeatures( for (required, 0..) |required_feature, feature_index| { const is_required = @truncate(u1, required_feature) != 0; if (is_required and !object_used_features[feature_index]) { - log.err("feature '{s}' is required but not used in linked object", .{(@intToEnum(types.Feature.Tag, feature_index)).toString()}); + log.err("feature '{}' is required but not used in linked object", .{@intToEnum(types.Feature.Tag, feature_index)}); log.err(" required by '{s}'", .{wasm.objects.items[required_feature >> 1].name}); log.err(" missing in '{s}'", .{object.name}); valid_feature_set = false; @@ -3432,7 +3464,8 @@ fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []con 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.tag.toString(); + var buf: [100]u8 = undefined; + const string = try std.fmt.bufPrint(&buf, "{}", .{feature.tag}); try leb.writeULEB128(writer, @intCast(u32, string.len)); try writer.writeAll(string); } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 92336efbf2..c2243bdf10 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -601,8 +601,8 @@ fn Parser(comptime ReaderType: type) type { }); for (relocations) |*relocation| { - const rel_type = try leb.readULEB128(u8, reader); - const rel_type_enum = @intToEnum(types.Relocation.RelocationType, rel_type); + const rel_type = try reader.readByte(); + const rel_type_enum = std.meta.intToEnum(types.Relocation.RelocationType, rel_type) catch return error.MalformedSection; relocation.* = .{ .relocation_type = rel_type_enum, .offset = try leb.readULEB128(u32, reader), diff --git a/src/link/Wasm/types.zig b/src/link/Wasm/types.zig index a65e352c46..d19f32b862 100644 --- a/src/link/Wasm/types.zig +++ b/src/link/Wasm/types.zig @@ -50,6 +50,8 @@ pub const Relocation = struct { .R_WASM_MEMORY_ADDR_LEB64, .R_WASM_MEMORY_ADDR_SLEB64, .R_WASM_MEMORY_ADDR_I64, + .R_WASM_MEMORY_ADDR_TLS_SLEB, + .R_WASM_MEMORY_ADDR_TLS_SLEB64, .R_WASM_FUNCTION_OFFSET_I32, .R_WASM_SECTION_OFFSET_I32, => true, @@ -218,8 +220,10 @@ pub const Feature = struct { return @intToEnum(Tag, @enumToInt(feature)); } - pub fn toString(tag: Tag) []const u8 { - return switch (tag) { + pub fn format(tag: Tag, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void { + _ = fmt; + _ = opt; + try writer.writeAll(switch (tag) { .atomics => "atomics", .bulk_memory => "bulk-memory", .exception_handling => "exception-handling", @@ -233,7 +237,7 @@ pub const Feature = struct { .simd128 => "simd128", .tail_call => "tail-call", .shared_mem => "shared-mem", - }; + }); } }; @@ -246,7 +250,7 @@ pub const Feature = struct { pub fn format(feature: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void { _ = opt; _ = fmt; - try writer.print("{c} {s}", .{ feature.prefix, feature.tag.toString() }); + try writer.print("{c} {}", .{ feature.prefix, feature.tag }); } }; |
