summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2018-04-05 17:01:39 +0000
committerSam Clegg <sbc@chromium.org>2018-04-05 17:01:39 +0000
commitcfd44a2e69fa0897d944bc66ca517a7d079c135d (patch)
tree7a03e934632933b10627dd65ec270a9233269d68 /llvm/lib
parentbc4987b8779ebda37e21908d8e91587a9b19cb30 (diff)
downloadbcm5719-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.cpp44
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp23
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() {
OpenPOWER on IntegriCloud