[lld][WebAssembly] Add `--extra-features` flag to add addional features

This flag acts just like the existing `--features` flag but instead
of replacing the set of inferred features it adds to it.

This is useful for example if you want to `--export` a mutable global
but none of the input of object were built with mutable global support.
In that case you can do `--extra-features=mutable-globals` to avoid the
linker error that would otherwise be generated in this case:

wasm-ld: error: mutable global exported but 'mutable-globals' feature not present in inputs: `__stack_pointer`. Use --no-check-features to suppress.

Differential Revision: https://reviews.llvm.org/D135831
This commit is contained in:
Sam Clegg 2022-10-12 16:39:47 -07:00
parent 0cd27cdc3a
commit c07e838130
5 changed files with 37 additions and 5 deletions

View File

@ -3,18 +3,17 @@
# Should fail without mutable globals feature enabled. # Should fail without mutable globals feature enabled.
# RUN: not wasm-ld --export-all %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s # RUN: not wasm-ld --export-all %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
# RUN: not wasm-ld --export=foo_global %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s # RUN: not wasm-ld --export=foo_global %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
#
# RUN: wasm-ld --features=mutable-globals --export=foo_global %t.o -o %t.wasm # RUN: wasm-ld --extra-features=mutable-globals --export=foo_global %t.o -o %t.wasm
# RUN: obj2yaml %t.wasm | FileCheck %s # RUN: obj2yaml %t.wasm | FileCheck %s
# Explcitly check that __stack_pointer can be exported # Explcitly check that __stack_pointer can be exported
# RUN: wasm-ld --features=mutable-globals --export=__stack_pointer %t.o -o %t.wasm # RUN: wasm-ld --extra-features=mutable-globals --export=__stack_pointer %t.o -o %t.wasm
# RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-SP %s # RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-SP %s
# RUN: wasm-ld --features=mutable-globals --export-all %t.o -o %t.wasm # RUN: wasm-ld --extra-features=mutable-globals --export-all %t.o -o %t.wasm
# RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-ALL %s # RUN: obj2yaml %t.wasm | FileCheck -check-prefix=CHECK-ALL %s
.globl _start .globl _start
.globl foo_global .globl foo_global
@ -25,6 +24,14 @@ _start:
.functype _start () -> () .functype _start () -> ()
end_function end_function
# Add a target feature and ensure that it is preserved when --extra-features is
# used above.
.section .custom_section.target_features,"",@
.int8 1
.int8 43
.int8 7
.ascii "atomics"
# CHECK-ERR: mutable global exported but 'mutable-globals' feature not present in inputs: `foo_global`. Use --no-check-features to suppress # CHECK-ERR: mutable global exported but 'mutable-globals' feature not present in inputs: `foo_global`. Use --no-check-features to suppress
# CHECK: - Type: EXPORT # CHECK: - Type: EXPORT
@ -86,3 +93,12 @@ _start:
# CHECK-ALL-NEXT: Kind: GLOBAL # CHECK-ALL-NEXT: Kind: GLOBAL
# CHECK-ALL-NEXT: Index: 7 # CHECK-ALL-NEXT: Index: 7
# CHECK-ALL-NEXT: - Type: CODE # CHECK-ALL-NEXT: - Type: CODE
# CHECK-ALL: Name: target_features
# CHECK-ALL-NEXT: Features:
# CHECK-ALL-NEXT: - Prefix: USED
# CHECK-ALL-NEXT: Name: atomics
# CHECK-ALL-NEXT: - Prefix: USED
# CHECK-ALL-NEXT: Name: mutable-globals
# CHECK-ALL-NEXT: ...

View File

@ -77,6 +77,7 @@ struct Configuration {
llvm::SmallVector<llvm::StringRef, 0> searchPaths; llvm::SmallVector<llvm::StringRef, 0> searchPaths;
llvm::CachePruningPolicy thinLTOCachePolicy; llvm::CachePruningPolicy thinLTOCachePolicy;
llvm::Optional<std::vector<std::string>> features; llvm::Optional<std::vector<std::string>> features;
llvm::Optional<std::vector<std::string>> extraFeatures;
// The following config options do not directly correspond to any // The following config options do not directly correspond to any
// particular command line options. // particular command line options.

View File

@ -469,6 +469,13 @@ static void readConfigs(opt::InputArgList &args) {
config->features->push_back(std::string(s)); config->features->push_back(std::string(s));
} }
if (auto *arg = args.getLastArg(OPT_extra_features)) {
config->extraFeatures =
llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
for (StringRef s : arg->getValues())
config->extraFeatures->push_back(std::string(s));
}
// Legacy --allow-undefined flag which is equivalent to // Legacy --allow-undefined flag which is equivalent to
// --unresolve-symbols=ignore + --import-undefined // --unresolve-symbols=ignore + --import-undefined
if (args.hasArg(OPT_allow_undefined)) { if (args.hasArg(OPT_allow_undefined)) {

View File

@ -220,6 +220,9 @@ defm check_features: BB<"check-features",
def features: CommaJoined<["--", "-"], "features=">, def features: CommaJoined<["--", "-"], "features=">,
HelpText<"Comma-separated used features, inferred from input objects by default.">; HelpText<"Comma-separated used features, inferred from input objects by default.">;
def extra_features: CommaJoined<["--", "-"], "extra-features=">,
HelpText<"Comma-separated list of features to add to the default set of features inferred from input objects.">;
// Aliases // Aliases
def: JoinedOrSeparate<["-"], "e">, Alias<entry>; def: JoinedOrSeparate<["-"], "e">, Alias<entry>;
def: J<"entry=">, Alias<entry>; def: J<"entry=">, Alias<entry>;

View File

@ -445,6 +445,11 @@ void Writer::populateTargetFeatures() {
allowed.insert("mutable-globals"); allowed.insert("mutable-globals");
} }
if (config->extraFeatures.has_value()) {
auto &extraFeatures = config->extraFeatures.value();
allowed.insert(extraFeatures.begin(), extraFeatures.end());
}
// Only infer used features if user did not specify features // Only infer used features if user did not specify features
bool inferFeatures = !config->features.has_value(); bool inferFeatures = !config->features.has_value();