diff options
author | Sam Clegg <sbc@chromium.org> | 2018-04-05 17:01:39 +0000 |
---|---|---|
committer | Sam Clegg <sbc@chromium.org> | 2018-04-05 17:01:39 +0000 |
commit | cfd44a2e69fa0897d944bc66ca517a7d079c135d (patch) | |
tree | 7a03e934632933b10627dd65ec270a9233269d68 /llvm/lib | |
parent | bc4987b8779ebda37e21908d8e91587a9b19cb30 (diff) | |
download | bcm5719-llvm-cfd44a2e69fa0897d944bc66ca517a7d079c135d.tar.gz bcm5719-llvm-cfd44a2e69fa0897d944bc66ca517a7d079c135d.zip |
[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
llvm-svn: 329315
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 44 | ||||
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 23 |
2 files changed, 65 insertions, 2 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index a05948e2946..44f5335b658 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -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 MCObjectWriter { 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(SectionBookkeeping &Section, // 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::writeLinkingMetaDataSection( 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(MCAssembler &Asm, // 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(MCAssembler &Asm, writeElemSection(TableElems); writeCodeSection(Asm, Layout, Functions); writeDataSection(); + writeUserCustomSections(CustomSections); writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); writeCodeRelocSection(); writeDataRelocSection(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 4f7c68d4882..e8144add3f7 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -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::EmitEndOfAsmFile(Module &M) { } } } + + 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() { |