Skip to content

Commit 443c006

Browse files
authored
More push/pop support (#2260)
This adds - `push`/`pop` support for other types: v128 and exnref - `push`/`pop` support for binaryen.js Because binaryen.js follows Binaryen's AST structure, without `pop` in binaryen.js, EH instructions cannot be represented in binaryen.js.
1 parent 7bf827d commit 443c006

10 files changed

Lines changed: 255 additions & 38 deletions

File tree

build-js.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ export_function "_BinaryenMemoryInitId"
226226
export_function "_BinaryenDataDropId"
227227
export_function "_BinaryenMemoryCopyId"
228228
export_function "_BinaryenMemoryFillId"
229+
export_function "_BinaryenPushId"
230+
export_function "_BinaryenPopId"
229231

230232
# External kinds
231233
export_function "_BinaryenExternalFunction"
@@ -576,6 +578,8 @@ export_function "_BinaryenMemoryInit"
576578
export_function "_BinaryenDataDrop"
577579
export_function "_BinaryenMemoryCopy"
578580
export_function "_BinaryenMemoryFill"
581+
export_function "_BinaryenPush"
582+
export_function "_BinaryenPop"
579583

580584
# 'Expression' operations
581585
export_function "_BinaryenExpressionGetId"
@@ -752,6 +756,9 @@ export_function "_BinaryenMemoryFillGetDest"
752756
export_function "_BinaryenMemoryFillGetValue"
753757
export_function "_BinaryenMemoryFillGetSize"
754758

759+
# 'Push' expression operations
760+
export_function "_BinaryenPushGetValue"
761+
755762
# 'Module' operations
756763
export_function "_BinaryenModuleCreate"
757764
export_function "_BinaryenModuleDispose"

scripts/gen-s-parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
("i64.pop", "makePop(i64)"),
4949
("f32.pop", "makePop(f32)"),
5050
("f64.pop", "makePop(f64)"),
51+
("v128.pop", "makePop(v128)"),
52+
("exnref.pop", "makePop(exnref)"),
5153
("i32.load", "makeLoad(s, i32, /*isAtomic=*/false)"),
5254
("i64.load", "makeLoad(s, i64, /*isAtomic=*/false)"),
5355
("f32.load", "makeLoad(s, f32, /*isAtomic=*/false)"),

src/binaryen-c.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ BinaryenExpressionId BinaryenMemoryCopyId(void) {
354354
BinaryenExpressionId BinaryenMemoryFillId(void) {
355355
return Expression::Id::MemoryFillId;
356356
}
357+
BinaryenExpressionId BinaryenPushId(void) { return Expression::Id::PushId; }
358+
BinaryenExpressionId BinaryenPopId(void) { return Expression::Id::PopId; }
357359

358360
// External kinds
359361

@@ -1573,6 +1575,21 @@ BinaryenExpressionRef BinaryenMemoryFill(BinaryenModuleRef module,
15731575
}
15741576
return static_cast<Expression*>(ret);
15751577
}
1578+
BinaryenExpressionRef BinaryenPush(BinaryenModuleRef module,
1579+
BinaryenExpressionRef value) {
1580+
auto* ret = Builder(*(Module*)module).makePush((Expression*)value);
1581+
if (tracing) {
1582+
traceExpression(ret, "BinaryenPush", value);
1583+
}
1584+
return static_cast<Expression*>(ret);
1585+
}
1586+
BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type) {
1587+
auto* ret = Builder(*(Module*)module).makePop(Type(type));
1588+
if (tracing) {
1589+
traceExpression(ret, "BinaryenPop", type);
1590+
}
1591+
return static_cast<Expression*>(ret);
1592+
}
15761593

15771594
// Expression utility
15781595

@@ -2704,6 +2721,16 @@ BinaryenExpressionRef BinaryenMemoryFillGetSize(BinaryenExpressionRef expr) {
27042721
assert(expression->is<MemoryFill>());
27052722
return static_cast<MemoryFill*>(expression)->size;
27062723
}
2724+
BinaryenExpressionRef BinaryenPushGetValue(BinaryenExpressionRef expr) {
2725+
if (tracing) {
2726+
std::cout << " BinaryenPushGetValue(expressions[" << expressions[expr]
2727+
<< "]);\n";
2728+
}
2729+
2730+
auto* expression = (Expression*)expr;
2731+
assert(expression->is<Push>());
2732+
return static_cast<Push*>(expression)->value;
2733+
}
27072734

27082735
// Functions
27092736

src/binaryen-c.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ BinaryenExpressionId BinaryenMemoryInitId(void);
127127
BinaryenExpressionId BinaryenDataDropId(void);
128128
BinaryenExpressionId BinaryenMemoryCopyId(void);
129129
BinaryenExpressionId BinaryenMemoryFillId(void);
130+
BinaryenExpressionId BinaryenPushId(void);
131+
BinaryenExpressionId BinaryenPopId(void);
130132

131133
// External kinds (call to get the value of each; you can cache them)
132134

@@ -699,6 +701,9 @@ BinaryenExpressionRef BinaryenMemoryFill(BinaryenModuleRef module,
699701
BinaryenExpressionRef dest,
700702
BinaryenExpressionRef value,
701703
BinaryenExpressionRef size);
704+
BinaryenExpressionRef BinaryenPush(BinaryenModuleRef module,
705+
BinaryenExpressionRef value);
706+
BinaryenExpressionRef BinaryenPop(BinaryenModuleRef module, BinaryenType type);
702707

703708
BinaryenExpressionId BinaryenExpressionGetId(BinaryenExpressionRef expr);
704709
BinaryenType BinaryenExpressionGetType(BinaryenExpressionRef expr);
@@ -850,6 +855,8 @@ BinaryenExpressionRef BinaryenMemoryFillGetDest(BinaryenExpressionRef expr);
850855
BinaryenExpressionRef BinaryenMemoryFillGetValue(BinaryenExpressionRef expr);
851856
BinaryenExpressionRef BinaryenMemoryFillGetSize(BinaryenExpressionRef expr);
852857

858+
BinaryenExpressionRef BinaryenPushGetValue(BinaryenExpressionRef expr);
859+
853860
// Functions
854861

855862
typedef void* BinaryenFunctionRef;

src/gen-s-parser.inc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,17 @@ switch (op[0]) {
5959
default: goto parse_error;
6060
}
6161
}
62-
case 'e':
63-
if (strcmp(op, "else") == 0) { return makeThenOrElse(s); }
64-
goto parse_error;
62+
case 'e': {
63+
switch (op[1]) {
64+
case 'l':
65+
if (strcmp(op, "else") == 0) { return makeThenOrElse(s); }
66+
goto parse_error;
67+
case 'x':
68+
if (strcmp(op, "exnref.pop") == 0) { return makePop(exnref); }
69+
goto parse_error;
70+
default: goto parse_error;
71+
}
72+
}
6573
case 'f': {
6674
switch (op[1]) {
6775
case '3': {
@@ -2278,6 +2286,9 @@ switch (op[0]) {
22782286
case 'o':
22792287
if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); }
22802288
goto parse_error;
2289+
case 'p':
2290+
if (strcmp(op, "v128.pop") == 0) { return makePop(v128); }
2291+
goto parse_error;
22812292
case 's':
22822293
if (strcmp(op, "v128.store") == 0) { return makeStore(s, v128, /*isAtomic=*/false); }
22832294
goto parse_error;

src/js/binaryen.js-post.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Module['MemoryInitId'] = Module['_BinaryenMemoryInitId']();
7878
Module['DataDropId'] = Module['_BinaryenDataDropId']();
7979
Module['MemoryCopyId'] = Module['_BinaryenMemoryCopyId']();
8080
Module['MemoryFillId'] = Module['_BinaryenMemoryFillId']();
81+
Module['PushId'] = Module['_BinaryenPushId']();
82+
Module['PopId'] = Module['_BinaryenPopId']();
8183

8284
// External kinds
8385
Module['ExternalFunction'] = Module['_BinaryenExternalFunction']();
@@ -761,6 +763,9 @@ function wrapModule(module, self) {
761763
'wait': function(ptr, expected, timeout) {
762764
return Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i32']);
763765
},
766+
'pop': function() {
767+
return Module['_BinaryenPop'](module, Module['i32']);
768+
}
764769
};
765770

766771
self['i64'] = {
@@ -1062,6 +1067,9 @@ function wrapModule(module, self) {
10621067
'wait': function(ptr, expected, timeout) {
10631068
return Module['_BinaryenAtomicWait'](module, ptr, expected, timeout, Module['i64']);
10641069
},
1070+
'pop': function() {
1071+
return Module['_BinaryenPop'](module, Module['i64']);
1072+
}
10651073
};
10661074

10671075
self['f32'] = {
@@ -1167,6 +1175,9 @@ function wrapModule(module, self) {
11671175
'ge': function(left, right) {
11681176
return Module['_BinaryenBinary'](module, Module['GeFloat32'], left, right);
11691177
},
1178+
'pop': function() {
1179+
return Module['_BinaryenPop'](module, Module['f32']);
1180+
}
11701181
};
11711182

11721183
self['f64'] = {
@@ -1272,6 +1283,9 @@ function wrapModule(module, self) {
12721283
'ge': function(left, right) {
12731284
return Module['_BinaryenBinary'](module, Module['GeFloat64'], left, right);
12741285
},
1286+
'pop': function() {
1287+
return Module['_BinaryenPop'](module, Module['f64']);
1288+
}
12751289
};
12761290

12771291
self['v128'] = {
@@ -1302,6 +1316,9 @@ function wrapModule(module, self) {
13021316
},
13031317
'bitselect': function(left, right, cond) {
13041318
return Module['_BinaryenSIMDBitselect'](module, left, right, cond);
1319+
},
1320+
'pop': function() {
1321+
return Module['_BinaryenPop'](module, Module['v128']);
13051322
}
13061323
};
13071324

@@ -1724,6 +1741,12 @@ function wrapModule(module, self) {
17241741
},
17251742
};
17261743

1744+
self['exnref'] = {
1745+
'pop': function() {
1746+
return Module['_BinaryenPop'](module, Module['exnref']);
1747+
}
1748+
};
1749+
17271750
self['select'] = function(condition, ifTrue, ifFalse) {
17281751
return Module['_BinaryenSelect'](module, condition, ifTrue, ifFalse);
17291752
};
@@ -1748,6 +1771,9 @@ function wrapModule(module, self) {
17481771
self['notify'] = function(ptr, notifyCount) {
17491772
return Module['_BinaryenAtomicNotify'](module, ptr, notifyCount);
17501773
};
1774+
self['push'] = function(value) {
1775+
return Module['_BinaryenPush'](module, value);
1776+
};
17511777

17521778
// 'Module' operations
17531779
self['addFunctionType'] = function(name, result, paramTypes) {
@@ -2225,6 +2251,7 @@ Module['getExpressionInfo'] = function(expr) {
22252251
};
22262252
case Module['NopId']:
22272253
case Module['UnreachableId']:
2254+
case Module['PopId']:
22282255
return {
22292256
'id': id,
22302257
'type': type
@@ -2349,6 +2376,11 @@ Module['getExpressionInfo'] = function(expr) {
23492376
'value': Module['_BinaryenMemoryFillGetValue'](expr),
23502377
'size': Module['_BinaryenMemoryFillGetSize'](expr)
23512378
};
2379+
case Module['PushId']:
2380+
return {
2381+
'id': id,
2382+
'value': Module['_BinaryenPushGetValue'](expr)
2383+
};
23522384

23532385
default:
23542386
throw Error('unexpected id: ' + id);

test/binaryen.js/kitchen-sink.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ function test_ids() {
111111
console.log("DataDropId: " + Binaryen.DataDropId);
112112
console.log("MemoryCopyId: " + Binaryen.MemoryCopyId);
113113
console.log("MemoryFillId: " + Binaryen.MemoryFillId);
114+
console.log("PushId: " + Binaryen.PushId);
115+
console.log("PopId: " + Binaryen.PopId);
114116
}
115117

116118
function test_core() {
@@ -399,6 +401,13 @@ function test_core() {
399401
// Tail Call
400402
module.returnCall("kitchen()sinker", [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], Binaryen.i32),
401403
module.returnCallIndirect(makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], "iiIfF"),
404+
// Push and pop
405+
module.push(module.i32.pop()),
406+
module.push(module.i64.pop()),
407+
module.push(module.f32.pop()),
408+
module.push(module.f64.pop()),
409+
module.push(module.v128.pop()),
410+
module.push(module.exnref.pop()),
402411
// TODO: Host
403412
module.nop(),
404413
module.unreachable(),

0 commit comments

Comments
 (0)