Skip to content

Commit 5fafb87

Browse files
tlivelykripken
authored andcommitted
wasm2asm test generation (#1124)
* Translate assert_return invokes to asm * Translate assert_trap tests to JS * Enable wasm2asm tests * Fix wasm2asm translation of store * Update ubuntu nodejs in Travis * Free JSPrinter buffer * Use unique_ptr for Functions to prevent leaks * Add tests for assert translation
1 parent 21d06ae commit 5fafb87

File tree

15 files changed

+566
-127
lines changed

15 files changed

+566
-127
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ jobs:
99
stage: test
1010
compiler: clang
1111
python: 2.7
12+
node_js: 7
1213
addons:
1314
apt:
1415
sources: ['ubuntu-toolchain-r-test']
15-
packages: ['cmake', 'nodejs', 'g++-5']
16+
packages: ['cmake', 'g++-5']
1617
before_install:
1718
- export CC="${CC_COMPILER}"
1819
- export CXX="${CXX_COMPILER}"

check.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ def fix(x):
433433

434434
s2wasm.test_s2wasm()
435435
s2wasm.test_linker()
436-
# wasm2asm.test_wasm2asm()
436+
wasm2asm.test_wasm2asm()
437437

438438
print '\n[ running validation tests... ]\n'
439439
# Ensure the tests validate by default

scripts/test/wasm2asm.py

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,48 @@
66
from shared import (WASM2ASM, MOZJS, NODEJS, fail_if_not_identical, tests)
77

88

9-
def test_wasm2asm():
10-
print '\n[ checking wasm2asm testcases... ]\n'
9+
# tests with i64s, invokes, etc.
10+
blacklist = ['address.wast']
11+
spec_tests = [os.path.join('spec', t) for t in
12+
sorted(os.listdir(os.path.join('test', 'spec')))]
13+
assert_tests = ['wasm2asm.wast.asserts']
1114

12-
# tests with i64s, invokes, etc.
13-
blacklist = ['atomics.wast', 'address.wast']
14-
spec_tests = [os.path.join('spec', t) for t in
15-
sorted(os.listdir(os.path.join('test', 'spec')))]
16-
for wasm in tests + spec_tests:
15+
16+
def test_wasm2asm_output():
17+
for wasm in tests + [w for w in spec_tests if '.fail' not in w]:
1718
if not wasm.endswith('.wast') or os.path.basename(wasm) in blacklist:
1819
continue
1920

2021
asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
2122
expected_file = os.path.join('test', asm)
23+
2224
if not os.path.exists(expected_file):
2325
continue
2426

2527
print '..', wasm
2628

2729
cmd = WASM2ASM + [os.path.join('test', wasm)]
2830
out = run_command(cmd)
29-
30-
# verify output
3131
expected = open(expected_file).read()
3232
fail_if_not_identical(out, expected)
3333

34+
if not NODEJS and not MOZJS:
35+
print 'No JS interpreters. Skipping spec tests.'
36+
continue
37+
3438
open('a.2asm.js', 'w').write(out)
3539

40+
cmd += ['--allow-asserts']
41+
out = run_command(cmd)
42+
43+
open('a.2asm.asserts.js', 'w').write(out)
44+
45+
# verify asm.js is valid js
3646
if NODEJS:
37-
# verify asm.js is valid js
3847
out = run_command([NODEJS, 'a.2asm.js'])
3948
fail_if_not_identical(out, '')
49+
out = run_command([NODEJS, 'a.2asm.asserts.js'], expected_err='')
50+
fail_if_not_identical(out, '')
4051

4152
if MOZJS:
4253
# verify asm.js validates
@@ -45,6 +56,34 @@ def test_wasm2asm():
4556
expected_err='Successfully compiled asm.js code',
4657
err_contains=True)
4758
fail_if_not_identical(out, '')
59+
out = run_command([MOZJS, 'a.2asm.asserts.js'], expected_err='')
60+
fail_if_not_identical(out, '')
61+
62+
63+
def test_asserts_output():
64+
for wasm in assert_tests:
65+
print '..', wasm
66+
67+
asserts = os.path.basename(wasm).replace('.wast.asserts', '.asserts.js')
68+
traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
69+
asserts_expected_file = os.path.join('test', asserts)
70+
traps_expected_file = os.path.join('test', traps)
71+
72+
cmd = WASM2ASM + [os.path.join('test', wasm), '--allow-asserts']
73+
out = run_command(cmd)
74+
expected = open(asserts_expected_file).read()
75+
fail_if_not_identical(out, expected)
76+
77+
cmd += ['--pedantic']
78+
out = run_command(cmd)
79+
expected = open(traps_expected_file).read()
80+
fail_if_not_identical(out, expected)
81+
82+
83+
def test_wasm2asm():
84+
print '\n[ checking wasm2asm testcases... ]\n'
85+
test_wasm2asm_output()
86+
test_asserts_output()
4887

4988

5089
if __name__ == "__main__":

src/asmjs/shared-constants.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ cashew::IString GLOBAL("global"),
3232
UINT32ARRAY("Uint32Array"),
3333
FLOAT32ARRAY("Float32Array"),
3434
FLOAT64ARRAY("Float64Array"),
35+
ARRAY_BUFFER("ArrayBuffer"),
36+
ASM_MODULE("asmModule"),
3537
IMPOSSIBLE_CONTINUE("impossible-continue"),
3638
MATH("Math"),
3739
IMUL("imul"),

src/asmjs/shared-constants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ extern cashew::IString GLOBAL,
3535
UINT32ARRAY,
3636
FLOAT32ARRAY,
3737
FLOAT64ARRAY,
38+
ARRAY_BUFFER,
39+
ASM_MODULE,
3840
IMPOSSIBLE_CONTINUE,
3941
MATH,
4042
IMUL,

src/emscripten-optimizer/parser.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ IString TOPLEVEL("toplevel"),
4141
CONTINUE("continue"),
4242
SWITCH("switch"),
4343
STRING("string"),
44+
TRY("try"),
4445
INF("inf"),
4546
NaN("nan"),
4647
TEMP_RET0("tempRet0"),

src/emscripten-optimizer/parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extern IString TOPLEVEL,
5656
CONTINUE,
5757
SWITCH,
5858
STRING,
59+
TRY,
5960
INF,
6061
NaN,
6162
TEMP_RET0,

src/emscripten-optimizer/simple_ast.h

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@ struct JSPrinter {
554554

555555
JSPrinter(bool pretty_, bool finalize_, Ref ast_) : pretty(pretty_), finalize(finalize_), buffer(0), size(0), used(0), indent(0), possibleSpace(false), ast(ast_) {}
556556

557+
~JSPrinter() {
558+
free(buffer);
559+
}
560+
557561
void printAst() {
558562
print(ast);
559563
buffer[used] = 0;
@@ -652,6 +656,7 @@ struct JSPrinter {
652656
}
653657
if (node->isAssign()) {
654658
printAssign(node);
659+
return;
655660
}
656661
IString type = node[0]->getIString();
657662
switch (type.str[0]) {
@@ -715,6 +720,7 @@ struct JSPrinter {
715720
}
716721
case 't': {
717722
if (type == TOPLEVEL) printToplevel(node);
723+
else if (type == TRY) printTry(node);
718724
else abort();
719725
break;
720726
}
@@ -808,7 +814,6 @@ struct JSPrinter {
808814
}
809815

810816
void printAssign(Ref node) {
811-
assert(false && "printAssign still used!");
812817
auto* assign = node->asAssign();
813818
printChild(assign->target(), node, -1);
814819
space();
@@ -1135,6 +1140,15 @@ struct JSPrinter {
11351140
emit('}');
11361141
}
11371142

1143+
void printTry(Ref node) {
1144+
emit("try ");
1145+
printBlock(node[1]);
1146+
emit(" catch (");
1147+
printName(node[2]);
1148+
emit(") ");
1149+
printBlock(node[3]);
1150+
}
1151+
11381152
void printSub(Ref node) {
11391153
printChild(node[1], node, -1);
11401154
emit('[');
@@ -1377,66 +1391,18 @@ class ValueBuilder {
13771391
.push_back(makeRawArray());
13781392
return ret;
13791393
}
1380-
static Ref makeCall(IString target, Ref arg) {
1381-
Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
1382-
.push_back(makeName(target))
1383-
.push_back(makeRawArray(1));
1384-
ret[2]->push_back(arg);
1385-
return ret;
1386-
}
1387-
static Ref makeCall(IString target, Ref arg1, Ref arg2) {
1388-
Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
1389-
.push_back(makeName(target))
1390-
.push_back(makeRawArray(2));
1391-
ret[2]->push_back(arg1);
1392-
ret[2]->push_back(arg2);
1393-
return ret;
1394-
}
1395-
static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4) {
1396-
Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
1397-
.push_back(makeName(target))
1398-
.push_back(makeRawArray(4));
1399-
ret[2]->push_back(arg1);
1400-
ret[2]->push_back(arg2);
1401-
ret[2]->push_back(arg3);
1402-
ret[2]->push_back(arg4);
1403-
return ret;
1404-
}
1405-
static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4, Ref arg5, Ref arg6, Ref arg7, Ref arg8) {
1406-
Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
1407-
.push_back(makeName(target))
1408-
.push_back(makeRawArray(8));
1409-
ret[2]->push_back(arg1);
1410-
ret[2]->push_back(arg2);
1411-
ret[2]->push_back(arg3);
1412-
ret[2]->push_back(arg4);
1413-
ret[2]->push_back(arg5);
1414-
ret[2]->push_back(arg6);
1415-
ret[2]->push_back(arg7);
1416-
ret[2]->push_back(arg8);
1417-
return ret;
1418-
}
1419-
static Ref makeCall(IString target, Ref arg1, Ref arg2, Ref arg3, Ref arg4, Ref arg5, Ref arg6, Ref arg7, Ref arg8, Ref arg9, Ref arg10, Ref arg11, Ref arg12, Ref arg13, Ref arg14, Ref arg15, Ref arg16) {
1420-
Ref ret = &makeRawArray(3)->push_back(makeRawString(CALL))
1421-
.push_back(makeName(target))
1422-
.push_back(makeRawArray(16));
1423-
ret[2]->push_back(arg1);
1424-
ret[2]->push_back(arg2);
1425-
ret[2]->push_back(arg3);
1426-
ret[2]->push_back(arg4);
1427-
ret[2]->push_back(arg5);
1428-
ret[2]->push_back(arg6);
1429-
ret[2]->push_back(arg7);
1430-
ret[2]->push_back(arg8);
1431-
ret[2]->push_back(arg9);
1432-
ret[2]->push_back(arg10);
1433-
ret[2]->push_back(arg11);
1434-
ret[2]->push_back(arg12);
1435-
ret[2]->push_back(arg13);
1436-
ret[2]->push_back(arg14);
1437-
ret[2]->push_back(arg15);
1438-
ret[2]->push_back(arg16);
1439-
return ret;
1394+
1395+
template<typename ...Ts>
1396+
static Ref makeCall(IString target, Ts... args) {
1397+
size_t nArgs = sizeof...(Ts);
1398+
Ref callArgs = makeRawArray(nArgs);
1399+
Ref argArray[] = {args...};
1400+
for (size_t i = 0; i < nArgs; ++i) {
1401+
callArgs->push_back(argArray[i]);
1402+
}
1403+
return &makeRawArray(3)->push_back(makeRawString(CALL))
1404+
.push_back(makeName(target))
1405+
.push_back(callArgs);
14401406
}
14411407

14421408
static void appendToCall(Ref call, Ref element) {
@@ -1610,12 +1576,26 @@ class ValueBuilder {
16101576
}
16111577
}
16121578

1579+
static Ref makeTry(Ref try_, Ref arg, Ref catch_) {
1580+
assert(try_[0] == BLOCK);
1581+
assert(catch_[0] == BLOCK);
1582+
return &makeRawArray(3)->push_back(makeRawString(TRY))
1583+
.push_back(try_)
1584+
.push_back(arg)
1585+
.push_back(catch_);
1586+
}
1587+
16131588
static Ref makeDot(Ref obj, IString key) {
16141589
return &makeRawArray(3)->push_back(makeRawString(DOT))
16151590
.push_back(obj)
16161591
.push_back(makeRawString(key));
16171592
}
16181593

1594+
template<typename ...Ts>
1595+
static Ref makeDot(Ref obj, Ref key, Ts... args) {
1596+
return makeDot(makeDot(obj, key), args...);
1597+
}
1598+
16191599
static Ref makeDot(Ref obj, Ref key) {
16201600
assert(key->isString());
16211601
return makeDot(obj, key->getIString());

src/wasm-s-parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ class SExpressionWasmBuilder {
159159
}
160160
Expression* parseExpression(Element& s);
161161

162+
MixedArena& getAllocator() {
163+
return allocator;
164+
}
165+
162166
private:
163167
Expression* makeExpression(Element& s);
164168
Expression* makeBinary(Element& s, BinaryOp op, WasmType type);

src/wasm/wasm-s-parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
495495
std::move(params),
496496
result,
497497
std::move(vars)
498-
));
498+
));
499499
};
500500
auto ensureAutoBlock = [&]() {
501501
if (!autoBlock) {

0 commit comments

Comments
 (0)