summaryrefslogtreecommitdiffstats
path: root/lld/wasm/Writer.cpp
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2019-07-03 22:04:54 +0000
committerThomas Lively <tlively@google.com>2019-07-03 22:04:54 +0000
commit6004d9a13d1f5796844d802ff0486f842a06f674 (patch)
tree4ef1c40af1c8d3f4ee41c6a9dc9a2130f3a38893 /lld/wasm/Writer.cpp
parentc96c174557c079aab31429aed3f3f8ec34384592 (diff)
downloadbcm5719-llvm-6004d9a13d1f5796844d802ff0486f842a06f674.tar.gz
bcm5719-llvm-6004d9a13d1f5796844d802ff0486f842a06f674.zip
[WebAssembly] Add option to emit passive segments
Summary: Adds `--passive-segments` and `--active-segments` flags to control what kind of segments are emitted. For now the default is always to emit active segments so this is not a breaking change, but in the future the default will be changed to passive segments when shared memory is requested and active segments otherwise. When passive segments are emitted, corresponding memory.init and data.drop instructions are emitted in a `__wasm_init_memory` function that is automatically called at the beginning of `__wasm_call_ctors`. Reviewers: sbc100, aheejin, dschuff Subscribers: azakai, dschuff, jgravelle-google, sunfish, jfb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59343 llvm-svn: 365088
Diffstat (limited to 'lld/wasm/Writer.cpp')
-rw-r--r--lld/wasm/Writer.cpp91
1 files changed, 69 insertions, 22 deletions
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 7c91eacadab..09a14307a6e 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -54,6 +54,7 @@ public:
private:
void openFile();
+ void createInitMemoryFunction();
void createApplyRelocationsFunction();
void createCallCtorsFunction();
@@ -407,6 +408,10 @@ void Writer::populateTargetFeatures() {
error("'atomics' feature is disallowed by " + Disallowed["atomics"] +
", so --shared-memory must not be used");
+ if (!Used.count("bulk-memory") && Config->PassiveSegments)
+ error("'bulk-memory' feature must be used in order to emit passive "
+ "segments");
+
// Validate that used features are allowed in output
if (!InferFeatures) {
for (auto &Feature : Used.keys()) {
@@ -621,6 +626,8 @@ void Writer::createOutputSegments() {
if (S == nullptr) {
LLVM_DEBUG(dbgs() << "new segment: " << Name << "\n");
S = make<OutputSegment>(Name, Segments.size());
+ if (Config->PassiveSegments)
+ S->InitFlags = WASM_SEGMENT_IS_PASSIVE;
Segments.push_back(S);
}
S->addInputSegment(Segment);
@@ -629,10 +636,57 @@ void Writer::createOutputSegments() {
}
}
+static void CreateFunction(DefinedFunction *Func, StringRef BodyContent) {
+ std::string FunctionBody;
+ {
+ raw_string_ostream OS(FunctionBody);
+ writeUleb128(OS, BodyContent.size(), "function size");
+ OS << BodyContent;
+ }
+ ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody));
+ cast<SyntheticFunction>(Func->Function)->setBody(Body);
+}
+
+void Writer::createInitMemoryFunction() {
+ LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
+ std::string BodyContent;
+ {
+ raw_string_ostream OS(BodyContent);
+ writeUleb128(OS, 0, "num locals");
+
+ // initialize passive data segments
+ for (const OutputSegment *S : Segments) {
+ if (S->InitFlags & WASM_SEGMENT_IS_PASSIVE) {
+ // destination address
+ writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const");
+ writeUleb128(OS, S->StartVA, "destination address");
+ // source segment offset
+ writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const");
+ writeUleb128(OS, 0, "segment offset");
+ // memory region size
+ writeU8(OS, WASM_OPCODE_I32_CONST, "i32.const");
+ writeUleb128(OS, S->Size, "memory region size");
+ // memory.init instruction
+ writeU8(OS, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
+ writeUleb128(OS, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
+ writeUleb128(OS, S->Index, "segment index immediate");
+ writeU8(OS, 0, "memory index immediate");
+ // data.drop instruction
+ writeU8(OS, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
+ writeUleb128(OS, WASM_OPCODE_DATA_DROP, "DATA.DROP");
+ writeUleb128(OS, S->Index, "segment index immediate");
+ }
+ }
+ writeU8(OS, WASM_OPCODE_END, "END");
+ }
+
+ CreateFunction(WasmSym::InitMemory, BodyContent);
+}
+
// For -shared (PIC) output, we create create a synthetic function which will
// apply any relocations to the data segments on startup. This function is
-// called __wasm_apply_relocs and is added at the very beginning of
-// __wasm_call_ctors before any of the constructors run.
+// called __wasm_apply_relocs and is added at the beginning of __wasm_call_ctors
+// before any of the constructors run.
void Writer::createApplyRelocationsFunction() {
LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n");
// First write the body's contents to a string.
@@ -646,16 +700,7 @@ void Writer::createApplyRelocationsFunction() {
writeU8(OS, WASM_OPCODE_END, "END");
}
- // Once we know the size of the body we can create the final function body
- std::string FunctionBody;
- {
- raw_string_ostream OS(FunctionBody);
- writeUleb128(OS, BodyContent.size(), "function size");
- OS << BodyContent;
- }
-
- ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody));
- cast<SyntheticFunction>(WasmSym::ApplyRelocs->Function)->setBody(Body);
+ CreateFunction(WasmSym::ApplyRelocs, BodyContent);
}
// Create synthetic "__wasm_call_ctors" function based on ctor functions
@@ -669,11 +714,20 @@ void Writer::createCallCtorsFunction() {
{
raw_string_ostream OS(BodyContent);
writeUleb128(OS, 0, "num locals");
+
+ if (Config->PassiveSegments) {
+ writeU8(OS, WASM_OPCODE_CALL, "CALL");
+ writeUleb128(OS, WasmSym::InitMemory->getFunctionIndex(),
+ "function index");
+ }
+
if (Config->Pic) {
writeU8(OS, WASM_OPCODE_CALL, "CALL");
writeUleb128(OS, WasmSym::ApplyRelocs->getFunctionIndex(),
"function index");
}
+
+ // Call constructors
for (const WasmInitEntry &F : InitFunctions) {
writeU8(OS, WASM_OPCODE_CALL, "CALL");
writeUleb128(OS, F.Sym->getFunctionIndex(), "function index");
@@ -681,16 +735,7 @@ void Writer::createCallCtorsFunction() {
writeU8(OS, WASM_OPCODE_END, "END");
}
- // Once we know the size of the body we can create the final function body
- std::string FunctionBody;
- {
- raw_string_ostream OS(FunctionBody);
- writeUleb128(OS, BodyContent.size(), "function size");
- OS << BodyContent;
- }
-
- ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody));
- cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body);
+ CreateFunction(WasmSym::CallCtors, BodyContent);
}
// Populate InitFunctions vector with init functions from all input objects.
@@ -779,6 +824,8 @@ void Writer::run() {
if (!Config->Relocatable) {
// Create linker synthesized functions
+ if (Config->PassiveSegments)
+ createInitMemoryFunction();
if (Config->Pic)
createApplyRelocationsFunction();
createCallCtorsFunction();
OpenPOWER on IntegriCloud