[lld] r356975 - Reland "[WebAssembly] Add linker options to control feature checking"

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 25 21:11:06 PDT 2019


Author: tlively
Date: Mon Mar 25 21:11:05 2019
New Revision: 356975

URL: http://llvm.org/viewvc/llvm-project?rev=356975&view=rev
Log:
Reland "[WebAssembly] Add linker options to control feature checking"

Do not pipe binary data between processes in lit tests this time,
since it turns out that can break on Windows.

This reverts commit 84c8652fc3085155d0f9c355455e5a797c6d9db6.

Added:
    lld/trunk/test/wasm/target-feature-none.yaml
Modified:
    lld/trunk/test/wasm/target-feature-disallowed.yaml
    lld/trunk/test/wasm/target-feature-required.yaml
    lld/trunk/test/wasm/target-feature-used.yaml
    lld/trunk/wasm/Config.h
    lld/trunk/wasm/Driver.cpp
    lld/trunk/wasm/Options.td
    lld/trunk/wasm/Writer.cpp

Modified: lld/trunk/test/wasm/target-feature-disallowed.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-disallowed.yaml?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/test/wasm/target-feature-disallowed.yaml (original)
+++ lld/trunk/test/wasm/target-feature-disallowed.yaml Mon Mar 25 21:11:05 2019
@@ -1,12 +1,18 @@
 # RUN: yaml2obj %s -o %t1.o
 
+# RUN: wasm-ld --no-entry --features=foo,bar,baz -o %t.specified.wasm %t1.o
+# RUN: obj2yaml %t.specified.wasm | FileCheck %s --check-prefix SPECIFIED
+
+# RUN: wasm-ld --no-entry --features=bar,baz,quux -o %t.unspecified.wasm %t1.o
+# RUN: obj2yaml %t.unspecified.wasm | FileCheck %s --check-prefix UNSPECIFIED
+
 # RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
-# RUN: wasm-ld --no-entry -o %t.disallowed.exe %t1.o %t.disallowed.o
-# RUN: obj2yaml < %t.disallowed.exe | FileCheck %s --check-prefix DISALLOWED
+# RUN: wasm-ld --no-entry -o %t.disallowed.wasm %t1.o %t.disallowed.o
+# RUN: obj2yaml %t.disallowed.wasm | FileCheck %s --check-prefix DISALLOWED
 
 # RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
-# RUN: wasm-ld --no-entry -o %t.none.exe %t1.o %t.none.o
-# RUN: obj2yaml < %t.none.exe | FileCheck %s --check-prefix NONE
+# RUN: wasm-ld --no-entry -o %t.none.wasm %t1.o %t.none.o
+# RUN: obj2yaml %t.none.wasm | FileCheck %s --check-prefix NONE
 
 # Check that the following combinations of feature linkage policies
 # give the expected results:
@@ -31,6 +37,28 @@ Sections:
         Name:          "bar"
 ...
 
+# SPECIFIED:        - Type:            CUSTOM
+# SPECIFIED-NEXT:     Name:            target_features
+# SPECIFIED-NEXT:     Features:
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            bar
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            baz
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            foo
+# SPECIFIED-NEXT: ...
+
+# UNSPECIFIED:        - Type:            CUSTOM
+# UNSPECIFIED-NEXT:     Name:            target_features
+# UNSPECIFIED-NEXT:     Features:
+# UNSPECIFIED-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NEXT:         Name:            bar
+# UNSPECIFIED-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NEXT:         Name:            baz
+# UNSPECIFIED-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NEXT:         Name:            quux
+# UNSPECIFIED-NEXT: ...
+
 # DISALLOWED:        - Type:            CUSTOM
 # DISALLOWED-NEXT:     Name:            target_features
 # DISALLOWED-NEXT:     Features:

Added: lld/trunk/test/wasm/target-feature-none.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-none.yaml?rev=356975&view=auto
==============================================================================
--- lld/trunk/test/wasm/target-feature-none.yaml (added)
+++ lld/trunk/test/wasm/target-feature-none.yaml Mon Mar 25 21:11:05 2019
@@ -0,0 +1,36 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# RUN: wasm-ld --no-entry -o %t.empty.wasm %t1.o
+# RUN: obj2yaml %t.empty.wasm | FileCheck %s --check-prefix EMPTY
+
+# RUN: wasm-ld --no-entry --features= -o %t.empty.2.wasm %t1.o
+# RUN: obj2yaml %t.empty.2.wasm | FileCheck %s --check-prefix EMPTY
+
+# RUN: wasm-ld --no-entry --features=foo,bar,baz -o %t.specified.wasm %t1.o
+# RUN: obj2yaml %t.specified.wasm | FileCheck %s --check-prefix SPECIFIED
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:        [ ]
+...
+
+# section is not emitted if it would be empty
+# EMPTY-NOT: target_features
+
+# SPECIFIED:        - Type:            CUSTOM
+# SPECIFIED-NEXT:     Name:            target_features
+# SPECIFIED-NEXT:     Features:
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            bar
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            baz
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            foo
+# SPECIFIED-NEXT: ...

Modified: lld/trunk/test/wasm/target-feature-required.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-required.yaml?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/test/wasm/target-feature-required.yaml (original)
+++ lld/trunk/test/wasm/target-feature-required.yaml Mon Mar 25 21:11:05 2019
@@ -1,15 +1,29 @@
 # RUN: yaml2obj %s -o %t1.o
 
+# RUN: wasm-ld --no-entry --features=foo,bar,baz -o %t.specified.wasm %t1.o
+# RUN: obj2yaml %t.specified.wasm | FileCheck %s --check-prefix SPECIFIED
+
+# RUN: not wasm-ld --no-entry --features=bar,baz,quux -o - %t1.o 2>&1 | FileCheck %s --check-prefix UNSPECIFIED
+
+# RUN: wasm-ld --no-entry --no-check-features --features=bar,baz,quux -o %t.unspecified.wasm %t1.o
+# RUN: obj2yaml %t.unspecified.wasm | FileCheck %s --check-prefix UNSPECIFIED-NOCHECK
+
 # RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
-# RUN: wasm-ld --no-entry -o %t.required.exe %t1.o %t.required.o
-# RUN: obj2yaml < %t.required.exe | FileCheck %s --check-prefix REQUIRED
+# RUN: wasm-ld --no-entry -o %t.required.wasm %t1.o %t.required.o
+# RUN: obj2yaml %t.required.wasm | FileCheck %s --check-prefix REQUIRED
 
 # RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
 # RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
 
+# RUN: wasm-ld --no-entry --no-check-features -o %t.disallowed.wasm %t1.o %t.disallowed.o
+# RUN: obj2yaml %t.disallowed.wasm | FileCheck %s --check-prefix DISALLOWED-NOCHECK
+
 # RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
 # RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.none.o 2>&1 | FileCheck %s --check-prefix NONE
 
+# RUN: wasm-ld --no-entry --no-check-features -o %t.none.wasm %t1.o %t.none.o
+# RUN: obj2yaml %t.none.wasm | FileCheck %s --check-prefix NONE-NOCHECK
+
 # Check that the following combinations of feature linkage policies
 # give the expected results:
 #
@@ -31,6 +45,30 @@ Sections:
         Name:          "foo"
 ...
 
+# SPECIFIED:        - Type:            CUSTOM
+# SPECIFIED-NEXT:     Name:            target_features
+# SPECIFIED-NEXT:     Features:
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            bar
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            baz
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            foo
+# SPECIFIED-NEXT: ...
+
+# UNSPECIFIED: Target feature 'foo' is not allowed.{{$}}
+
+# UNSPECIFIED-NOCHECK:        - Type:            CUSTOM
+# UNSPECIFIED-NOCHECK-NEXT:     Name:            target_features
+# UNSPECIFIED-NOCHECK-NEXT:     Features:
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            bar
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            baz
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            quux
+# UNSPECIFIED-NOCHECK-NEXT: ...
+
 # REQUIRED:        - Type:            CUSTOM
 # REQUIRED-NEXT:     Name:            target_features
 # REQUIRED-NEXT:     Features:
@@ -38,6 +76,20 @@ Sections:
 # REQUIRED-NEXT:         Name:            foo
 # REQUIRED-NEXT: ...
 
-# DISALLOWED: Target feature "foo" is disallowed
+# DISALLOWED: Target feature 'foo' is disallowed. Use --no-check-features to suppress.{{$}}
 
-# NONE: Missing required target feature "foo"
+# DISALLOWED-NOCHECK:        - Type:            CUSTOM
+# DISALLOWED-NOCHECK-NEXT:     Name:            target_features
+# DISALLOWED-NOCHECK-NEXT:     Features:
+# DISALLOWED-NOCHECK-NEXT:       - Prefix:          USED
+# DISALLOWED-NOCHECK-NEXT:         Name:            foo
+# DISALLOWED-NOCHECK-NEXT: ...
+
+# NONE: Missing required target feature 'foo'. Use --no-check-features to suppress.{{$}}
+
+# NONE-NOCHECK:        - Type:            CUSTOM
+# NONE-NOCHECK-NEXT:     Name:            target_features
+# NONE-NOCHECK-NEXT:     Features:
+# NONE-NOCHECK-NEXT:       - Prefix:          USED
+# NONE-NOCHECK-NEXT:         Name:            foo
+# NONE-NOCHECK-NEXT: ...

Modified: lld/trunk/test/wasm/target-feature-used.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-used.yaml?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/test/wasm/target-feature-used.yaml (original)
+++ lld/trunk/test/wasm/target-feature-used.yaml Mon Mar 25 21:11:05 2019
@@ -1,19 +1,30 @@
 # RUN: yaml2obj %s -o %t1.o
 
+# RUN: wasm-ld --no-entry --features=foo,bar,baz -o %t.specified.wasm %t1.o
+# RUN: obj2yaml %t.specified.wasm | FileCheck %s --check-prefix SPECIFIED
+
+# RUN: not wasm-ld --no-entry --features=bar,baz,quux -o - %t1.o 2>&1 | FileCheck %s --check-prefix UNSPECIFIED
+
+# RUN: wasm-ld --no-entry --no-check-features --features=bar,baz,quux -o %t.unspecified.wasm %t1.o
+# RUN: obj2yaml %t.unspecified.wasm| FileCheck %s --check-prefix UNSPECIFIED-NOCHECK
+
 # RUN: yaml2obj %S/Inputs/use-feature-foo.yaml -o %t.used.o
-# RUN: wasm-ld --no-entry -o %t.used.exe %t1.o %t.used.o
-# RUN: obj2yaml < %t.used.exe | FileCheck %s --check-prefix USED
+# RUN: wasm-ld --no-entry -o %t.used.wasm %t1.o %t.used.o
+# RUN: obj2yaml %t.used.wasm | FileCheck %s --check-prefix USED
 
 # RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
-# RUN: wasm-ld --no-entry -o %t.required.exe %t1.o %t.required.o
-# RUN: obj2yaml < %t.required.exe | FileCheck %s --check-prefix REQUIRED
+# RUN: wasm-ld --no-entry -o %t.required.wasm %t1.o %t.required.o
+# RUN: obj2yaml %t.required.wasm | FileCheck %s --check-prefix REQUIRED
 
 # RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
 # RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
 
+# RUN: wasm-ld --no-entry --no-check-features -o %t.disallowed.wasm %t1.o %t.disallowed.o
+# RUN: obj2yaml %t.disallowed.wasm | FileCheck %s --check-prefix DISALLOWED-NOCHECK
+
 # RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
-# RUN: wasm-ld --no-entry -o %t.none.exe %t1.o %t.none.o
-# RUN: obj2yaml %t.none.exe | FileCheck %s --check-prefix NONE
+# RUN: wasm-ld --no-entry -o %t.none.wasm %t1.o %t.none.o
+# RUN: obj2yaml %t.none.wasm | FileCheck %s --check-prefix NONE
 
 # Check that the following combinations of feature linkage policies
 # give the expected results:
@@ -37,6 +48,30 @@ Sections:
         Name:          "foo"
 ...
 
+# SPECIFIED:        - Type:            CUSTOM
+# SPECIFIED-NEXT:     Name:            target_features
+# SPECIFIED-NEXT:     Features:
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            bar
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            baz
+# SPECIFIED-NEXT:       - Prefix:          USED
+# SPECIFIED-NEXT:         Name:            foo
+# SPECIFIED-NEXT: ...
+
+# UNSPECIFIED: Target feature 'foo' is not allowed.{{$}}
+
+# UNSPECIFIED-NOCHECK:        - Type:            CUSTOM
+# UNSPECIFIED-NOCHECK-NEXT:     Name:            target_features
+# UNSPECIFIED-NOCHECK-NEXT:     Features:
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            bar
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            baz
+# UNSPECIFIED-NOCHECK-NEXT:       - Prefix:          USED
+# UNSPECIFIED-NOCHECK-NEXT:         Name:            quux
+# UNSPECIFIED-NOCHECK-NEXT: ...
+
 # USED:        - Type:            CUSTOM
 # USED-NEXT:     Name:            target_features
 # USED-NEXT:     Features:
@@ -51,7 +86,14 @@ Sections:
 # REQUIRED-NEXT:         Name:            foo
 # REQUIRED-NEXT: ...
 
-# DISALLOWED: Target feature "foo" is disallowed
+# DISALLOWED: Target feature 'foo' is disallowed. Use --no-check-features to suppress.{{$}}
+
+# DISALLOWED-NOCHECK:        - Type:            CUSTOM
+# DISALLOWED-NOCHECK-NEXT:     Name:            target_features
+# DISALLOWED-NOCHECK-NEXT:     Features:
+# DISALLOWED-NOCHECK-NEXT:       - Prefix:          USED
+# DISALLOWED-NOCHECK-NEXT:         Name:            foo
+# DISALLOWED-NOCHECK-NEXT: ...
 
 # NONE:        - Type:            CUSTOM
 # NONE-NEXT:     Name:            target_features

Modified: lld/trunk/wasm/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Config.h?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/wasm/Config.h (original)
+++ lld/trunk/wasm/Config.h Mon Mar 25 21:11:05 2019
@@ -19,6 +19,7 @@ namespace wasm {
 
 struct Configuration {
   bool AllowUndefined;
+  bool CheckFeatures;
   bool CompressRelocations;
   bool Demangle;
   bool DisableVerify;
@@ -54,6 +55,7 @@ struct Configuration {
   llvm::StringSet<> AllowUndefinedSymbols;
   std::vector<llvm::StringRef> SearchPaths;
   llvm::CachePruningPolicy ThinLTOCachePolicy;
+  llvm::Optional<std::vector<std::string>> Features;
 
   // True if we are creating position-independent code.
   bool Pic;

Modified: lld/trunk/wasm/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Driver.cpp?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/wasm/Driver.cpp (original)
+++ lld/trunk/wasm/Driver.cpp Mon Mar 25 21:11:05 2019
@@ -21,6 +21,7 @@
 #include "lld/Common/Version.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Object/Wasm.h"
+#include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Path.h"
@@ -292,6 +293,8 @@ static StringRef getEntry(opt::InputArgL
 // of these values.
 static void setConfigs(opt::InputArgList &Args) {
   Config->AllowUndefined = Args.hasArg(OPT_allow_undefined);
+  Config->CheckFeatures =
+      Args.hasFlag(OPT_check_features, OPT_no_check_features, true);
   Config->CompressRelocations = Args.hasArg(OPT_compress_relocations);
   Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
   Config->DisableVerify = Args.hasArg(OPT_disable_verify);
@@ -339,6 +342,13 @@ static void setConfigs(opt::InputArgList
   Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0);
   Config->ZStackSize =
       args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize);
+
+  if (auto *Arg = Args.getLastArg(OPT_features)) {
+    Config->Features =
+        llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
+    for (StringRef S : Arg->getValues())
+      Config->Features->push_back(S);
+  }
 }
 
 // Some command line options or some combinations of them are not allowed.

Modified: lld/trunk/wasm/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Options.td?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/wasm/Options.td (original)
+++ lld/trunk/wasm/Options.td Mon Mar 25 21:11:05 2019
@@ -155,6 +155,13 @@ defm whole_archive: B<"whole-archive",
     "Force load of all members in a static library",
     "Do not force load of all members in a static library (default)">;
 
+defm check_features: B<"check-features",
+    "Check feature compatibility of linked objects (default)",
+    "Ignore feature compatibility of linked objects">;
+
+def features: CommaJoined<["--", "-"], "features=">,
+  HelpText<"Comma-separated used features, inferred from input objects by default.">;
+
 // Aliases
 def: JoinedOrSeparate<["-"], "e">, Alias<entry>;
 def: J<"entry=">, Alias<entry>;

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=356975&r1=356974&r2=356975&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Mon Mar 25 21:11:05 2019
@@ -878,18 +878,30 @@ void Writer::createSections() {
 }
 
 void Writer::calculateTargetFeatures() {
+  SmallSet<std::string, 8> Used;
   SmallSet<std::string, 8> Required;
   SmallSet<std::string, 8> Disallowed;
 
+  // Only infer used features if user did not specify features
+  bool InferFeatures = !Config->Features.hasValue();
+
+  if (!InferFeatures) {
+    for (auto &Feature : Config->Features.getValue())
+      TargetFeatures.insert(Feature);
+    // No need to read or check features
+    if (!Config->CheckFeatures)
+      return;
+  }
+
   // Find the sets of used, required, and disallowed features
   for (ObjFile *File : Symtab->ObjectFiles) {
     for (auto &Feature : File->getWasmObj()->getTargetFeatures()) {
       switch (Feature.Prefix) {
       case WASM_FEATURE_PREFIX_USED:
-        TargetFeatures.insert(Feature.Name);
+        Used.insert(Feature.Name);
         break;
       case WASM_FEATURE_PREFIX_REQUIRED:
-        TargetFeatures.insert(Feature.Name);
+        Used.insert(Feature.Name);
         Required.insert(Feature.Name);
         break;
       case WASM_FEATURE_PREFIX_DISALLOWED:
@@ -902,6 +914,20 @@ void Writer::calculateTargetFeatures() {
     }
   }
 
+  if (InferFeatures)
+    TargetFeatures.insert(Used.begin(), Used.end());
+
+  if (!Config->CheckFeatures)
+    return;
+
+  // Validate that used features are allowed in output
+  if (!InferFeatures) {
+    for (auto &Feature : Used) {
+      if (!TargetFeatures.count(Feature))
+        error(Twine("Target feature '") + Feature + "' is not allowed.");
+    }
+  }
+
   // Validate the required and disallowed constraints for each file
   for (ObjFile *File : Symtab->ObjectFiles) {
     SmallSet<std::string, 8> ObjectFeatures;
@@ -910,11 +936,13 @@ void Writer::calculateTargetFeatures() {
         continue;
       ObjectFeatures.insert(Feature.Name);
       if (Disallowed.count(Feature.Name))
-        error("Target feature \"" + Feature.Name + "\" is disallowed");
+        error(Twine("Target feature '") + Feature.Name +
+              "' is disallowed. Use --no-check-features to suppress.");
     }
     for (auto &Feature : Required) {
       if (!ObjectFeatures.count(Feature))
-        error(Twine("Missing required target feature \"") + Feature + "\"");
+        error(Twine("Missing required target feature '") + Feature +
+              "'. Use --no-check-features to suppress.");
     }
   }
 }




More information about the llvm-commits mailing list