Skip to content

Commit 2841edd

Browse files
authored
Refactor Host expression to MemorySize and MemoryGrow (#3137)
Aligns the internal representations of `memory.size` and `memory.grow` with other more recent memory instructions by removing the legacy `Host` expression class and adding separate expression classes for `MemorySize` and `MemoryGrow`. Simplifies related APIs, but is also a breaking API change.
1 parent e1d74ef commit 2841edd

38 files changed

+402
-482
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ Current Trunk
2020
basic subtyping of `externref`, `funcref` and `exnref` (if enabled).
2121
- Enabling the exception handling or anyref features without also enabling
2222
reference types is a validation error now.
23+
- The `Host` expression and its respective APIs have been refactored into
24+
separate `MemorySize` and `MemoryGrow` expressions to align with other memory
25+
instructions.
2326

2427
v96
2528
---

scripts/gen-s-parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@
6666
("i64.store8", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
6767
("i64.store16", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
6868
("i64.store32", "makeStore(s, Type::i64, /*isAtomic=*/false)"),
69-
("memory.size", "makeHost(s, HostOp::MemorySize)"),
70-
("memory.grow", "makeHost(s, HostOp::MemoryGrow)"),
69+
("memory.size", "makeMemorySize(s)"),
70+
("memory.grow", "makeMemoryGrow(s)"),
7171
("i32.const", "makeConst(s, Type::i32)"),
7272
("i64.const", "makeConst(s, Type::i64)"),
7373
("f32.const", "makeConst(s, Type::f32)"),

src/binaryen-c.cpp

Lines changed: 22 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,12 @@ BinaryenExpressionId BinaryenBinaryId(void) { return Expression::Id::BinaryId; }
199199
BinaryenExpressionId BinaryenSelectId(void) { return Expression::Id::SelectId; }
200200
BinaryenExpressionId BinaryenDropId(void) { return Expression::Id::DropId; }
201201
BinaryenExpressionId BinaryenReturnId(void) { return Expression::Id::ReturnId; }
202-
BinaryenExpressionId BinaryenHostId(void) { return Expression::Id::HostId; }
202+
BinaryenExpressionId BinaryenMemorySizeId(void) {
203+
return Expression::Id::MemorySizeId;
204+
}
205+
BinaryenExpressionId BinaryenMemoryGrowId(void) {
206+
return Expression::Id::MemoryGrowId;
207+
}
203208
BinaryenExpressionId BinaryenNopId(void) { return Expression::Id::NopId; }
204209
BinaryenExpressionId BinaryenUnreachableId(void) {
205210
return Expression::Id::UnreachableId;
@@ -509,8 +514,6 @@ BinaryenOp BinaryenLtFloat64(void) { return LtFloat64; }
509514
BinaryenOp BinaryenLeFloat64(void) { return LeFloat64; }
510515
BinaryenOp BinaryenGtFloat64(void) { return GtFloat64; }
511516
BinaryenOp BinaryenGeFloat64(void) { return GeFloat64; }
512-
BinaryenOp BinaryenMemorySize(void) { return MemorySize; }
513-
BinaryenOp BinaryenMemoryGrow(void) { return MemoryGrow; }
514517
BinaryenOp BinaryenAtomicRMWAdd(void) { return AtomicRMWOp::Add; }
515518
BinaryenOp BinaryenAtomicRMWSub(void) { return AtomicRMWOp::Sub; }
516519
BinaryenOp BinaryenAtomicRMWAnd(void) { return AtomicRMWOp::And; }
@@ -1056,20 +1059,13 @@ BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module,
10561059
auto* ret = Builder(*(Module*)module).makeReturn((Expression*)value);
10571060
return static_cast<Expression*>(ret);
10581061
}
1059-
BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module,
1060-
BinaryenOp op,
1061-
const char* name,
1062-
BinaryenExpressionRef* operands,
1063-
BinaryenIndex numOperands) {
1064-
auto* ret = ((Module*)module)->allocator.alloc<Host>();
1065-
ret->op = HostOp(op);
1066-
if (name) {
1067-
ret->nameOperand = name;
1068-
}
1069-
for (BinaryenIndex i = 0; i < numOperands; i++) {
1070-
ret->operands.push_back((Expression*)operands[i]);
1071-
}
1072-
ret->finalize();
1062+
BinaryenExpressionRef BinaryenMemorySize(BinaryenModuleRef module) {
1063+
auto* ret = Builder(*(Module*)module).makeMemorySize();
1064+
return static_cast<Expression*>(ret);
1065+
}
1066+
BinaryenExpressionRef BinaryenMemoryGrow(BinaryenModuleRef module,
1067+
BinaryenExpressionRef delta) {
1068+
auto* ret = Builder(*(Module*)module).makeMemoryGrow((Expression*)delta);
10731069
return static_cast<Expression*>(ret);
10741070
}
10751071
BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module) {
@@ -1826,72 +1822,18 @@ void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr,
18261822
assert(valueExpr);
18271823
static_cast<GlobalSet*>(expression)->value = (Expression*)valueExpr;
18281824
}
1829-
// Host
1830-
BinaryenOp BinaryenHostGetOp(BinaryenExpressionRef expr) {
1831-
auto* expression = (Expression*)expr;
1832-
assert(expression->is<Host>());
1833-
return static_cast<Host*>(expression)->op;
1834-
}
1835-
void BinaryenHostSetOp(BinaryenExpressionRef expr, BinaryenOp op) {
1836-
auto* expression = (Expression*)expr;
1837-
assert(expression->is<Host>());
1838-
static_cast<Host*>(expression)->op = (HostOp)op;
1839-
}
1840-
const char* BinaryenHostGetNameOperand(BinaryenExpressionRef expr) {
1841-
auto* expression = (Expression*)expr;
1842-
assert(expression->is<Host>());
1843-
return static_cast<Host*>(expression)->nameOperand.c_str();
1844-
}
1845-
void BinaryenHostSetNameOperand(BinaryenExpressionRef expr, const char* name) {
1846-
auto* expression = (Expression*)expr;
1847-
assert(expression->is<Host>());
1848-
static_cast<Host*>(expression)->nameOperand = name ? name : "";
1849-
}
1850-
BinaryenIndex BinaryenHostGetNumOperands(BinaryenExpressionRef expr) {
1851-
auto* expression = (Expression*)expr;
1852-
assert(expression->is<Host>());
1853-
return static_cast<Host*>(expression)->operands.size();
1854-
}
1855-
BinaryenExpressionRef BinaryenHostGetOperandAt(BinaryenExpressionRef expr,
1856-
BinaryenIndex index) {
1825+
// MemoryGrow
1826+
BinaryenExpressionRef BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr) {
18571827
auto* expression = (Expression*)expr;
1858-
assert(expression->is<Host>());
1859-
assert(index < static_cast<Host*>(expression)->operands.size());
1860-
return static_cast<Host*>(expression)->operands[index];
1828+
assert(expression->is<MemoryGrow>());
1829+
return static_cast<MemoryGrow*>(expression)->delta;
18611830
}
1862-
void BinaryenHostSetOperandAt(BinaryenExpressionRef expr,
1863-
BinaryenIndex index,
1864-
BinaryenExpressionRef operandExpr) {
1865-
auto* expression = (Expression*)expr;
1866-
assert(expression->is<Host>());
1867-
assert(index < static_cast<Host*>(expression)->operands.size());
1868-
assert(operandExpr);
1869-
static_cast<Host*>(expression)->operands[index] = (Expression*)operandExpr;
1870-
}
1871-
BinaryenIndex BinaryenHostAppendOperand(BinaryenExpressionRef expr,
1872-
BinaryenExpressionRef operandExpr) {
1873-
auto* expression = (Expression*)expr;
1874-
assert(expression->is<Host>());
1875-
assert(operandExpr);
1876-
auto& list = static_cast<Host*>(expression)->operands;
1877-
auto index = list.size();
1878-
list.push_back((Expression*)operandExpr);
1879-
return index;
1880-
}
1881-
void BinaryenHostInsertOperandAt(BinaryenExpressionRef expr,
1882-
BinaryenIndex index,
1883-
BinaryenExpressionRef operandExpr) {
1884-
auto* expression = (Expression*)expr;
1885-
assert(expression->is<Host>());
1886-
assert(operandExpr);
1887-
static_cast<Host*>(expression)
1888-
->operands.insertAt(index, (Expression*)operandExpr);
1889-
}
1890-
BinaryenExpressionRef BinaryenHostRemoveOperandAt(BinaryenExpressionRef expr,
1891-
BinaryenIndex index) {
1831+
void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr,
1832+
BinaryenExpressionRef deltaExpr) {
18921833
auto* expression = (Expression*)expr;
1893-
assert(expression->is<Host>());
1894-
return static_cast<Host*>(expression)->operands.removeAt(index);
1834+
assert(expression->is<MemoryGrow>());
1835+
assert(deltaExpr);
1836+
static_cast<MemoryGrow*>(expression)->delta = (Expression*)deltaExpr;
18951837
}
18961838
// Load
18971839
int BinaryenLoadIsAtomic(BinaryenExpressionRef expr) {

src/binaryen-c.h

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ BINARYEN_API BinaryenExpressionId BinaryenBinaryId(void);
142142
BINARYEN_API BinaryenExpressionId BinaryenSelectId(void);
143143
BINARYEN_API BinaryenExpressionId BinaryenDropId(void);
144144
BINARYEN_API BinaryenExpressionId BinaryenReturnId(void);
145-
BINARYEN_API BinaryenExpressionId BinaryenHostId(void);
145+
BINARYEN_API BinaryenExpressionId BinaryenMemorySizeId(void);
146+
BINARYEN_API BinaryenExpressionId BinaryenMemoryGrowId(void);
146147
BINARYEN_API BinaryenExpressionId BinaryenNopId(void);
147148
BINARYEN_API BinaryenExpressionId BinaryenUnreachableId(void);
148149
BINARYEN_API BinaryenExpressionId BinaryenAtomicCmpxchgId(void);
@@ -383,8 +384,6 @@ BINARYEN_API BinaryenOp BinaryenLtFloat64(void);
383384
BINARYEN_API BinaryenOp BinaryenLeFloat64(void);
384385
BINARYEN_API BinaryenOp BinaryenGtFloat64(void);
385386
BINARYEN_API BinaryenOp BinaryenGeFloat64(void);
386-
BINARYEN_API BinaryenOp BinaryenMemorySize(void);
387-
BINARYEN_API BinaryenOp BinaryenMemoryGrow(void);
388387
BINARYEN_API BinaryenOp BinaryenAtomicRMWAdd(void);
389388
BINARYEN_API BinaryenOp BinaryenAtomicRMWSub(void);
390389
BINARYEN_API BinaryenOp BinaryenAtomicRMWAnd(void);
@@ -729,12 +728,9 @@ BINARYEN_API BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module,
729728
// Return: value can be NULL
730729
BINARYEN_API BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module,
731730
BinaryenExpressionRef value);
732-
// Host: name may be NULL
733-
BINARYEN_API BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module,
734-
BinaryenOp op,
735-
const char* name,
736-
BinaryenExpressionRef* operands,
737-
BinaryenIndex numOperands);
731+
BINARYEN_API BinaryenExpressionRef BinaryenMemorySize(BinaryenModuleRef module);
732+
BINARYEN_API BinaryenExpressionRef
733+
BinaryenMemoryGrow(BinaryenModuleRef module, BinaryenExpressionRef delta);
738734
BINARYEN_API BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module);
739735
BINARYEN_API BinaryenExpressionRef
740736
BinaryenUnreachable(BinaryenModuleRef module);
@@ -1153,43 +1149,14 @@ BinaryenGlobalSetGetValue(BinaryenExpressionRef expr);
11531149
BINARYEN_API void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr,
11541150
BinaryenExpressionRef valueExpr);
11551151

1156-
// Host
1157-
1158-
// Gets the operation being performed by a host expression.
1159-
BINARYEN_API BinaryenOp BinaryenHostGetOp(BinaryenExpressionRef expr);
1160-
// Sets the operation being performed by a host expression.
1161-
BINARYEN_API void BinaryenHostSetOp(BinaryenExpressionRef expr, BinaryenOp op);
1162-
// Gets the name operand, if any, of a host expression.
1163-
BINARYEN_API const char* BinaryenHostGetNameOperand(BinaryenExpressionRef expr);
1164-
// Sets the name operand, if any, of a host expression.
1165-
BINARYEN_API void BinaryenHostSetNameOperand(BinaryenExpressionRef expr,
1166-
const char* nameOperand);
1167-
// Gets the number of operands of a host expression.
1168-
BINARYEN_API BinaryenIndex
1169-
BinaryenHostGetNumOperands(BinaryenExpressionRef expr);
1170-
// Gets the operand at the specified index of a host expression.
1171-
BINARYEN_API BinaryenExpressionRef
1172-
BinaryenHostGetOperandAt(BinaryenExpressionRef expr, BinaryenIndex index);
1173-
// Sets the operand at the specified index of a host expression.
1174-
BINARYEN_API void BinaryenHostSetOperandAt(BinaryenExpressionRef expr,
1175-
BinaryenIndex index,
1176-
BinaryenExpressionRef operandExpr);
1177-
// Appends an operand expression to a host expression, returning its insertion
1178-
// index.
1179-
BINARYEN_API BinaryenIndex BinaryenHostAppendOperand(
1180-
BinaryenExpressionRef expr, BinaryenExpressionRef operandExpr);
1181-
// Inserts an operand expression at the specified index of a host expression,
1182-
// moving existing operands including the one previously at that index one index
1183-
// up.
1184-
BINARYEN_API void
1185-
BinaryenHostInsertOperandAt(BinaryenExpressionRef expr,
1186-
BinaryenIndex index,
1187-
BinaryenExpressionRef operandExpr);
1188-
// Removes the operand expression at the specified index of a host expression,
1189-
// moving all subsequent operands one index down. Returns the operand
1190-
// expression.
1152+
// MemoryGrow
1153+
1154+
// Gets the delta of a `memory.grow` expression.
11911155
BINARYEN_API BinaryenExpressionRef
1192-
BinaryenHostRemoveOperandAt(BinaryenExpressionRef expr, BinaryenIndex index);
1156+
BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr);
1157+
// Sets the delta of a `memory.grow` expression.
1158+
BINARYEN_API void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr,
1159+
BinaryenExpressionRef delta);
11931160

11941161
// Load
11951162

src/gen-s-parser.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,13 +2503,13 @@ switch (op[0]) {
25032503
if (strcmp(op, "memory.fill") == 0) { return makeMemoryFill(s); }
25042504
goto parse_error;
25052505
case 'g':
2506-
if (strcmp(op, "memory.grow") == 0) { return makeHost(s, HostOp::MemoryGrow); }
2506+
if (strcmp(op, "memory.grow") == 0) { return makeMemoryGrow(s); }
25072507
goto parse_error;
25082508
case 'i':
25092509
if (strcmp(op, "memory.init") == 0) { return makeMemoryInit(s); }
25102510
goto parse_error;
25112511
case 's':
2512-
if (strcmp(op, "memory.size") == 0) { return makeHost(s, HostOp::MemorySize); }
2512+
if (strcmp(op, "memory.size") == 0) { return makeMemorySize(s); }
25132513
goto parse_error;
25142514
default: goto parse_error;
25152515
}

src/ir/ExpressionAnalyzer.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,8 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
215215
void visitSelect(Select* curr) {}
216216
void visitDrop(Drop* curr) {}
217217
void visitReturn(Return* curr) {}
218-
void visitHost(Host* curr) {
219-
visitor.visitInt(curr->op);
220-
visitor.visitNonScopeName(curr->nameOperand);
221-
}
218+
void visitMemorySize(MemorySize* curr) {}
219+
void visitMemoryGrow(MemoryGrow* curr) {}
222220
void visitRefNull(RefNull* curr) { visitor.visitType(curr->type); }
223221
void visitRefIsNull(RefIsNull* curr) {}
224222
void visitRefFunc(RefFunc* curr) { visitor.visitNonScopeName(curr->func); }

src/ir/ExpressionManipulator.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,11 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
218218
Expression* visitReturn(Return* curr) {
219219
return builder.makeReturn(copy(curr->value));
220220
}
221-
Expression* visitHost(Host* curr) {
222-
std::vector<Expression*> operands;
223-
for (Index i = 0; i < curr->operands.size(); i++) {
224-
operands.push_back(copy(curr->operands[i]));
225-
}
226-
auto* ret =
227-
builder.makeHost(curr->op, curr->nameOperand, std::move(operands));
228-
return ret;
221+
Expression* visitMemorySize(MemorySize* curr) {
222+
return builder.makeMemorySize();
223+
}
224+
Expression* visitMemoryGrow(MemoryGrow* curr) {
225+
return builder.makeMemoryGrow(copy(curr->delta));
229226
}
230227
Expression* visitRefNull(RefNull* curr) {
231228
return builder.makeRefNull(curr->type);

src/ir/ReFinalize.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ void ReFinalize::visitBinary(Binary* curr) { curr->finalize(); }
119119
void ReFinalize::visitSelect(Select* curr) { curr->finalize(); }
120120
void ReFinalize::visitDrop(Drop* curr) { curr->finalize(); }
121121
void ReFinalize::visitReturn(Return* curr) { curr->finalize(); }
122-
void ReFinalize::visitHost(Host* curr) { curr->finalize(); }
122+
void ReFinalize::visitMemorySize(MemorySize* curr) { curr->finalize(); }
123+
void ReFinalize::visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); }
123124
void ReFinalize::visitRefNull(RefNull* curr) { curr->finalize(); }
124125
void ReFinalize::visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
125126
void ReFinalize::visitRefFunc(RefFunc* curr) { curr->finalize(); }

src/ir/cost.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> {
754754
}
755755
Index visitDrop(Drop* curr) { return visit(curr->value); }
756756
Index visitReturn(Return* curr) { return maybeVisit(curr->value); }
757-
Index visitHost(Host* curr) { return 100; }
757+
Index visitMemorySize(MemorySize* curr) { return 1; }
758+
Index visitMemoryGrow(MemoryGrow* curr) { return 100; }
758759
Index visitRefNull(RefNull* curr) { return 1; }
759760
Index visitRefIsNull(RefIsNull* curr) { return 1; }
760761
Index visitRefFunc(RefFunc* curr) { return 1; }

src/ir/effects.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,8 @@ struct EffectAnalyzer
428428
implicitTrap = true;
429429
break;
430430
}
431-
default: {}
431+
default: {
432+
}
432433
}
433434
}
434435
}
@@ -446,17 +447,27 @@ struct EffectAnalyzer
446447
implicitTrap = true;
447448
break;
448449
}
449-
default: {}
450+
default: {
451+
}
450452
}
451453
}
452454
}
453455
void visitSelect(Select* curr) {}
454456
void visitDrop(Drop* curr) {}
455457
void visitReturn(Return* curr) { branchesOut = true; }
456-
void visitHost(Host* curr) {
458+
void visitMemorySize(MemorySize* curr) {
459+
// memory.size accesses the size of the memory, and thus can be modeled as
460+
// reading memory
461+
readsMemory = true;
462+
// Atomics are sequentially consistent with memory.size.
463+
isAtomic = true;
464+
}
465+
void visitMemoryGrow(MemoryGrow* curr) {
457466
calls = true;
458-
// memory.grow modifies the set of valid addresses, and thus can be modeled
459-
// as modifying memory
467+
// memory.grow technically does a read-modify-write operation on the memory
468+
// size in the successful case, modifying the set of valid addresses, and
469+
// just a read operation in the failure case
470+
readsMemory = true;
460471
writesMemory = true;
461472
// Atomics are also sequentially consistent with memory.grow.
462473
isAtomic = true;

src/ir/utils.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ struct ReFinalize
145145
void visitSelect(Select* curr);
146146
void visitDrop(Drop* curr);
147147
void visitReturn(Return* curr);
148-
void visitHost(Host* curr);
148+
void visitMemorySize(MemorySize* curr);
149+
void visitMemoryGrow(MemoryGrow* curr);
149150
void visitRefNull(RefNull* curr);
150151
void visitRefIsNull(RefIsNull* curr);
151152
void visitRefFunc(RefFunc* curr);
@@ -213,7 +214,8 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
213214
void visitSelect(Select* curr) { curr->finalize(); }
214215
void visitDrop(Drop* curr) { curr->finalize(); }
215216
void visitReturn(Return* curr) { curr->finalize(); }
216-
void visitHost(Host* curr) { curr->finalize(); }
217+
void visitMemorySize(MemorySize* curr) { curr->finalize(); }
218+
void visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); }
217219
void visitRefNull(RefNull* curr) { curr->finalize(); }
218220
void visitRefIsNull(RefIsNull* curr) { curr->finalize(); }
219221
void visitRefFunc(RefFunc* curr) { curr->finalize(); }

0 commit comments

Comments
 (0)