[lld] r356610 - [WebAssembly] Target features section

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 20 13:26:45 PDT 2019


Author: tlively
Date: Wed Mar 20 13:26:45 2019
New Revision: 356610

URL: http://llvm.org/viewvc/llvm-project?rev=356610&view=rev
Log:
[WebAssembly] Target features section

Summary:
Implements a new target features section in assembly and object files
that records what features are used, required, and disallowed in
WebAssembly objects. The linker uses this information to ensure that
all objects participating in a link are feature-compatible and records
the set of used features in the output binary for use by optimizers
and other tools later in the toolchain.

The "atomics" feature is always required or disallowed to prevent
linking code with stripped atomics into multithreaded binaries. Other
features are marked used if they are enabled globally or on any
function in a module.

Future CLs will add linker flags for ignoring feature compatibility
checks and for specifying the set of allowed features, implement using
the presence of the "atomics" feature to control the type of memory
and segments in the linked binary, and add front-end flags for
relaxing the linkage policy for atomics.

Reviewers: aheejin, sbc100, dschuff

Subscribers: jgravelle-google, hiraditya, sunfish, mgrang, jfb, jdoerfert, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59173

Added:
    lld/trunk/test/wasm/Inputs/disallow-feature-foo.yaml
    lld/trunk/test/wasm/Inputs/no-feature-foo.yaml
    lld/trunk/test/wasm/Inputs/require-feature-foo.yaml
    lld/trunk/test/wasm/Inputs/use-feature-foo.yaml
    lld/trunk/test/wasm/target-feature-disallowed.yaml
    lld/trunk/test/wasm/target-feature-required.yaml
    lld/trunk/test/wasm/target-feature-used.yaml
Modified:
    lld/trunk/wasm/InputFiles.cpp
    lld/trunk/wasm/InputFiles.h
    lld/trunk/wasm/Writer.cpp

Added: lld/trunk/test/wasm/Inputs/disallow-feature-foo.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/disallow-feature-foo.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/disallow-feature-foo.yaml (added)
+++ lld/trunk/test/wasm/Inputs/disallow-feature-foo.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,13 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        DISALLOWED
+        Name:          "foo"
+...

Added: lld/trunk/test/wasm/Inputs/no-feature-foo.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/no-feature-foo.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/no-feature-foo.yaml (added)
+++ lld/trunk/test/wasm/Inputs/no-feature-foo.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,11 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:        [ ]
+...

Added: lld/trunk/test/wasm/Inputs/require-feature-foo.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/require-feature-foo.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/require-feature-foo.yaml (added)
+++ lld/trunk/test/wasm/Inputs/require-feature-foo.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,13 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        REQUIRED
+        Name:          "foo"
+...

Added: lld/trunk/test/wasm/Inputs/use-feature-foo.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/use-feature-foo.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/use-feature-foo.yaml (added)
+++ lld/trunk/test/wasm/Inputs/use-feature-foo.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,13 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        USED
+        Name:          "foo"
+...

Added: lld/trunk/test/wasm/target-feature-disallowed.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-disallowed.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/target-feature-disallowed.yaml (added)
+++ lld/trunk/test/wasm/target-feature-disallowed.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,44 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.disallowed.o | obj2yaml | FileCheck %s --check-prefix DISALLOWED
+
+# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.none.o | obj2yaml | FileCheck %s --check-prefix NONE
+
+# Check that the following combinations of feature linkage policies
+# give the expected results:
+#
+#     DISALLOWED x DISALLOWED => NONE
+#     DISALLOWED x NONE => NONE
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        DISALLOWED
+        Name:          "foo"
+        # included so output has target features section
+      - Prefix:        USED
+        Name:          "bar"
+...
+
+# DISALLOWED:        - Type:            CUSTOM
+# DISALLOWED-NEXT:     Name:            target_features
+# DISALLOWED-NEXT:     Features:
+# DISALLOWED-NEXT:       - Prefix:          USED
+# DISALLOWED-NEXT:         Name:            bar
+# DISALLOWED-NEXT: ...
+
+# NONE:        - Type:            CUSTOM
+# NONE-NEXT:     Name:            target_features
+# NONE-NEXT:     Features:
+# NONE-NEXT:       - Prefix:          USED
+# NONE-NEXT:         Name:            bar
+# NONE-NEXT: ...

Added: lld/trunk/test/wasm/target-feature-required.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-required.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/target-feature-required.yaml (added)
+++ lld/trunk/test/wasm/target-feature-required.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,42 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.required.o | obj2yaml | FileCheck %s --check-prefix REQUIRED
+
+# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
+# RUN: not wasm-ld --no-entry -o - %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
+
+# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
+# RUN: not wasm-ld --no-entry -o - %t1.o %t.none.o 2>&1 | FileCheck %s --check-prefix NONE
+
+# Check that the following combinations of feature linkage policies
+# give the expected results:
+#
+#     REQUIRED x REQUIRED => USED
+#     REQUIRED x DISALLOWED => Error
+#     REQUIRED x NONE => Error
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        REQUIRED
+        Name:          "foo"
+...
+
+# REQUIRED:        - Type:            CUSTOM
+# REQUIRED-NEXT:     Name:            target_features
+# REQUIRED-NEXT:     Features:
+# REQUIRED-NEXT:       - Prefix:          USED
+# REQUIRED-NEXT:         Name:            foo
+# REQUIRED-NEXT: ...
+
+# DISALLOWED: Target feature "foo" is disallowed
+
+# NONE: Missing required target feature "foo"

Added: lld/trunk/test/wasm/target-feature-used.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/target-feature-used.yaml?rev=356610&view=auto
==============================================================================
--- lld/trunk/test/wasm/target-feature-used.yaml (added)
+++ lld/trunk/test/wasm/target-feature-used.yaml Wed Mar 20 13:26:45 2019
@@ -0,0 +1,58 @@
+# RUN: yaml2obj %s -o %t1.o
+
+# RUN: yaml2obj %S/Inputs/use-feature-foo.yaml -o %t.used.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.used.o | obj2yaml | FileCheck %s --check-prefix USED
+
+# RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.required.o | obj2yaml | FileCheck %s --check-prefix REQUIRED
+
+# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
+# RUN: not wasm-ld --no-entry -o - %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
+
+# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
+# RUN: wasm-ld --no-entry -o - %t1.o %t.none.o | obj2yaml | FileCheck %s --check-prefix NONE
+
+# Check that the following combinations of feature linkage policies
+# give the expected results:
+#
+#     USED x USED => USED
+#     USED x REQUIRED => USED
+#     USED x DISALLOWED => Error
+#     USED x NONE => USED
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            linking
+    Version:         2
+  - Type:            CUSTOM
+    Name:            target_features
+    Features:
+      - Prefix:        USED
+        Name:          "foo"
+...
+
+# USED:        - Type:            CUSTOM
+# USED-NEXT:     Name:            target_features
+# USED-NEXT:     Features:
+# USED-NEXT:       - Prefix:          USED
+# USED-NEXT:         Name:            foo
+# USED-NEXT: ...
+
+# REQUIRED:        - Type:            CUSTOM
+# REQUIRED-NEXT:     Name:            target_features
+# REQUIRED-NEXT:     Features:
+# REQUIRED-NEXT:       - Prefix:          USED
+# REQUIRED-NEXT:         Name:            foo
+# REQUIRED-NEXT: ...
+
+# DISALLOWED: Target feature "foo" is disallowed
+
+# NONE:        - Type:            CUSTOM
+# NONE-NEXT:     Name:            target_features
+# NONE-NEXT:     Features:
+# NONE-NEXT:       - Prefix:          USED
+# NONE-NEXT:         Name:            foo
+# NONE-NEXT: ...

Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=356610&r1=356609&r2=356610&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Wed Mar 20 13:26:45 2019
@@ -244,8 +244,6 @@ void ObjFile::parse() {
       CustomSections.emplace_back(make<InputSection>(Section, this));
       CustomSections.back()->setRelocations(Section.Relocations);
       CustomSectionsByIndex[SectionIndex] = CustomSections.back();
-      if (Section.Name == "producers")
-        ProducersSection = &Section;
     }
     SectionIndex++;
   }

Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=356610&r1=356609&r2=356610&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Wed Mar 20 13:26:45 2019
@@ -99,7 +99,6 @@ public:
 
   const WasmSection *CodeSection = nullptr;
   const WasmSection *DataSection = nullptr;
-  const WasmSection *ProducersSection = nullptr;
 
   // Maps input type indices to output type indices
   std::vector<uint32_t> TypeMap;

Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=356610&r1=356609&r2=356610&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Wed Mar 20 13:26:45 2019
@@ -20,6 +20,7 @@
 #include "lld/Common/Strings.h"
 #include "lld/Common/Threads.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/BinaryFormat/Wasm.h"
@@ -68,6 +69,7 @@ private:
   void calculateInitFunctions();
   void processRelocations(InputChunk *Chunk);
   void assignIndexes();
+  void calculateTargetFeatures();
   void calculateImports();
   void calculateExports();
   void calculateCustomSections();
@@ -99,6 +101,7 @@ private:
   void createLinkingSection();
   void createNameSection();
   void createProducersSection();
+  void createTargetFeaturesSection();
 
   void writeHeader();
   void writeSections();
@@ -129,6 +132,7 @@ private:
 
   llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
   llvm::StringMap<SectionSymbol *> CustomSectionSymbols;
+  llvm::SmallSet<std::string, 8> TargetFeatures;
 
   // Elements that are used to construct the final output
   std::string Header;
@@ -344,7 +348,7 @@ void Writer::calculateCustomSections() {
       // These custom sections are known the linker and synthesized rather than
       // blindly copied
       if (Name == "linking" || Name == "name" || Name == "producers" ||
-          Name.startswith("reloc."))
+          Name == "target_features" || Name.startswith("reloc."))
         continue;
       // .. or it is a debug section
       if (StripDebug && Name.startswith(".debug_"))
@@ -701,6 +705,23 @@ void Writer::createProducersSection() {
   }
 }
 
+void Writer::createTargetFeaturesSection() {
+  if (TargetFeatures.size() == 0)
+    return;
+
+  SmallVector<std::string, 8> Emitted(TargetFeatures.begin(),
+                                      TargetFeatures.end());
+  std::sort(Emitted.begin(), Emitted.end());
+  SyntheticSection *Section =
+      createSyntheticSection(WASM_SEC_CUSTOM, "target_features");
+  auto &OS = Section->getStream();
+  writeUleb128(OS, Emitted.size(), "feature count");
+  for (auto &Feature : Emitted) {
+    writeU8(OS, WASM_FEATURE_PREFIX_USED, "feature used prefix");
+    writeStr(OS, Feature, "feature name");
+  }
+}
+
 void Writer::writeHeader() {
   memcpy(Buffer->getBufferStart(), Header.data(), Header.size());
 }
@@ -844,8 +865,10 @@ void Writer::createSections() {
   if (!Config->StripDebug && !Config->StripAll)
     createNameSection();
 
-  if (!Config->StripAll)
+  if (!Config->StripAll) {
     createProducersSection();
+    createTargetFeaturesSection();
+  }
 
   for (OutputSection *S : OutputSections) {
     S->setOffset(FileSize);
@@ -854,6 +877,48 @@ void Writer::createSections() {
   }
 }
 
+void Writer::calculateTargetFeatures() {
+  SmallSet<std::string, 8> Required;
+  SmallSet<std::string, 8> Disallowed;
+
+  // 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);
+        break;
+      case WASM_FEATURE_PREFIX_REQUIRED:
+        TargetFeatures.insert(Feature.Name);
+        Required.insert(Feature.Name);
+        break;
+      case WASM_FEATURE_PREFIX_DISALLOWED:
+        Disallowed.insert(Feature.Name);
+        break;
+      default:
+        error("Unrecognized feature policy prefix " +
+              std::to_string(Feature.Prefix));
+      }
+    }
+  }
+
+  // Validate the required and disallowed constraints for each file
+  for (ObjFile *File : Symtab->ObjectFiles) {
+    SmallSet<std::string, 8> ObjectFeatures;
+    for (auto &Feature : File->getWasmObj()->getTargetFeatures()) {
+      if (Feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED)
+        continue;
+      ObjectFeatures.insert(Feature.Name);
+      if (Disallowed.count(Feature.Name))
+        error("Target feature \"" + Feature.Name + "\" is disallowed");
+    }
+    for (auto &Feature : Required) {
+      if (!ObjectFeatures.count(Feature))
+        error(Twine("Missing required target feature \"") + Feature + "\"");
+    }
+  }
+}
+
 void Writer::calculateImports() {
   for (Symbol *Sym : Symtab->getSymbols()) {
     if (!Sym->isUndefined())
@@ -1225,6 +1290,8 @@ void Writer::run() {
   if (!Config->Pic)
     TableBase = 1;
 
+  log("-- calculateTargetFeatures");
+  calculateTargetFeatures();
   log("-- calculateImports");
   calculateImports();
   log("-- assignIndexes");




More information about the llvm-commits mailing list