bleeding edge binaryen

This commit is contained in:
dcode
2019-05-23 13:20:10 +02:00
parent 81c212b208
commit fbba76ef2c
76 changed files with 560 additions and 386 deletions

View File

@ -1997,7 +1997,7 @@ export function compileCall(
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 0, reportNode, compiler)
) return module.createUnreachable();
return module.createHost(HostOp.CurrentMemory);
return module.createHost(HostOp.MemorySize);
}
case BuiltinSymbols.memory_grow: { // memory.grow(pages: i32) -> i32
compiler.currentType = Type.i32;
@ -2005,7 +2005,7 @@ export function compileCall(
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
) return module.createUnreachable();
return module.createHost(HostOp.GrowMemory, null, [
return module.createHost(HostOp.MemoryGrow, null, [
compiler.compileExpression(operands[0], Type.i32, ContextualFlags.IMPLICIT)
]);
}

View File

@ -2173,7 +2173,7 @@ export class Compiler extends DiagnosticEmitter {
// of retaining it as the return value and releasing it as a variable
if (!this.skippedAutoreleases.has(expr)) {
if (returnType.isManaged) {
if (getExpressionId(expr) == ExpressionId.GetLocal) {
if (getExpressionId(expr) == ExpressionId.LocalGet) {
if (flow.isAnyLocalFlag(getGetLocalIndex(expr), LocalFlags.ANY_RETAINED)) {
flow.unsetLocalFlag(getGetLocalIndex(expr), LocalFlags.ANY_RETAINED);
this.skippedAutoreleases.add(expr);
@ -6222,7 +6222,7 @@ export class Compiler extends DiagnosticEmitter {
if (thisArg) {
let classInstance = assert(instance.parent); assert(classInstance.kind == ElementKind.CLASS);
let thisType = assert(instance.signature.thisType);
if (canAlias && getExpressionId(thisArg) == ExpressionId.GetLocal) {
if (canAlias && getExpressionId(thisArg) == ExpressionId.LocalGet) {
flow.addScopedAlias(CommonSymbols.this_, thisType, getGetLocalIndex(thisArg));
let baseInstance = (<Class>classInstance).base;
if (baseInstance) flow.addScopedAlias(CommonSymbols.super_, baseInstance.type, getGetLocalIndex(thisArg));
@ -6244,7 +6244,7 @@ export class Compiler extends DiagnosticEmitter {
for (let i = 0; i < numArguments; ++i) {
let paramExpr = args[i];
let paramType = parameterTypes[i];
if (canAlias && getExpressionId(paramExpr) == ExpressionId.GetLocal) {
if (canAlias && getExpressionId(paramExpr) == ExpressionId.LocalGet) {
flow.addScopedAlias(signature.getParameterName(i), paramType, getGetLocalIndex(paramExpr));
} else {
let argumentLocal = flow.addScopedLocal(
@ -6277,7 +6277,7 @@ export class Compiler extends DiagnosticEmitter {
initType,
ContextualFlags.IMPLICIT
);
if (canAlias && getExpressionId(initExpr) == ExpressionId.GetLocal) {
if (canAlias && getExpressionId(initExpr) == ExpressionId.LocalGet) {
flow.addScopedAlias(signature.getParameterName(i), initType, getGetLocalIndex(initExpr));
} else {
let argumentLocal = flow.addScopedLocal(
@ -6537,7 +6537,7 @@ export class Compiler extends DiagnosticEmitter {
// and a child of something else. Preventing the final release however should
// make it optimize away.
switch (getExpressionId(expr)) {
case ExpressionId.SetLocal: { // local.tee(__retain(expr))
case ExpressionId.LocalSet: { // local.tee(__retain(expr))
if (isTeeLocal(expr)) {
let index = getSetLocalIndex(expr);
if (flow.isAnyLocalFlag(index, LocalFlags.ANY_RETAINED)) {

View File

@ -173,20 +173,20 @@ export class Decompiler {
case ExpressionId.CallIndirect: {
throw new Error("not implemented");
}
case ExpressionId.GetLocal: {
case ExpressionId.LocalGet: {
this.push("$");
this.push(getGetLocalIndex(expr).toString(10));
return;
}
case ExpressionId.SetLocal: {
case ExpressionId.LocalSet: {
this.push("$");
this.push(getSetLocalIndex(expr).toString(10));
this.push(" = ");
this.decompileExpression(getSetLocalValue(expr));
return;
}
case ExpressionId.GetGlobal:
case ExpressionId.SetGlobal: {
case ExpressionId.GlobalGet:
case ExpressionId.GlobalSet: {
throw new Error("not implemented");
}
case ExpressionId.Load: {
@ -832,11 +832,11 @@ export class Decompiler {
}
case ExpressionId.Host: {
switch (getHostOp(expr)) {
case HostOp.CurrentMemory: {
case HostOp.MemorySize: {
this.push("memory.size()");
return;
}
case HostOp.GrowMemory: {
case HostOp.MemoryGrow: {
this.push("memory.grow(");
this.decompileExpression(getHostOperand(expr, 0));
this.push(")");

View File

@ -641,12 +641,12 @@ export class Flow {
// depend on a dynamic nullable state (flag = LocalFlags.NONNULL), while everything else
// has already been handled by the nullable type check above.
switch (getExpressionId(expr)) {
case ExpressionId.SetLocal: {
case ExpressionId.LocalSet: {
if (!isTeeLocal(expr)) break;
let local = this.parentFunction.localsByIndex[getSetLocalIndex(expr)];
return !local.type.is(TypeFlags.NULLABLE) || this.isLocalFlag(local.index, LocalFlags.NONNULL, false);
}
case ExpressionId.GetLocal: {
case ExpressionId.LocalGet: {
let local = this.parentFunction.localsByIndex[getGetLocalIndex(expr)];
return !local.type.is(TypeFlags.NULLABLE) || this.isLocalFlag(local.index, LocalFlags.NONNULL, false);
}
@ -658,14 +658,14 @@ export class Flow {
inheritNonnullIfTrue(expr: ExpressionRef): void {
// A: `expr` is true-ish -> Q: how did that happen?
switch (getExpressionId(expr)) {
case ExpressionId.SetLocal: {
case ExpressionId.LocalSet: {
if (!isTeeLocal(expr)) break;
let local = this.parentFunction.localsByIndex[getSetLocalIndex(expr)];
this.setLocalFlag(local.index, LocalFlags.NONNULL);
this.inheritNonnullIfTrue(getSetLocalValue(expr)); // must have been true-ish as well
break;
}
case ExpressionId.GetLocal: {
case ExpressionId.LocalGet: {
let local = this.parentFunction.localsByIndex[getGetLocalIndex(expr)];
this.setLocalFlag(local.index, LocalFlags.NONNULL);
break;
@ -854,20 +854,20 @@ export class Flow {
switch (getExpressionId(expr)) {
// overflows if the local isn't wrapped or the conversion does
case ExpressionId.GetLocal: {
case ExpressionId.LocalGet: {
let local = this.parentFunction.localsByIndex[getGetLocalIndex(expr)];
return !this.isLocalFlag(local.index, LocalFlags.WRAPPED, true)
|| canConversionOverflow(local.type, type);
}
// overflows if the value does
case ExpressionId.SetLocal: { // tee
case ExpressionId.LocalSet: { // tee
assert(isTeeLocal(expr));
return this.canOverflow(getSetLocalValue(expr), type);
}
// overflows if the conversion does (globals are wrapped on set)
case ExpressionId.GetGlobal: {
case ExpressionId.GlobalGet: {
// TODO: this is inefficient because it has to read a string
let global = assert(this.parentFunction.program.elementsByName.get(assert(getGetGlobalName(expr))));
assert(global.kind == ElementKind.GLOBAL);

View File

@ -42,10 +42,10 @@ declare function _BinaryenBreakId(): BinaryenExpressionId;
declare function _BinaryenSwitchId(): BinaryenExpressionId;
declare function _BinaryenCallId(): BinaryenExpressionId;
declare function _BinaryenCallIndirectId(): BinaryenExpressionId;
declare function _BinaryenGetLocalId(): BinaryenExpressionId;
declare function _BinaryenSetLocalId(): BinaryenExpressionId;
declare function _BinaryenGetGlobalId(): BinaryenExpressionId;
declare function _BinaryenSetGlobalId(): BinaryenExpressionId;
declare function _BinaryenLocalGetId(): BinaryenExpressionId;
declare function _BinaryenLocalSetId(): BinaryenExpressionId;
declare function _BinaryenGlobalGetId(): BinaryenExpressionId;
declare function _BinaryenGlobalSetId(): BinaryenExpressionId;
declare function _BinaryenLoadId(): BinaryenExpressionId;
declare function _BinaryenStoreId(): BinaryenExpressionId;
declare function _BinaryenConstId(): BinaryenExpressionId;
@ -221,8 +221,8 @@ declare function _BinaryenGeFloat64(): BinaryenOp;
declare type BinaryenHostOp = BinaryenOp;
declare function _BinaryenCurrentMemory(): BinaryenHostOp;
declare function _BinaryenGrowMemory(): BinaryenHostOp;
declare function _BinaryenMemorySize(): BinaryenHostOp;
declare function _BinaryenMemoryGrow(): BinaryenHostOp;
declare type BinaryenAtomicRMWOp = BinaryenOp;
@ -380,11 +380,11 @@ declare function _BinaryenBreak(module: BinaryenModuleRef, name: usize, conditio
declare function _BinaryenSwitch(module: BinaryenModuleRef, names: usize, numNames: BinaryenIndex, defaultName: usize, condition: BinaryenExpressionRef, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenCall(module: BinaryenModuleRef, target: usize, operands: usize, numOperands: BinaryenIndex, returnType: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenCallIndirect(module: BinaryenModuleRef, target: BinaryenExpressionRef, operands: usize, numOperands: BinaryenIndex, type: usize): BinaryenExpressionRef;
declare function _BinaryenGetLocal(module: BinaryenModuleRef, index: BinaryenIndex, type: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenSetLocal(module: BinaryenModuleRef, index: BinaryenIndex, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenTeeLocal(module: BinaryenModuleRef, index: BinaryenIndex, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenGetGlobal(module: BinaryenModuleRef, name: usize, type: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenSetGlobal(module: BinaryenModuleRef, name: usize, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenLocalGet(module: BinaryenModuleRef, index: BinaryenIndex, type: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenLocalSet(module: BinaryenModuleRef, index: BinaryenIndex, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenLocalTee(module: BinaryenModuleRef, index: BinaryenIndex, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenGlobalGet(module: BinaryenModuleRef, name: usize, type: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenGlobalSet(module: BinaryenModuleRef, name: usize, value: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenLoad(module: BinaryenModuleRef, bytes: u32, signed: i8, offset: u32, align: u32, type: BinaryenType, ptr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenStore(module: BinaryenModuleRef, bytes: u32, offset: u32, align: u32, ptr: BinaryenExpressionRef, value: BinaryenExpressionRef, type: BinaryenType): BinaryenExpressionRef;
declare function _BinaryenConst(module: BinaryenModuleRef, value: usize): BinaryenExpressionRef;
@ -448,16 +448,16 @@ declare function _BinaryenCallIndirectGetTarget(expr: BinaryenExpressionRef): Bi
declare function _BinaryenCallIndirectGetNumOperands(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenCallIndirectGetOperand(expr: BinaryenExpressionRef, index: BinaryenIndex): BinaryenExpressionRef;
declare function _BinaryenGetLocalGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenLocalGetGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenSetLocalIsTee(expr: BinaryenExpressionRef): bool;
declare function _BinaryenSetLocalGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenSetLocalGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenLocalSetIsTee(expr: BinaryenExpressionRef): bool;
declare function _BinaryenLocalSetGetIndex(expr: BinaryenExpressionRef): BinaryenIndex;
declare function _BinaryenLocalSetGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenGetGlobalGetName(expr: BinaryenExpressionRef): usize;
declare function _BinaryenGlobalGetGetName(expr: BinaryenExpressionRef): usize;
declare function _BinaryenSetGlobalGetName(expr: BinaryenExpressionRef): usize;
declare function _BinaryenSetGlobalGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenGlobalSetGetName(expr: BinaryenExpressionRef): usize;
declare function _BinaryenGlobalSetGetValue(expr: BinaryenExpressionRef): BinaryenExpressionRef;
declare function _BinaryenHostGetOp(expr: BinaryenExpressionRef): BinaryenOp;
declare function _BinaryenHostGetNameOperand(expr: BinaryenExpressionRef): usize;
@ -622,8 +622,8 @@ declare function _BinaryenModuleRead(input: usize, inputSize: usize): BinaryenMo
declare function _BinaryenModuleInterpret(module: BinaryenModuleRef): void;
declare function _BinaryenModuleAddDebugInfoFileName(module: BinaryenModuleRef, filename: usize): BinaryenIndex;
declare function _BinaryenModuleGetDebugInfoFileName(module: BinaryenModuleRef, index: BinaryenIndex): usize;
declare function _BinaryenGetFeatures(module: BinaryenModuleRef): BinaryenFeatureFlags;
declare function _BinaryenSetFeatures(module: BinaryenModuleRef, featureFlags: BinaryenFeatureFlags): void;
declare function _BinaryenModuleGetFeatures(module: BinaryenModuleRef): BinaryenFeatureFlags;
declare function _BinaryenModuleSetFeatures(module: BinaryenModuleRef, featureFlags: BinaryenFeatureFlags): void;
declare type BinaryenRelooperRef = usize;
declare type BinaryenRelooperBlockRef = usize;

View File

@ -46,10 +46,10 @@ export enum ExpressionId {
Switch = _BinaryenSwitchId(),
Call = _BinaryenCallId(),
CallIndirect = _BinaryenCallIndirectId(),
GetLocal = _BinaryenGetLocalId(),
SetLocal = _BinaryenSetLocalId(),
GetGlobal = _BinaryenGetGlobalId(),
SetGlobal = _BinaryenSetGlobalId(),
LocalGet = _BinaryenLocalGetId(),
LocalSet = _BinaryenLocalSetId(),
GlobalGet = _BinaryenGlobalGetId(),
GlobalSet = _BinaryenGlobalSetId(),
Load = _BinaryenLoadId(),
Store = _BinaryenStoreId(),
Const = _BinaryenConstId(),
@ -336,8 +336,8 @@ export enum BinaryOp {
}
export enum HostOp {
CurrentMemory = _BinaryenCurrentMemory(),
GrowMemory = _BinaryenGrowMemory(),
MemorySize = _BinaryenMemorySize(),
MemoryGrow = _BinaryenMemoryGrow(),
}
export enum AtomicRMWOp {
@ -526,14 +526,14 @@ export class Module {
index: i32,
type: NativeType
): ExpressionRef {
return _BinaryenGetLocal(this.ref, index, type);
return _BinaryenLocalGet(this.ref, index, type);
}
createTeeLocal(
index: i32,
value: ExpressionRef
): ExpressionRef {
return _BinaryenTeeLocal(this.ref, index, value);
return _BinaryenLocalTee(this.ref, index, value);
}
createGetGlobal(
@ -541,7 +541,7 @@ export class Module {
type: NativeType
): ExpressionRef {
var cStr = this.allocStringCached(name);
return _BinaryenGetGlobal(this.ref, cStr, type);
return _BinaryenGlobalGet(this.ref, cStr, type);
}
createLoad(
@ -630,7 +630,7 @@ export class Module {
index: Index,
value: ExpressionRef
): ExpressionRef {
return _BinaryenSetLocal(this.ref, index, value);
return _BinaryenLocalSet(this.ref, index, value);
}
createSetGlobal(
@ -638,7 +638,7 @@ export class Module {
value: ExpressionRef
): ExpressionRef {
var cStr = this.allocStringCached(name);
return _BinaryenSetGlobal(this.ref, cStr, value);
return _BinaryenGlobalSet(this.ref, cStr, value);
}
createBlock(
@ -1056,11 +1056,11 @@ export class Module {
}
getFeatures(): BinaryenFeatureFlags {
return _BinaryenGetFeatures(this.ref);
return _BinaryenModuleGetFeatures(this.ref);
}
setFeatures(featureFlags: BinaryenFeatureFlags): void {
_BinaryenSetFeatures(this.ref, featureFlags);
_BinaryenModuleSetFeatures(this.ref, featureFlags);
}
optimize(func: FunctionRef = 0): void {
@ -1221,16 +1221,16 @@ export class Module {
}
}
}
case ExpressionId.GetLocal: {
return _BinaryenGetLocal(this.ref,
_BinaryenGetLocalGetIndex(expr),
case ExpressionId.LocalGet: {
return _BinaryenLocalGet(this.ref,
_BinaryenLocalGetGetIndex(expr),
_BinaryenExpressionGetType(expr)
);
}
case ExpressionId.GetGlobal: {
let globalName = _BinaryenGetGlobalGetName(expr);
case ExpressionId.GlobalGet: {
let globalName = _BinaryenGlobalGetGetName(expr);
if (!globalName) break;
return _BinaryenGetGlobal(this.ref, globalName, _BinaryenExpressionGetType(expr));
return _BinaryenGlobalGet(this.ref, globalName, _BinaryenExpressionGetType(expr));
}
case ExpressionId.Load: {
if (!(nested1 = this.cloneExpression(_BinaryenLoadGetPtr(expr), noSideEffects, maxDepth))) {
@ -1330,23 +1330,23 @@ export function getConstValueF64(expr: ExpressionRef): f32 {
}
export function getGetLocalIndex(expr: ExpressionRef): Index {
return _BinaryenGetLocalGetIndex(expr);
return _BinaryenLocalGetGetIndex(expr);
}
export function getSetLocalIndex(expr: ExpressionRef): Index {
return _BinaryenSetLocalGetIndex(expr);
return _BinaryenLocalSetGetIndex(expr);
}
export function getSetLocalValue(expr: ExpressionRef): ExpressionRef {
return _BinaryenSetLocalGetValue(expr);
return _BinaryenLocalSetGetValue(expr);
}
export function isTeeLocal(expr: ExpressionRef): bool {
return _BinaryenSetLocalIsTee(expr);
return _BinaryenLocalSetIsTee(expr);
}
export function getGetGlobalName(expr: ExpressionRef): string | null {
return readString(_BinaryenGetGlobalGetName(expr));
return readString(_BinaryenGlobalGetGetName(expr));
}
export function getBinaryOp(expr: ExpressionRef): BinaryOp {
@ -1790,3 +1790,177 @@ export function needsExplicitUnreachable(expr: ExpressionRef): bool {
}
return true;
}
/** Traverses all expression members of an expression, calling the given visitor. */
export function traverse(expr: ExpressionRef, visit: (expr: ExpressionRef) => bool): bool {
switch (getExpressionId(expr)) {
case ExpressionId.Block: {
for (let i = 0, n = _BinaryenBlockGetNumChildren(expr); i < n; ++i) {
if (!visit(_BinaryenBlockGetChild(expr, i))) return false;
}
break;
}
case ExpressionId.If: {
if (!visit(_BinaryenIfGetCondition(expr))) return false;
if (!visit(_BinaryenIfGetIfTrue(expr))) return false;
let ifFalse = _BinaryenIfGetIfFalse(expr);
if (ifFalse) if (!visit(ifFalse)) return false;
break;
}
case ExpressionId.Loop: {
if (!visit(_BinaryenLoopGetBody(expr))) return false;
break;
}
case ExpressionId.Break: {
let condition = _BinaryenBreakGetCondition(expr);
if (condition) if (!visit(condition)) return false;
break;
}
case ExpressionId.Switch: {
if (!visit(_BinaryenSwitchGetCondition(expr))) return false;
break;
}
case ExpressionId.Call: {
for (let i = 0, n = _BinaryenCallGetNumOperands(expr); i < n; ++i) {
if (!visit(_BinaryenCallGetOperand(expr, i))) return false;
}
break;
}
case ExpressionId.CallIndirect: {
for (let i = 0, n = _BinaryenCallIndirectGetNumOperands(expr); i < n; ++i) {
if (!visit(_BinaryenCallIndirectGetOperand(expr, i))) return false;
}
break;
}
case ExpressionId.LocalGet: {
break;
}
case ExpressionId.LocalSet: {
if (!visit(_BinaryenLocalSetGetValue(expr))) return false;
break;
}
case ExpressionId.GlobalGet: {
break;
}
case ExpressionId.GlobalSet: {
if (!visit(_BinaryenGlobalSetGetValue(expr))) return false;
break;
}
case ExpressionId.Load: {
if (!visit(_BinaryenLoadGetPtr(expr))) return false;
break;
}
case ExpressionId.Store: {
if (!visit(_BinaryenStoreGetPtr(expr))) return false;
if (!visit(_BinaryenStoreGetValue(expr))) return false;
break;
}
case ExpressionId.AtomicRMW: {
if (!visit(_BinaryenAtomicRMWGetPtr(expr))) return false;
if (!visit(_BinaryenAtomicRMWGetValue(expr))) return false;
break;
}
case ExpressionId.AtomicCmpxchg: {
if (!visit(_BinaryenAtomicCmpxchgGetPtr(expr))) return false;
if (!visit(_BinaryenAtomicCmpxchgGetExpected(expr))) return false;
if (!visit(_BinaryenAtomicCmpxchgGetReplacement(expr))) return false;
break;
}
case ExpressionId.AtomicWait: {
if (!visit(_BinaryenAtomicWaitGetPtr(expr))) return false;
if (!visit(_BinaryenAtomicWaitGetExpected(expr))) return false;
if (!visit(_BinaryenAtomicWaitGetTimeout(expr))) return false;
break;
}
case ExpressionId.AtomicNotify: {
if (!visit(_BinaryenAtomicNotifyGetPtr(expr))) return false;
break;
}
case ExpressionId.SIMDExtract: {
if (!visit(_BinaryenSIMDExtractGetVec(expr))) return false;
break;
}
case ExpressionId.SIMDReplace: {
if (!visit(_BinaryenSIMDReplaceGetVec(expr))) return false;
if (!visit(_BinaryenSIMDReplaceGetValue(expr))) return false;
break;
}
case ExpressionId.SIMDShuffle: {
if (!visit(_BinaryenSIMDShuffleGetLeft(expr))) return false;
if (!visit(_BinaryenSIMDShuffleGetRight(expr))) return false;
break;
}
case ExpressionId.SIMDBitselect: {
if (!visit(_BinaryenSIMDBitselectGetLeft(expr))) return false;
if (!visit(_BinaryenSIMDBitselectGetRight(expr))) return false;
if (!visit(_BinaryenSIMDBitselectGetCond(expr))) return false;
break;
}
case ExpressionId.SIMDShift: {
if (!visit(_BinaryenSIMDShiftGetVec(expr))) return false;
if (!visit(_BinaryenSIMDShiftGetShift(expr))) return false;
break;
}
case ExpressionId.MemoryInit: {
if (!visit(_BinaryenMemoryInitGetDest(expr))) return false;
if (!visit(_BinaryenMemoryInitGetOffset(expr))) return false;
if (!visit(_BinaryenMemoryInitGetSize(expr))) return false;
break;
}
case ExpressionId.DataDrop: {
break;
}
case ExpressionId.MemoryCopy: {
if (!visit(_BinaryenMemoryCopyGetDest(expr))) return false;
if (!visit(_BinaryenMemoryCopyGetSource(expr))) return false;
if (!visit(_BinaryenMemoryCopyGetSize(expr))) return false;
break;
}
case ExpressionId.MemoryFill: {
if (!visit(_BinaryenMemoryFillGetDest(expr))) return false;
if (!visit(_BinaryenMemoryFillGetValue(expr))) return false;
if (!visit(_BinaryenMemoryFillGetSize(expr))) return false;
break;
}
case ExpressionId.Const: {
break;
}
case ExpressionId.Unary: {
if (!visit(_BinaryenUnaryGetValue(expr))) return false;
break;
}
case ExpressionId.Binary: {
if (!visit(_BinaryenBinaryGetLeft(expr))) return false;
if (!visit(_BinaryenBinaryGetRight(expr))) return false;
break;
}
case ExpressionId.Select: {
if (!visit(_BinaryenSelectGetIfTrue(expr))) return false;
if (!visit(_BinaryenSelectGetIfFalse(expr))) return false;
if (!visit(_BinaryenSelectGetCondition(expr))) return false;
break;
}
case ExpressionId.Drop: {
if (!visit(_BinaryenDropGetValue(expr))) return false;
break;
}
case ExpressionId.Return: {
if (!visit(_BinaryenReturnGetValue(expr))) return false;
break;
}
case ExpressionId.Host: {
for (let i = 0, n = _BinaryenHostGetNumOperands(expr); i < n; ++i) {
if (!visit(_BinaryenHostGetOperand(expr, i))) return false;
}
break;
}
case ExpressionId.Nop: {
break;
}
case ExpressionId.Unreachable: {
break;
}
default: assert(false);
}
return true;
}