Skip to content

Binary format support for wasm globals #652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 70 additions & 13 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -418,6 +412,8 @@ enum ASTNodes {
CallFunction = 0x16,
CallIndirect = 0x17,
CallImport = 0x18,
GetGlobal = 0x1a,
SetGlobal = 0x1b,

Nop = 0x00,
Block = 0x01,
Expand Down Expand Up @@ -486,6 +482,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
writeFunctionSignatures();
writeFunctionTable();
writeMemory();
writeGlobals();
writeExports();
writeStart();
writeFunctions();
Expand Down Expand Up @@ -632,6 +629,12 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
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;
Expand All @@ -657,9 +660,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
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;
Expand All @@ -668,6 +669,20 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
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;
Expand Down Expand Up @@ -797,7 +812,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {

// 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;
Expand Down Expand Up @@ -920,6 +935,15 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
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));
Expand Down Expand Up @@ -1230,6 +1254,7 @@ class WasmBinaryBuilder {
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();
Expand Down Expand Up @@ -1519,7 +1544,7 @@ class WasmBinaryBuilder {
// process body
assert(breakStack.empty());
assert(expressionStack.empty());
depth = 0;
assert(depth == 0);
func->body = getMaybeBlock();
assert(depth == 0);
assert(breakStack.empty());
Expand Down Expand Up @@ -1547,6 +1572,23 @@ class WasmBinaryBuilder {
}
}

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;
Expand Down Expand Up @@ -1643,7 +1685,7 @@ class WasmBinaryBuilder {

// AST reading

int depth; // only for debugging
int depth = 0; // only for debugging

BinaryConsts::ASTNodes readExpression(Expression*& curr) {
if (pos == endOfFunction) {
Expand All @@ -1665,6 +1707,8 @@ class WasmBinaryBuilder {
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;
Expand Down Expand Up @@ -1863,6 +1907,19 @@ class WasmBinaryBuilder {
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());
Expand Down
1 change: 1 addition & 0 deletions src/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down