summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rwxr-xr-xscripts/gen-s-parser.py4
-rw-r--r--src/binaryen-c.cpp102
-rw-r--r--src/binaryen-c.h57
-rw-r--r--src/gen-s-parser.inc4
-rw-r--r--src/ir/ExpressionAnalyzer.cpp6
-rw-r--r--src/ir/ExpressionManipulator.cpp13
-rw-r--r--src/ir/ReFinalize.cpp3
-rw-r--r--src/ir/cost.h3
-rw-r--r--src/ir/effects.h21
-rw-r--r--src/ir/utils.h6
-rw-r--r--src/js/binaryen.js-post.js89
-rw-r--r--src/passes/DeadCodeElimination.cpp12
-rw-r--r--src/passes/MemoryPacking.cpp5
-rw-r--r--src/passes/Print.cpp37
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp7
-rw-r--r--src/passes/Vacuum.cpp3
-rw-r--r--src/wasm-binary.h3
-rw-r--r--src/wasm-builder.h14
-rw-r--r--src/wasm-interpreter.h67
-rw-r--r--src/wasm-s-parser.h3
-rw-r--r--src/wasm-stack.h3
-rw-r--r--src/wasm-traversal.h49
-rw-r--r--src/wasm.h22
-rw-r--r--src/wasm/wasm-binary.cpp44
-rw-r--r--src/wasm/wasm-emscripten.cpp2
-rw-r--r--src/wasm/wasm-s-parser.cpp22
-rw-r--r--src/wasm/wasm-stack.cpp18
-rw-r--r--src/wasm/wasm-validator.cpp29
-rw-r--r--src/wasm/wasm.cpp28
-rw-r--r--src/wasm2js.h31
-rw-r--r--test/binaryen.js/exception-handling.js.txt8
-rw-r--r--test/binaryen.js/expressions.js72
-rw-r--r--test/binaryen.js/expressions.js.txt7
-rw-r--r--test/binaryen.js/kitchen-sink.js10
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt63
-rw-r--r--test/example/c-api-kitchen-sink.c6
-rw-r--r--test/example/c-api-kitchen-sink.txt8
38 files changed, 402 insertions, 482 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80534dab8..47b8798cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,9 @@ Current Trunk
basic subtyping of `externref`, `funcref` and `exnref` (if enabled).
- Enabling the exception handling or anyref features without also enabling
reference types is a validation error now.
+- The `Host` expression and its respective APIs have been refactored into
+ separate `MemorySize` and `MemoryGrow` expressions to align with other memory
+ instructions.
v96
---
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index db0dbc66f..d66f10852 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -66,8 +66,8 @@ instructions = [
("i64.store8", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
("i64.store16", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
("i64.store32", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
- ("memory.size", "makeHost(s, HostOp::MemorySize)"),
- ("memory.grow", "makeHost(s, HostOp::MemoryGrow)"),
+ ("memory.size", "makeMemorySize(s)"),
+ ("memory.grow", "makeMemoryGrow(s)"),
("i32.const", "makeConst(s, Type::i32)"),
("i64.const", "makeConst(s, Type::i64)"),
("f32.const", "makeConst(s, Type::f32)"),
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 3084ae2ae..e833692d5 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -199,7 +199,12 @@ BinaryenExpressionId BinaryenBinaryId(void) { return Expression::Id::BinaryId; }
BinaryenExpressionId BinaryenSelectId(void) { return Expression::Id::SelectId; }
BinaryenExpressionId BinaryenDropId(void) { return Expression::Id::DropId; }
BinaryenExpressionId BinaryenReturnId(void) { return Expression::Id::ReturnId; }
-BinaryenExpressionId BinaryenHostId(void) { return Expression::Id::HostId; }
+BinaryenExpressionId BinaryenMemorySizeId(void) {
+ return Expression::Id::MemorySizeId;
+}
+BinaryenExpressionId BinaryenMemoryGrowId(void) {
+ return Expression::Id::MemoryGrowId;
+}
BinaryenExpressionId BinaryenNopId(void) { return Expression::Id::NopId; }
BinaryenExpressionId BinaryenUnreachableId(void) {
return Expression::Id::UnreachableId;
@@ -509,8 +514,6 @@ BinaryenOp BinaryenLtFloat64(void) { return LtFloat64; }
BinaryenOp BinaryenLeFloat64(void) { return LeFloat64; }
BinaryenOp BinaryenGtFloat64(void) { return GtFloat64; }
BinaryenOp BinaryenGeFloat64(void) { return GeFloat64; }
-BinaryenOp BinaryenMemorySize(void) { return MemorySize; }
-BinaryenOp BinaryenMemoryGrow(void) { return MemoryGrow; }
BinaryenOp BinaryenAtomicRMWAdd(void) { return AtomicRMWOp::Add; }
BinaryenOp BinaryenAtomicRMWSub(void) { return AtomicRMWOp::Sub; }
BinaryenOp BinaryenAtomicRMWAnd(void) { return AtomicRMWOp::And; }
@@ -1056,20 +1059,13 @@ BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module,
auto* ret = Builder(*(Module*)module).makeReturn((Expression*)value);
return static_cast<Expression*>(ret);
}
-BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module,
- BinaryenOp op,
- const char* name,
- BinaryenExpressionRef* operands,
- BinaryenIndex numOperands) {
- auto* ret = ((Module*)module)->allocator.alloc<Host>();
- ret->op = HostOp(op);
- if (name) {
- ret->nameOperand = name;
- }
- for (BinaryenIndex i = 0; i < numOperands; i++) {
- ret->operands.push_back((Expression*)operands[i]);
- }
- ret->finalize();
+BinaryenExpressionRef BinaryenMemorySize(BinaryenModuleRef module) {
+ auto* ret = Builder(*(Module*)module).makeMemorySize();
+ return static_cast<Expression*>(ret);
+}
+BinaryenExpressionRef BinaryenMemoryGrow(BinaryenModuleRef module,
+ BinaryenExpressionRef delta) {
+ auto* ret = Builder(*(Module*)module).makeMemoryGrow((Expression*)delta);
return static_cast<Expression*>(ret);
}
BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module) {
@@ -1826,72 +1822,18 @@ void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr,
assert(valueExpr);
static_cast<GlobalSet*>(expression)->value = (Expression*)valueExpr;
}
-// Host
-BinaryenOp BinaryenHostGetOp(BinaryenExpressionRef expr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- return static_cast<Host*>(expression)->op;
-}
-void BinaryenHostSetOp(BinaryenExpressionRef expr, BinaryenOp op) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- static_cast<Host*>(expression)->op = (HostOp)op;
-}
-const char* BinaryenHostGetNameOperand(BinaryenExpressionRef expr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- return static_cast<Host*>(expression)->nameOperand.c_str();
-}
-void BinaryenHostSetNameOperand(BinaryenExpressionRef expr, const char* name) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- static_cast<Host*>(expression)->nameOperand = name ? name : "";
-}
-BinaryenIndex BinaryenHostGetNumOperands(BinaryenExpressionRef expr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- return static_cast<Host*>(expression)->operands.size();
-}
-BinaryenExpressionRef BinaryenHostGetOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index) {
+// MemoryGrow
+BinaryenExpressionRef BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- assert(index < static_cast<Host*>(expression)->operands.size());
- return static_cast<Host*>(expression)->operands[index];
+ assert(expression->is<MemoryGrow>());
+ return static_cast<MemoryGrow*>(expression)->delta;
}
-void BinaryenHostSetOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index,
- BinaryenExpressionRef operandExpr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- assert(index < static_cast<Host*>(expression)->operands.size());
- assert(operandExpr);
- static_cast<Host*>(expression)->operands[index] = (Expression*)operandExpr;
-}
-BinaryenIndex BinaryenHostAppendOperand(BinaryenExpressionRef expr,
- BinaryenExpressionRef operandExpr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- assert(operandExpr);
- auto& list = static_cast<Host*>(expression)->operands;
- auto index = list.size();
- list.push_back((Expression*)operandExpr);
- return index;
-}
-void BinaryenHostInsertOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index,
- BinaryenExpressionRef operandExpr) {
- auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- assert(operandExpr);
- static_cast<Host*>(expression)
- ->operands.insertAt(index, (Expression*)operandExpr);
-}
-BinaryenExpressionRef BinaryenHostRemoveOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index) {
+void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr,
+ BinaryenExpressionRef deltaExpr) {
auto* expression = (Expression*)expr;
- assert(expression->is<Host>());
- return static_cast<Host*>(expression)->operands.removeAt(index);
+ assert(expression->is<MemoryGrow>());
+ assert(deltaExpr);
+ static_cast<MemoryGrow*>(expression)->delta = (Expression*)deltaExpr;
}
// Load
int BinaryenLoadIsAtomic(BinaryenExpressionRef expr) {
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index c462bfc0f..f368ad122 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -142,7 +142,8 @@ BINARYEN_API BinaryenExpressionId BinaryenBinaryId(void);
BINARYEN_API BinaryenExpressionId BinaryenSelectId(void);
BINARYEN_API BinaryenExpressionId BinaryenDropId(void);
BINARYEN_API BinaryenExpressionId BinaryenReturnId(void);
-BINARYEN_API BinaryenExpressionId BinaryenHostId(void);
+BINARYEN_API BinaryenExpressionId BinaryenMemorySizeId(void);
+BINARYEN_API BinaryenExpressionId BinaryenMemoryGrowId(void);
BINARYEN_API BinaryenExpressionId BinaryenNopId(void);
BINARYEN_API BinaryenExpressionId BinaryenUnreachableId(void);
BINARYEN_API BinaryenExpressionId BinaryenAtomicCmpxchgId(void);
@@ -383,8 +384,6 @@ BINARYEN_API BinaryenOp BinaryenLtFloat64(void);
BINARYEN_API BinaryenOp BinaryenLeFloat64(void);
BINARYEN_API BinaryenOp BinaryenGtFloat64(void);
BINARYEN_API BinaryenOp BinaryenGeFloat64(void);
-BINARYEN_API BinaryenOp BinaryenMemorySize(void);
-BINARYEN_API BinaryenOp BinaryenMemoryGrow(void);
BINARYEN_API BinaryenOp BinaryenAtomicRMWAdd(void);
BINARYEN_API BinaryenOp BinaryenAtomicRMWSub(void);
BINARYEN_API BinaryenOp BinaryenAtomicRMWAnd(void);
@@ -729,12 +728,9 @@ BINARYEN_API BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
// Return: value can be NULL
BINARYEN_API BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module,
BinaryenExpressionRef value);
-// Host: name may be NULL
-BINARYEN_API BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module,
- BinaryenOp op,
- const char* name,
- BinaryenExpressionRef* operands,
- BinaryenIndex numOperands);
+BINARYEN_API BinaryenExpressionRef BinaryenMemorySize(BinaryenModuleRef module);
+BINARYEN_API BinaryenExpressionRef
+BinaryenMemoryGrow(BinaryenModuleRef module, BinaryenExpressionRef delta);
BINARYEN_API BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module);
BINARYEN_API BinaryenExpressionRef
BinaryenUnreachable(BinaryenModuleRef module);
@@ -1153,43 +1149,14 @@ BinaryenGlobalSetGetValue(BinaryenExpressionRef expr);
BINARYEN_API void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr,
BinaryenExpressionRef valueExpr);
-// Host
-
-// Gets the operation being performed by a host expression.
-BINARYEN_API BinaryenOp BinaryenHostGetOp(BinaryenExpressionRef expr);
-// Sets the operation being performed by a host expression.
-BINARYEN_API void BinaryenHostSetOp(BinaryenExpressionRef expr, BinaryenOp op);
-// Gets the name operand, if any, of a host expression.
-BINARYEN_API const char* BinaryenHostGetNameOperand(BinaryenExpressionRef expr);
-// Sets the name operand, if any, of a host expression.
-BINARYEN_API void BinaryenHostSetNameOperand(BinaryenExpressionRef expr,
- const char* nameOperand);
-// Gets the number of operands of a host expression.
-BINARYEN_API BinaryenIndex
-BinaryenHostGetNumOperands(BinaryenExpressionRef expr);
-// Gets the operand at the specified index of a host expression.
-BINARYEN_API BinaryenExpressionRef
-BinaryenHostGetOperandAt(BinaryenExpressionRef expr, BinaryenIndex index);
-// Sets the operand at the specified index of a host expression.
-BINARYEN_API void BinaryenHostSetOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index,
- BinaryenExpressionRef operandExpr);
-// Appends an operand expression to a host expression, returning its insertion
-// index.
-BINARYEN_API BinaryenIndex BinaryenHostAppendOperand(
- BinaryenExpressionRef expr, BinaryenExpressionRef operandExpr);
-// Inserts an operand expression at the specified index of a host expression,
-// moving existing operands including the one previously at that index one index
-// up.
-BINARYEN_API void
-BinaryenHostInsertOperandAt(BinaryenExpressionRef expr,
- BinaryenIndex index,
- BinaryenExpressionRef operandExpr);
-// Removes the operand expression at the specified index of a host expression,
-// moving all subsequent operands one index down. Returns the operand
-// expression.
+// MemoryGrow
+
+// Gets the delta of a `memory.grow` expression.
BINARYEN_API BinaryenExpressionRef
-BinaryenHostRemoveOperandAt(BinaryenExpressionRef expr, BinaryenIndex index);
+BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr);
+// Sets the delta of a `memory.grow` expression.
+BINARYEN_API void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr,
+ BinaryenExpressionRef delta);
// Load
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 6d9160c88..d14e5bbdc 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -2503,13 +2503,13 @@ switch (op[0]) {
if (strcmp(op, "memory.fill") == 0) { return makeMemoryFill(s); }
goto parse_error;
case 'g':
- if (strcmp(op, "memory.grow") == 0) { return makeHost(s, HostOp::MemoryGrow); }
+ if (strcmp(op, "memory.grow") == 0) { return makeMemoryGrow(s); }
goto parse_error;
case 'i':
if (strcmp(op, "memory.init") == 0) { return makeMemoryInit(s); }
goto parse_error;
case 's':
- if (strcmp(op, "memory.size") == 0) { return makeHost(s, HostOp::MemorySize); }
+ if (strcmp(op, "memory.size") == 0) { return makeMemorySize(s); }
goto parse_error;
default: goto parse_error;
}
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index d2f9611f9..37ba82e81 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -215,10 +215,8 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
void visitSelect(Select* curr) {}
void visitDrop(Drop* curr) {}
void visitReturn(Return* curr) {}
- void visitHost(Host* curr) {
- visitor.visitInt(curr->op);
- visitor.visitNonScopeName(curr->nameOperand);
- }
+ void visitMemorySize(MemorySize* curr) {}
+ void visitMemoryGrow(MemoryGrow* curr) {}
void visitRefNull(RefNull* curr) { visitor.visitType(curr->type); }
void visitRefIsNull(RefIsNull* curr) {}
void visitRefFunc(RefFunc* curr) { visitor.visitNonScopeName(curr->func); }
diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp
index 6f64ec77b..e1264e96e 100644
--- a/src/ir/ExpressionManipulator.cpp
+++ b/src/ir/ExpressionManipulator.cpp
@@ -218,14 +218,11 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
Expression* visitReturn(Return* curr) {
return builder.makeReturn(copy(curr->value));
}
- Expression* visitHost(Host* curr) {
- std::vector<Expression*> operands;
- for (Index i = 0; i < curr->operands.size(); i++) {
- operands.push_back(copy(curr->operands[i]));
- }
- auto* ret =
- builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
- return ret;
+ Expression* visitMemorySize(MemorySize* curr) {
+ return builder.makeMemorySize();
+ }
+ Expression* visitMemoryGrow(MemoryGrow* curr) {
+ return builder.makeMemoryGrow(copy(curr->delta));
}
Expression* visitRefNull(RefNull* curr) {
return builder.makeRefNull(curr->type);
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 822fc5808..b6e2a1b59 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -119,7 +119,8 @@ void ReFinalize::visitBinary(Binary* curr) { curr->finalize(); }
void ReFinalize::visitSelect(Select* curr) { curr->finalize(); }
void ReFinalize::visitDrop(Drop* curr) { curr->finalize(); }
void ReFinalize::visitReturn(Return* curr) { curr->finalize(); }
-void ReFinalize::visitHost(Host* curr) { curr->finalize(); }
+void ReFinalize::visitMemorySize(MemorySize* curr) { curr->finalize(); }
+void ReFinalize::visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); }
void ReFinalize::visitRefNull(RefNull* curr) { curr->finalize(); }
void ReFinalize::visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
void ReFinalize::visitRefFunc(RefFunc* curr) { curr->finalize(); }
diff --git a/src/ir/cost.h b/src/ir/cost.h
index ea3e32909..056d51447 100644
--- a/src/ir/cost.h
+++ b/src/ir/cost.h
@@ -754,7 +754,8 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
}
Index visitDrop(Drop* curr) { return visit(curr->value); }
Index visitReturn(Return* curr) { return maybeVisit(curr->value); }
- Index visitHost(Host* curr) { return 100; }
+ Index visitMemorySize(MemorySize* curr) { return 1; }
+ Index visitMemoryGrow(MemoryGrow* curr) { return 100; }
Index visitRefNull(RefNull* curr) { return 1; }
Index visitRefIsNull(RefIsNull* curr) { return 1; }
Index visitRefFunc(RefFunc* curr) { return 1; }
diff --git a/src/ir/effects.h b/src/ir/effects.h
index 9d6e90936..b973d7446 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -428,7 +428,8 @@ struct EffectAnalyzer
implicitTrap = true;
break;
}
- default: {}
+ default: {
+ }
}
}
}
@@ -446,17 +447,27 @@ struct EffectAnalyzer
implicitTrap = true;
break;
}
- default: {}
+ default: {
+ }
}
}
}
void visitSelect(Select* curr) {}
void visitDrop(Drop* curr) {}
void visitReturn(Return* curr) { branchesOut = true; }
- void visitHost(Host* curr) {
+ void visitMemorySize(MemorySize* curr) {
+ // memory.size accesses the size of the memory, and thus can be modeled as
+ // reading memory
+ readsMemory = true;
+ // Atomics are sequentially consistent with memory.size.
+ isAtomic = true;
+ }
+ void visitMemoryGrow(MemoryGrow* curr) {
calls = true;
- // memory.grow modifies the set of valid addresses, and thus can be modeled
- // as modifying memory
+ // memory.grow technically does a read-modify-write operation on the memory
+ // size in the successful case, modifying the set of valid addresses, and
+ // just a read operation in the failure case
+ readsMemory = true;
writesMemory = true;
// Atomics are also sequentially consistent with memory.grow.
isAtomic = true;
diff --git a/src/ir/utils.h b/src/ir/utils.h
index 176699591..51fe4c9e7 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -145,7 +145,8 @@ struct ReFinalize
void visitSelect(Select* curr);
void visitDrop(Drop* curr);
void visitReturn(Return* curr);
- void visitHost(Host* curr);
+ void visitMemorySize(MemorySize* curr);
+ void visitMemoryGrow(MemoryGrow* curr);
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
@@ -213,7 +214,8 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitSelect(Select* curr) { curr->finalize(); }
void visitDrop(Drop* curr) { curr->finalize(); }
void visitReturn(Return* curr) { curr->finalize(); }
- void visitHost(Host* curr) { curr->finalize(); }
+ void visitMemorySize(MemorySize* curr) { curr->finalize(); }
+ void visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); }
void visitRefNull(RefNull* curr) { curr->finalize(); }
void visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
void visitRefFunc(RefFunc* curr) { curr->finalize(); }
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 7f5467312..b02216509 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -65,7 +65,8 @@ function initializeConstants() {
'Select',
'Drop',
'Return',
- 'Host',
+ 'MemorySize',
+ 'MemoryGrow',
'Nop',
'Unreachable',
'AtomicCmpxchg',
@@ -265,8 +266,6 @@ function initializeConstants() {
'LeFloat64',
'GtFloat64',
'GeFloat64',
- 'MemorySize',
- 'MemoryGrow',
'AtomicRMWAdd',
'AtomicRMWSub',
'AtomicRMWAnd',
@@ -599,10 +598,10 @@ function wrapModule(module, self = {}) {
self['memory'] = {
'size'() {
- return Module['_BinaryenHost'](module, Module['MemorySize']);
+ return Module['_BinaryenMemorySize'](module);
},
'grow'(value) {
- return Module['_BinaryenHost'](module, Module['MemoryGrow'], null, i32sToStack([value]), 1);
+ return Module['_BinaryenMemoryGrow'](module, value);
},
'init'(segment, dest, offset, size) {
return Module['_BinaryenMemoryInit'](module, segment, dest, offset, size);
@@ -2092,9 +2091,6 @@ function wrapModule(module, self = {}) {
self['return'] = function(value) {
return Module['_BinaryenReturn'](module, value);
};
- self['host'] = function(op, name, operands = []) {
- return preserveStack(() => Module['_BinaryenHost'](module, op, strToStack(name), i32sToStack(operands), operands.length));
- };
self['nop'] = function() {
return Module['_BinaryenNop'](module);
};
@@ -2637,14 +2633,17 @@ Module['getExpressionInfo'] = function(expr) {
'id': id,
'type': type
};
- case Module['HostId']:
+ case Module['MemorySizeId']:
return {
'id': id,
- 'type': type,
- 'op': Module['_BinaryenHostGetOp'](expr),
- 'nameOperand': UTF8ToString(Module['_BinaryenHostGetNameOperand'](expr)),
- 'operands': getAllNested(expr, Module['_BinaryenHostGetNumOperands'], Module['_BinaryenHostGetOperandAt'])
+ 'type': type
};
+ case Module['MemoryGrowId']:
+ return {
+ 'id': id,
+ 'type': type,
+ 'delta': Module['_BinaryenMemoryGrowGetDelta'](expr)
+ }
case Module['AtomicRMWId']:
return {
'id': id,
@@ -3479,63 +3478,15 @@ Module['GlobalSet'] = makeExpressionWrapper({
}
});
-Module['Host'] = makeExpressionWrapper({
- 'getOp'(expr) {
- return Module['_BinaryenHostGetOp'](expr);
- },
- 'setOp'(expr, op) {
- Module['_BinaryenHostSetOp'](expr, op);
- },
- 'getNameOperand'(expr) {
- const name = Module['_BinaryenHostGetNameOperand'](expr);
- return name ? UTF8ToString(name) : null;
- },
- 'setNameOperand'(expr, name) {
- preserveStack(() => { Module['_BinaryenHostSetNameOperand'](expr, strToStack(name)) });
- },
- 'getNumOperands'(expr) {
- return Module['_BinaryenHostGetNumOperands'](expr);
- },
- 'getOperands'(expr) {
- const numOperands = Module['_BinaryenHostGetNumOperands'](expr);
- const operands = new Array(numOperands);
- let index = 0;
- while (index < numOperands) {
- operands[index] = Module['_BinaryenHostGetOperandAt'](expr, index++);
- }
- return operands;
- },
- 'setOperands'(expr, operands) {
- const numOperands = operands.length;
- let prevNumOperands = Module['_BinaryenHostGetNumOperands'](expr);
- let index = 0;
- while (index < numOperands) {
- if (index < prevNumOperands) {
- Module['_BinaryenHostSetOperandAt'](expr, index, operands[index]);
- } else {
- Module['_BinaryenHostAppendOperand'](expr, operands[index]);
- }
- ++index;
- }
- while (prevNumOperands > index) {
- Module['_BinaryenHostRemoveOperandAt'](expr, --prevNumOperands);
- }
- },
- 'getOperandAt'(expr, index) {
- return Module['_BinaryenHostGetOperandAt'](expr, index);
- },
- 'setOperandAt'(expr, index, operandExpr) {
- Module['_BinaryenHostSetOperandAt'](expr, index, operandExpr);
- },
- 'appendOperand'(expr, operandExpr) {
- return Module['_BinaryenHostAppendOperand'](expr, operandExpr);
- },
- 'insertOperandAt'(expr, index, operandExpr) {
- Module['_BinaryenHostInsertOperandAt'](expr, index, operandExpr);
- },
- 'removeOperandAt'(expr, index) {
- return Module['_BinaryenHostRemoveOperandAt'](expr, index);
+Module['MemorySize'] = makeExpressionWrapper({});
+
+Module['MemoryGrow'] = makeExpressionWrapper({
+ 'getDelta'(expr) {
+ return Module['_BinaryenMemoryGrowGetDelta'](expr);
},
+ 'setDelta'(expr, deltaExpr) {
+ Module['_BinaryenMemoryGrowSetDelta'](expr, deltaExpr);
+ }
});
Module['Load'] = makeExpressionWrapper({
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 9e2e194cb..4215de3f8 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -315,8 +315,10 @@ struct DeadCodeElimination
DELEGATE(Drop);
case Expression::Id::ReturnId:
DELEGATE(Return);
- case Expression::Id::HostId:
- DELEGATE(Host);
+ case Expression::Id::MemorySizeId:
+ DELEGATE(MemorySize);
+ case Expression::Id::MemoryGrowId:
+ DELEGATE(MemoryGrow);
case Expression::Id::NopId:
DELEGATE(Nop);
case Expression::Id::UnreachableId:
@@ -519,7 +521,11 @@ struct DeadCodeElimination
blockifyReachableOperands({curr->value}, curr->type);
}
- void visitHost(Host* curr) { handleCall(curr); }
+ void visitMemorySize(MemorySize* curr) {}
+
+ void visitMemoryGrow(MemoryGrow* curr) {
+ blockifyReachableOperands({curr->delta}, curr->type);
+ }
void visitFunction(Function* curr) { assert(reachableBreaks.size() == 0); }
};
diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp
index 1a1e87502..eac7fb7f0 100644
--- a/src/passes/MemoryPacking.cpp
+++ b/src/passes/MemoryPacking.cpp
@@ -77,9 +77,8 @@ const size_t DATA_DROP_SIZE = 3;
namespace {
Expression* makeShiftedMemorySize(Builder& builder) {
- return builder.makeBinary(ShlInt32,
- builder.makeHost(MemorySize, Name(), {}),
- builder.makeConst(int32_t(16)));
+ return builder.makeBinary(
+ ShlInt32, builder.makeMemorySize(), builder.makeConst(int32_t(16)));
}
} // anonymous namespace
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 15ab97098..916615e07 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1430,16 +1430,8 @@ struct PrintExpressionContents
}
void visitDrop(Drop* curr) { printMedium(o, "drop"); }
void visitReturn(Return* curr) { printMedium(o, "return"); }
- void visitHost(Host* curr) {
- switch (curr->op) {
- case MemorySize:
- printMedium(o, "memory.size");
- break;
- case MemoryGrow:
- printMedium(o, "memory.grow");
- break;
- }
- }
+ void visitMemorySize(MemorySize* curr) { printMedium(o, "memory.size"); }
+ void visitMemoryGrow(MemoryGrow* curr) { printMedium(o, "memory.grow"); }
void visitRefNull(RefNull* curr) {
printMedium(o, "ref.null ");
o << curr->type.getHeapType();
@@ -1577,7 +1569,9 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
o << ')';
}
void printFullLine(Expression* expression) {
- !minify && doIndent(o, indent);
+ if (!minify) {
+ doIndent(o, indent);
+ }
if (full) {
o << "[" << expression->type << "] ";
}
@@ -1945,20 +1939,17 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
printFullLine(curr->value);
decIndent();
}
- void visitHost(Host* curr) {
+ void visitMemorySize(MemorySize* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
- switch (curr->op) {
- case MemoryGrow: {
- incIndent();
- printFullLine(curr->operands[0]);
- decIndent();
- break;
- }
- case MemorySize: {
- o << ')';
- }
- }
+ o << ')';
+ }
+ void visitMemoryGrow(MemoryGrow* curr) {
+ o << '(';
+ PrintExpressionContents(currFunction, o).visit(curr);
+ incIndent();
+ printFullLine(curr->delta);
+ decIndent();
}
void visitRefNull(RefNull* curr) {
o << '(';
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp
index 21cbc5e5b..3795022c2 100644
--- a/src/passes/RemoveUnusedModuleElements.cpp
+++ b/src/passes/RemoveUnusedModuleElements.cpp
@@ -111,11 +111,8 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> {
void visitDataDrop(DataDrop* curr) { usesMemory = true; }
void visitMemoryCopy(MemoryCopy* curr) { usesMemory = true; }
void visitMemoryFill(MemoryFill* curr) { usesMemory = true; }
- void visitHost(Host* curr) {
- if (curr->op == MemorySize || curr->op == MemoryGrow) {
- usesMemory = true;
- }
- }
+ void visitMemorySize(MemorySize* curr) { usesMemory = true; }
+ void visitMemoryGrow(MemoryGrow* curr) { usesMemory = true; }
void visitRefFunc(RefFunc* curr) {
if (reachable.count(
ModuleElement(ModuleElementKind::Function, curr->func)) == 0) {
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 94537619c..618a198e5 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -92,7 +92,8 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
case Expression::Id::StoreId:
case Expression::Id::ReturnId:
case Expression::Id::GlobalSetId:
- case Expression::Id::HostId:
+ case Expression::Id::MemorySizeId:
+ case Expression::Id::MemoryGrowId:
case Expression::Id::UnreachableId:
return curr; // always needed
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 77f53fcd2..da2378993 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1437,7 +1437,8 @@ public:
bool maybeVisitMemoryFill(Expression*& out, uint32_t code);
void visitSelect(Select* curr, uint8_t code);
void visitReturn(Return* curr);
- bool maybeVisitHost(Expression*& out, uint8_t code);
+ void visitMemorySize(MemorySize* curr);
+ void visitMemoryGrow(MemoryGrow* curr);
void visitNop(Nop* curr);
void visitUnreachable(Unreachable* curr);
void visitDrop(Drop* curr);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 6c1923482..762d89dbe 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -519,12 +519,14 @@ public:
ret->value = value;
return ret;
}
- Host*
- makeHost(HostOp op, Name nameOperand, std::vector<Expression*>&& operands) {
- auto* ret = allocator.alloc<Host>();
- ret->op = op;
- ret->nameOperand = nameOperand;
- ret->operands.set(operands);
+ MemorySize* makeMemorySize() {
+ auto* ret = allocator.alloc<MemorySize>();
+ ret->finalize();
+ return ret;
+ }
+ MemoryGrow* makeMemoryGrow(Expression* delta) {
+ auto* ret = allocator.alloc<MemoryGrow>();
+ ret->delta = delta;
ret->finalize();
return ret;
}
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 361545a2c..8fc595034 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1226,7 +1226,8 @@ public:
Flow visitCallIndirect(CallIndirect* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitLoad(Load* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitStore(Store* curr) { WASM_UNREACHABLE("unimp"); }
- Flow visitHost(Host* curr) { WASM_UNREACHABLE("unimp"); }
+ Flow visitMemorySize(MemorySize* curr) { WASM_UNREACHABLE("unimp"); }
+ Flow visitMemoryGrow(MemoryGrow* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitMemoryInit(MemoryInit* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitDataDrop(DataDrop* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitMemoryCopy(MemoryCopy* curr) { WASM_UNREACHABLE("unimp"); }
@@ -1491,8 +1492,12 @@ public:
NOTE_ENTER("Store");
return Flow(NONCONSTANT_FLOW);
}
- Flow visitHost(Host* curr) {
- NOTE_ENTER("Host");
+ Flow visitMemorySize(MemorySize* curr) {
+ NOTE_ENTER("MemorySize");
+ return Flow(NONCONSTANT_FLOW);
+ }
+ Flow visitMemoryGrow(MemoryGrow* curr) {
+ NOTE_ENTER("MemoryGrow");
return Flow(NONCONSTANT_FLOW);
}
Flow visitMemoryInit(MemoryInit* curr) {
@@ -2288,37 +2293,33 @@ private:
return Literal(std::array<Literal, 2>{{val, zero}});
}
}
- Flow visitHost(Host* curr) {
- NOTE_ENTER("Host");
- switch (curr->op) {
- case MemorySize:
- return Literal(int32_t(instance.memorySize));
- case MemoryGrow: {
- auto fail = Literal(int32_t(-1));
- Flow flow = this->visit(curr->operands[0]);
- if (flow.breaking()) {
- return flow;
- }
- int32_t ret = instance.memorySize;
- uint32_t delta = flow.getSingleValue().geti32();
- if (delta > uint32_t(-1) / Memory::kPageSize) {
- return fail;
- }
- if (instance.memorySize >= uint32_t(-1) - delta) {
- return fail;
- }
- uint32_t newSize = instance.memorySize + delta;
- if (newSize > instance.wasm.memory.max) {
- return fail;
- }
- instance.externalInterface->growMemory(instance.memorySize *
- Memory::kPageSize,
- newSize * Memory::kPageSize);
- instance.memorySize = newSize;
- return Literal(int32_t(ret));
- }
+ Flow visitMemorySize(MemorySize* curr) {
+ NOTE_ENTER("MemorySize");
+ return Literal(int32_t(instance.memorySize));
+ }
+ Flow visitMemoryGrow(MemoryGrow* curr) {
+ NOTE_ENTER("MemoryGrow");
+ auto fail = Literal(int32_t(-1));
+ Flow flow = this->visit(curr->delta);
+ if (flow.breaking()) {
+ return flow;
}
- WASM_UNREACHABLE("invalid op");
+ int32_t ret = instance.memorySize;
+ uint32_t delta = flow.getSingleValue().geti32();
+ if (delta > uint32_t(-1) / Memory::kPageSize) {
+ return fail;
+ }
+ if (instance.memorySize >= uint32_t(-1) - delta) {
+ return fail;
+ }
+ uint32_t newSize = instance.memorySize + delta;
+ if (newSize > instance.wasm.memory.max) {
+ return fail;
+ }
+ instance.externalInterface->growMemory(
+ instance.memorySize * Memory::kPageSize, newSize * Memory::kPageSize);
+ instance.memorySize = newSize;
+ return Literal(int32_t(ret));
}
Flow visitMemoryInit(MemoryInit* curr) {
NOTE_ENTER("MemoryInit");
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 85ca217e7..68baf7b08 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -183,7 +183,8 @@ private:
Expression* makeUnary(Element& s, UnaryOp op);
Expression* makeSelect(Element& s);
Expression* makeDrop(Element& s);
- Expression* makeHost(Element& s, HostOp op);
+ Expression* makeMemorySize(Element& s);
+ Expression* makeMemoryGrow(Element& s);
Index getLocalIndex(Element& s);
Expression* makeLocalGet(Element& s);
Expression* makeLocalTee(Element& s);
diff --git a/src/wasm-stack.h b/src/wasm-stack.h
index ed9245d4f..6a926eddf 100644
--- a/src/wasm-stack.h
+++ b/src/wasm-stack.h
@@ -132,7 +132,8 @@ public:
void visitBinary(Binary* curr);
void visitSelect(Select* curr);
void visitReturn(Return* curr);
- void visitHost(Host* curr);
+ void visitMemorySize(MemorySize* curr);
+ void visitMemoryGrow(MemoryGrow* curr);
void visitRefNull(RefNull* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index fc6b1cbb8..94997caf1 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -71,7 +71,8 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
ReturnType visitSelect(Select* curr) { return ReturnType(); }
ReturnType visitDrop(Drop* curr) { return ReturnType(); }
ReturnType visitReturn(Return* curr) { return ReturnType(); }
- ReturnType visitHost(Host* curr) { return ReturnType(); }
+ ReturnType visitMemorySize(MemorySize* curr) { return ReturnType(); }
+ ReturnType visitMemoryGrow(MemoryGrow* curr) { return ReturnType(); }
ReturnType visitRefNull(RefNull* curr) { return ReturnType(); }
ReturnType visitRefIsNull(RefIsNull* curr) { return ReturnType(); }
ReturnType visitRefFunc(RefFunc* curr) { return ReturnType(); }
@@ -169,8 +170,10 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
DELEGATE(Drop);
case Expression::Id::ReturnId:
DELEGATE(Return);
- case Expression::Id::HostId:
- DELEGATE(Host);
+ case Expression::Id::MemorySizeId:
+ DELEGATE(MemorySize);
+ case Expression::Id::MemoryGrowId:
+ DELEGATE(MemoryGrow);
case Expression::Id::RefNullId:
DELEGATE(RefNull);
case Expression::Id::RefIsNullId:
@@ -252,7 +255,8 @@ struct OverriddenVisitor {
UNIMPLEMENTED(Select);
UNIMPLEMENTED(Drop);
UNIMPLEMENTED(Return);
- UNIMPLEMENTED(Host);
+ UNIMPLEMENTED(MemorySize);
+ UNIMPLEMENTED(MemoryGrow);
UNIMPLEMENTED(RefNull);
UNIMPLEMENTED(RefIsNull);
UNIMPLEMENTED(RefFunc);
@@ -351,8 +355,10 @@ struct OverriddenVisitor {
DELEGATE(Drop);
case Expression::Id::ReturnId:
DELEGATE(Return);
- case Expression::Id::HostId:
- DELEGATE(Host);
+ case Expression::Id::MemorySizeId:
+ DELEGATE(MemorySize);
+ case Expression::Id::MemoryGrowId:
+ DELEGATE(MemoryGrow);
case Expression::Id::RefNullId:
DELEGATE(RefNull);
case Expression::Id::RefIsNullId:
@@ -497,7 +503,10 @@ struct UnifiedExpressionVisitor : public Visitor<SubType, ReturnType> {
ReturnType visitReturn(Return* curr) {
return static_cast<SubType*>(this)->visitExpression(curr);
}
- ReturnType visitHost(Host* curr) {
+ ReturnType visitMemorySize(MemorySize* curr) {
+ return static_cast<SubType*>(this)->visitExpression(curr);
+ }
+ ReturnType visitMemoryGrow(MemoryGrow* curr) {
return static_cast<SubType*>(this)->visitExpression(curr);
}
ReturnType visitRefNull(RefNull* curr) {
@@ -811,8 +820,11 @@ struct Walker : public VisitorType {
static void doVisitReturn(SubType* self, Expression** currp) {
self->visitReturn((*currp)->cast<Return>());
}
- static void doVisitHost(SubType* self, Expression** currp) {
- self->visitHost((*currp)->cast<Host>());
+ static void doVisitMemorySize(SubType* self, Expression** currp) {
+ self->visitMemorySize((*currp)->cast<MemorySize>());
+ }
+ static void doVisitMemoryGrow(SubType* self, Expression** currp) {
+ self->visitMemoryGrow((*currp)->cast<MemoryGrow>());
}
static void doVisitRefNull(SubType* self, Expression** currp) {
self->visitRefNull((*currp)->cast<RefNull>());
@@ -1076,14 +1088,13 @@ struct PostWalker : public Walker<SubType, VisitorType> {
self->maybePushTask(SubType::scan, &curr->cast<Return>()->value);
break;
}
- case Expression::Id::HostId: {
- self->pushTask(SubType::doVisitHost, currp);
- auto& list = curr->cast<Host>()->operands;
- for (int i = int(list.size()) - 1; i >= 0; i--) {
- self->pushTask(SubType::scan, &list[i]);
- }
+ case Expression::Id::MemorySizeId:
+ self->pushTask(SubType::doVisitMemorySize, currp);
+ break;
+ case Expression::Id::MemoryGrowId:
+ self->pushTask(SubType::doVisitMemoryGrow, currp);
+ self->pushTask(SubType::scan, &curr->cast<MemoryGrow>()->delta);
break;
- }
case Expression::Id::RefNullId: {
self->pushTask(SubType::doVisitRefNull, currp);
break;
@@ -1210,7 +1221,8 @@ struct ControlFlowWalker : public PostWalker<SubType, VisitorType> {
self->pushTask(SubType::doPostVisitControlFlow, currp);
break;
}
- default: {}
+ default: {
+ }
}
PostWalker<SubType, VisitorType>::scan(self, currp);
@@ -1223,7 +1235,8 @@ struct ControlFlowWalker : public PostWalker<SubType, VisitorType> {
self->pushTask(SubType::doPreVisitControlFlow, currp);
break;
}
- default: {}
+ default: {
+ }
}
}
};
diff --git a/src/wasm.h b/src/wasm.h
index c5db2fbd3..419e02875 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -434,8 +434,6 @@ enum BinaryOp {
InvalidBinary
};
-enum HostOp { MemorySize, MemoryGrow };
-
enum AtomicRMWOp { Add, Sub, And, Or, Xor, Xchg };
enum SIMDExtractOp {
@@ -534,7 +532,8 @@ public:
SelectId,
DropId,
ReturnId,
- HostId,
+ MemorySizeId,
+ MemoryGrowId,
NopId,
UnreachableId,
AtomicRMWId,
@@ -1066,13 +1065,20 @@ public:
Expression* value = nullptr;
};
-class Host : public SpecificExpression<Expression::HostId> {
+class MemorySize : public SpecificExpression<Expression::MemorySizeId> {
public:
- Host(MixedArena& allocator) : operands(allocator) {}
+ MemorySize() { type = Type::i32; }
+ MemorySize(MixedArena& allocator) : MemorySize() {}
- HostOp op;
- Name nameOperand;
- ExpressionList operands;
+ void finalize();
+};
+
+class MemoryGrow : public SpecificExpression<Expression::MemoryGrowId> {
+public:
+ MemoryGrow() { type = Type::i32; }
+ MemoryGrow(MixedArena& allocator) : MemoryGrow() {}
+
+ Expression* delta = nullptr;
void finalize();
};
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 2910bb383..e958dca6e 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2452,6 +2452,14 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::BrOnExn:
visitBrOnExn((curr = allocator.alloc<BrOnExn>())->cast<BrOnExn>());
break;
+ case BinaryConsts::MemorySize:
+ visitMemorySize(
+ (curr = allocator.alloc<MemorySize>())->cast<MemorySize>());
+ break;
+ case BinaryConsts::MemoryGrow:
+ visitMemoryGrow(
+ (curr = allocator.alloc<MemoryGrow>())->cast<MemoryGrow>());
+ break;
case BinaryConsts::AtomicPrefix: {
code = static_cast<uint8_t>(getU32LEB());
if (maybeVisitLoad(curr, code, /*isAtomic=*/true)) {
@@ -2551,9 +2559,6 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitStore(curr, code, /*isAtomic=*/false)) {
break;
}
- if (maybeVisitHost(curr, code)) {
- break;
- }
throwError("bad node code " + std::to_string(code));
break;
}
@@ -4763,32 +4768,23 @@ void WasmBinaryBuilder::visitReturn(Return* curr) {
curr->finalize();
}
-bool WasmBinaryBuilder::maybeVisitHost(Expression*& out, uint8_t code) {
- Host* curr;
- switch (code) {
- case BinaryConsts::MemorySize: {
- curr = allocator.alloc<Host>();
- curr->op = MemorySize;
- break;
- }
- case BinaryConsts::MemoryGrow: {
- curr = allocator.alloc<Host>();
- curr->op = MemoryGrow;
- curr->operands.resize(1);
- curr->operands[0] = popNonVoidExpression();
- break;
- }
- default:
- return false;
+void WasmBinaryBuilder::visitMemorySize(MemorySize* curr) {
+ BYN_TRACE("zz node: MemorySize\n");
+ auto reserved = getU32LEB();
+ if (reserved != 0) {
+ throwError("Invalid reserved field on memory.size");
}
- BYN_TRACE("zz node: Host\n");
+ curr->finalize();
+}
+
+void WasmBinaryBuilder::visitMemoryGrow(MemoryGrow* curr) {
+ BYN_TRACE("zz node: MemoryGrow\n");
+ curr->delta = popNonVoidExpression();
auto reserved = getU32LEB();
if (reserved != 0) {
- throwError("Invalid reserved field on memory.grow/memory.size");
+ throwError("Invalid reserved field on memory.grow");
}
curr->finalize();
- out = curr;
- return true;
}
void WasmBinaryBuilder::visitNop(Nop* curr) { BYN_TRACE("zz node: Nop\n"); }
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index e41d0df48..a0f0ade9d 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -122,7 +122,7 @@ Function* EmscriptenGlueGenerator::generateMemoryGrowthFunction() {
Function* growFunction =
builder.makeFunction(name, std::move(params), Type::i32, {});
growFunction->body =
- builder.makeHost(MemoryGrow, Name(), {builder.makeLocalGet(0, Type::i32)});
+ builder.makeMemoryGrow(builder.makeLocalGet(0, Type::i32));
addExportedFunction(wasm, growFunction);
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 97da80fea..2883519f2 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1021,19 +1021,15 @@ Expression* SExpressionWasmBuilder::makeDrop(Element& s) {
return ret;
}
-Expression* SExpressionWasmBuilder::makeHost(Element& s, HostOp op) {
- auto ret = allocator.alloc<Host>();
- ret->op = op;
- parseCallOperands(s, 1, s.size(), ret);
- if (ret->op == HostOp::MemoryGrow) {
- if (ret->operands.size() != 1) {
- throw ParseException("memory.grow needs one operand", s.line, s.col);
- }
- } else {
- if (ret->operands.size() != 0) {
- throw ParseException("host needs zero operands", s.line, s.col);
- }
- }
+Expression* SExpressionWasmBuilder::makeMemorySize(Element& s) {
+ auto ret = allocator.alloc<MemorySize>();
+ ret->finalize();
+ return ret;
+}
+
+Expression* SExpressionWasmBuilder::makeMemoryGrow(Element& s) {
+ auto ret = allocator.alloc<MemoryGrow>();
+ ret->delta = parseExpression(s[1]);
ret->finalize();
return ret;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 64622e814..edfdf31d1 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1671,17 +1671,13 @@ void BinaryInstWriter::visitReturn(Return* curr) {
o << int8_t(BinaryConsts::Return);
}
-void BinaryInstWriter::visitHost(Host* curr) {
- switch (curr->op) {
- case MemorySize: {
- o << int8_t(BinaryConsts::MemorySize);
- break;
- }
- case MemoryGrow: {
- o << int8_t(BinaryConsts::MemoryGrow);
- break;
- }
- }
+void BinaryInstWriter::visitMemorySize(MemorySize* curr) {
+ o << int8_t(BinaryConsts::MemorySize);
+ o << U32LEB(0); // Reserved flags field
+}
+
+void BinaryInstWriter::visitMemoryGrow(MemoryGrow* curr) {
+ o << int8_t(BinaryConsts::MemoryGrow);
o << U32LEB(0); // Reserved flags field
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 15fb66926..c141fdd6f 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -326,7 +326,8 @@ public:
void visitSelect(Select* curr);
void visitDrop(Drop* curr);
void visitReturn(Return* curr);
- void visitHost(Host* curr);
+ void visitMemorySize(MemorySize* curr);
+ void visitMemoryGrow(MemoryGrow* curr);
void visitRefIsNull(RefIsNull* curr);
void visitRefFunc(RefFunc* curr);
void visitTry(Try* curr);
@@ -1897,24 +1898,18 @@ void FunctionValidator::visitReturn(Return* curr) {
returnTypes.insert(curr->value ? curr->value->type : Type::none);
}
-void FunctionValidator::visitHost(Host* curr) {
+void FunctionValidator::visitMemorySize(MemorySize* curr) {
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
- switch (curr->op) {
- case MemoryGrow: {
- shouldBeEqual(curr->operands.size(),
- size_t(1),
- curr,
- "memory.grow must have 1 operand");
- shouldBeEqualOrFirstIsUnreachable(curr->operands[0]->type,
- Type(Type::i32),
- curr,
- "memory.grow must have i32 operand");
- break;
- }
- case MemorySize:
- break;
- }
+}
+
+void FunctionValidator::visitMemoryGrow(MemoryGrow* curr) {
+ shouldBeTrue(
+ getModule()->memory.exists, curr, "Memory operations require a memory");
+ shouldBeEqualOrFirstIsUnreachable(curr->delta->type,
+ Type(Type::i32),
+ curr,
+ "memory.grow must have i32 operand");
}
void FunctionValidator::visitRefIsNull(RefIsNull* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 9d43a33b1..d3c0b46e8 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -145,8 +145,10 @@ const char* getExpressionName(Expression* curr) {
return "drop";
case Expression::Id::ReturnId:
return "return";
- case Expression::Id::HostId:
- return "host";
+ case Expression::Id::MemorySizeId:
+ return "memory.size";
+ case Expression::Id::MemoryGrowId:
+ return "memory.grow";
case Expression::Id::NopId:
return "nop";
case Expression::Id::UnreachableId:
@@ -879,21 +881,13 @@ void Drop::finalize() {
}
}
-void Host::finalize() {
- switch (op) {
- case MemorySize: {
- type = Type::i32;
- break;
- }
- case MemoryGrow: {
- // if the single operand is not reachable, so are we
- if (operands[0]->type == Type::unreachable) {
- type = Type::unreachable;
- } else {
- type = Type::i32;
- }
- break;
- }
+void MemorySize::finalize() { type = Type::i32; }
+
+void MemoryGrow::finalize() {
+ if (delta->type == Type::unreachable) {
+ type = Type::unreachable;
+ } else {
+ type = Type::i32;
}
}
diff --git a/src/wasm2js.h b/src/wasm2js.h
index ac0268e5b..8418d5b15 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -1321,8 +1321,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
!FindAll<Call>(curr->value).list.empty() ||
!FindAll<CallIndirect>(curr->ptr).list.empty() ||
!FindAll<CallIndirect>(curr->value).list.empty() ||
- !FindAll<Host>(curr->ptr).list.empty() ||
- !FindAll<Host>(curr->value).list.empty()) {
+ !FindAll<MemoryGrow>(curr->ptr).list.empty() ||
+ !FindAll<MemoryGrow>(curr->value).list.empty()) {
Ref ret;
ScopedTemp ptr(Type::i32, parent, func);
sequenceAppend(ret, visitAndAssign(curr->ptr, ptr));
@@ -1842,21 +1842,20 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
return ValueBuilder::makeReturn(val);
}
- Ref visitHost(Host* curr) {
- if (curr->op == HostOp::MemoryGrow) {
- if (module->memory.exists &&
- module->memory.max > module->memory.initial) {
- return ValueBuilder::makeCall(
- WASM_MEMORY_GROW,
- makeAsmCoercion(visit(curr->operands[0], EXPRESSION_RESULT),
- wasmToAsmType(curr->operands[0]->type)));
- } else {
- return ValueBuilder::makeCall(ABORT_FUNC);
- }
- } else if (curr->op == HostOp::MemorySize) {
- return ValueBuilder::makeCall(WASM_MEMORY_SIZE);
+ Ref visitMemorySize(MemorySize* curr) {
+ return ValueBuilder::makeCall(WASM_MEMORY_SIZE);
+ }
+
+ Ref visitMemoryGrow(MemoryGrow* curr) {
+ if (module->memory.exists &&
+ module->memory.max > module->memory.initial) {
+ return ValueBuilder::makeCall(
+ WASM_MEMORY_GROW,
+ makeAsmCoercion(visit(curr->delta, EXPRESSION_RESULT),
+ wasmToAsmType(curr->delta->type)));
+ } else {
+ return ValueBuilder::makeCall(ABORT_FUNC);
}
- WASM_UNREACHABLE("unexpected expr type"); // TODO
}
Ref visitNop(Nop* curr) { return ValueBuilder::makeToplevel(); }
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index 21eb9a70d..ab545aac9 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -28,7 +28,7 @@
)
)
-getExpressionInfo(throw) = {"id":43,"type":1,"event":"e"}
-getExpressionInfo(br_on_exn) = {"id":45,"type":9,"name":"l","event":"e"}
-getExpressionInfo(rethrow) = {"id":44,"type":1}
-getExpressionInfo(try) = {"id":42,"type":0}
+getExpressionInfo(throw) = {"id":44,"type":1,"event":"e"}
+getExpressionInfo(br_on_exn) = {"id":46,"type":9,"name":"l","event":"e"}
+getExpressionInfo(rethrow) = {"id":45,"type":1}
+getExpressionInfo(try) = {"id":43,"type":0}
diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js
index a0f3e6d4b..a9a0ab982 100644
--- a/test/binaryen.js/expressions.js
+++ b/test/binaryen.js/expressions.js
@@ -465,39 +465,55 @@ console.log("# GlobalSet");
module.dispose();
})();
-console.log("# Host");
-(function testHost() {
+console.log("# MemorySize");
+(function testMemorySize() {
const module = new binaryen.Module();
- var op = binaryen.Operations.MemorySize;
- var nameOp = null;
- var operands = [];
- const theHost = binaryen.Host(module.memory.size());
- assert(theHost instanceof binaryen.Host);
- assert(theHost instanceof binaryen.Expression);
- assert(theHost.op === op);
- assert(theHost.nameOperand === nameOp);
- assertDeepEqual(theHost.operands, operands);
- assert(theHost.type === binaryen.i32);
-
- theHost.op = op = binaryen.Operations.MemoryGrow;
- assert(theHost.op === op);
- theHost.nameOperand = nameOp = "a";
- assert(theHost.nameOperand === nameOp);
- theHost.nameOperand = null;
- theHost.operands = operands = [
- module.i32.const(1)
- ];
- assertDeepEqual(theHost.operands, operands);
- theHost.type = binaryen.f64;
- theHost.finalize();
- assert(theHost.type === binaryen.i32);
+ var type = binaryen.i32;
+ const theMemorySize = binaryen.MemorySize(module.memory.size());
+ assert(theMemorySize instanceof binaryen.MemorySize);
+ assert(theMemorySize instanceof binaryen.Expression);
+ assert(theMemorySize.type === type);
+
+ theMemorySize.type = type = binaryen.f64;
+ assert(theMemorySize.type === type);
+ theMemorySize.finalize();
+ assert(theMemorySize.type === binaryen.i32);
+
+ console.log(theMemorySize.toText());
+ assert(
+ theMemorySize.toText()
+ ==
+ "(memory.size)\n"
+ );
- console.log(theHost.toText());
+ module.dispose();
+})();
+
+console.log("# MemoryGrow");
+(function testMemoryGrow() {
+ const module = new binaryen.Module();
+
+ var type = binaryen.i32;
+ var delta = module.i32.const(1);
+ const theMemoryGrow = binaryen.MemoryGrow(module.memory.grow(delta));
+ assert(theMemoryGrow instanceof binaryen.MemoryGrow);
+ assert(theMemoryGrow instanceof binaryen.Expression);
+ assert(theMemoryGrow.delta === delta);
+ assert(theMemoryGrow.type === type);
+
+ theMemoryGrow.delta = delta = module.i32.const(2);
+ assert(theMemoryGrow.delta === delta);
+ theMemoryGrow.type = type = binaryen.f64;
+ assert(theMemoryGrow.type === type);
+ theMemoryGrow.finalize();
+ assert(theMemoryGrow.type === binaryen.i32);
+
+ console.log(theMemoryGrow.toText());
assert(
- theHost.toText()
+ theMemoryGrow.toText()
==
- "(memory.grow\n (i32.const 1)\n)\n"
+ "(memory.grow\n (i32.const 2)\n)\n"
);
module.dispose();
diff --git a/test/binaryen.js/expressions.js.txt b/test/binaryen.js/expressions.js.txt
index 239498b1f..a8946875a 100644
--- a/test/binaryen.js/expressions.js.txt
+++ b/test/binaryen.js/expressions.js.txt
@@ -64,9 +64,12 @@
(f64.const 3)
)
-# Host
+# MemorySize
+(memory.size)
+
+# MemoryGrow
(memory.grow
- (i32.const 1)
+ (i32.const 2)
)
# Load
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index 5a3da277e..d985b39aa 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -131,7 +131,8 @@ function test_ids() {
console.log("SelectId: " + binaryen.SelectId);
console.log("DropId: " + binaryen.DropId);
console.log("ReturnId: " + binaryen.ReturnId);
- console.log("HostId: " + binaryen.HostId);
+ console.log("MemorySizeId: " + binaryen.MemorySizeId);
+ console.log("MemoryGrowId: " + binaryen.MemoryGrowId);
console.log("NopId: " + binaryen.NopId);
console.log("UnreachableId: " + binaryen.UnreachableId);
console.log("AtomicCmpxchgId: " + binaryen.AtomicCmpxchgId);
@@ -572,7 +573,12 @@ function test_core() {
module.externref.pop(),
module.funcref.pop(),
module.exnref.pop(),
- // TODO: Host
+
+ // Memory
+ module.memory.size(),
+ module.memory.grow(makeInt32(0)),
+
+ // Other
module.nop(),
module.unreachable(),
];
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 2f75640d1..54052a597 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -57,28 +57,29 @@ BinaryId: 16
SelectId: 17
DropId: 18
ReturnId: 19
-HostId: 20
-NopId: 21
-UnreachableId: 22
-AtomicCmpxchgId: 24
-AtomicRMWId: 23
-AtomicWaitId: 25
-AtomicNotifyId: 26
-SIMDExtractId: 28
-SIMDReplaceId: 29
-SIMDShuffleId: 30
-SIMDTernaryId: 31
-SIMDShiftId: 32
-SIMDLoadId: 33
-MemoryInitId: 34
-DataDropId: 35
-MemoryCopyId: 36
-MemoryFillId: 37
-TryId: 42
-ThrowId: 43
-RethrowId: 44
-BrOnExnId: 45
-PopId: 38
+MemorySizeId: 20
+MemoryGrowId: 21
+NopId: 22
+UnreachableId: 23
+AtomicCmpxchgId: 25
+AtomicRMWId: 24
+AtomicWaitId: 26
+AtomicNotifyId: 27
+SIMDExtractId: 29
+SIMDReplaceId: 30
+SIMDShuffleId: 31
+SIMDTernaryId: 32
+SIMDShiftId: 33
+SIMDLoadId: 34
+MemoryInitId: 35
+DataDropId: 36
+MemoryCopyId: 37
+MemoryFillId: 38
+TryId: 43
+ThrowId: 44
+RethrowId: 45
+BrOnExnId: 46
+PopId: 39
getExpressionInfo={"id":15,"type":4,"op":6}
(f32.neg
(f32.const -33.61199951171875)
@@ -1919,6 +1920,14 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7}
(drop
(pop exnref)
)
+ (drop
+ (memory.size)
+ )
+ (drop
+ (memory.grow
+ (i32.const 0)
+ )
+ )
(nop)
(unreachable)
)
@@ -3759,6 +3768,14 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7}
(drop
(pop exnref)
)
+ (drop
+ (memory.size)
+ )
+ (drop
+ (memory.grow
+ (i32.const 0)
+ )
+ )
(nop)
(unreachable)
)
@@ -4336,5 +4353,5 @@ sizeof Literal: 24
)
)
-getExpressionInfo(memory.grow)={"id":20,"type":2,"op":1,"nameOperand":"","operands":[1]}
+getExpressionInfo(memory.grow)={"id":21,"type":2,"delta":1}
getExpressionInfo(switch)={"id":5,"type":1,"names":["label"],"defaultName":"label","condition":0,"value":0}
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index d4072476e..f619e6db5 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -756,8 +756,10 @@ void test_core() {
BinaryenPop(module, BinaryenTypeExternref()),
BinaryenPop(module, BinaryenTypeExnref()),
BinaryenPop(module, iIfF),
-
- // TODO: Host
+ // Memory
+ BinaryenMemorySize(module),
+ BinaryenMemoryGrow(module, makeInt32(module, 0)),
+ // Other
BinaryenNop(module),
BinaryenUnreachable(module),
};
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index b891bf6ce..d92009c35 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -1857,6 +1857,14 @@ BinaryenFeatureAll: 2047
(drop
(pop i32 i64 f32 f64)
)
+ (drop
+ (memory.size)
+ )
+ (drop
+ (memory.grow
+ (i32.const 0)
+ )
+ )
(nop)
(unreachable)
)