[llvm] r329315 - [WebAssembly] Allow for the creation of user-defined custom sections

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 5 10:01:39 PDT 2018


Author: sbc
Date: Thu Apr  5 10:01:39 2018
New Revision: 329315

URL: http://llvm.org/viewvc/llvm-project?rev=329315&view=rev
Log:
[WebAssembly] Allow for the creation of user-defined custom sections

This patch adds a way for users to create their own custom sections to
be added to wasm files. At the LLVM IR layer, they are defined through
the "wasm.custom_sections" named metadata. The expected use case for
this is bindings generators such as wasm-bindgen.

Patch by Dan Gohman

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

Added:
    llvm/trunk/test/CodeGen/WebAssembly/custom-sections.ll
    llvm/trunk/test/MC/WebAssembly/custom-sections.ll
Modified:
    llvm/trunk/lib/MC/WasmObjectWriter.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp

Modified: llvm/trunk/lib/MC/WasmObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WasmObjectWriter.cpp?rev=329315&r1=329314&r2=329315&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WasmObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WasmObjectWriter.cpp Thu Apr  5 10:01:39 2018
@@ -167,6 +167,14 @@ struct WasmRelocationEntry {
 #endif
 };
 
+struct WasmCustomSection {
+  StringRef Name;
+  const SmallVectorImpl<char> &Contents;
+
+  WasmCustomSection(StringRef Name, const SmallVectorImpl<char> &Contents)
+      : Name(Name), Contents(Contents) {}
+};
+
 #if !defined(NDEBUG)
 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
   Rel.print(OS);
@@ -202,6 +210,7 @@ class WasmObjectWriter : public MCObject
   SmallVector<WasmFunctionType, 4> FunctionTypes;
   SmallVector<WasmGlobal, 4> Globals;
   SmallVector<WasmDataSegment, 4> DataSegments;
+  std::vector<WasmCustomSection> CustomSections;
   unsigned NumFunctionImports = 0;
   unsigned NumGlobalImports = 0;
 
@@ -277,6 +286,7 @@ private:
       ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
       ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
       const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
+  void writeUserCustomSections(ArrayRef<WasmCustomSection> CustomSections);
 
   uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@@ -314,7 +324,7 @@ void WasmObjectWriter::startSection(Sect
   // Custom sections in wasm also have a string identifier.
   if (SectionId == wasm::WASM_SEC_CUSTOM) {
     assert(Name);
-    writeString(StringRef(Name));
+    writeString(Name);
   }
 }
 
@@ -936,6 +946,17 @@ void WasmObjectWriter::writeLinkingMetaD
   endSection(Section);
 }
 
+void WasmObjectWriter::writeUserCustomSections(
+    ArrayRef<WasmCustomSection> CustomSections) {
+  for (const auto &CustomSection : CustomSections) {
+    SectionBookkeeping Section;
+    startSection(Section, wasm::WASM_SEC_CUSTOM,
+                 CustomSection.Name.str().c_str());
+    writeBytes(CustomSection.Contents);
+    endSection(Section);
+  }
+}
+
 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
   assert(Symbol.isFunction());
   assert(TypeIndices.count(&Symbol));
@@ -1041,6 +1062,26 @@ void WasmObjectWriter::writeObject(MCAss
   // Populate DataSegments, which must be done before populating DataLocations.
   for (MCSection &Sec : Asm) {
     auto &Section = static_cast<MCSectionWasm &>(Sec);
+
+    if (cast<MCSectionWasm>(Sec).getSectionName().startswith(
+            ".custom_section.")) {
+      if (Section.getFragmentList().empty())
+        continue;
+      if (Section.getFragmentList().size() != 1)
+        report_fatal_error(
+            "only one .custom_section section fragment supported");
+      const MCFragment &Frag = *Section.begin();
+      if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+        report_fatal_error("only data supported in .custom_section section");
+      const auto &DataFrag = cast<MCDataFragment>(Frag);
+      if (!DataFrag.getFixups().empty())
+        report_fatal_error("fixups not supported in .custom_section section");
+      StringRef UserName = Section.getSectionName().substr(16);
+      const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+      CustomSections.push_back(WasmCustomSection(UserName, Contents));
+      continue;
+    }
+
     if (!Section.isWasmData())
       continue;
 
@@ -1310,6 +1351,7 @@ void WasmObjectWriter::writeObject(MCAss
   writeElemSection(TableElems);
   writeCodeSection(Asm, Layout, Functions);
   writeDataSection();
+  writeUserCustomSections(CustomSections);
   writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
   writeCodeRelocSection();
   writeDataRelocSection();

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=329315&r1=329314&r2=329315&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Thu Apr  5 10:01:39 2018
@@ -31,10 +31,11 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionWasm.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCSymbolWasm.h"
 #include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolWasm.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
@@ -107,6 +108,26 @@ void WebAssemblyAsmPrinter::EmitEndOfAsm
       }
     }
   }
+
+  if (const NamedMDNode *Named = M.getNamedMetadata("wasm.custom_sections")) {
+    for (const Metadata *MD : Named->operands()) {
+      const MDTuple *Tuple = dyn_cast<MDTuple>(MD);
+      if (!Tuple || Tuple->getNumOperands() != 2)
+        continue;
+      const MDString *Name = dyn_cast<MDString>(Tuple->getOperand(0));
+      const MDString *Contents = dyn_cast<MDString>(Tuple->getOperand(1));
+      if (!Name || !Contents)
+        continue;
+
+      OutStreamer->PushSection();
+      std::string SectionName = (".custom_section." + Name->getString()).str();
+      MCSectionWasm *mySection =
+          OutContext.getWasmSection(SectionName, SectionKind::getMetadata());
+      OutStreamer->SwitchSection(mySection);
+      OutStreamer->EmitBytes(Contents->getString());
+      OutStreamer->PopSection();
+    }
+  }
 }
 
 void WebAssemblyAsmPrinter::EmitConstantPool() {

Added: llvm/trunk/test/CodeGen/WebAssembly/custom-sections.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/custom-sections.ll?rev=329315&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/custom-sections.ll (added)
+++ llvm/trunk/test/CodeGen/WebAssembly/custom-sections.ll Thu Apr  5 10:01:39 2018
@@ -0,0 +1,20 @@
+; RUN: llc < %s -asm-verbose=false | FileCheck %s
+
+; Test the mechanism for defining user custom sections.
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+!0 = !{ !"red", !"foo" }
+!1 = !{ !"green", !"bar" }
+!2 = !{ !"green", !"qux" }
+!wasm.custom_sections = !{ !0, !1, !2 }
+
+; CHECK:      .section	.custom_section.red,"",@
+; CHECK-NEXT: .ascii	"foo"
+
+; CHECK:      .section	.custom_section.green,"",@
+; CHECK-NEXT: .ascii	"bar"
+
+; CHECK:      .section	.custom_section.green,"",@
+; CHECK-NEXT: .ascii	"qux"

Added: llvm/trunk/test/MC/WebAssembly/custom-sections.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/custom-sections.ll?rev=329315&view=auto
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/custom-sections.ll (added)
+++ llvm/trunk/test/MC/WebAssembly/custom-sections.ll Thu Apr  5 10:01:39 2018
@@ -0,0 +1,23 @@
+; RUN: llc -filetype=obj %s -o - | llvm-readobj -s | FileCheck %s
+
+; Test the mechanism for defining user custom sections.
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+!0 = !{ !"red", !"foo" }
+!1 = !{ !"green", !"bar" }
+!2 = !{ !"green", !"qux" }
+!wasm.custom_sections = !{ !0, !1, !2 }
+
+; CHECK:  Section {
+; CHECK:    Type: CUSTOM (0x0)
+; CHECK:    Size: 7
+; CHECK:    Offset: 72
+; CHECK:    Name: red
+; CHECK:  }
+; CHECK:  Section {
+; CHECK:    Type: CUSTOM (0x0)
+; CHECK:    Size: 12
+; CHECK:    Offset: 85
+; CHECK:    Name: green
+; CHECK:  }




More information about the llvm-commits mailing list