Skip to content

Commit 8aa91ec

Browse files
authored
S-expression parsing in C API and binaryen.js (#1050)
* add C API and binaryen.js support for parsing s-expressions * update js builds and tests
1 parent b5b40c9 commit 8aa91ec

9 files changed

Lines changed: 727 additions & 637 deletions

File tree

bin/binaryen.js

Lines changed: 632 additions & 614 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/wasm.js

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build-js.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ else
5656
# See https://gist.github.com/rsms/e33c61a25a31c08260161a087be03169
5757
fi
5858

59-
6059
echo "building wasm.js"
6160

6261
"$EMSCRIPTEN/em++" \
@@ -176,6 +175,7 @@ fi
176175
src/wasm/wasm.cpp \
177176
src/wasm/wasm-type.cpp \
178177
src/wasm/wasm-binary.cpp \
178+
src/wasm/wasm-s-parser.cpp \
179179
src/wasm/literal.cpp \
180180
src/binaryen-c.cpp \
181181
src/cfg/Relooper.cpp \
@@ -187,7 +187,7 @@ echo "building binaryen.js to js"
187187
"$EMSCRIPTEN/em++" \
188188
$EMCC_ARGS \
189189
binaryen.bc \
190-
-s 'EXPORTED_FUNCTIONS=["_BinaryenNone", "_BinaryenInt32", "_BinaryenInt64", "_BinaryenFloat32", "_BinaryenFloat64", "_BinaryenUndefined", "_BinaryenModuleCreate", "_BinaryenModuleDispose", "_BinaryenAddFunctionType", "_BinaryenGetFunctionTypeBySignature", "_BinaryenLiteralInt32", "_BinaryenLiteralInt64", "_BinaryenLiteralFloat32", "_BinaryenLiteralFloat64", "_BinaryenLiteralFloat32Bits", "_BinaryenLiteralFloat64Bits", "_BinaryenClzInt32", "_BinaryenCtzInt32", "_BinaryenPopcntInt32", "_BinaryenNegFloat32", "_BinaryenAbsFloat32", "_BinaryenCeilFloat32", "_BinaryenFloorFloat32", "_BinaryenTruncFloat32", "_BinaryenNearestFloat32", "_BinaryenSqrtFloat32", "_BinaryenEqZInt32", "_BinaryenClzInt64", "_BinaryenCtzInt64", "_BinaryenPopcntInt64", "_BinaryenNegFloat64", "_BinaryenAbsFloat64", "_BinaryenCeilFloat64", "_BinaryenFloorFloat64", "_BinaryenTruncFloat64", "_BinaryenNearestFloat64", "_BinaryenSqrtFloat64", "_BinaryenEqZInt64", "_BinaryenExtendSInt32", "_BinaryenExtendUInt32", "_BinaryenWrapInt64", "_BinaryenTruncSFloat32ToInt32", "_BinaryenTruncSFloat32ToInt64", "_BinaryenTruncUFloat32ToInt32", "_BinaryenTruncUFloat32ToInt64", "_BinaryenTruncSFloat64ToInt32", "_BinaryenTruncSFloat64ToInt64", "_BinaryenTruncUFloat64ToInt32", "_BinaryenTruncUFloat64ToInt64", "_BinaryenReinterpretFloat32", "_BinaryenReinterpretFloat64", "_BinaryenConvertSInt32ToFloat32", "_BinaryenConvertSInt32ToFloat64", "_BinaryenConvertUInt32ToFloat32", "_BinaryenConvertUInt32ToFloat64", "_BinaryenConvertSInt64ToFloat32", "_BinaryenConvertSInt64ToFloat64", "_BinaryenConvertUInt64ToFloat32", "_BinaryenConvertUInt64ToFloat64", "_BinaryenPromoteFloat32", "_BinaryenDemoteFloat64", "_BinaryenReinterpretInt32", "_BinaryenReinterpretInt64", "_BinaryenAddInt32", "_BinaryenSubInt32", "_BinaryenMulInt32", "_BinaryenDivSInt32", "_BinaryenDivUInt32", "_BinaryenRemSInt32", "_BinaryenRemUInt32", "_BinaryenAndInt32", "_BinaryenOrInt32", "_BinaryenXorInt32", "_BinaryenShlInt32", "_BinaryenShrUInt32", "_BinaryenShrSInt32", "_BinaryenRotLInt32", "_BinaryenRotRInt32", "_BinaryenEqInt32", "_BinaryenNeInt32", "_BinaryenLtSInt32", "_BinaryenLtUInt32", "_BinaryenLeSInt32", "_BinaryenLeUInt32", "_BinaryenGtSInt32", "_BinaryenGtUInt32", "_BinaryenGeSInt32", "_BinaryenGeUInt32", "_BinaryenAddInt64", "_BinaryenSubInt64", "_BinaryenMulInt64", "_BinaryenDivSInt64", "_BinaryenDivUInt64", "_BinaryenRemSInt64", "_BinaryenRemUInt64", "_BinaryenAndInt64", "_BinaryenOrInt64", "_BinaryenXorInt64", "_BinaryenShlInt64", "_BinaryenShrUInt64", "_BinaryenShrSInt64", "_BinaryenRotLInt64", "_BinaryenRotRInt64", "_BinaryenEqInt64", "_BinaryenNeInt64", "_BinaryenLtSInt64", "_BinaryenLtUInt64", "_BinaryenLeSInt64", "_BinaryenLeUInt64", "_BinaryenGtSInt64", "_BinaryenGtUInt64", "_BinaryenGeSInt64", "_BinaryenGeUInt64", "_BinaryenAddFloat32", "_BinaryenSubFloat32", "_BinaryenMulFloat32", "_BinaryenDivFloat32", "_BinaryenCopySignFloat32", "_BinaryenMinFloat32", "_BinaryenMaxFloat32", "_BinaryenEqFloat32", "_BinaryenNeFloat32", "_BinaryenLtFloat32", "_BinaryenLeFloat32", "_BinaryenGtFloat32", "_BinaryenGeFloat32", "_BinaryenAddFloat64", "_BinaryenSubFloat64", "_BinaryenMulFloat64", "_BinaryenDivFloat64", "_BinaryenCopySignFloat64", "_BinaryenMinFloat64", "_BinaryenMaxFloat64", "_BinaryenEqFloat64", "_BinaryenNeFloat64", "_BinaryenLtFloat64", "_BinaryenLeFloat64", "_BinaryenGtFloat64", "_BinaryenGeFloat64", "_BinaryenPageSize", "_BinaryenCurrentMemory", "_BinaryenGrowMemory", "_BinaryenHasFeature", "_BinaryenBlock", "_BinaryenIf", "_BinaryenLoop", "_BinaryenBreak", "_BinaryenSwitch", "_BinaryenCall", "_BinaryenCallImport", "_BinaryenCallIndirect", "_BinaryenGetLocal", "_BinaryenSetLocal", "_BinaryenTeeLocal", "_BinaryenGetGlobal", "_BinaryenSetGlobal", "_BinaryenLoad", "_BinaryenStore", "_BinaryenConst", "_BinaryenUnary", "_BinaryenBinary", "_BinaryenSelect", "_BinaryenDrop", "_BinaryenReturn", "_BinaryenHost", "_BinaryenNop", "_BinaryenUnreachable", "_BinaryenExpressionPrint", "_BinaryenAddFunction", "_BinaryenAddGlobal", "_BinaryenAddImport", "_BinaryenRemoveImport", "_BinaryenAddExport", "_BinaryenRemoveExport", "_BinaryenSetFunctionTable", "_BinaryenSetMemory", "_BinaryenSetStart", "_BinaryenModulePrint", "_BinaryenModuleValidate", "_BinaryenModuleOptimize", "_BinaryenModuleAutoDrop", "_BinaryenModuleWrite", "_BinaryenModuleRead", "_BinaryenModuleInterpret", "_RelooperCreate", "_RelooperAddBlock", "_RelooperAddBranch", "_RelooperAddBlockWithSwitch", "_RelooperAddBranchForSwitch", "_RelooperRenderAndDispose", "_BinaryenSetAPITracing"]' \
190+
-s 'EXPORTED_FUNCTIONS=["_BinaryenNone", "_BinaryenInt32", "_BinaryenInt64", "_BinaryenFloat32", "_BinaryenFloat64", "_BinaryenUndefined", "_BinaryenModuleCreate", "_BinaryenModuleDispose", "_BinaryenAddFunctionType", "_BinaryenGetFunctionTypeBySignature", "_BinaryenLiteralInt32", "_BinaryenLiteralInt64", "_BinaryenLiteralFloat32", "_BinaryenLiteralFloat64", "_BinaryenLiteralFloat32Bits", "_BinaryenLiteralFloat64Bits", "_BinaryenClzInt32", "_BinaryenCtzInt32", "_BinaryenPopcntInt32", "_BinaryenNegFloat32", "_BinaryenAbsFloat32", "_BinaryenCeilFloat32", "_BinaryenFloorFloat32", "_BinaryenTruncFloat32", "_BinaryenNearestFloat32", "_BinaryenSqrtFloat32", "_BinaryenEqZInt32", "_BinaryenClzInt64", "_BinaryenCtzInt64", "_BinaryenPopcntInt64", "_BinaryenNegFloat64", "_BinaryenAbsFloat64", "_BinaryenCeilFloat64", "_BinaryenFloorFloat64", "_BinaryenTruncFloat64", "_BinaryenNearestFloat64", "_BinaryenSqrtFloat64", "_BinaryenEqZInt64", "_BinaryenExtendSInt32", "_BinaryenExtendUInt32", "_BinaryenWrapInt64", "_BinaryenTruncSFloat32ToInt32", "_BinaryenTruncSFloat32ToInt64", "_BinaryenTruncUFloat32ToInt32", "_BinaryenTruncUFloat32ToInt64", "_BinaryenTruncSFloat64ToInt32", "_BinaryenTruncSFloat64ToInt64", "_BinaryenTruncUFloat64ToInt32", "_BinaryenTruncUFloat64ToInt64", "_BinaryenReinterpretFloat32", "_BinaryenReinterpretFloat64", "_BinaryenConvertSInt32ToFloat32", "_BinaryenConvertSInt32ToFloat64", "_BinaryenConvertUInt32ToFloat32", "_BinaryenConvertUInt32ToFloat64", "_BinaryenConvertSInt64ToFloat32", "_BinaryenConvertSInt64ToFloat64", "_BinaryenConvertUInt64ToFloat32", "_BinaryenConvertUInt64ToFloat64", "_BinaryenPromoteFloat32", "_BinaryenDemoteFloat64", "_BinaryenReinterpretInt32", "_BinaryenReinterpretInt64", "_BinaryenAddInt32", "_BinaryenSubInt32", "_BinaryenMulInt32", "_BinaryenDivSInt32", "_BinaryenDivUInt32", "_BinaryenRemSInt32", "_BinaryenRemUInt32", "_BinaryenAndInt32", "_BinaryenOrInt32", "_BinaryenXorInt32", "_BinaryenShlInt32", "_BinaryenShrUInt32", "_BinaryenShrSInt32", "_BinaryenRotLInt32", "_BinaryenRotRInt32", "_BinaryenEqInt32", "_BinaryenNeInt32", "_BinaryenLtSInt32", "_BinaryenLtUInt32", "_BinaryenLeSInt32", "_BinaryenLeUInt32", "_BinaryenGtSInt32", "_BinaryenGtUInt32", "_BinaryenGeSInt32", "_BinaryenGeUInt32", "_BinaryenAddInt64", "_BinaryenSubInt64", "_BinaryenMulInt64", "_BinaryenDivSInt64", "_BinaryenDivUInt64", "_BinaryenRemSInt64", "_BinaryenRemUInt64", "_BinaryenAndInt64", "_BinaryenOrInt64", "_BinaryenXorInt64", "_BinaryenShlInt64", "_BinaryenShrUInt64", "_BinaryenShrSInt64", "_BinaryenRotLInt64", "_BinaryenRotRInt64", "_BinaryenEqInt64", "_BinaryenNeInt64", "_BinaryenLtSInt64", "_BinaryenLtUInt64", "_BinaryenLeSInt64", "_BinaryenLeUInt64", "_BinaryenGtSInt64", "_BinaryenGtUInt64", "_BinaryenGeSInt64", "_BinaryenGeUInt64", "_BinaryenAddFloat32", "_BinaryenSubFloat32", "_BinaryenMulFloat32", "_BinaryenDivFloat32", "_BinaryenCopySignFloat32", "_BinaryenMinFloat32", "_BinaryenMaxFloat32", "_BinaryenEqFloat32", "_BinaryenNeFloat32", "_BinaryenLtFloat32", "_BinaryenLeFloat32", "_BinaryenGtFloat32", "_BinaryenGeFloat32", "_BinaryenAddFloat64", "_BinaryenSubFloat64", "_BinaryenMulFloat64", "_BinaryenDivFloat64", "_BinaryenCopySignFloat64", "_BinaryenMinFloat64", "_BinaryenMaxFloat64", "_BinaryenEqFloat64", "_BinaryenNeFloat64", "_BinaryenLtFloat64", "_BinaryenLeFloat64", "_BinaryenGtFloat64", "_BinaryenGeFloat64", "_BinaryenPageSize", "_BinaryenCurrentMemory", "_BinaryenGrowMemory", "_BinaryenHasFeature", "_BinaryenBlock", "_BinaryenIf", "_BinaryenLoop", "_BinaryenBreak", "_BinaryenSwitch", "_BinaryenCall", "_BinaryenCallImport", "_BinaryenCallIndirect", "_BinaryenGetLocal", "_BinaryenSetLocal", "_BinaryenTeeLocal", "_BinaryenGetGlobal", "_BinaryenSetGlobal", "_BinaryenLoad", "_BinaryenStore", "_BinaryenConst", "_BinaryenUnary", "_BinaryenBinary", "_BinaryenSelect", "_BinaryenDrop", "_BinaryenReturn", "_BinaryenHost", "_BinaryenNop", "_BinaryenUnreachable", "_BinaryenExpressionPrint", "_BinaryenAddFunction", "_BinaryenAddGlobal", "_BinaryenAddImport", "_BinaryenRemoveImport", "_BinaryenAddExport", "_BinaryenRemoveExport", "_BinaryenSetFunctionTable", "_BinaryenSetMemory", "_BinaryenSetStart", "_BinaryenModuleParse", "_BinaryenModulePrint", "_BinaryenModuleValidate", "_BinaryenModuleOptimize", "_BinaryenModuleAutoDrop", "_BinaryenModuleWrite", "_BinaryenModuleRead", "_BinaryenModuleInterpret", "_RelooperCreate", "_RelooperAddBlock", "_RelooperAddBranch", "_RelooperAddBlockWithSwitch", "_RelooperAddBranchForSwitch", "_RelooperRenderAndDispose", "_BinaryenSetAPITracing"]' \
191191
-o bin/binaryen${OUT_FILE_SUFFIX}.js \
192192
--memory-init-file 0 \
193193
--pre-js src/js/binaryen.js-pre.js \

src/binaryen-c.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "wasm-builder.h"
2828
#include "wasm-interpreter.h"
2929
#include "wasm-printing.h"
30+
#include "wasm-s-parser.h"
3031
#include "wasm-validator.h"
3132
#include "cfg/Relooper.h"
3233
#include "shell-interface.h"
@@ -905,6 +906,23 @@ void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start) {
905906
// ========== Module Operations ==========
906907
//
907908

909+
BinaryenModuleRef BinaryenModuleParse(const char* text) {
910+
if (tracing) {
911+
std::cout << " // BinaryenModuleRead\n";
912+
}
913+
914+
auto* wasm = new Module;
915+
try {
916+
SExpressionParser parser(const_cast<char*>(text));
917+
Element& root = *parser.root;
918+
SExpressionWasmBuilder builder(*wasm, *root[0]);
919+
} catch (ParseException& p) {
920+
p.dump(std::cerr);
921+
Fatal() << "error in parsing wasm text";
922+
}
923+
return wasm;
924+
}
925+
908926
void BinaryenModulePrint(BinaryenModuleRef module) {
909927
if (tracing) {
910928
std::cout << " BinaryenModulePrint(the_module);\n";

src/binaryen-c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ void BinaryenSetStart(BinaryenModuleRef module, BinaryenFunctionRef start);
366366
// ========== Module Operations ==========
367367
//
368368

369+
// Parse a module in s-expression text format
370+
BinaryenModuleRef BinaryenModuleParse(const char* text);
371+
369372
// Print a module to stdout. Useful for debugging.
370373
void BinaryenModulePrint(BinaryenModuleRef module);
371374

src/js/binaryen.js-post.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,14 @@
899899
return new Module['Module'](ptr);
900900
};
901901

902+
Module['parseText'] = function(text) {
903+
var buffer = _malloc(text.length + 1);
904+
writeAsciiToMemory(text, buffer);
905+
var ptr = Module['_BinaryenModuleParse'](buffer);
906+
_free(buffer);
907+
return new Module['Module'](ptr);
908+
};
909+
902910
Module['setAPITracing'] = function(on) {
903911
return Module['_BinaryenSetAPITracing'](on);
904912
};

test/binaryen.js/kitchen-sink.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,30 @@ function test_tracing() {
494494
Binaryen.setAPITracing(0);
495495
}
496496

497+
function test_parsing() {
498+
var text;
499+
500+
// create a module and write it to text
501+
module = new Binaryen.Module();
502+
var iii = module.addFunctionType("iii", Binaryen.i32, [ Binaryen.i32, Binaryen.i32 ]);
503+
var x = module.getLocal(0, Binaryen.i32),
504+
y = module.getLocal(1, Binaryen.i32);
505+
var add = module.i32.add(x, y);
506+
var adder = module.addFunction("adder", iii, [], add);
507+
text = module.emitText();
508+
module.dispose();
509+
module = null;
510+
print('test_parsing text:\n' + text);
511+
512+
text = text.replace('adder', 'ADD_ER');
513+
514+
var module2 = Binaryen.parseText(text);
515+
assert(module2.validate());
516+
console.log("module loaded from text form:");
517+
console.log(module2.emitText());
518+
module2.dispose();
519+
}
520+
497521
function main() {
498522
test_types();
499523
test_core();
@@ -502,6 +526,7 @@ function main() {
502526
test_interpret();
503527
test_nonvalid();
504528
test_tracing();
529+
test_parsing();
505530
}
506531

507532
main();

test/binaryen.js/kitchen-sink.js.txt

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,9 +1028,6 @@ raw:
10281028

10291029
optimized:
10301030
(module
1031-
(type $v (func))
1032-
(type $vi (func (param i32)))
1033-
(type $i (func (result i32)))
10341031
(memory $0 0)
10351032
)
10361033

@@ -2910,9 +2907,6 @@ raw:
29102907
optimized:
29112908
BinaryenModulePrint(the_module);
29122909
(module
2913-
(type $v (func))
2914-
(type $vi (func (param i32)))
2915-
(type $i (func (result i32)))
29162910
(memory $0 0)
29172911
)
29182912

@@ -2923,3 +2917,27 @@ optimized:
29232917
relooperBlocks.clear();
29242918
return 0;
29252919
}
2920+
test_parsing text:
2921+
(module
2922+
(type $iii (func (param i32 i32) (result i32)))
2923+
(memory $0 0)
2924+
(func $adder (type $iii) (param $0 i32) (param $1 i32) (result i32)
2925+
(i32.add
2926+
(get_local $0)
2927+
(get_local $1)
2928+
)
2929+
)
2930+
)
2931+
2932+
module loaded from text form:
2933+
(module
2934+
(type $iii (func (param i32 i32) (result i32)))
2935+
(memory $0 0)
2936+
(func $ADD_ER (type $iii) (param $0 i32) (param $1 i32) (result i32)
2937+
(i32.add
2938+
(get_local $0)
2939+
(get_local $1)
2940+
)
2941+
)
2942+
)
2943+

test/passes/ssa.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
)
7171
(block
7272
(drop
73-
(if i32
73+
(if (result i32)
7474
(i32.const 1)
7575
(i32.const 0)
7676
(i32.const 0)

0 commit comments

Comments
 (0)