Skip to content

Commit b17a18a

Browse files
authored
binary support for wasm globals (WebAssembly#652)
1 parent fdbba5e commit b17a18a

2 files changed

Lines changed: 71 additions & 13 deletions

File tree

src/wasm-binary.h

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -244,19 +244,13 @@ namespace Section {
244244
extern const char* FunctionSignatures;
245245
extern const char* Functions;
246246
extern const char* ExportTable;
247+
extern const char* Globals;
247248
extern const char* DataSegments;
248249
extern const char* FunctionTable;
249250
extern const char* Names;
250251
extern const char* Start;
251252
};
252253

253-
enum FunctionEntry {
254-
Named = 1,
255-
Import = 2,
256-
Locals = 4,
257-
Export = 8
258-
};
259-
260254
enum ASTNodes {
261255
CurrentMemory = 0x3b,
262256
GrowMemory = 0x39,
@@ -418,6 +412,8 @@ enum ASTNodes {
418412
CallFunction = 0x16,
419413
CallIndirect = 0x17,
420414
CallImport = 0x18,
415+
GetGlobal = 0x1a,
416+
SetGlobal = 0x1b,
421417

422418
Nop = 0x00,
423419
Block = 0x01,
@@ -486,6 +482,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
486482
writeFunctionSignatures();
487483
writeFunctionTable();
488484
writeMemory();
485+
writeGlobals();
489486
writeExports();
490487
writeStart();
491488
writeFunctions();
@@ -632,6 +629,12 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
632629
finishSection(start);
633630
}
634631

632+
void writeExpression(Expression* curr) {
633+
assert(depth == 0);
634+
recurse(curr);
635+
assert(depth == 0);
636+
}
637+
635638
void writeFunctions() {
636639
if (wasm->functions.size() == 0) return;
637640
if (debug) std::cerr << "== writeFunctions" << std::endl;
@@ -657,9 +660,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
657660
if (numLocalsByType[i64]) o << U32LEB(numLocalsByType[i64]) << binaryWasmType(i64);
658661
if (numLocalsByType[f32]) o << U32LEB(numLocalsByType[f32]) << binaryWasmType(f32);
659662
if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64);
660-
depth = 0;
661-
recurse(function->body);
662-
assert(depth == 0);
663+
writeExpression(function->body);
663664
size_t size = o.size() - start;
664665
assert(size <= std::numeric_limits<uint32_t>::max());
665666
if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl;
@@ -668,6 +669,20 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
668669
finishSection(start);
669670
}
670671

672+
void writeGlobals() {
673+
if (wasm->globals.size() == 0) return;
674+
if (debug) std::cerr << "== writeglobals" << std::endl;
675+
auto start = startSection(BinaryConsts::Section::Globals);
676+
o << U32LEB(wasm->globals.size());
677+
for (auto& curr : wasm->globals) {
678+
if (debug) std::cerr << "write one" << std::endl;
679+
o << binaryWasmType(curr->type);
680+
writeExpression(curr->init);
681+
o << int8_t(BinaryConsts::End);
682+
}
683+
finishSection(start);
684+
}
685+
671686
void writeExports() {
672687
if (wasm->exports.size() == 0) return;
673688
if (debug) std::cerr << "== writeexports" << std::endl;
@@ -797,7 +812,7 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
797812

798813
// AST writing via visitors
799814

800-
int depth; // only for debugging
815+
int depth = 0; // only for debugging
801816

802817
void recurse(Expression*& curr) {
803818
if (debug) std::cerr << "zz recurse into " << ++depth << " at " << o.size() << std::endl;
@@ -920,6 +935,15 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
920935
recurse(curr->value);
921936
o << int8_t(BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->index]);
922937
}
938+
void visitGetGlobal(GetGlobal *curr) {
939+
if (debug) std::cerr << "zz node: GetGlobal " << (o.size() + 1) << std::endl;
940+
o << int8_t(BinaryConsts::GetGlobal) << U32LEB(curr->index);
941+
}
942+
void visitSetGlobal(SetGlobal *curr) {
943+
if (debug) std::cerr << "zz node: SetGlobal" << std::endl;
944+
recurse(curr->value);
945+
o << int8_t(BinaryConsts::SetGlobal) << U32LEB(curr->index);
946+
}
923947

924948
void emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset) {
925949
o << U32LEB(Log2(alignment ? alignment : bytes));
@@ -1230,6 +1254,7 @@ class WasmBinaryBuilder {
12301254
else if (match(BinaryConsts::Section::FunctionSignatures)) readFunctionSignatures();
12311255
else if (match(BinaryConsts::Section::Functions)) readFunctions();
12321256
else if (match(BinaryConsts::Section::ExportTable)) readExports();
1257+
else if (match(BinaryConsts::Section::Globals)) readGlobals();
12331258
else if (match(BinaryConsts::Section::DataSegments)) readDataSegments();
12341259
else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTable();
12351260
else if (match(BinaryConsts::Section::Names)) readNames();
@@ -1519,7 +1544,7 @@ class WasmBinaryBuilder {
15191544
// process body
15201545
assert(breakStack.empty());
15211546
assert(expressionStack.empty());
1522-
depth = 0;
1547+
assert(depth == 0);
15231548
func->body = getMaybeBlock();
15241549
assert(depth == 0);
15251550
assert(breakStack.empty());
@@ -1547,6 +1572,23 @@ class WasmBinaryBuilder {
15471572
}
15481573
}
15491574

1575+
void readGlobals() {
1576+
if (debug) std::cerr << "== readGlobals" << std::endl;
1577+
size_t num = getU32LEB();
1578+
if (debug) std::cerr << "num: " << num << std::endl;
1579+
for (size_t i = 0; i < num; i++) {
1580+
if (debug) std::cerr << "read one" << std::endl;
1581+
auto curr = new Global;
1582+
curr->type = getWasmType();
1583+
assert(depth == 0);
1584+
processExpressions();
1585+
assert(expressionStack.size() == 1);
1586+
curr->init = popExpression();
1587+
assert(depth == 0);
1588+
wasm.addGlobal(curr);
1589+
}
1590+
}
1591+
15501592
std::vector<Name> breakStack;
15511593

15521594
std::vector<Expression*> expressionStack;
@@ -1643,7 +1685,7 @@ class WasmBinaryBuilder {
16431685

16441686
// AST reading
16451687

1646-
int depth; // only for debugging
1688+
int depth = 0; // only for debugging
16471689

16481690
BinaryConsts::ASTNodes readExpression(Expression*& curr) {
16491691
if (pos == endOfFunction) {
@@ -1665,6 +1707,8 @@ class WasmBinaryBuilder {
16651707
case BinaryConsts::CallIndirect: visitCallIndirect((curr = allocator.alloc<CallIndirect>())->cast<CallIndirect>()); break;
16661708
case BinaryConsts::GetLocal: visitGetLocal((curr = allocator.alloc<GetLocal>())->cast<GetLocal>()); break;
16671709
case BinaryConsts::SetLocal: visitSetLocal((curr = allocator.alloc<SetLocal>())->cast<SetLocal>()); break;
1710+
case BinaryConsts::GetGlobal: visitGetGlobal((curr = allocator.alloc<GetGlobal>())->cast<GetGlobal>()); break;
1711+
case BinaryConsts::SetGlobal: visitSetGlobal((curr = allocator.alloc<SetGlobal>())->cast<SetGlobal>()); break;
16681712
case BinaryConsts::Select: visitSelect((curr = allocator.alloc<Select>())->cast<Select>()); break;
16691713
case BinaryConsts::Return: visitReturn((curr = allocator.alloc<Return>())->cast<Return>()); break;
16701714
case BinaryConsts::Nop: visitNop((curr = allocator.alloc<Nop>())->cast<Nop>()); break;
@@ -1863,6 +1907,19 @@ class WasmBinaryBuilder {
18631907
curr->value = popExpression();
18641908
curr->type = curr->value->type;
18651909
}
1910+
void visitGetGlobal(GetGlobal *curr) {
1911+
if (debug) std::cerr << "zz node: GetGlobal " << pos << std::endl;
1912+
curr->index = getU32LEB();
1913+
assert(curr->index < wasm.globals.size());
1914+
curr->type = wasm.globals[curr->index]->type;
1915+
}
1916+
void visitSetGlobal(SetGlobal *curr) {
1917+
if (debug) std::cerr << "zz node: SetGlobal" << std::endl;
1918+
curr->index = getU32LEB();
1919+
assert(curr->index < wasm.globals.size());
1920+
curr->value = popExpression();
1921+
curr->type = curr->value->type;
1922+
}
18661923

18671924
void readMemoryAccess(Address& alignment, size_t bytes, Address& offset) {
18681925
alignment = Pow2(getU32LEB());

src/wasm.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace Section {
3333
const char* FunctionSignatures = "function";
3434
const char* Functions = "code";
3535
const char* ExportTable = "export";
36+
const char* Globals = "global";
3637
const char* DataSegments = "data";
3738
const char* FunctionTable = "table";
3839
const char* Names = "name";

0 commit comments

Comments
 (0)