Skip to content

Commit 01b2398

Browse files
dcodeIOkripken
authored andcommitted
Add optimize, shrink level and debug info options to C/JS (#1357)
* Add optimize, shrink level and debug info options to C/JS * Add instantiate functionality for creating additional unique instances of the API * Use a workaround when running tests in node Tests misuse a module as a script by concatenating, so instead of catching this case in the library, catch it there * Update sieve test Seems optimized output changed due to running with optimize levels 2/1 now * Use the options with all pass runners * Update relooper-fuzz C-API test * Share defaults between tools and the C-API * Add a test for optimize levels * Unify node test support in check.by and auto_update_tests.py * Also add getters for optimize levels and test them * Also test debugInfo * Add debug info to C tests that used it as well * Fix missing NODEJS import in auto_update_tests * Detect node.js version (WASM support) * Update hello-world JS test (now also runs with node) * feature-test WebAssembly in node instead * Document that these options apply globally, and where * Make sure hello-world.js output doesn't differ between mozjs/node
1 parent 3d8358f commit 01b2398

23 files changed

+677
-280
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ cmake_install.cmake
4545
*.vcxproj*
4646
*.dir/
4747
*.sln
48+
*.sdf
49+
*.VC.opendb
4850
bin/
4951
lib/
5052
Win32/

auto_update_tests.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import os, sys, subprocess, difflib
44

5-
from scripts.test.support import run_command, split_wast
5+
from scripts.test.support import run_command, split_wast, node_test_glue, node_has_webassembly
66
from scripts.test.shared import (
7-
ASM2WASM, MOZJS, S2WASM, WASM_SHELL, WASM_OPT, WASM_AS, WASM_DIS,
7+
ASM2WASM, MOZJS, NODEJS, S2WASM, WASM_SHELL, WASM_OPT, WASM_AS, WASM_DIS,
88
WASM_CTOR_EVAL, WASM_MERGE, WASM_REDUCE, WASM2ASM, WASM_METADCE,
99
BINARYEN_INSTALL_DIR, has_shell_timeout)
1010
from scripts.test.wasm2asm import tests, spec_tests, extra_tests, assert_tests
@@ -231,20 +231,27 @@
231231
with open(out, 'w') as o: o.write(actual)
232232
with open(out + '.stdout', 'w') as o: o.write(stdout)
233233

234-
if MOZJS:
234+
if MOZJS or NODEJS:
235235
print '\n[ checking binaryen.js testcases... ]\n'
236236

237+
node_has_wasm = NODEJS and node_has_webassembly(NODEJS)
237238
for s in sorted(os.listdir(os.path.join('test', 'binaryen.js'))):
238239
if not s.endswith('.js'): continue
239240
print s
240241
f = open('a.js', 'w')
241242
f.write(open(os.path.join('bin', 'binaryen.js')).read())
242-
# node/shell test support
243-
f.write(open(os.path.join('test', 'binaryen.js', s)).read())
243+
if NODEJS:
244+
f.write(node_test_glue())
245+
test_path = os.path.join('test', 'binaryen.js', s)
246+
test_src = open(test_path).read()
247+
f.write(test_src)
244248
f.close()
245-
cmd = [MOZJS, 'a.js']
246-
out = run_command(cmd, stderr=subprocess.STDOUT)
247-
with open(os.path.join('test', 'binaryen.js', s + '.txt'), 'w') as o: o.write(out)
249+
if MOZJS or node_has_wasm or not 'WebAssembly.' in test_src:
250+
cmd = [MOZJS or NODEJS, 'a.js']
251+
out = run_command(cmd, stderr=subprocess.STDOUT)
252+
with open(os.path.join('test', 'binaryen.js', s + '.txt'), 'w') as o: o.write(out)
253+
else:
254+
print 'Skipping ' + test_path + ' because WebAssembly might not be supported'
248255

249256
print '\n[ checking wasm-ctor-eval... ]\n'
250257

@@ -320,4 +327,4 @@
320327
expected = t + '.txt'
321328
run_command(WASM_DIS + ['c.wasm', '-o', expected])
322329

323-
print '\n[ success! ]'
330+
print '\n[ success! ]'

bin/binaryen.js

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

bin/wasm.js

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

build-js.sh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ echo "building shared bitcode"
109109
src/passes/ReReloop.cpp \
110110
src/passes/SafeHeap.cpp \
111111
src/passes/SimplifyLocals.cpp \
112+
src/passes/SpillPointers.cpp \
112113
src/passes/SSAify.cpp \
113114
src/passes/TrapMode.cpp \
114115
src/passes/Untee.cpp \
@@ -524,6 +525,12 @@ export_function "_BinaryenModulePrint"
524525
export_function "_BinaryenModulePrintAsmjs"
525526
export_function "_BinaryenModuleValidate"
526527
export_function "_BinaryenModuleOptimize"
528+
export_function "_BinaryenGetOptimizeLevel"
529+
export_function "_BinaryenSetOptimizeLevel"
530+
export_function "_BinaryenGetShrinkLevel"
531+
export_function "_BinaryenSetShrinkLevel"
532+
export_function "_BinaryenGetDebugInfo"
533+
export_function "_BinaryenSetDebugInfo"
527534
export_function "_BinaryenModuleRunPasses"
528535
export_function "_BinaryenModuleAutoDrop"
529536
export_function "_BinaryenModuleWrite"
@@ -579,10 +586,5 @@ export_function "_BinaryenSetAPITracing"
579586
-Isrc/ \
580587
-s EXPORTED_FUNCTIONS=[${EXPORTED_FUNCTIONS}] \
581588
-o bin/binaryen${OUT_FILE_SUFFIX}.js \
582-
--post-js src/js/binaryen.js-post.js \
583-
-s MODULARIZE=1 \
584-
-s 'EXPORT_NAME="Binaryen"'
585-
586-
# Create a singleton instance from the MODULARIZE module
587-
echo "Binaryen = Binaryen();" >> bin/binaryen${OUT_FILE_SUFFIX}.js
588-
589+
--pre-js src/js/binaryen.js-pre.js \
590+
--post-js src/js/binaryen.js-post.js

check.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import subprocess
2121
import sys
2222

23-
from scripts.test.support import run_command, split_wast
23+
from scripts.test.support import run_command, split_wast, node_test_glue, node_has_webassembly
2424
from scripts.test.shared import (
2525
BIN_DIR, EMCC, MOZJS, NATIVECC, NATIVEXX, NODEJS, S2WASM_EXE,
2626
WASM_AS, WASM_CTOR_EVAL, WASM_OPT, WASM_SHELL, WASM_MERGE, WASM_SHELL_EXE, WASM_METADCE,
@@ -351,6 +351,7 @@ def fix(x):
351351
def run_binaryen_js_tests():
352352
if not MOZJS and not NODEJS:
353353
return
354+
node_has_wasm = NODEJS and node_has_webassembly(NODEJS)
354355

355356
print '\n[ checking binaryen.js testcases... ]\n'
356357

@@ -360,10 +361,11 @@ def run_binaryen_js_tests():
360361
f = open('a.js', 'w')
361362
binaryen_js = open(os.path.join(options.binaryen_bin, 'binaryen.js')).read()
362363
f.write(binaryen_js)
364+
if NODEJS:
365+
f.write(node_test_glue())
363366
test_path = os.path.join(options.binaryen_test, 'binaryen.js', s)
364-
test = open(test_path).read()
365-
need_wasm = 'WebAssembly.' in test # some tests use wasm support in the VM
366-
f.write(test)
367+
test_src = open(test_path).read()
368+
f.write(test_src)
367369
f.close()
368370
def test(engine):
369371
cmd = [engine, 'a.js']
@@ -374,8 +376,11 @@ def test(engine):
374376
# run in all possible shells
375377
if MOZJS:
376378
test(MOZJS)
377-
if NODEJS and not need_wasm: # TODO: check if node is new and has wasm support
378-
test(NODEJS)
379+
if NODEJS:
380+
if node_has_wasm or not 'WebAssembly.' in test_src:
381+
test(NODEJS)
382+
else:
383+
print 'Skipping ' + test_path + ' because WebAssembly might not be supported'
379384

380385
def run_validator_tests():
381386
print '\n[ running validation tests... ]\n'

scripts/test/support.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,17 @@ def run_command(cmd, expected_status=0, stderr=None,
165165
raise Exception(('run_command unexpected stderr',
166166
"expected '%s', actual '%s'" % (expected_err, err)))
167167
return out
168+
169+
170+
def node_has_webassembly(cmd):
171+
cmd = [cmd, '-e', 'process.stdout.write(typeof WebAssembly)']
172+
return run_command(cmd) == 'object'
173+
174+
175+
def node_test_glue():
176+
# running concatenated files (a.js) in node interferes with module loading
177+
# because the concatenated file expects a 'var Binaryen' but binaryen.js
178+
# assigned to module.exports. this is correct behavior but tests then need
179+
# a workaround:
180+
return ('if (typeof module === "object" && typeof exports === "object")\n'
181+
' Binaryen = module.exports;\n')

src/binaryen-c.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "cfg/Relooper.h"
3434
#include "ir/utils.h"
3535
#include "shell-interface.h"
36+
#include "support/defaults.h"
3637

3738
using namespace wasm;
3839

@@ -70,6 +71,11 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) {
7071
static std::mutex BinaryenFunctionMutex;
7172
static std::mutex BinaryenFunctionTypeMutex;
7273

74+
// Optimization options
75+
static int optimizeLevel = BINARYEN_DEFAULT_OPTIMIZE_LEVEL;
76+
static int shrinkLevel = BINARYEN_DEFAULT_SHRINK_LEVEL;
77+
static bool debugInfo = BINARYEN_DEFAULT_DEBUG_INFO;
78+
7379
// Tracing support
7480

7581
static int tracing = 0;
@@ -2007,10 +2013,61 @@ void BinaryenModuleOptimize(BinaryenModuleRef module) {
20072013

20082014
Module* wasm = (Module*)module;
20092015
PassRunner passRunner(wasm);
2016+
passRunner.options.optimizeLevel = optimizeLevel;
2017+
passRunner.options.shrinkLevel = shrinkLevel;
2018+
passRunner.options.debugInfo = debugInfo;
20102019
passRunner.addDefaultOptimizationPasses();
20112020
passRunner.run();
20122021
}
20132022

2023+
int BinaryenGetOptimizeLevel() {
2024+
if (tracing) {
2025+
std::cout << " BinaryenGetOptimizeLevel();\n";
2026+
}
2027+
2028+
return optimizeLevel;
2029+
}
2030+
2031+
void BinaryenSetOptimizeLevel(int level) {
2032+
if (tracing) {
2033+
std::cout << " BinaryenSetOptimizeLevel(" << level << ");\n";
2034+
}
2035+
2036+
optimizeLevel = level;
2037+
}
2038+
2039+
int BinaryenGetShrinkLevel() {
2040+
if (tracing) {
2041+
std::cout << " BinaryenGetShrinkLevel();\n";
2042+
}
2043+
2044+
return shrinkLevel;
2045+
}
2046+
2047+
void BinaryenSetShrinkLevel(int level) {
2048+
if (tracing) {
2049+
std::cout << " BinaryenSetShrinkLevel(" << level << ");\n";
2050+
}
2051+
2052+
shrinkLevel = level;
2053+
}
2054+
2055+
int BinaryenGetDebugInfo() {
2056+
if (tracing) {
2057+
std::cout << " BinaryenGetDebugInfo();\n";
2058+
}
2059+
2060+
return debugInfo;
2061+
}
2062+
2063+
void BinaryenSetDebugInfo(int on) {
2064+
if (tracing) {
2065+
std::cout << " BinaryenSetDebugInfo(" << on << ");\n";
2066+
}
2067+
2068+
debugInfo = bool(on);
2069+
}
2070+
20142071
void BinaryenModuleRunPasses(BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses) {
20152072
if (tracing) {
20162073
std::cout << " {\n";
@@ -2026,6 +2083,9 @@ void BinaryenModuleRunPasses(BinaryenModuleRef module, const char **passes, Bina
20262083

20272084
Module* wasm = (Module*)module;
20282085
PassRunner passRunner(wasm);
2086+
passRunner.options.optimizeLevel = optimizeLevel;
2087+
passRunner.options.shrinkLevel = shrinkLevel;
2088+
passRunner.options.debugInfo = debugInfo;
20292089
for (BinaryenIndex i = 0; i < numPasses; i++) {
20302090
passRunner.add(passes[i]);
20312091
}
@@ -2039,6 +2099,7 @@ void BinaryenModuleAutoDrop(BinaryenModuleRef module) {
20392099

20402100
Module* wasm = (Module*)module;
20412101
PassRunner passRunner(wasm);
2102+
passRunner.options.debugInfo = debugInfo;
20422103
passRunner.add<AutoDrop>();
20432104
passRunner.run();
20442105
}
@@ -2051,6 +2112,7 @@ size_t BinaryenModuleWrite(BinaryenModuleRef module, char* output, size_t output
20512112
Module* wasm = (Module*)module;
20522113
BufferWithRandomAccess buffer(false);
20532114
WasmBinaryWriter writer(wasm, buffer, false);
2115+
writer.setNamesSection(debugInfo);
20542116
writer.write();
20552117
size_t bytes = std::min(buffer.size(), outputSize);
20562118
std::copy_n(buffer.begin(), bytes, output);
@@ -2192,6 +2254,9 @@ void BinaryenFunctionOptimize(BinaryenFunctionRef func, BinaryenModuleRef module
21922254

21932255
Module* wasm = (Module*)module;
21942256
PassRunner passRunner(wasm);
2257+
passRunner.options.optimizeLevel = optimizeLevel;
2258+
passRunner.options.shrinkLevel = shrinkLevel;
2259+
passRunner.options.debugInfo = debugInfo;
21952260
passRunner.addDefaultOptimizationPasses();
21962261
passRunner.runOnFunction((Function*)func);
21972262
}
@@ -2210,6 +2275,9 @@ void BinaryenFunctionRunPasses(BinaryenFunctionRef func, BinaryenModuleRef modul
22102275

22112276
Module* wasm = (Module*)module;
22122277
PassRunner passRunner(wasm);
2278+
passRunner.options.optimizeLevel = optimizeLevel;
2279+
passRunner.options.shrinkLevel = shrinkLevel;
2280+
passRunner.options.debugInfo = debugInfo;
22132281
for (BinaryenIndex i = 0; i < numPasses; i++) {
22142282
passRunner.add(passes[i]);
22152283
}

src/binaryen-c.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include <stdint.h>
4949

5050
#include "compiler-support.h"
51+
#include "support/defaults.h"
5152

5253
#ifdef __cplusplus
5354
extern "C" {
@@ -656,18 +657,44 @@ void BinaryenModulePrintAsmjs(BinaryenModuleRef module);
656657
// @return 0 if an error occurred, 1 if validated succesfully
657658
int BinaryenModuleValidate(BinaryenModuleRef module);
658659

659-
// Runs the standard optimization passes on the module.
660+
// Runs the standard optimization passes on the module. Uses the currently set
661+
// global optimize and shrink level.
660662
void BinaryenModuleOptimize(BinaryenModuleRef module);
661663

662-
// Runs the specified passes on the module.
664+
// Gets the currently set optimize level. Applies to all modules, globally.
665+
// 0, 1, 2 correspond to -O0, -O1, -O2 (default), etc.
666+
int BinaryenGetOptimizeLevel();
667+
668+
// Sets the optimization level to use. Applies to all modules, globally.
669+
// 0, 1, 2 correspond to -O0, -O1, -O2 (default), etc.
670+
void BinaryenSetOptimizeLevel(int level);
671+
672+
// Gets the currently set shrink level. Applies to all modules, globally.
673+
// 0, 1, 2 correspond to -O0, -Os (default), -Oz.
674+
int BinaryenGetShrinkLevel();
675+
676+
// Sets the shrink level to use. Applies to all modules, globally.
677+
// 0, 1, 2 correspond to -O0, -Os (default), -Oz.
678+
void BinaryenSetShrinkLevel(int level);
679+
680+
// Gets whether generating debug information is currently enabled or not.
681+
// Applies to all modules, globally.
682+
int BinaryenGetDebugInfo();
683+
684+
// Enables or disables debug information in emitted binaries.
685+
// Applies to all modules, globally.
686+
void BinaryenSetDebugInfo(int on);
687+
688+
// Runs the specified passes on the module. Uses the currently set global
689+
// optimize and shrink level.
663690
void BinaryenModuleRunPasses(BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses);
664691

665692
// Auto-generate drop() operations where needed. This lets you generate code without
666693
// worrying about where they are needed. (It is more efficient to do it yourself,
667694
// but simpler to use autodrop).
668695
void BinaryenModuleAutoDrop(BinaryenModuleRef module);
669696

670-
// Serialize a module into binary form.
697+
// Serialize a module into binary form. Uses the currently set global debugInfo option.
671698
// @return how many bytes were written. This will be less than or equal to outputSize
672699
size_t BinaryenModuleWrite(BinaryenModuleRef module, char* output, size_t outputSize);
673700

@@ -713,10 +740,12 @@ BinaryenType BinaryenFunctionGetVar(BinaryenFunctionRef func, BinaryenIndex inde
713740
// Gets the body of the specified `Function`.
714741
BinaryenExpressionRef BinaryenFunctionGetBody(BinaryenFunctionRef func);
715742

716-
// Runs the standard optimization passes on the function.
743+
// Runs the standard optimization passes on the function. Uses the currently set
744+
// global optimize and shrink level.
717745
void BinaryenFunctionOptimize(BinaryenFunctionRef func, BinaryenModuleRef module);
718746

719-
// Runs the specified passes on the function.
747+
// Runs the specified passes on the function. Uses the currently set global
748+
// optimize and shrink level.
720749
void BinaryenFunctionRunPasses(BinaryenFunctionRef func, BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses);
721750

722751
//

0 commit comments

Comments
 (0)