diff options
-rw-r--r-- | src/wasm-binary.h | 83 | ||||
-rw-r--r-- | src/wasm.cpp | 1 |
2 files changed, 71 insertions, 13 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index e77f3992e..bb2b9b1fc 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -244,19 +244,13 @@ namespace Section { extern const char* FunctionSignatures; extern const char* Functions; extern const char* ExportTable; + extern const char* Globals; extern const char* DataSegments; extern const char* FunctionTable; extern const char* Names; extern const char* Start; }; -enum FunctionEntry { - Named = 1, - Import = 2, - Locals = 4, - Export = 8 -}; - enum ASTNodes { CurrentMemory = 0x3b, GrowMemory = 0x39, @@ -418,6 +412,8 @@ enum ASTNodes { CallFunction = 0x16, CallIndirect = 0x17, CallImport = 0x18, + GetGlobal = 0x1a, + SetGlobal = 0x1b, Nop = 0x00, Block = 0x01, @@ -486,6 +482,7 @@ public: writeFunctionSignatures(); writeFunctionTable(); writeMemory(); + writeGlobals(); writeExports(); writeStart(); writeFunctions(); @@ -632,6 +629,12 @@ public: finishSection(start); } + void writeExpression(Expression* curr) { + assert(depth == 0); + recurse(curr); + assert(depth == 0); + } + void writeFunctions() { if (wasm->functions.size() == 0) return; if (debug) std::cerr << "== writeFunctions" << std::endl; @@ -657,9 +660,7 @@ public: if (numLocalsByType[i64]) o << U32LEB(numLocalsByType[i64]) << binaryWasmType(i64); if (numLocalsByType[f32]) o << U32LEB(numLocalsByType[f32]) << binaryWasmType(f32); if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64); - depth = 0; - recurse(function->body); - assert(depth == 0); + writeExpression(function->body); size_t size = o.size() - start; assert(size <= std::numeric_limits<uint32_t>::max()); if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl; @@ -668,6 +669,20 @@ public: finishSection(start); } + void writeGlobals() { + if (wasm->globals.size() == 0) return; + if (debug) std::cerr << "== writeglobals" << std::endl; + auto start = startSection(BinaryConsts::Section::Globals); + o << U32LEB(wasm->globals.size()); + for (auto& curr : wasm->globals) { + if (debug) std::cerr << "write one" << std::endl; + o << binaryWasmType(curr->type); + writeExpression(curr->init); + o << int8_t(BinaryConsts::End); + } + finishSection(start); + } + void writeExports() { if (wasm->exports.size() == 0) return; if (debug) std::cerr << "== writeexports" << std::endl; @@ -797,7 +812,7 @@ public: // AST writing via visitors - int depth; // only for debugging + int depth = 0; // only for debugging void recurse(Expression*& curr) { if (debug) std::cerr << "zz recurse into " << ++depth << " at " << o.size() << std::endl; @@ -920,6 +935,15 @@ public: recurse(curr->value); o << int8_t(BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->index]); } + void visitGetGlobal(GetGlobal *curr) { + if (debug) std::cerr << "zz node: GetGlobal " << (o.size() + 1) << std::endl; + o << int8_t(BinaryConsts::GetGlobal) << U32LEB(curr->index); + } + void visitSetGlobal(SetGlobal *curr) { + if (debug) std::cerr << "zz node: SetGlobal" << std::endl; + recurse(curr->value); + o << int8_t(BinaryConsts::SetGlobal) << U32LEB(curr->index); + } void emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset) { o << U32LEB(Log2(alignment ? alignment : bytes)); @@ -1230,6 +1254,7 @@ public: else if (match(BinaryConsts::Section::FunctionSignatures)) readFunctionSignatures(); else if (match(BinaryConsts::Section::Functions)) readFunctions(); else if (match(BinaryConsts::Section::ExportTable)) readExports(); + else if (match(BinaryConsts::Section::Globals)) readGlobals(); else if (match(BinaryConsts::Section::DataSegments)) readDataSegments(); else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTable(); else if (match(BinaryConsts::Section::Names)) readNames(); @@ -1519,7 +1544,7 @@ public: // process body assert(breakStack.empty()); assert(expressionStack.empty()); - depth = 0; + assert(depth == 0); func->body = getMaybeBlock(); assert(depth == 0); assert(breakStack.empty()); @@ -1547,6 +1572,23 @@ public: } } + void readGlobals() { + if (debug) std::cerr << "== readGlobals" << std::endl; + size_t num = getU32LEB(); + if (debug) std::cerr << "num: " << num << std::endl; + for (size_t i = 0; i < num; i++) { + if (debug) std::cerr << "read one" << std::endl; + auto curr = new Global; + curr->type = getWasmType(); + assert(depth == 0); + processExpressions(); + assert(expressionStack.size() == 1); + curr->init = popExpression(); + assert(depth == 0); + wasm.addGlobal(curr); + } + } + std::vector<Name> breakStack; std::vector<Expression*> expressionStack; @@ -1643,7 +1685,7 @@ public: // AST reading - int depth; // only for debugging + int depth = 0; // only for debugging BinaryConsts::ASTNodes readExpression(Expression*& curr) { if (pos == endOfFunction) { @@ -1665,6 +1707,8 @@ public: case BinaryConsts::CallIndirect: visitCallIndirect((curr = allocator.alloc<CallIndirect>())->cast<CallIndirect>()); break; case BinaryConsts::GetLocal: visitGetLocal((curr = allocator.alloc<GetLocal>())->cast<GetLocal>()); break; case BinaryConsts::SetLocal: visitSetLocal((curr = allocator.alloc<SetLocal>())->cast<SetLocal>()); break; + case BinaryConsts::GetGlobal: visitGetGlobal((curr = allocator.alloc<GetGlobal>())->cast<GetGlobal>()); break; + case BinaryConsts::SetGlobal: visitSetGlobal((curr = allocator.alloc<SetGlobal>())->cast<SetGlobal>()); break; case BinaryConsts::Select: visitSelect((curr = allocator.alloc<Select>())->cast<Select>()); break; case BinaryConsts::Return: visitReturn((curr = allocator.alloc<Return>())->cast<Return>()); break; case BinaryConsts::Nop: visitNop((curr = allocator.alloc<Nop>())->cast<Nop>()); break; @@ -1863,6 +1907,19 @@ public: curr->value = popExpression(); curr->type = curr->value->type; } + void visitGetGlobal(GetGlobal *curr) { + if (debug) std::cerr << "zz node: GetGlobal " << pos << std::endl; + curr->index = getU32LEB(); + assert(curr->index < wasm.globals.size()); + curr->type = wasm.globals[curr->index]->type; + } + void visitSetGlobal(SetGlobal *curr) { + if (debug) std::cerr << "zz node: SetGlobal" << std::endl; + curr->index = getU32LEB(); + assert(curr->index < wasm.globals.size()); + curr->value = popExpression(); + curr->type = curr->value->type; + } void readMemoryAccess(Address& alignment, size_t bytes, Address& offset) { alignment = Pow2(getU32LEB()); diff --git a/src/wasm.cpp b/src/wasm.cpp index 6732f9ca4..dbbd209b4 100644 --- a/src/wasm.cpp +++ b/src/wasm.cpp @@ -33,6 +33,7 @@ namespace Section { const char* FunctionSignatures = "function"; const char* Functions = "code"; const char* ExportTable = "export"; + const char* Globals = "global"; const char* DataSegments = "data"; const char* FunctionTable = "table"; const char* Names = "name"; |