summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/Inputs/disallow-feature-foo.yaml13
-rw-r--r--lld/test/wasm/Inputs/no-feature-foo.yaml11
-rw-r--r--lld/test/wasm/Inputs/require-feature-foo.yaml13
-rw-r--r--lld/test/wasm/Inputs/use-feature-foo.yaml13
-rw-r--r--lld/test/wasm/target-feature-disallowed.yaml44
-rw-r--r--lld/test/wasm/target-feature-required.yaml42
-rw-r--r--lld/test/wasm/target-feature-used.yaml58
-rw-r--r--lld/wasm/InputFiles.cpp2
-rw-r--r--lld/wasm/InputFiles.h1
-rw-r--r--lld/wasm/Writer.cpp71
-rw-r--r--llvm/include/llvm/BinaryFormat/Wasm.h12
-rw-r--r--llvm/include/llvm/Object/Wasm.h7
-rw-r--r--llvm/include/llvm/ObjectYAML/WasmYAML.h26
-rw-r--r--llvm/lib/MC/MCParser/WasmAsmParser.cpp7
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp11
-rw-r--r--llvm/lib/Object/WasmObjectFile.cpp37
-rw-r--r--llvm/lib/ObjectYAML/WasmYAML.cpp25
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp58
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h1
-rw-r--r--llvm/test/CodeGen/WebAssembly/target-features.ll67
-rw-r--r--llvm/test/MC/WebAssembly/array-fill.ll5
-rw-r--r--llvm/test/MC/WebAssembly/assembler-binary.ll5
-rw-r--r--llvm/test/MC/WebAssembly/bss.ll5
-rw-r--r--llvm/test/MC/WebAssembly/comdat.ll5
-rw-r--r--llvm/test/MC/WebAssembly/debug-info.ll6
-rw-r--r--llvm/test/MC/WebAssembly/explicit-sections.ll5
-rw-r--r--llvm/test/MC/WebAssembly/global-ctor-dtor.ll5
-rw-r--r--llvm/test/MC/WebAssembly/visibility.ll5
-rw-r--r--llvm/test/MC/WebAssembly/weak-alias.ll5
-rw-r--r--llvm/test/MC/WebAssembly/weak.ll5
-rw-r--r--llvm/test/ObjectYAML/wasm/target-features-section.yaml25
-rw-r--r--llvm/tools/obj2yaml/wasm2yaml.cpp10
-rw-r--r--llvm/tools/yaml2obj/yaml2wasm.cpp16
33 files changed, 611 insertions, 10 deletions
diff --git a/lld/test/wasm/Inputs/disallow-feature-foo.yaml b/lld/test/wasm/Inputs/disallow-feature-foo.yaml
new file mode 100644
index 00000000000..f4f987ef090
--- /dev/null
+++ b/lld/test/wasm/Inputs/disallow-feature-foo.yaml
@@ -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"
+...
diff --git a/lld/test/wasm/Inputs/no-feature-foo.yaml b/lld/test/wasm/Inputs/no-feature-foo.yaml
new file mode 100644
index 00000000000..6456d042707
--- /dev/null
+++ b/lld/test/wasm/Inputs/no-feature-foo.yaml
@@ -0,0 +1,11 @@
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: CUSTOM
+ Name: linking
+ Version: 2
+ - Type: CUSTOM
+ Name: target_features
+ Features: [ ]
+...
diff --git a/lld/test/wasm/Inputs/require-feature-foo.yaml b/lld/test/wasm/Inputs/require-feature-foo.yaml
new file mode 100644
index 00000000000..cf42b79fa4b
--- /dev/null
+++ b/lld/test/wasm/Inputs/require-feature-foo.yaml
@@ -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"
+...
diff --git a/lld/test/wasm/Inputs/use-feature-foo.yaml b/lld/test/wasm/Inputs/use-feature-foo.yaml
new file mode 100644
index 00000000000..0d1203454c0
--- /dev/null
+++ b/lld/test/wasm/Inputs/use-feature-foo.yaml
@@ -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"
+...
diff --git a/lld/test/wasm/target-feature-disallowed.yaml b/lld/test/wasm/target-feature-disallowed.yaml
new file mode 100644
index 00000000000..9a94f0d1f10
--- /dev/null
+++ b/lld/test/wasm/target-feature-disallowed.yaml
@@ -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: ...
diff --git a/lld/test/wasm/target-feature-required.yaml b/lld/test/wasm/target-feature-required.yaml
new file mode 100644
index 00000000000..68df45c194a
--- /dev/null
+++ b/lld/test/wasm/target-feature-required.yaml
@@ -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"
diff --git a/lld/test/wasm/target-feature-used.yaml b/lld/test/wasm/target-feature-used.yaml
new file mode 100644
index 00000000000..6a353991f54
--- /dev/null
+++ b/lld/test/wasm/target-feature-used.yaml
@@ -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: ...
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 5c9ae60e543..b43cab7fd38 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -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++;
}
diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h
index 1f44f5b5ec3..0913725b854 100644
--- a/lld/wasm/InputFiles.h
+++ b/lld/wasm/InputFiles.h
@@ -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;
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 96c473629cf..897908a5ad0 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -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");
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 7848be1cbfa..443c2a5d2c6 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -48,6 +48,11 @@ struct WasmProducerInfo {
std::vector<std::pair<std::string, std::string>> SDKs;
};
+struct WasmFeatureEntry {
+ uint8_t Prefix;
+ std::string Name;
+};
+
struct WasmExport {
StringRef Name;
uint8_t Kind;
@@ -253,6 +258,13 @@ enum : unsigned {
WASM_SEGMENT_HAS_MEMINDEX = 0x02,
};
+// Feature policy prefixes used in the custom "target_features" section
+enum : uint8_t {
+ WASM_FEATURE_PREFIX_USED = '+',
+ WASM_FEATURE_PREFIX_REQUIRED = '=',
+ WASM_FEATURE_PREFIX_DISALLOWED = '-',
+};
+
// Kind codes used in the custom "name" section
enum : unsigned {
WASM_NAMES_FUNCTION = 0x1,
diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h
index e3d1e24bdbc..02220dbcf0f 100644
--- a/llvm/include/llvm/Object/Wasm.h
+++ b/llvm/include/llvm/Object/Wasm.h
@@ -130,6 +130,9 @@ public:
const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
+ ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
+ return TargetFeatures;
+ }
ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
ArrayRef<wasm::WasmImport> imports() const { return Imports; }
@@ -252,12 +255,14 @@ private:
Error parseLinkingSectionSymtab(ReadContext &Ctx);
Error parseLinkingSectionComdat(ReadContext &Ctx);
Error parseProducersSection(ReadContext &Ctx);
+ Error parseTargetFeaturesSection(ReadContext &Ctx);
Error parseRelocSection(StringRef Name, ReadContext &Ctx);
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
wasm::WasmDylinkInfo DylinkInfo;
wasm::WasmProducerInfo ProducerInfo;
+ std::vector<wasm::WasmFeatureEntry> TargetFeatures;
std::vector<wasm::WasmSignature> Signatures;
std::vector<uint32_t> FunctionTypes;
std::vector<wasm::WasmTable> Tables;
@@ -318,6 +323,8 @@ public:
WASM_SEC_ORDER_NAME,
// "producers" section must appear after "name" section.
WASM_SEC_ORDER_PRODUCERS,
+ // "target_features" section must appear after producers section
+ WASM_SEC_ORDER_TARGET_FEATURES,
// Must be last
WASM_NUM_SEC_ORDERS
diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index 1d69d78e613..60ed1aae1bd 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -38,6 +38,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, FeaturePolicyPrefix)
struct FileHeader {
yaml::Hex32 Version;
@@ -128,6 +129,11 @@ struct ProducerEntry {
std::string Version;
};
+struct FeatureEntry {
+ FeaturePolicyPrefix Prefix;
+ std::string Name;
+};
+
struct SegmentInfo {
uint32_t Index;
StringRef Name;
@@ -242,6 +248,17 @@ struct ProducersSection : CustomSection {
std::vector<ProducerEntry> SDKs;
};
+struct TargetFeaturesSection : CustomSection {
+ TargetFeaturesSection() : CustomSection("target_features") {}
+
+ static bool classof(const Section *S) {
+ auto C = dyn_cast<CustomSection>(S);
+ return C && C->Name == "target_features";
+ }
+
+ std::vector<FeatureEntry> Features;
+};
+
struct TypeSection : Section {
TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
@@ -385,6 +402,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ProducerEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::FeatureEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
@@ -467,6 +485,14 @@ template <> struct MappingTraits<WasmYAML::ProducerEntry> {
static void mapping(IO &IO, WasmYAML::ProducerEntry &ProducerEntry);
};
+template <> struct ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix> {
+ static void enumeration(IO &IO, WasmYAML::FeaturePolicyPrefix &Prefix);
+};
+
+template <> struct MappingTraits<WasmYAML::FeatureEntry> {
+ static void mapping(IO &IO, WasmYAML::FeatureEntry &FeatureEntry);
+};
+
template <> struct MappingTraits<WasmYAML::SegmentInfo> {
static void mapping(IO &IO, WasmYAML::SegmentInfo &SegmentInfo);
};
diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
index 197e9052566..1054b871052 100644
--- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
@@ -135,9 +135,10 @@ public:
SectionKind Kind;
};
static SectionType SectionTypes[] = {
- { ".text", SectionKind::getText() },
- { ".rodata", SectionKind::getReadOnly() },
- { ".data", SectionKind::getData() },
+ {".text", SectionKind::getText()},
+ {".rodata", SectionKind::getReadOnly()},
+ {".data", SectionKind::getData()},
+ {".custom_section", SectionKind::getMetadata()},
// TODO: add more types.
};
for (size_t I = 0; I < sizeof(SectionTypes) / sizeof(SectionType); I++) {
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index e82ed5898b4..0014b695b90 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -250,6 +250,7 @@ class WasmObjectWriter : public MCObjectWriter {
// section.
std::vector<WasmCustomSection> CustomSections;
std::unique_ptr<WasmCustomSection> ProducersSection;
+ std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
// Relocations for fixing up references in the custom sections.
DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
CustomSectionsRelocations;
@@ -291,6 +292,7 @@ private:
DataLocations.clear();
CustomSections.clear();
ProducersSection.reset();
+ TargetFeaturesSection.reset();
CustomSectionsRelocations.clear();
SignatureIndices.clear();
Signatures.clear();
@@ -1286,11 +1288,16 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
Twine(SectionName));
}
- // Separate out the producers section
+ // Separate out the producers and target features sections
if (Name == "producers") {
ProducersSection = llvm::make_unique<WasmCustomSection>(Name, &Section);
continue;
}
+ if (Name == "target_features") {
+ TargetFeaturesSection =
+ llvm::make_unique<WasmCustomSection>(Name, &Section);
+ continue;
+ }
CustomSections.emplace_back(Name, &Section);
}
@@ -1593,6 +1600,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
writeCustomRelocSections();
if (ProducersSection)
writeCustomSection(*ProducersSection, Asm, Layout);
+ if (TargetFeaturesSection)
+ writeCustomSection(*TargetFeaturesSection, Asm, Layout);
// TODO: Translate the .comment section to the output.
return W.OS.tell() - StartOffset;
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 2ff2c555d5e..14b17bcfa5e 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -715,6 +715,36 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
return Error::success();
}
+Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
+ llvm::SmallSet<std::string, 8> FeaturesSeen;
+ uint32_t FeatureCount = readVaruint32(Ctx);
+ for (size_t I = 0; I < FeatureCount; ++I) {
+ wasm::WasmFeatureEntry Feature;
+ Feature.Prefix = readUint8(Ctx);
+ switch (Feature.Prefix) {
+ case wasm::WASM_FEATURE_PREFIX_USED:
+ case wasm::WASM_FEATURE_PREFIX_REQUIRED:
+ case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
+ break;
+ default:
+ return make_error<GenericBinaryError>("Unknown feature policy prefix",
+ object_error::parse_failed);
+ }
+ Feature.Name = readString(Ctx);
+ if (!FeaturesSeen.insert(Feature.Name).second)
+ return make_error<GenericBinaryError>(
+ "Target features section contains repeated feature \"" +
+ Feature.Name + "\"",
+ object_error::parse_failed);
+ TargetFeatures.push_back(Feature);
+ }
+ if (Ctx.Ptr != Ctx.End)
+ return make_error<GenericBinaryError>(
+ "Target features section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
uint32_t SectionIndex = readVaruint32(Ctx);
if (SectionIndex >= Sections.size())
@@ -816,6 +846,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
} else if (Sec.Name == "producers") {
if (Error Err = parseProducersSection(Ctx))
return Err;
+ } else if (Sec.Name == "target_features") {
+ if (Error Err = parseTargetFeaturesSection(Ctx))
+ return Err;
} else if (Sec.Name.startswith("reloc.")) {
if (Error Err = parseRelocSection(Sec.Name, Ctx))
return Err;
@@ -1528,6 +1561,7 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
.StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
.Case("name", WASM_SEC_ORDER_NAME)
.Case("producers", WASM_SEC_ORDER_PRODUCERS)
+ .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
.Default(WASM_SEC_ORDER_NONE);
case wasm::WASM_SEC_TYPE:
return WASM_SEC_ORDER_TYPE;
@@ -1584,7 +1618,8 @@ int WasmSectionOrderChecker::DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NU
{WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, // WASM_SEC_ORDER_LINKING,
{}, // WASM_SEC_ORDER_RELOC (can be repeated),
{WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_NAME,
- {WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_PRODUCERS,
+ {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, // WASM_SEC_ORDER_PRODUCERS,
+ {WASM_SEC_ORDER_TARGET_FEATURES} // WASM_SEC_ORDER_TARGET_FEATURES
};
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index 1865dcf7aa6..3841c5b7712 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -81,6 +81,12 @@ static void sectionMapping(IO &IO, WasmYAML::ProducersSection &Section) {
IO.mapOptional("SDKs", Section.SDKs);
}
+static void sectionMapping(IO &IO, WasmYAML::TargetFeaturesSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapRequired("Name", Section.Name);
+ IO.mapRequired("Features", Section.Features);
+}
+
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
commonSectionMapping(IO, Section);
IO.mapRequired("Name", Section.Name);
@@ -180,6 +186,10 @@ void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
if (!IO.outputting())
Section.reset(new WasmYAML::ProducersSection());
sectionMapping(IO, *cast<WasmYAML::ProducersSection>(Section.get()));
+ } else if (SectionName == "target_features") {
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::TargetFeaturesSection());
+ sectionMapping(IO, *cast<WasmYAML::TargetFeaturesSection>(Section.get()));
} else {
if (!IO.outputting())
Section.reset(new WasmYAML::CustomSection(SectionName));
@@ -310,6 +320,21 @@ void MappingTraits<WasmYAML::ProducerEntry>::mapping(
IO.mapRequired("Version", ProducerEntry.Version);
}
+void ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix>::enumeration(
+ IO &IO, WasmYAML::FeaturePolicyPrefix &Kind) {
+#define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_FEATURE_PREFIX_##X);
+ ECase(USED);
+ ECase(REQUIRED);
+ ECase(DISALLOWED);
+#undef ECase
+}
+
+void MappingTraits<WasmYAML::FeatureEntry>::mapping(
+ IO &IO, WasmYAML::FeatureEntry &FeatureEntry) {
+ IO.mapRequired("Prefix", FeatureEntry.Prefix);
+ IO.mapRequired("Name", FeatureEntry.Name);
+}
+
void MappingTraits<WasmYAML::SegmentInfo>::mapping(
IO &IO, WasmYAML::SegmentInfo &SegmentInfo) {
IO.mapRequired("Index", SegmentInfo.Index);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index b0a80b0ca79..c8a53ebd4cc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -21,8 +21,10 @@
#include "WebAssemblyMCInstLower.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblyRegisterInfo.h"
+#include "WebAssemblyTargetMachine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -159,6 +161,7 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
}
EmitProducerInfo(M);
+ EmitTargetFeatures();
}
void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
@@ -212,6 +215,61 @@ void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
}
}
+void WebAssemblyAsmPrinter::EmitTargetFeatures() {
+ static const std::pair<unsigned, const char *> FeaturePairs[] = {
+ {WebAssembly::FeatureAtomics, "atomics"},
+ {WebAssembly::FeatureBulkMemory, "bulk-memory"},
+ {WebAssembly::FeatureExceptionHandling, "exception-handling"},
+ {WebAssembly::FeatureNontrappingFPToInt, "nontrapping-fptoint"},
+ {WebAssembly::FeatureSignExt, "sign-ext"},
+ {WebAssembly::FeatureSIMD128, "simd128"},
+ };
+
+ struct FeatureEntry {
+ uint8_t Prefix;
+ StringRef Name;
+ };
+
+ FeatureBitset UsedFeatures =
+ static_cast<WebAssemblyTargetMachine &>(TM).getUsedFeatures();
+
+ // Calculate the features and linkage policies to emit
+ SmallVector<FeatureEntry, 4> EmittedFeatures;
+ for (auto &F : FeaturePairs) {
+ FeatureEntry Entry;
+ Entry.Name = F.second;
+ if (F.first == WebAssembly::FeatureAtomics) {
+ // "atomics" is special: code compiled without atomics may have had its
+ // atomics lowered to nonatomic operations. Such code would be dangerous
+ // to mix with proper atomics, so it is always Required or Disallowed.
+ Entry.Prefix = UsedFeatures[F.first] ? wasm::WASM_FEATURE_PREFIX_REQUIRED
+ : wasm::WASM_FEATURE_PREFIX_DISALLOWED;
+ EmittedFeatures.push_back(Entry);
+ } else {
+ // Other features are marked Used or not mentioned
+ if (UsedFeatures[F.first]) {
+ Entry.Prefix = wasm::WASM_FEATURE_PREFIX_USED;
+ EmittedFeatures.push_back(Entry);
+ }
+ }
+ }
+
+ // Emit features and linkage policies into the "target_features" section
+ MCSectionWasm *FeaturesSection = OutContext.getWasmSection(
+ ".custom_section.target_features", SectionKind::getMetadata());
+ OutStreamer->PushSection();
+ OutStreamer->SwitchSection(FeaturesSection);
+
+ OutStreamer->EmitULEB128IntValue(EmittedFeatures.size());
+ for (auto &F : EmittedFeatures) {
+ OutStreamer->EmitIntValue(F.Prefix, 1);
+ OutStreamer->EmitULEB128IntValue(F.Name.size());
+ OutStreamer->EmitBytes(F.Name);
+ }
+
+ OutStreamer->PopSection();
+}
+
void WebAssemblyAsmPrinter::EmitConstantPool() {
assert(MF->getConstantPool()->getConstants().empty() &&
"WebAssembly disables constant pools");
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index 579cc9a493e..35e7d8d0f66 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -59,6 +59,7 @@ public:
void EmitEndOfAsmFile(Module &M) override;
void EmitProducerInfo(Module &M);
+ void EmitTargetFeatures();
void EmitJumpTableInfo() override;
void EmitConstantPool() override;
void EmitFunctionBodyStart() override;
diff --git a/llvm/test/CodeGen/WebAssembly/target-features.ll b/llvm/test/CodeGen/WebAssembly/target-features.ll
new file mode 100644
index 00000000000..f262657a56d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/target-features.ll
@@ -0,0 +1,67 @@
+; RUN: llc < %s | FileCheck %s --check-prefixes CHECK,ATTRS
+; RUN: llc < %s -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128
+; RUN; llc < %s -mattr=+atomics | FileCheck %s --check-prefixes CHECK,ATOMICS
+; RUN: llc < %s -mcpu=bleeding-edge | FileCheck %s --check-prefixes CHECK,BLEEDING-EDGE
+
+; Test that codegen emits target features from the command line or
+; function attributes correctly.
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+define void @foo() #0 {
+ ret void
+}
+
+define void @bar() #1 {
+ ret void
+}
+
+attributes #0 = { "target-features"="+sign-ext" }
+attributes #1 = { "target-features"="+nontrapping-fptoint" }
+
+; CHECK-LABEL: .custom_section.target_features,"",@
+
+; -atomics, +sign_ext
+; ATTRS-NEXT: .int8 3
+; ATTRS-NEXT: .int8 45
+; ATTRS-NEXT: .int8 7
+; ATTRS-NEXT: .ascii "atomics"
+; ATTRS-NEXT: .int8 43
+; ATTRS-NEXT: .int8 19
+; ATTRS-NEXT: .ascii "nontrapping-fptoint"
+; ATTRS-NEXT: .int8 43
+; ATTRS-NEXT: int8 8
+; ATTRS-NEXT: .ascii "sign-ext"
+
+; -atomics, +simd128
+; SIMD128-NEXT: .int8 2
+; SIMD128-NEXT: .int8 45
+; SIMD128-NEXT: .int8 7
+; SIMD128-NEXT: .ascii "atomics"
+; SIMD128-NEXT: .int8 43
+; SIMD128-NEXT: .int8 7
+; SIMD128-NEXT: .ascii "simd128"
+
+; =atomics
+; ATOMICS-NEXT: .int8 1
+; ATOMICS-NEXT: .int8 61
+; ATOMICS-NEXT: .int8 7
+; ATOMICS-NEXT: .ascii "atomics"
+
+; =atomics, +nontrapping-fptoint, +sign-ext, +simd128
+; BLEEDING-EDGE-NEXT: .int8 4
+; BLEEDING-EDGE-NEXT: .int8 61
+; BLEEDING-EDGE-NEXT: .int8 7
+; BLEEDING-EDGE-NEXT: .ascii "atomics"
+; BLEEDING-EDGE-NEXT: .int8 43
+; BLEEDING-EDGE-NEXT: .int8 19
+; BLEEDING-EDGE-NEXT: .ascii "nontrapping-fptoint"
+; BLEEDING-EDGE-NEXT: .int8 43
+; BLEEDING-EDGE-NEXT: .int8 8
+; BLEEDING-EDGE-NEXT: .ascii "sign-ext"
+; BLEEDING-EDGE-NEXT: .int8 43
+; BLEEDING-EDGE-NEXT: .int8 7
+; BLEEDING-EDGE-NEXT: .ascii "simd128"
+
+; CHECK-NEXT: .text
diff --git a/llvm/test/MC/WebAssembly/array-fill.ll b/llvm/test/MC/WebAssembly/array-fill.ll
index 61cdb91368c..9e2eba4a3f2 100644
--- a/llvm/test/MC/WebAssembly/array-fill.ll
+++ b/llvm/test/MC/WebAssembly/array-fill.ll
@@ -24,4 +24,9 @@ target triple = "wasm32-unknown-unknown"
; CHECK-NEXT: Name: .data
; CHECK-NEXT: Alignment: 0
; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll
index 3683d63e435..d838320aeed 100644
--- a/llvm/test/MC/WebAssembly/assembler-binary.ll
+++ b/llvm/test/MC/WebAssembly/assembler-binary.ll
@@ -87,4 +87,9 @@ entry:
; CHECK-NEXT: Name: bar
; CHECK-NEXT: Flags: [ UNDEFINED ]
; CHECK-NEXT: Function: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/bss.ll b/llvm/test/MC/WebAssembly/bss.ll
index b3d95a161d1..de8b9f88ec3 100644
--- a/llvm/test/MC/WebAssembly/bss.ll
+++ b/llvm/test/MC/WebAssembly/bss.ll
@@ -78,4 +78,9 @@ target triple = "wasm32-unknown-unknown"
; CHECK-NEXT: Name: .bss.bar
; CHECK-NEXT: Alignment: 0
; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/comdat.ll b/llvm/test/MC/WebAssembly/comdat.ll
index 18905890776..0327a8bed3f 100644
--- a/llvm/test/MC/WebAssembly/comdat.ll
+++ b/llvm/test/MC/WebAssembly/comdat.ll
@@ -119,4 +119,9 @@ define linkonce_odr i32 @sharedFn() #1 comdat($sharedComdat) {
; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Kind: DATA
; CHECK-NEXT: Index: 0
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/debug-info.ll b/llvm/test/MC/WebAssembly/debug-info.ll
index fe4a4cf6983..f76bba93c9b 100644
--- a/llvm/test/MC/WebAssembly/debug-info.ll
+++ b/llvm/test/MC/WebAssembly/debug-info.ll
@@ -130,6 +130,12 @@
; CHECK-NEXT: Offset: 1021
; CHECK-NEXT: Name: producers
; CHECK-NEXT: }
+; CHECK-NEXT: Section {
+; CHECK-NEXT: Type: CUSTOM (0x0)
+; CHECK-NEXT: Size: 10
+; CHECK-NEXT: Offset: 1114
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: }
; CHECK-NEXT:]
; CHECK-NEXT:Relocations [
; CHECK-NEXT: Section (6) DATA {
diff --git a/llvm/test/MC/WebAssembly/explicit-sections.ll b/llvm/test/MC/WebAssembly/explicit-sections.ll
index b94190f8143..f43189ad247 100644
--- a/llvm/test/MC/WebAssembly/explicit-sections.ll
+++ b/llvm/test/MC/WebAssembly/explicit-sections.ll
@@ -70,4 +70,9 @@ target triple = "wasm32-unknown-unknown"
; CHECK-NEXT: Name: .sec2
; CHECK-NEXT: Alignment: 3
; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
index df7ff92acff..9b384e3ad0f 100644
--- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
+++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
@@ -181,4 +181,9 @@ declare void @func3()
; CHECK-NEXT: Symbol: 10
; CHECK-NEXT: - Priority: 65535
; CHECK-NEXT: Symbol: 7
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/visibility.ll b/llvm/test/MC/WebAssembly/visibility.ll
index 5bb757b28f1..63b46ebf2e0 100644
--- a/llvm/test/MC/WebAssembly/visibility.ll
+++ b/llvm/test/MC/WebAssembly/visibility.ll
@@ -25,4 +25,9 @@ entry:
; CHECK-NEXT: Name: hiddenVis
; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
; CHECK-NEXT: Function: 1
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/weak-alias.ll b/llvm/test/MC/WebAssembly/weak-alias.ll
index 7abdc79b569..cf5783a017e 100644
--- a/llvm/test/MC/WebAssembly/weak-alias.ll
+++ b/llvm/test/MC/WebAssembly/weak-alias.ll
@@ -207,6 +207,11 @@ entry:
; CHECK-NEXT: Name: .data.alias_address
; CHECK-NEXT: Alignment: 3
; CHECK-NEXT: Flags: [ ]
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
; CHECK-SYMS: SYMBOL TABLE:
diff --git a/llvm/test/MC/WebAssembly/weak.ll b/llvm/test/MC/WebAssembly/weak.ll
index 6a94ee627b6..2278f97c89d 100644
--- a/llvm/test/MC/WebAssembly/weak.ll
+++ b/llvm/test/MC/WebAssembly/weak.ll
@@ -30,4 +30,9 @@ entry:
; CHECK-NEXT: Kind: DATA
; CHECK-NEXT: Name: weak_external_data
; CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ]
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: target_features
+; CHECK-NEXT: Features:
+; CHECK-NEXT: - Prefix: DISALLOWED
+; CHECK-NEXT: Name: atomics
; CHECK-NEXT: ...
diff --git a/llvm/test/ObjectYAML/wasm/target-features-section.yaml b/llvm/test/ObjectYAML/wasm/target-features-section.yaml
new file mode 100644
index 00000000000..22d2645095d
--- /dev/null
+++ b/llvm/test/ObjectYAML/wasm/target-features-section.yaml
@@ -0,0 +1,25 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: CUSTOM
+ Name: target_features
+ Features:
+ - Prefix: USED
+ Name: "foo"
+ - Prefix: REQUIRED
+ Name: "bar"
+ - Prefix: DISALLOWED
+ Name: ""
+...
+# CHECK-LABEL: Sections:
+# CHECK-NEXT: - Type: CUSTOM
+# CHECK-NEXT: Name: target_features
+# CHECK-NEXT: Features:
+# CHECK-NEXT: - Prefix: USED
+# CHECK-NEXT: Name: foo
+# CHECK-NEXT: - Prefix: REQUIRED
+# CHECK-NEXT: Name: bar
+# CHECK-NEXT: - Prefix: DISALLOWED
+# CHECK-NEXT: Name: ''
diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index b6eef9cf9fb..eacbe621e0e 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -155,6 +155,16 @@ WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
ProducersSec->SDKs.push_back(Producer);
}
CustomSec = std::move(ProducersSec);
+ } else if (WasmSec.Name == "target_features") {
+ std::unique_ptr<WasmYAML::TargetFeaturesSection> TargetFeaturesSec =
+ make_unique<WasmYAML::TargetFeaturesSection>();
+ for (auto &E : Obj.getTargetFeatures()) {
+ WasmYAML::FeatureEntry Feature;
+ Feature.Prefix = E.Prefix;
+ Feature.Name = E.Name;
+ TargetFeaturesSec->Features.push_back(Feature);
+ }
+ CustomSec = std::move(TargetFeaturesSec);
} else {
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
}
diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp
index fcbcb8a40d5..322ac0117ba 100644
--- a/llvm/tools/yaml2obj/yaml2wasm.cpp
+++ b/llvm/tools/yaml2obj/yaml2wasm.cpp
@@ -49,6 +49,8 @@ private:
int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
+ int writeSectionContent(raw_ostream &OS,
+ WasmYAML::TargetFeaturesSection &Section);
WasmYAML::Object &Obj;
uint32_t NumImportedFunctions = 0;
uint32_t NumImportedGlobals = 0;
@@ -280,6 +282,17 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
}
int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::TargetFeaturesSection &Section) {
+ writeStringRef(Section.Name, OS);
+ encodeULEB128(Section.Features.size(), OS);
+ for (auto &E : Section.Features) {
+ writeUint8(OS, E.Prefix);
+ writeStringRef(E.Name, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
WasmYAML::CustomSection &Section) {
if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
if (auto Err = writeSectionContent(OS, *S))
@@ -293,6 +306,9 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
} else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
if (auto Err = writeSectionContent(OS, *S))
return Err;
+ } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
+ if (auto Err = writeSectionContent(OS, *S))
+ return Err;
} else {
writeStringRef(Section.Name, OS);
Section.Payload.writeAsBinary(OS);
OpenPOWER on IntegriCloud