Bug 1316651 - Baldr: rename Expr to Op (r=sunfish)
authorLuke Wagner <luke@mozilla.com>
Fri, 11 Nov 2016 13:53:15 -0600
changeset 352330 52a2f468a31c73eed841e91a4a68fcb35ae645c5
parent 352329 8a0300ec29c9e7523c62263eb9e98d89c23739b1
child 352331 ef58f71d8e7b9431e4c8ea1eaedf86ebc289068f
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1316651
milestone52.0a1
Bug 1316651 - Baldr: rename Expr to Op (r=sunfish) MozReview-Commit-ID: Bsn7uC1axkh
js/src/wasm/AsmJS.cpp
js/src/wasm/WasmAST.h
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmBinaryConstants.h
js/src/wasm/WasmBinaryFormat.cpp
js/src/wasm/WasmBinaryFormat.h
js/src/wasm/WasmBinaryIterator.cpp
js/src/wasm/WasmBinaryIterator.h
js/src/wasm/WasmBinaryToAST.cpp
js/src/wasm/WasmBinaryToExperimentalText.cpp
js/src/wasm/WasmBinaryToText.cpp
js/src/wasm/WasmCompile.cpp
js/src/wasm/WasmIonCompile.cpp
js/src/wasm/WasmTextToBinary.cpp
js/src/wasm/WasmTypes.h
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -2727,116 +2727,116 @@ IsLiteralInt(ModuleValidator& m, ParseNo
     return IsNumericLiteral(m, pn) &&
            IsLiteralInt(ExtractNumericLiteral(m, pn), u32);
 }
 
 /*****************************************************************************/
 
 namespace {
 
-#define CASE(TYPE, OP) case SimdOperation::Fn_##OP: return Expr::TYPE##OP;
+#define CASE(TYPE, OP) case SimdOperation::Fn_##OP: return Op::TYPE##OP;
 #define I8x16CASE(OP) CASE(I8x16, OP)
 #define I16x8CASE(OP) CASE(I16x8, OP)
 #define I32x4CASE(OP) CASE(I32x4, OP)
 #define F32x4CASE(OP) CASE(F32x4, OP)
 #define B8x16CASE(OP) CASE(B8x16, OP)
 #define B16x8CASE(OP) CASE(B16x8, OP)
 #define B32x4CASE(OP) CASE(B32x4, OP)
 #define ENUMERATE(TYPE, FOR_ALL, DO)                                     \
     switch(op) {                                                         \
-        case SimdOperation::Constructor: return Expr::TYPE##Constructor; \
+        case SimdOperation::Constructor: return Op::TYPE##Constructor;   \
         FOR_ALL(DO)                                                      \
         default: break;                                                  \
     }
 
-static inline Expr
-SimdToExpr(SimdType type, SimdOperation op)
+static inline Op
+SimdToOp(SimdType type, SimdOperation op)
 {
     switch (type) {
       case SimdType::Uint8x16:
         // Handle the special unsigned opcodes, then fall through to Int8x16.
         switch (op) {
-          case SimdOperation::Fn_addSaturate:        return Expr::I8x16addSaturateU;
-          case SimdOperation::Fn_subSaturate:        return Expr::I8x16subSaturateU;
-          case SimdOperation::Fn_extractLane:        return Expr::I8x16extractLaneU;
-          case SimdOperation::Fn_shiftRightByScalar: return Expr::I8x16shiftRightByScalarU;
-          case SimdOperation::Fn_lessThan:           return Expr::I8x16lessThanU;
-          case SimdOperation::Fn_lessThanOrEqual:    return Expr::I8x16lessThanOrEqualU;
-          case SimdOperation::Fn_greaterThan:        return Expr::I8x16greaterThanU;
-          case SimdOperation::Fn_greaterThanOrEqual: return Expr::I8x16greaterThanOrEqualU;
-          case SimdOperation::Fn_fromInt8x16Bits:    return Expr::Limit;
+          case SimdOperation::Fn_addSaturate:        return Op::I8x16addSaturateU;
+          case SimdOperation::Fn_subSaturate:        return Op::I8x16subSaturateU;
+          case SimdOperation::Fn_extractLane:        return Op::I8x16extractLaneU;
+          case SimdOperation::Fn_shiftRightByScalar: return Op::I8x16shiftRightByScalarU;
+          case SimdOperation::Fn_lessThan:           return Op::I8x16lessThanU;
+          case SimdOperation::Fn_lessThanOrEqual:    return Op::I8x16lessThanOrEqualU;
+          case SimdOperation::Fn_greaterThan:        return Op::I8x16greaterThanU;
+          case SimdOperation::Fn_greaterThanOrEqual: return Op::I8x16greaterThanOrEqualU;
+          case SimdOperation::Fn_fromInt8x16Bits:    return Op::Limit;
           default: break;
         }
         MOZ_FALLTHROUGH;
       case SimdType::Int8x16:
         // Bitcasts Uint8x16 <--> Int8x16 become noops.
         switch (op) {
-          case SimdOperation::Fn_fromUint8x16Bits: return Expr::Limit;
-          case SimdOperation::Fn_fromUint16x8Bits: return Expr::I8x16fromInt16x8Bits;
-          case SimdOperation::Fn_fromUint32x4Bits: return Expr::I8x16fromInt32x4Bits;
+          case SimdOperation::Fn_fromUint8x16Bits: return Op::Limit;
+          case SimdOperation::Fn_fromUint16x8Bits: return Op::I8x16fromInt16x8Bits;
+          case SimdOperation::Fn_fromUint32x4Bits: return Op::I8x16fromInt32x4Bits;
           default: break;
         }
         ENUMERATE(I8x16, FORALL_INT8X16_ASMJS_OP, I8x16CASE)
         break;
 
       case SimdType::Uint16x8:
         // Handle the special unsigned opcodes, then fall through to Int16x8.
         switch(op) {
-          case SimdOperation::Fn_addSaturate:        return Expr::I16x8addSaturateU;
-          case SimdOperation::Fn_subSaturate:        return Expr::I16x8subSaturateU;
-          case SimdOperation::Fn_extractLane:        return Expr::I16x8extractLaneU;
-          case SimdOperation::Fn_shiftRightByScalar: return Expr::I16x8shiftRightByScalarU;
-          case SimdOperation::Fn_lessThan:           return Expr::I16x8lessThanU;
-          case SimdOperation::Fn_lessThanOrEqual:    return Expr::I16x8lessThanOrEqualU;
-          case SimdOperation::Fn_greaterThan:        return Expr::I16x8greaterThanU;
-          case SimdOperation::Fn_greaterThanOrEqual: return Expr::I16x8greaterThanOrEqualU;
-          case SimdOperation::Fn_fromInt16x8Bits:    return Expr::Limit;
+          case SimdOperation::Fn_addSaturate:        return Op::I16x8addSaturateU;
+          case SimdOperation::Fn_subSaturate:        return Op::I16x8subSaturateU;
+          case SimdOperation::Fn_extractLane:        return Op::I16x8extractLaneU;
+          case SimdOperation::Fn_shiftRightByScalar: return Op::I16x8shiftRightByScalarU;
+          case SimdOperation::Fn_lessThan:           return Op::I16x8lessThanU;
+          case SimdOperation::Fn_lessThanOrEqual:    return Op::I16x8lessThanOrEqualU;
+          case SimdOperation::Fn_greaterThan:        return Op::I16x8greaterThanU;
+          case SimdOperation::Fn_greaterThanOrEqual: return Op::I16x8greaterThanOrEqualU;
+          case SimdOperation::Fn_fromInt16x8Bits:    return Op::Limit;
           default: break;
         }
         MOZ_FALLTHROUGH;
       case SimdType::Int16x8:
         // Bitcasts Uint16x8 <--> Int16x8 become noops.
         switch (op) {
-          case SimdOperation::Fn_fromUint8x16Bits: return Expr::I16x8fromInt8x16Bits;
-          case SimdOperation::Fn_fromUint16x8Bits: return Expr::Limit;
-          case SimdOperation::Fn_fromUint32x4Bits: return Expr::I16x8fromInt32x4Bits;
+          case SimdOperation::Fn_fromUint8x16Bits: return Op::I16x8fromInt8x16Bits;
+          case SimdOperation::Fn_fromUint16x8Bits: return Op::Limit;
+          case SimdOperation::Fn_fromUint32x4Bits: return Op::I16x8fromInt32x4Bits;
           default: break;
         }
         ENUMERATE(I16x8, FORALL_INT16X8_ASMJS_OP, I16x8CASE)
         break;
 
       case SimdType::Uint32x4:
         // Handle the special unsigned opcodes, then fall through to Int32x4.
         switch(op) {
-          case SimdOperation::Fn_shiftRightByScalar: return Expr::I32x4shiftRightByScalarU;
-          case SimdOperation::Fn_lessThan:           return Expr::I32x4lessThanU;
-          case SimdOperation::Fn_lessThanOrEqual:    return Expr::I32x4lessThanOrEqualU;
-          case SimdOperation::Fn_greaterThan:        return Expr::I32x4greaterThanU;
-          case SimdOperation::Fn_greaterThanOrEqual: return Expr::I32x4greaterThanOrEqualU;
-          case SimdOperation::Fn_fromFloat32x4:      return Expr::I32x4fromFloat32x4U;
-          case SimdOperation::Fn_fromInt32x4Bits:    return Expr::Limit;
+          case SimdOperation::Fn_shiftRightByScalar: return Op::I32x4shiftRightByScalarU;
+          case SimdOperation::Fn_lessThan:           return Op::I32x4lessThanU;
+          case SimdOperation::Fn_lessThanOrEqual:    return Op::I32x4lessThanOrEqualU;
+          case SimdOperation::Fn_greaterThan:        return Op::I32x4greaterThanU;
+          case SimdOperation::Fn_greaterThanOrEqual: return Op::I32x4greaterThanOrEqualU;
+          case SimdOperation::Fn_fromFloat32x4:      return Op::I32x4fromFloat32x4U;
+          case SimdOperation::Fn_fromInt32x4Bits:    return Op::Limit;
           default: break;
         }
         MOZ_FALLTHROUGH;
       case SimdType::Int32x4:
         // Bitcasts Uint32x4 <--> Int32x4 become noops.
         switch (op) {
-          case SimdOperation::Fn_fromUint8x16Bits: return Expr::I32x4fromInt8x16Bits;
-          case SimdOperation::Fn_fromUint16x8Bits: return Expr::I32x4fromInt16x8Bits;
-          case SimdOperation::Fn_fromUint32x4Bits: return Expr::Limit;
+          case SimdOperation::Fn_fromUint8x16Bits: return Op::I32x4fromInt8x16Bits;
+          case SimdOperation::Fn_fromUint16x8Bits: return Op::I32x4fromInt16x8Bits;
+          case SimdOperation::Fn_fromUint32x4Bits: return Op::Limit;
           default: break;
         }
         ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32x4CASE)
         break;
 
       case SimdType::Float32x4:
         switch (op) {
-          case SimdOperation::Fn_fromUint8x16Bits: return Expr::F32x4fromInt8x16Bits;
-          case SimdOperation::Fn_fromUint16x8Bits: return Expr::F32x4fromInt16x8Bits;
-          case SimdOperation::Fn_fromUint32x4Bits: return Expr::F32x4fromInt32x4Bits;
+          case SimdOperation::Fn_fromUint8x16Bits: return Op::F32x4fromInt8x16Bits;
+          case SimdOperation::Fn_fromUint16x8Bits: return Op::F32x4fromInt16x8Bits;
+          case SimdOperation::Fn_fromUint32x4Bits: return Op::F32x4fromInt32x4Bits;
           default: break;
         }
         ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32x4CASE)
         break;
 
       case SimdType::Bool8x16:
         ENUMERATE(B8x16, FORALL_BOOL_SIMD_OP, B8x16CASE)
         break;
@@ -2993,116 +2993,116 @@ class MOZ_STACK_CLASS FunctionValidator
 
     void setReturnedType(ExprType ret) {
         ret_ = ret;
         hasAlreadyReturned_ = true;
     }
 
     /**************************************************************** Labels */
   private:
-    bool writeBr(uint32_t absolute, Expr expr = Expr::Br) {
-        MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf);
+    bool writeBr(uint32_t absolute, Op op = Op::Br) {
+        MOZ_ASSERT(op == Op::Br || op == Op::BrIf);
         MOZ_ASSERT(absolute < blockDepth_);
-        return encoder().writeExpr(expr) &&
+        return encoder().writeOp(op) &&
                encoder().writeVarU32(blockDepth_ - 1 - absolute);
     }
     void removeLabel(PropertyName* label, LabelMap* map) {
         LabelMap::Ptr p = map->lookup(label);
         MOZ_ASSERT(p);
         map->remove(p);
     }
 
   public:
     bool pushBreakableBlock() {
-        return encoder().writeExpr(Expr::Block) &&
+        return encoder().writeOp(Op::Block) &&
                encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                breakableStack_.append(blockDepth_++);
     }
     bool popBreakableBlock() {
         JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
-        return encoder().writeExpr(Expr::End);
+        return encoder().writeOp(Op::End);
     }
 
     bool pushUnbreakableBlock(const NameVector* labels = nullptr) {
         if (labels) {
             for (PropertyName* label : *labels) {
                 if (!breakLabels_.putNew(label, blockDepth_))
                     return false;
             }
         }
         blockDepth_++;
-        return encoder().writeExpr(Expr::Block) &&
+        return encoder().writeOp(Op::Block) &&
                encoder().writeFixedU8(uint8_t(ExprType::Void));
     }
     bool popUnbreakableBlock(const NameVector* labels = nullptr) {
         if (labels) {
             for (PropertyName* label : *labels)
                 removeLabel(label, &breakLabels_);
         }
         --blockDepth_;
-        return encoder().writeExpr(Expr::End);
+        return encoder().writeOp(Op::End);
     }
 
     bool pushContinuableBlock() {
-        return encoder().writeExpr(Expr::Block) &&
+        return encoder().writeOp(Op::Block) &&
                encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                continuableStack_.append(blockDepth_++);
     }
     bool popContinuableBlock() {
         JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
-        return encoder().writeExpr(Expr::End);
+        return encoder().writeOp(Op::End);
     }
 
     bool pushLoop() {
-        return encoder().writeExpr(Expr::Block) &&
+        return encoder().writeOp(Op::Block) &&
                encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
-               encoder().writeExpr(Expr::Loop) &&
+               encoder().writeOp(Op::Loop) &&
                encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                breakableStack_.append(blockDepth_++) &&
                continuableStack_.append(blockDepth_++);
     }
     bool popLoop() {
         JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
         JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
-        return encoder().writeExpr(Expr::End) &&
-               encoder().writeExpr(Expr::End);
+        return encoder().writeOp(Op::End) &&
+               encoder().writeOp(Op::End);
     }
 
     bool pushIf(size_t* typeAt) {
         ++blockDepth_;
-        return encoder().writeExpr(Expr::If) &&
+        return encoder().writeOp(Op::If) &&
                encoder().writePatchableFixedU7(typeAt);
     }
     bool switchToElse() {
         MOZ_ASSERT(blockDepth_ > 0);
-        return encoder().writeExpr(Expr::Else);
+        return encoder().writeOp(Op::Else);
     }
     void setIfType(size_t typeAt, ExprType type) {
         encoder().patchFixedU7(typeAt, uint8_t(type));
     }
     bool popIf() {
         MOZ_ASSERT(blockDepth_ > 0);
         --blockDepth_;
-        return encoder().writeExpr(Expr::End);
+        return encoder().writeOp(Op::End);
     }
     bool popIf(size_t typeAt, ExprType type) {
         MOZ_ASSERT(blockDepth_ > 0);
         --blockDepth_;
-        if (!encoder().writeExpr(Expr::End))
+        if (!encoder().writeOp(Op::End))
             return false;
 
         setIfType(typeAt, type);
         return true;
     }
 
     bool writeBreakIf() {
-        return writeBr(breakableStack_.back(), Expr::BrIf);
+        return writeBr(breakableStack_.back(), Op::BrIf);
     }
     bool writeContinueIf() {
-        return writeBr(continuableStack_.back(), Expr::BrIf);
+        return writeBr(continuableStack_.back(), Op::BrIf);
     }
     bool writeUnlabeledBreakOrContinue(bool isBreak) {
         return writeBr(isBreak? breakableStack_.back() : continuableStack_.back());
     }
     bool writeContinue() {
         return writeBr(continuableStack_.back());
     }
 
@@ -3146,75 +3146,75 @@ class MOZ_STACK_CLASS FunctionValidator
 
     size_t numLocals() const { return locals_.count(); }
 
     /**************************************************** Encoding interface */
 
     Encoder& encoder() { return *encoder_; }
 
     MOZ_MUST_USE bool writeInt32Lit(int32_t i32) {
-        return encoder().writeExpr(Expr::I32Const) &&
+        return encoder().writeOp(Op::I32Const) &&
                encoder().writeVarS32(i32);
     }
     MOZ_MUST_USE bool writeConstExpr(const NumLit& lit) {
         switch (lit.which()) {
           case NumLit::Fixnum:
           case NumLit::NegativeInt:
           case NumLit::BigUnsigned:
             return writeInt32Lit(lit.toInt32());
           case NumLit::Float:
-            return encoder().writeExpr(Expr::F32Const) &&
+            return encoder().writeOp(Op::F32Const) &&
                    encoder().writeFixedF32(lit.toFloat());
           case NumLit::Double:
-            return encoder().writeExpr(Expr::F64Const) &&
+            return encoder().writeOp(Op::F64Const) &&
                    encoder().writeFixedF64(lit.toDouble());
           case NumLit::Int8x16:
           case NumLit::Uint8x16:
-            return encoder().writeExpr(Expr::I8x16Const) &&
+            return encoder().writeOp(Op::I8x16Const) &&
                    encoder().writeFixedI8x16(lit.simdValue().asInt8x16());
           case NumLit::Int16x8:
           case NumLit::Uint16x8:
-            return encoder().writeExpr(Expr::I16x8Const) &&
+            return encoder().writeOp(Op::I16x8Const) &&
                    encoder().writeFixedI16x8(lit.simdValue().asInt16x8());
           case NumLit::Int32x4:
           case NumLit::Uint32x4:
-            return encoder().writeExpr(Expr::I32x4Const) &&
+            return encoder().writeOp(Op::I32x4Const) &&
                    encoder().writeFixedI32x4(lit.simdValue().asInt32x4());
           case NumLit::Float32x4:
-            return encoder().writeExpr(Expr::F32x4Const) &&
+            return encoder().writeOp(Op::F32x4Const) &&
                    encoder().writeFixedF32x4(lit.simdValue().asFloat32x4());
           case NumLit::Bool8x16:
             // Boolean vectors use the Int8x16 memory representation.
-            return encoder().writeExpr(Expr::B8x16Const) &&
+            return encoder().writeOp(Op::B8x16Const) &&
                    encoder().writeFixedI8x16(lit.simdValue().asInt8x16());
           case NumLit::Bool16x8:
             // Boolean vectors use the Int16x8 memory representation.
-            return encoder().writeExpr(Expr::B16x8Const) &&
+            return encoder().writeOp(Op::B16x8Const) &&
                    encoder().writeFixedI16x8(lit.simdValue().asInt16x8());
           case NumLit::Bool32x4:
             // Boolean vectors use the Int32x4 memory representation.
-            return encoder().writeExpr(Expr::B32x4Const) &&
+            return encoder().writeOp(Op::B32x4Const) &&
                    encoder().writeFixedI32x4(lit.simdValue().asInt32x4());
           case NumLit::OutOfRangeInt:
             break;
         }
         MOZ_CRASH("unexpected literal type");
     }
-    MOZ_MUST_USE bool writeCall(ParseNode* pn, Expr op) {
-        return encoder().writeExpr(op) &&
+    MOZ_MUST_USE bool writeCall(ParseNode* pn, Op op) {
+        return encoder().writeOp(op) &&
                fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
     }
     MOZ_MUST_USE bool prepareCall(ParseNode* pn) {
         return fg_.addCallSiteLineNum(m().tokenStream().srcCoords.lineNum(pn->pn_pos.begin));
     }
-    MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation op) {
-        Expr expr = SimdToExpr(simdType, op);
-        if (expr == Expr::Limit)
+    MOZ_MUST_USE bool writeSimdOp(SimdType simdType, SimdOperation simdOp) {
+        Op op = SimdToOp(simdType, simdOp);
+        if (op == Op::Limit)
             return true;
-        return encoder().writeExpr(expr);
+        return encoder().writeOp(op);
     }
 };
 
 } /* anonymous namespace */
 
 /*****************************************************************************/
 // asm.js type-checking and code-generation algorithm
 
@@ -3873,17 +3873,17 @@ IsLiteralOrConst(FunctionValidator& f, P
 
     *lit = ExtractNumericLiteral(f.m(), pn);
     return true;
 }
 
 static bool
 CheckFinalReturn(FunctionValidator& f, ParseNode* lastNonEmptyStmt)
 {
-    if (!f.encoder().writeExpr(Expr::End))
+    if (!f.encoder().writeOp(Op::End))
         return false;
 
     if (!f.hasAlreadyReturned()) {
         f.setReturnedType(ExprType::Void);
         return true;
     }
 
     if (!lastNonEmptyStmt->isKind(PNK_RETURN) && !IsVoid(f.returnedType()))
@@ -3944,28 +3944,28 @@ CheckVariables(FunctionValidator& f, Par
         return false;
 
     for (uint32_t i = 0; i < inits.length(); i++) {
         NumLit lit = inits[i];
         if (lit.isZeroBits())
             continue;
         if (!f.writeConstExpr(lit))
             return false;
-        if (!f.encoder().writeExpr(Expr::SetLocal))
+        if (!f.encoder().writeOp(Op::SetLocal))
             return false;
         if (!f.encoder().writeVarU32(firstVar + i))
             return false;
     }
 
     *stmtIter = stmt;
     return true;
 }
 
 static bool
-CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type);
+CheckExpr(FunctionValidator& f, ParseNode* op, Type* type);
 
 static bool
 CheckNumericLiteral(FunctionValidator& f, ParseNode* num, Type* type)
 {
     NumLit lit = ExtractNumericLiteral(f.m(), num);
     if (!lit.valid())
         return f.fail(num, "numeric literal out of representable integer range");
     *type = Type::lit(lit);
@@ -3973,33 +3973,33 @@ CheckNumericLiteral(FunctionValidator& f
 }
 
 static bool
 CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
 {
     PropertyName* name = varRef->name();
 
     if (const FunctionValidator::Local* local = f.lookupLocal(name)) {
-        if (!f.encoder().writeExpr(Expr::GetLocal))
+        if (!f.encoder().writeOp(Op::GetLocal))
             return false;
         if (!f.encoder().writeVarU32(local->slot))
             return false;
         *type = local->type;
         return true;
     }
 
     if (const ModuleValidator::Global* global = f.lookupGlobal(name)) {
         switch (global->which()) {
           case ModuleValidator::Global::ConstantLiteral:
             *type = global->varOrConstType();
             return f.writeConstExpr(global->constLiteralValue());
           case ModuleValidator::Global::ConstantImport:
           case ModuleValidator::Global::Variable: {
             *type = global->varOrConstType();
-            return f.encoder().writeExpr(Expr::GetGlobal) &&
+            return f.encoder().writeOp(Op::GetGlobal) &&
                    f.encoder().writeVarU32(global->varOrConstIndex());
           }
           case ModuleValidator::Global::Function:
           case ModuleValidator::Global::FFI:
           case ModuleValidator::Global::MathBuiltinFunction:
           case ModuleValidator::Global::AtomicsBuiltinFunction:
           case ModuleValidator::Global::FuncPtrTable:
           case ModuleValidator::Global::ArrayView:
@@ -4097,17 +4097,17 @@ CheckArrayAccess(FunctionValidator& f, P
                 return f.failf(pointerNode, "%s is not a subtype of int", pointerType.toChars());
         }
     }
 
     // Don't generate the mask op if there is no need for it which could happen for
     // a shift of zero or a SIMD access.
     if (mask != NoMask) {
         return f.writeInt32Lit(mask) &&
-               f.encoder().writeExpr(Expr::I32And);
+               f.encoder().writeOp(Op::I32And);
     }
 
     return true;
 }
 
 static bool
 CheckAndPrepareArrayAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
                            bool isSimd, Scalar::Type* viewType)
@@ -4135,24 +4135,24 @@ static bool
 CheckLoadArray(FunctionValidator& f, ParseNode* elem, Type* type)
 {
     Scalar::Type viewType;
 
     if (!CheckAndPrepareArrayAccess(f, ElemBase(elem), ElemIndex(elem), NoSimd, &viewType))
         return false;
 
     switch (viewType) {
-      case Scalar::Int8:    if (!f.encoder().writeExpr(Expr::I32Load8S))  return false; break;
-      case Scalar::Uint8:   if (!f.encoder().writeExpr(Expr::I32Load8U))  return false; break;
-      case Scalar::Int16:   if (!f.encoder().writeExpr(Expr::I32Load16S)) return false; break;
-      case Scalar::Uint16:  if (!f.encoder().writeExpr(Expr::I32Load16U)) return false; break;
+      case Scalar::Int8:    if (!f.encoder().writeOp(Op::I32Load8S))  return false; break;
+      case Scalar::Uint8:   if (!f.encoder().writeOp(Op::I32Load8U))  return false; break;
+      case Scalar::Int16:   if (!f.encoder().writeOp(Op::I32Load16S)) return false; break;
+      case Scalar::Uint16:  if (!f.encoder().writeOp(Op::I32Load16U)) return false; break;
       case Scalar::Uint32:
-      case Scalar::Int32:   if (!f.encoder().writeExpr(Expr::I32Load))    return false; break;
-      case Scalar::Float32: if (!f.encoder().writeExpr(Expr::F32Load))    return false; break;
-      case Scalar::Float64: if (!f.encoder().writeExpr(Expr::F64Load))    return false; break;
+      case Scalar::Int32:   if (!f.encoder().writeOp(Op::I32Load))    return false; break;
+      case Scalar::Float32: if (!f.encoder().writeOp(Op::F32Load))    return false; break;
+      case Scalar::Float64: if (!f.encoder().writeOp(Op::F64Load))    return false; break;
       default: MOZ_CRASH("unexpected scalar type");
     }
 
     switch (viewType) {
       case Scalar::Int8:
       case Scalar::Int16:
       case Scalar::Int32:
       case Scalar::Uint8:
@@ -4206,44 +4206,44 @@ CheckStoreArray(FunctionValidator& f, Pa
         break;
       default:
         MOZ_CRASH("Unexpected view type");
     }
 
     switch (viewType) {
       case Scalar::Int8:
       case Scalar::Uint8:
-        if (!f.encoder().writeExpr(Expr::I32TeeStore8))
+        if (!f.encoder().writeOp(Op::I32TeeStore8))
             return false;
         break;
       case Scalar::Int16:
       case Scalar::Uint16:
-        if (!f.encoder().writeExpr(Expr::I32TeeStore16))
+        if (!f.encoder().writeOp(Op::I32TeeStore16))
             return false;
         break;
       case Scalar::Int32:
       case Scalar::Uint32:
-        if (!f.encoder().writeExpr(Expr::I32TeeStore))
+        if (!f.encoder().writeOp(Op::I32TeeStore))
             return false;
         break;
       case Scalar::Float32:
         if (rhsType.isFloatish()) {
-            if (!f.encoder().writeExpr(Expr::F32TeeStore))
+            if (!f.encoder().writeOp(Op::F32TeeStore))
                 return false;
         } else {
-            if (!f.encoder().writeExpr(Expr::F64TeeStoreF32))
+            if (!f.encoder().writeOp(Op::F64TeeStoreF32))
                 return false;
         }
         break;
       case Scalar::Float64:
         if (rhsType.isFloatish()) {
-            if (!f.encoder().writeExpr(Expr::F32TeeStoreF64))
+            if (!f.encoder().writeOp(Op::F32TeeStoreF64))
                 return false;
         } else {
-            if (!f.encoder().writeExpr(Expr::F64TeeStore))
+            if (!f.encoder().writeOp(Op::F64TeeStore))
                 return false;
         }
         break;
       default: MOZ_CRASH("unexpected scalar type");
     }
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
@@ -4257,17 +4257,17 @@ CheckAssignName(FunctionValidator& f, Pa
 {
     RootedPropertyName name(f.cx(), lhs->name());
 
     if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType))
             return false;
 
-        if (!f.encoder().writeExpr(Expr::TeeLocal))
+        if (!f.encoder().writeOp(Op::TeeLocal))
             return false;
         if (!f.encoder().writeVarU32(lhsVar->slot))
             return false;
 
         if (!(rhsType <= lhsVar->type)) {
             return f.failf(lhs, "%s is not a subtype of %s",
                            rhsType.toChars(), lhsVar->type.toChars());
         }
@@ -4281,17 +4281,17 @@ CheckAssignName(FunctionValidator& f, Pa
 
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType))
             return false;
 
         Type globType = global->varOrConstType();
         if (!(rhsType <= globType))
             return f.failf(lhs, "%s is not a subtype of %s", rhsType.toChars(), globType.toChars());
-        if (!f.encoder().writeExpr(Expr::TeeGlobal))
+        if (!f.encoder().writeOp(Op::TeeGlobal))
             return false;
         if (!f.encoder().writeVarU32(global->varOrConstIndex()))
             return false;
 
         *type = rhsType;
         return true;
     }
 
@@ -4333,17 +4333,17 @@ CheckMathIMul(FunctionValidator& f, Pars
         return false;
 
     if (!lhsType.isIntish())
         return f.failf(lhs, "%s is not a subtype of intish", lhsType.toChars());
     if (!rhsType.isIntish())
         return f.failf(rhs, "%s is not a subtype of intish", rhsType.toChars());
 
     *type = Type::Signed;
-    return f.encoder().writeExpr(Expr::I32Mul);
+    return f.encoder().writeOp(Op::I32Mul);
 }
 
 static bool
 CheckMathClz32(FunctionValidator& f, ParseNode* call, Type* type)
 {
     if (CallArgListLength(call) != 1)
         return f.fail(call, "Math.clz32 must be passed 1 argument");
 
@@ -4352,44 +4352,44 @@ CheckMathClz32(FunctionValidator& f, Par
     Type argType;
     if (!CheckExpr(f, arg, &argType))
         return false;
 
     if (!argType.isIntish())
         return f.failf(arg, "%s is not a subtype of intish", argType.toChars());
 
     *type = Type::Fixnum;
-    return f.encoder().writeExpr(Expr::I32Clz);
+    return f.encoder().writeOp(Op::I32Clz);
 }
 
 static bool
 CheckMathAbs(FunctionValidator& f, ParseNode* call, Type* type)
 {
     if (CallArgListLength(call) != 1)
         return f.fail(call, "Math.abs must be passed 1 argument");
 
     ParseNode* arg = CallArgList(call);
 
     Type argType;
     if (!CheckExpr(f, arg, &argType))
         return false;
 
     if (argType.isSigned()) {
         *type = Type::Unsigned;
-        return f.encoder().writeExpr(Expr::I32Abs);
+        return f.encoder().writeOp(Op::I32Abs);
     }
 
     if (argType.isMaybeDouble()) {
         *type = Type::Double;
-        return f.encoder().writeExpr(Expr::F64Abs);
+        return f.encoder().writeOp(Op::F64Abs);
     }
 
     if (argType.isMaybeFloat()) {
         *type = Type::Floatish;
-        return f.encoder().writeExpr(Expr::F32Abs);
+        return f.encoder().writeOp(Op::F32Abs);
     }
 
     return f.failf(call, "%s is not a subtype of signed, float? or double?", argType.toChars());
 }
 
 static bool
 CheckMathSqrt(FunctionValidator& f, ParseNode* call, Type* type)
 {
@@ -4399,66 +4399,66 @@ CheckMathSqrt(FunctionValidator& f, Pars
     ParseNode* arg = CallArgList(call);
 
     Type argType;
     if (!CheckExpr(f, arg, &argType))
         return false;
 
     if (argType.isMaybeDouble()) {
         *type = Type::Double;
-        return f.encoder().writeExpr(Expr::F64Sqrt);
+        return f.encoder().writeOp(Op::F64Sqrt);
     }
 
     if (argType.isMaybeFloat()) {
         *type = Type::Floatish;
-        return f.encoder().writeExpr(Expr::F32Sqrt);
+        return f.encoder().writeOp(Op::F32Sqrt);
     }
 
     return f.failf(call, "%s is neither a subtype of double? nor float?", argType.toChars());
 }
 
 static bool
 CheckMathMinMax(FunctionValidator& f, ParseNode* callNode, bool isMax, Type* type)
 {
     if (CallArgListLength(callNode) < 2)
         return f.fail(callNode, "Math.min/max must be passed at least 2 arguments");
 
     ParseNode* firstArg = CallArgList(callNode);
     Type firstType;
     if (!CheckExpr(f, firstArg, &firstType))
         return false;
 
-    Expr expr;
+    Op op;
     if (firstType.isMaybeDouble()) {
         *type = Type::Double;
         firstType = Type::MaybeDouble;
-        expr = isMax ? Expr::F64Max : Expr::F64Min;
+        op = isMax ? Op::F64Max : Op::F64Min;
     } else if (firstType.isMaybeFloat()) {
         *type = Type::Float;
         firstType = Type::MaybeFloat;
-        expr = isMax ? Expr::F32Max : Expr::F32Min;
+        op = isMax ? Op::F32Max : Op::F32Min;
     } else if (firstType.isSigned()) {
         *type = Type::Signed;
         firstType = Type::Signed;
-        expr = isMax ? Expr::I32Max : Expr::I32Min;
+        op = isMax ? Op::I32Max : Op::I32Min;
     } else {
         return f.failf(firstArg, "%s is not a subtype of double?, float? or signed",
                        firstType.toChars());
     }
 
     unsigned numArgs = CallArgListLength(callNode);
     ParseNode* nextArg = NextNode(firstArg);
     for (unsigned i = 1; i < numArgs; i++, nextArg = NextNode(nextArg)) {
         Type nextType;
         if (!CheckExpr(f, nextArg, &nextType))
             return false;
         if (!(nextType <= firstType))
             return f.failf(nextArg, "%s is not a subtype of %s", nextType.toChars(), firstType.toChars());
 
-        if (!f.encoder().writeExpr(expr))
+        if (!f.encoder().writeOp(op))
             return false;
     }
 
     return true;
 }
 
 static bool
 CheckSharedArrayAtomicAccess(FunctionValidator& f, ParseNode* viewName, ParseNode* indexExpr,
@@ -4485,36 +4485,36 @@ CheckSharedArrayAtomicAccess(FunctionVal
       default:
         return f.failf(viewName, "not an integer array");
     }
 
     return true;
 }
 
 static bool
-WriteAtomicOperator(FunctionValidator& f, Expr opcode, Scalar::Type viewType)
-{
-    return f.encoder().writeExpr(opcode) &&
+WriteAtomicOperator(FunctionValidator& f, Op opcode, Scalar::Type viewType)
+{
+    return f.encoder().writeOp(opcode) &&
            f.encoder().writeFixedU8(viewType);
 }
 
 static bool
 CheckAtomicsLoad(FunctionValidator& f, ParseNode* call, Type* type)
 {
     if (CallArgListLength(call) != 2)
         return f.fail(call, "Atomics.load must be passed 2 arguments");
 
     ParseNode* arrayArg = CallArgList(call);
     ParseNode* indexArg = NextNode(arrayArg);
 
     Scalar::Type viewType;
     if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
         return false;
 
-    if (!WriteAtomicOperator(f, Expr::I32AtomicsLoad, viewType))
+    if (!WriteAtomicOperator(f, Op::I32AtomicsLoad, viewType))
         return false;
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
 
     *type = Type::Int;
     return true;
 }
@@ -4535,17 +4535,17 @@ CheckAtomicsStore(FunctionValidator& f, 
 
     if (!rhsType.isIntish())
         return f.failf(arrayArg, "%s is not a subtype of intish", rhsType.toChars());
 
     Scalar::Type viewType;
     if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
         return false;
 
-    if (!WriteAtomicOperator(f, Expr::I32AtomicsStore, viewType))
+    if (!WriteAtomicOperator(f, Op::I32AtomicsStore, viewType))
         return false;
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
 
     *type = rhsType;
     return true;
 }
@@ -4566,17 +4566,17 @@ CheckAtomicsBinop(FunctionValidator& f, 
 
     if (!valueArgType.isIntish())
         return f.failf(valueArg, "%s is not a subtype of intish", valueArgType.toChars());
 
     Scalar::Type viewType;
     if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
         return false;
 
-    if (!WriteAtomicOperator(f, Expr::I32AtomicsBinOp, viewType))
+    if (!WriteAtomicOperator(f, Op::I32AtomicsBinOp, viewType))
         return false;
     if (!f.encoder().writeFixedU8(uint8_t(op)))
         return false;
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
 
     *type = Type::Int;
@@ -4623,17 +4623,17 @@ CheckAtomicsCompareExchange(FunctionVali
 
     if (!newValueArgType.isIntish())
         return f.failf(newValueArg, "%s is not a subtype of intish", newValueArgType.toChars());
 
     Scalar::Type viewType;
     if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
         return false;
 
-    if (!WriteAtomicOperator(f, Expr::I32AtomicsCompareExchange, viewType))
+    if (!WriteAtomicOperator(f, Op::I32AtomicsCompareExchange, viewType))
         return false;
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
 
     *type = Type::Int;
     return true;
 }
@@ -4654,17 +4654,17 @@ CheckAtomicsExchange(FunctionValidator& 
 
     if (!valueArgType.isIntish())
         return f.failf(arrayArg, "%s is not a subtype of intish", valueArgType.toChars());
 
     Scalar::Type viewType;
     if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType))
         return false;
 
-    if (!WriteAtomicOperator(f, Expr::I32AtomicsExchange, viewType))
+    if (!WriteAtomicOperator(f, Op::I32AtomicsExchange, viewType))
         return false;
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
 
     *type = Type::Int;
     return true;
 }
@@ -4787,17 +4787,17 @@ CheckInternalCall(FunctionValidator& f, 
         return false;
 
     Sig sig(Move(args), ret.canonicalToExprType());
 
     ModuleValidator::Func* callee;
     if (!CheckFunctionSignature(f.m(), callNode, Move(sig), calleeName, &callee))
         return false;
 
-    if (!f.writeCall(callNode, Expr::Call))
+    if (!f.writeCall(callNode, Op::Call))
         return false;
 
     if (!f.encoder().writeVarU32(callee->index()))
         return false;
 
     *type = Type::ret(ret);
     return true;
 }
@@ -4870,17 +4870,17 @@ CheckFuncPtrCall(FunctionValidator& f, P
         return false;
 
     Sig sig(Move(args), ret.canonicalToExprType());
 
     uint32_t tableIndex;
     if (!CheckFuncPtrTableAgainstExisting(f.m(), tableNode, name, Move(sig), mask, &tableIndex))
         return false;
 
-    if (!f.writeCall(callNode, Expr::OldCallIndirect))
+    if (!f.writeCall(callNode, Op::OldCallIndirect))
         return false;
 
     // Call signature
     if (!f.encoder().writeVarU32(f.m().funcPtrTable(tableIndex).sigIndex()))
         return false;
 
     *type = Type::ret(ret);
     return true;
@@ -4911,35 +4911,35 @@ CheckFFICall(FunctionValidator& f, Parse
         return false;
 
     Sig sig(Move(args), ret.canonicalToExprType());
 
     uint32_t funcIndex;
     if (!f.m().declareImport(calleeName, Move(sig), ffiIndex, &funcIndex))
         return false;
 
-    if (!f.writeCall(callNode, Expr::Call))
+    if (!f.writeCall(callNode, Op::Call))
         return false;
 
     if (!f.encoder().writeVarU32(funcIndex))
         return false;
 
     *type = Type::ret(ret);
     return true;
 }
 
 static bool
 CheckFloatCoercionArg(FunctionValidator& f, ParseNode* inputNode, Type inputType)
 {
     if (inputType.isMaybeDouble())
-        return f.encoder().writeExpr(Expr::F32DemoteF64);
+        return f.encoder().writeOp(Op::F32DemoteF64);
     if (inputType.isSigned())
-        return f.encoder().writeExpr(Expr::F32ConvertSI32);
+        return f.encoder().writeOp(Op::F32ConvertSI32);
     if (inputType.isUnsigned())
-        return f.encoder().writeExpr(Expr::F32ConvertUI32);
+        return f.encoder().writeOp(Op::F32ConvertUI32);
     if (inputType.isFloatish())
         return true;
 
     return f.failf(inputNode, "%s is not a subtype of signed, unsigned, double? or floatish",
                    inputType.toChars());
 }
 
 static bool
@@ -4987,38 +4987,38 @@ CheckMathFRound(FunctionValidator& f, Pa
     return true;
 }
 
 static bool
 CheckMathBuiltinCall(FunctionValidator& f, ParseNode* callNode, AsmJSMathBuiltinFunction func,
                      Type* type)
 {
     unsigned arity = 0;
-    Expr f32;
-    Expr f64;
+    Op f32;
+    Op f64;
     switch (func) {
       case AsmJSMathBuiltin_imul:   return CheckMathIMul(f, callNode, type);
       case AsmJSMathBuiltin_clz32:  return CheckMathClz32(f, callNode, type);
       case AsmJSMathBuiltin_abs:    return CheckMathAbs(f, callNode, type);
       case AsmJSMathBuiltin_sqrt:   return CheckMathSqrt(f, callNode, type);
       case AsmJSMathBuiltin_fround: return CheckMathFRound(f, callNode, type);
       case AsmJSMathBuiltin_min:    return CheckMathMinMax(f, callNode, /* isMax = */ false, type);
       case AsmJSMathBuiltin_max:    return CheckMathMinMax(f, callNode, /* isMax = */ true, type);
-      case AsmJSMathBuiltin_ceil:   arity = 1; f64 = Expr::F64Ceil;  f32 = Expr::F32Ceil;     break;
-      case AsmJSMathBuiltin_floor:  arity = 1; f64 = Expr::F64Floor; f32 = Expr::F32Floor;    break;
-      case AsmJSMathBuiltin_sin:    arity = 1; f64 = Expr::F64Sin;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_cos:    arity = 1; f64 = Expr::F64Cos;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_tan:    arity = 1; f64 = Expr::F64Tan;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_asin:   arity = 1; f64 = Expr::F64Asin;  f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_acos:   arity = 1; f64 = Expr::F64Acos;  f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_atan:   arity = 1; f64 = Expr::F64Atan;  f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_exp:    arity = 1; f64 = Expr::F64Exp;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_log:    arity = 1; f64 = Expr::F64Log;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_pow:    arity = 2; f64 = Expr::F64Pow;   f32 = Expr::Unreachable; break;
-      case AsmJSMathBuiltin_atan2:  arity = 2; f64 = Expr::F64Atan2; f32 = Expr::Unreachable; break;
+      case AsmJSMathBuiltin_ceil:   arity = 1; f64 = Op::F64Ceil;  f32 = Op::F32Ceil;     break;
+      case AsmJSMathBuiltin_floor:  arity = 1; f64 = Op::F64Floor; f32 = Op::F32Floor;    break;
+      case AsmJSMathBuiltin_sin:    arity = 1; f64 = Op::F64Sin;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_cos:    arity = 1; f64 = Op::F64Cos;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_tan:    arity = 1; f64 = Op::F64Tan;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_asin:   arity = 1; f64 = Op::F64Asin;  f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_acos:   arity = 1; f64 = Op::F64Acos;  f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_atan:   arity = 1; f64 = Op::F64Atan;  f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_exp:    arity = 1; f64 = Op::F64Exp;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_log:    arity = 1; f64 = Op::F64Log;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_pow:    arity = 2; f64 = Op::F64Pow;   f32 = Op::Unreachable; break;
+      case AsmJSMathBuiltin_atan2:  arity = 2; f64 = Op::F64Atan2; f32 = Op::Unreachable; break;
       default: MOZ_CRASH("unexpected mathBuiltin function");
     }
 
     unsigned actualArity = CallArgListLength(callNode);
     if (actualArity != arity)
         return f.failf(callNode, "call passed %u arguments, expected %u", actualArity, arity);
 
     if (!f.prepareCall(callNode))
@@ -5028,36 +5028,36 @@ CheckMathBuiltinCall(FunctionValidator& 
     ParseNode* argNode = CallArgList(callNode);
     if (!CheckExpr(f, argNode, &firstType))
         return false;
 
     if (!firstType.isMaybeFloat() && !firstType.isMaybeDouble())
         return f.fail(argNode, "arguments to math call should be a subtype of double? or float?");
 
     bool opIsDouble = firstType.isMaybeDouble();
-    if (!opIsDouble && f32 == Expr::Unreachable)
+    if (!opIsDouble && f32 == Op::Unreachable)
         return f.fail(callNode, "math builtin cannot be used as float");
 
     if (arity == 2) {
         Type secondType;
         argNode = NextNode(argNode);
         if (!CheckExpr(f, argNode, &secondType))
             return false;
 
         if (firstType.isMaybeDouble() && !secondType.isMaybeDouble())
             return f.fail(argNode, "both arguments to math builtin call should be the same type");
         if (firstType.isMaybeFloat() && !secondType.isMaybeFloat())
             return f.fail(argNode, "both arguments to math builtin call should be the same type");
     }
 
     if (opIsDouble) {
-        if (!f.encoder().writeExpr(f64))
+        if (!f.encoder().writeOp(f64))
             return false;
     } else {
-        if (!f.encoder().writeExpr(f32))
+        if (!f.encoder().writeOp(f32))
             return false;
     }
 
     *type = opIsDouble ? Type::Double : Type::Floatish;
     return true;
 }
 
 namespace {
@@ -5142,17 +5142,17 @@ class CheckSimdScalarArgs
             // re-emitting them as float32 constants.
             if (simdType_ != SimdType::Float32x4 || !actualType.isDoubleLit()) {
                 return f.failf(arg, "%s is not a subtype of %s%s",
                                actualType.toChars(), formalType_.toChars(),
                                simdType_ == SimdType::Float32x4 ? " or doublelit" : "");
             }
 
             // We emitted a double literal and actually want a float32.
-            return f.encoder().writeExpr(Expr::F32DemoteF64);
+            return f.encoder().writeOp(Op::F32DemoteF64);
         }
 
         return true;
     }
 };
 
 class CheckSimdSelectArgs
 {
@@ -5329,17 +5329,17 @@ CheckSimdReplaceLane(FunctionValidator& 
     arg = NextNode(arg);
 
     // Third argument is the scalar
     Type scalarType;
     if (!CheckExpr(f, arg, &scalarType))
         return false;
     if (!(scalarType <= SimdToCoercedScalarType(opType))) {
         if (opType == SimdType::Float32x4 && scalarType.isDoubleLit()) {
-            if (!f.encoder().writeExpr(Expr::F32DemoteF64))
+            if (!f.encoder().writeOp(Op::F32DemoteF64))
                 return false;
         } else {
             return f.failf(arg, "%s is not the correct type to replace an element of %s",
                            scalarType.toChars(), vecType.toChars());
         }
     }
 
     if (!f.writeSimdOp(opType, SimdOperation::Fn_replaceLane))
@@ -5722,39 +5722,39 @@ CoerceResult(FunctionValidator& f, Parse
 {
     MOZ_ASSERT(expected.isCanonical());
 
     // At this point, the bytecode resembles this:
     //      | the thing we wanted to coerce | current position |>
     switch (expected.which()) {
       case Type::Void:
         if (!actual.isVoid()) {
-            if (!f.encoder().writeExpr(Expr::Drop))
+            if (!f.encoder().writeOp(Op::Drop))
                 return false;
         }
         break;
       case Type::Int:
         if (!actual.isIntish())
             return f.failf(expr, "%s is not a subtype of intish", actual.toChars());
         break;
       case Type::Float:
         if (!CheckFloatCoercionArg(f, expr, actual))
             return false;
         break;
       case Type::Double:
         if (actual.isMaybeDouble()) {
             // No conversion necessary.
         } else if (actual.isMaybeFloat()) {
-            if (!f.encoder().writeExpr(Expr::F64PromoteF32))
+            if (!f.encoder().writeOp(Op::F64PromoteF32))
                 return false;
         } else if (actual.isSigned()) {
-            if (!f.encoder().writeExpr(Expr::F64ConvertSI32))
+            if (!f.encoder().writeOp(Op::F64ConvertSI32))
                 return false;
         } else if (actual.isUnsigned()) {
-            if (!f.encoder().writeExpr(Expr::F64ConvertUI32))
+            if (!f.encoder().writeOp(Op::F64ConvertUI32))
                 return false;
         } else {
             return f.failf(expr, "%s is not a subtype of double?, float?, signed or unsigned", actual.toChars());
         }
         break;
       default:
         MOZ_ASSERT(expected.isSimd(), "Incomplete switch");
         if (actual != expected)
@@ -5886,42 +5886,42 @@ CheckNot(FunctionValidator& f, ParseNode
     Type operandType;
     if (!CheckExpr(f, operand, &operandType))
         return false;
 
     if (!operandType.isInt())
         return f.failf(operand, "%s is not a subtype of int", operandType.toChars());
 
     *type = Type::Int;
-    return f.encoder().writeExpr(Expr::I32Eqz);
+    return f.encoder().writeOp(Op::I32Eqz);
 }
 
 static bool
 CheckNeg(FunctionValidator& f, ParseNode* expr, Type* type)
 {
     MOZ_ASSERT(expr->isKind(PNK_NEG));
     ParseNode* operand = UnaryKid(expr);
 
     Type operandType;
     if (!CheckExpr(f, operand, &operandType))
         return false;
 
     if (operandType.isInt()) {
         *type = Type::Intish;
-        return f.encoder().writeExpr(Expr::I32Neg);
+        return f.encoder().writeOp(Op::I32Neg);
     }
 
     if (operandType.isMaybeDouble()) {
         *type = Type::Double;
-        return f.encoder().writeExpr(Expr::F64Neg);
+        return f.encoder().writeOp(Op::F64Neg);
     }
 
     if (operandType.isMaybeFloat()) {
         *type = Type::Floatish;
-        return f.encoder().writeExpr(Expr::F32Neg);
+        return f.encoder().writeOp(Op::F32Neg);
     }
 
     return f.failf(operand, "%s is not a subtype of int, float? or double?", operandType.toChars());
 }
 
 static bool
 CheckCoerceToInt(FunctionValidator& f, ParseNode* expr, Type* type)
 {
@@ -5929,18 +5929,18 @@ CheckCoerceToInt(FunctionValidator& f, P
     ParseNode* operand = UnaryKid(expr);
 
     Type operandType;
     if (!CheckExpr(f, operand, &operandType))
         return false;
 
     if (operandType.isMaybeDouble() || operandType.isMaybeFloat()) {
         *type = Type::Signed;
-        Expr opcode = operandType.isMaybeDouble() ? Expr::I32TruncSF64 : Expr::I32TruncSF32;
-        return f.encoder().writeExpr(opcode);
+        Op opcode = operandType.isMaybeDouble() ? Op::I32TruncSF64 : Op::I32TruncSF32;
+        return f.encoder().writeOp(opcode);
     }
 
     if (!operandType.isIntish())
         return f.failf(operand, "%s is not a subtype of double?, float? or intish", operandType.toChars());
 
     *type = Type::Signed;
     return true;
 }
@@ -5956,17 +5956,17 @@ CheckBitNot(FunctionValidator& f, ParseN
 
     Type operandType;
     if (!CheckExpr(f, operand, &operandType))
         return false;
 
     if (!operandType.isIntish())
         return f.failf(operand, "%s is not a subtype of intish", operandType.toChars());
 
-    if (!f.encoder().writeExpr(Expr::I32BitNot))
+    if (!f.encoder().writeOp(Op::I32BitNot))
         return false;
 
     *type = Type::Signed;
     return true;
 }
 
 static bool
 CheckAsExprStatement(FunctionValidator& f, ParseNode* exprStmt);
@@ -5974,17 +5974,17 @@ CheckAsExprStatement(FunctionValidator& 
 static bool
 CheckComma(FunctionValidator& f, ParseNode* comma, Type* type)
 {
     MOZ_ASSERT(comma->isKind(PNK_COMMA));
     ParseNode* operands = ListHead(comma);
 
     // The block depth isn't taken into account here, because a comma list can't
     // contain breaks and continues and nested control flow structures.
-    if (!f.encoder().writeExpr(Expr::Block))
+    if (!f.encoder().writeOp(Op::Block))
         return false;
 
     size_t typeAt;
     if (!f.encoder().writePatchableFixedU7(&typeAt))
         return false;
 
     ParseNode* pn = operands;
     for (; NextNode(pn); pn = NextNode(pn)) {
@@ -5992,17 +5992,17 @@ CheckComma(FunctionValidator& f, ParseNo
             return false;
     }
 
     if (!CheckExpr(f, pn, type))
         return false;
 
     f.encoder().patchFixedU7(typeAt, uint8_t(type->toWasmBlockSignatureType()));
 
-    return f.encoder().writeExpr(Expr::End);
+    return f.encoder().writeOp(Op::End);
 }
 
 static bool
 CheckConditional(FunctionValidator& f, ParseNode* ternary, Type* type)
 {
     MOZ_ASSERT(ternary->isKind(PNK_CONDITIONAL));
 
     ParseNode* cond = TernaryKid1(ternary);
@@ -6098,27 +6098,27 @@ CheckMultiply(FunctionValidator& f, Pars
     Type rhsType;
     if (!CheckExpr(f, rhs, &rhsType))
         return false;
 
     if (lhsType.isInt() && rhsType.isInt()) {
         if (!IsValidIntMultiplyConstant(f.m(), lhs) && !IsValidIntMultiplyConstant(f.m(), rhs))
             return f.fail(star, "one arg to int multiply must be a small (-2^20, 2^20) int literal");
         *type = Type::Intish;
-        return f.encoder().writeExpr(Expr::I32Mul);
+        return f.encoder().writeOp(Op::I32Mul);
     }
 
     if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
         *type = Type::Double;
-        return f.encoder().writeExpr(Expr::F64Mul);
+        return f.encoder().writeOp(Op::F64Mul);
     }
 
     if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
         *type = Type::Floatish;
-        return f.encoder().writeExpr(Expr::F32Mul);
+        return f.encoder().writeOp(Op::F32Mul);
     }
 
     return f.fail(star, "multiply operands must be both int, both double? or both float?");
 }
 
 static bool
 CheckAddOrSub(FunctionValidator& f, ParseNode* expr, Type* type, unsigned* numAddOrSubOut = nullptr)
 {
@@ -6153,25 +6153,25 @@ CheckAddOrSub(FunctionValidator& f, Pars
         rhsNumAddOrSub = 0;
     }
 
     unsigned numAddOrSub = lhsNumAddOrSub + rhsNumAddOrSub + 1;
     if (numAddOrSub > (1<<20))
         return f.fail(expr, "too many + or - without intervening coercion");
 
     if (lhsType.isInt() && rhsType.isInt()) {
-        if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::I32Add : Expr::I32Sub))
+        if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::I32Add : Op::I32Sub))
             return false;
         *type = Type::Intish;
     } else if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
-        if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::F64Add : Expr::F64Sub))
+        if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::F64Add : Op::F64Sub))
             return false;
         *type = Type::Double;
     } else if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
-        if (!f.encoder().writeExpr(expr->isKind(PNK_ADD) ? Expr::F32Add : Expr::F32Sub))
+        if (!f.encoder().writeOp(expr->isKind(PNK_ADD) ? Op::F32Add : Op::F32Sub))
             return false;
         *type = Type::Floatish;
     } else {
         return f.failf(expr, "operands to + or - must both be int, float? or double?, got %s and %s",
                        lhsType.toChars(), rhsType.toChars());
     }
 
     if (numAddOrSubOut)
@@ -6190,35 +6190,35 @@ CheckDivOrMod(FunctionValidator& f, Pars
     Type lhsType, rhsType;
     if (!CheckExpr(f, lhs, &lhsType))
         return false;
     if (!CheckExpr(f, rhs, &rhsType))
         return false;
 
     if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
         *type = Type::Double;
-        return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::F64Div : Expr::F64Mod);
+        return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::F64Div : Op::F64Mod);
     }
 
     if (lhsType.isMaybeFloat() && rhsType.isMaybeFloat()) {
         *type = Type::Floatish;
         if (expr->isKind(PNK_DIV))
-            return f.encoder().writeExpr(Expr::F32Div);
+            return f.encoder().writeOp(Op::F32Div);
         else
             return f.fail(expr, "modulo cannot receive float arguments");
     }
 
     if (lhsType.isSigned() && rhsType.isSigned()) {
         *type = Type::Intish;
-        return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::I32DivS : Expr::I32RemS);
+        return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::I32DivS : Op::I32RemS);
     }
 
     if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
         *type = Type::Intish;
-        return f.encoder().writeExpr(expr->isKind(PNK_DIV) ? Expr::I32DivU : Expr::I32RemU);
+        return f.encoder().writeOp(expr->isKind(PNK_DIV) ? Op::I32DivU : Op::I32RemU);
     }
 
     return f.failf(expr, "arguments to / or %% must both be double?, float?, signed, or unsigned; "
                    "%s and %s are given", lhsType.toChars(), rhsType.toChars());
 }
 
 static bool
 CheckComparison(FunctionValidator& f, ParseNode* comp, Type* type)
@@ -6239,63 +6239,63 @@ CheckComparison(FunctionValidator& f, Pa
         !(lhsType.isUnsigned() && rhsType.isUnsigned()) &&
         !(lhsType.isDouble() && rhsType.isDouble()) &&
         !(lhsType.isFloat() && rhsType.isFloat()))
     {
         return f.failf(comp, "arguments to a comparison must both be signed, unsigned, floats or doubles; "
                        "%s and %s are given", lhsType.toChars(), rhsType.toChars());
     }
 
-    Expr stmt;
+    Op stmt;
     if (lhsType.isSigned() && rhsType.isSigned()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32Eq;  break;
-          case JSOP_NE: stmt = Expr::I32Ne;  break;
-          case JSOP_LT: stmt = Expr::I32LtS; break;
-          case JSOP_LE: stmt = Expr::I32LeS; break;
-          case JSOP_GT: stmt = Expr::I32GtS; break;
-          case JSOP_GE: stmt = Expr::I32GeS; break;
+          case JSOP_EQ: stmt = Op::I32Eq;  break;
+          case JSOP_NE: stmt = Op::I32Ne;  break;
+          case JSOP_LT: stmt = Op::I32LtS; break;
+          case JSOP_LE: stmt = Op::I32LeS; break;
+          case JSOP_GT: stmt = Op::I32GtS; break;
+          case JSOP_GE: stmt = Op::I32GeS; break;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32Eq;  break;
-          case JSOP_NE: stmt = Expr::I32Ne;  break;
-          case JSOP_LT: stmt = Expr::I32LtU; break;
-          case JSOP_LE: stmt = Expr::I32LeU; break;
-          case JSOP_GT: stmt = Expr::I32GtU; break;
-          case JSOP_GE: stmt = Expr::I32GeU; break;
+          case JSOP_EQ: stmt = Op::I32Eq;  break;
+          case JSOP_NE: stmt = Op::I32Ne;  break;
+          case JSOP_LT: stmt = Op::I32LtU; break;
+          case JSOP_LE: stmt = Op::I32LeU; break;
+          case JSOP_GT: stmt = Op::I32GtU; break;
+          case JSOP_GE: stmt = Op::I32GeU; break;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isDouble()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::F64Eq; break;
-          case JSOP_NE: stmt = Expr::F64Ne; break;
-          case JSOP_LT: stmt = Expr::F64Lt; break;
-          case JSOP_LE: stmt = Expr::F64Le; break;
-          case JSOP_GT: stmt = Expr::F64Gt; break;
-          case JSOP_GE: stmt = Expr::F64Ge; break;
+          case JSOP_EQ: stmt = Op::F64Eq; break;
+          case JSOP_NE: stmt = Op::F64Ne; break;
+          case JSOP_LT: stmt = Op::F64Lt; break;
+          case JSOP_LE: stmt = Op::F64Le; break;
+          case JSOP_GT: stmt = Op::F64Gt; break;
+          case JSOP_GE: stmt = Op::F64Ge; break;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isFloat()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::F32Eq; break;
-          case JSOP_NE: stmt = Expr::F32Ne; break;
-          case JSOP_LT: stmt = Expr::F32Lt; break;
-          case JSOP_LE: stmt = Expr::F32Le; break;
-          case JSOP_GT: stmt = Expr::F32Gt; break;
-          case JSOP_GE: stmt = Expr::F32Ge; break;
+          case JSOP_EQ: stmt = Op::F32Eq; break;
+          case JSOP_NE: stmt = Op::F32Ne; break;
+          case JSOP_LT: stmt = Op::F32Lt; break;
+          case JSOP_LE: stmt = Op::F32Le; break;
+          case JSOP_GT: stmt = Op::F32Gt; break;
+          case JSOP_GE: stmt = Op::F32Ge; break;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else {
         MOZ_CRASH("unexpected type");
     }
 
     *type = Type::Int;
-    return f.encoder().writeExpr(stmt);
+    return f.encoder().writeOp(stmt);
 }
 
 static bool
 CheckBitwise(FunctionValidator& f, ParseNode* bitwise, Type* type)
 {
     ParseNode* lhs = BitwiseLeft(bitwise);
     ParseNode* rhs = BitwiseRight(bitwise);
 
@@ -6342,22 +6342,22 @@ CheckBitwise(FunctionValidator& f, Parse
         return false;
 
     if (!lhsType.isIntish())
         return f.failf(lhs, "%s is not a subtype of intish", lhsType.toChars());
     if (!rhsType.isIntish())
         return f.failf(rhs, "%s is not a subtype of intish", rhsType.toChars());
 
     switch (bitwise->getKind()) {
-      case PNK_BITOR:  if (!f.encoder().writeExpr(Expr::I32Or))   return false; break;
-      case PNK_BITAND: if (!f.encoder().writeExpr(Expr::I32And))  return false; break;
-      case PNK_BITXOR: if (!f.encoder().writeExpr(Expr::I32Xor))  return false; break;
-      case PNK_LSH:    if (!f.encoder().writeExpr(Expr::I32Shl))  return false; break;
-      case PNK_RSH:    if (!f.encoder().writeExpr(Expr::I32ShrS)) return false; break;
-      case PNK_URSH:   if (!f.encoder().writeExpr(Expr::I32ShrU)) return false; break;
+      case PNK_BITOR:  if (!f.encoder().writeOp(Op::I32Or))   return false; break;
+      case PNK_BITAND: if (!f.encoder().writeOp(Op::I32And))  return false; break;
+      case PNK_BITXOR: if (!f.encoder().writeOp(Op::I32Xor))  return false; break;
+      case PNK_LSH:    if (!f.encoder().writeOp(Op::I32Shl))  return false; break;
+      case PNK_RSH:    if (!f.encoder().writeOp(Op::I32ShrS)) return false; break;
+      case PNK_URSH:   if (!f.encoder().writeOp(Op::I32ShrU)) return false; break;
       default: MOZ_CRASH("not a bitwise op");
     }
 
     return true;
 }
 
 static bool
 CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type)
@@ -6421,17 +6421,17 @@ CheckAsExprStatement(FunctionValidator& 
         return CheckCoercedCall(f, expr, Type::Void, &ignored);
     }
 
     Type resultType;
     if (!CheckExpr(f, expr, &resultType))
         return false;
 
     if (!resultType.isVoid()) {
-        if (!f.encoder().writeExpr(Expr::Drop))
+        if (!f.encoder().writeOp(Op::Drop))
             return false;
     }
 
     return true;
 }
 
 static bool
 CheckExprStatement(FunctionValidator& f, ParseNode* exprStmt)
@@ -6455,17 +6455,17 @@ CheckLoopConditionOnEntry(FunctionValida
         return false;
     if (!condType.isInt())
         return f.failf(cond, "%s is not a subtype of int", condType.toChars());
 
     // TODO change this to i32.eqz
     // i32.eq 0 $f
     if (!f.writeInt32Lit(0))
         return false;
-    if (!f.encoder().writeExpr(Expr::I32Eq))
+    if (!f.encoder().writeOp(Op::I32Eq))
         return false;
 
     // brIf (i32.eq 0 $f) $out
     if (!f.writeBreakIf())
         return false;
 
     return true;
 }
@@ -6828,17 +6828,17 @@ CheckSwitch(FunctionValidator& f, ParseN
             return f.fail(switchBody, "switch body may not contain lexical declarations");
         switchBody = switchBody->scopeBody();
     }
 
     ParseNode* stmt = ListHead(switchBody);
     if (!stmt) {
         if (!CheckSwitchExpr(f, switchExpr))
             return false;
-        if (!f.encoder().writeExpr(Expr::Drop))
+        if (!f.encoder().writeOp(Op::Drop))
             return false;
         return true;
     }
 
     if (!CheckDefaultAtEnd(f, stmt))
         return false;
 
     int32_t low = 0, high = 0;
@@ -6883,25 +6883,25 @@ CheckSwitch(FunctionValidator& f, ParseN
     uint32_t defaultDepth = numCases;
 
     // Subtract lowest case value, so that all the cases start from 0.
     if (low) {
         if (!CheckSwitchExpr(f, switchExpr))
             return false;
         if (!f.writeInt32Lit(low))
             return false;
-        if (!f.encoder().writeExpr(Expr::I32Sub))
+        if (!f.encoder().writeOp(Op::I32Sub))
             return false;
     } else {
         if (!CheckSwitchExpr(f, switchExpr))
             return false;
     }
 
     // Start the br_table block.
-    if (!f.encoder().writeExpr(Expr::BrTable))
+    if (!f.encoder().writeOp(Op::BrTable))
         return false;
 
     // Write the number of cases (tableLength - 1 + 1 (default)).
     // Write the number of cases (tableLength - 1 + 1 (default)).
     if (!f.encoder().writeVarU32(tableLength))
         return false;
 
     // Each case value describes the relative depth to the actual block. When
@@ -6970,17 +6970,17 @@ CheckReturn(FunctionValidator& f, ParseN
 
         if (!type.isReturnType())
             return f.failf(expr, "%s is not a valid return type", type.toChars());
 
         if (!CheckReturnType(f, expr, Type::canonicalize(type)))
             return false;
     }
 
-    if (!f.encoder().writeExpr(Expr::Return))
+    if (!f.encoder().writeOp(Op::Return))
         return false;
 
     return true;
 }
 
 static bool
 CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const NameVector* labels /*= nullptr */)
 {
--- a/js/src/wasm/WasmAST.h
+++ b/js/src/wasm/WasmAST.h
@@ -369,71 +369,71 @@ class AstTeeLocal : public AstExpr
     }
     AstExpr& value() const {
         return value_;
     }
 };
 
 class AstBlock : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstName name_;
     AstExprVector exprs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Block;
-    explicit AstBlock(Expr expr, ExprType type, AstName name, AstExprVector&& exprs)
+    explicit AstBlock(Op op, ExprType type, AstName name, AstExprVector&& exprs)
       : AstExpr(Kind, type),
-        expr_(expr),
+        op_(op),
         name_(name),
         exprs_(Move(exprs))
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstName name() const { return name_; }
     const AstExprVector& exprs() const { return exprs_; }
 };
 
 class AstBranch : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstExpr* cond_;
     AstRef target_;
     AstExpr* value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Branch;
-    explicit AstBranch(Expr expr, ExprType type,
+    explicit AstBranch(Op op, ExprType type,
                        AstExpr* cond, AstRef target, AstExpr* value)
       : AstExpr(Kind, type),
-        expr_(expr),
+        op_(op),
         cond_(cond),
         target_(target),
         value_(value)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstRef& target() { return target_; }
     AstExpr& cond() const { MOZ_ASSERT(cond_); return *cond_; }
     AstExpr* maybeValue() const { return value_; }
 };
 
 class AstCall : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstRef func_;
     AstExprVector args_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Call;
-    AstCall(Expr expr, ExprType type, AstRef func, AstExprVector&& args)
-      : AstExpr(Kind, type), expr_(expr), func_(func), args_(Move(args))
+    AstCall(Op op, ExprType type, AstRef func, AstExprVector&& args)
+      : AstExpr(Kind, type), op_(op), func_(func), args_(Move(args))
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstRef& func() { return func_; }
     const AstExprVector& args() const { return args_; }
 };
 
 class AstCallIndirect : public AstExpr
 {
     AstRef sig_;
     AstExprVector args_;
@@ -502,72 +502,71 @@ class AstLoadStoreAddress
 
     AstExpr& base() const { return *base_; }
     int32_t flags() const { return flags_; }
     int32_t offset() const { return offset_; }
 };
 
 class AstLoad : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstLoadStoreAddress address_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Load;
-    explicit AstLoad(Expr expr, const AstLoadStoreAddress &address)
+    explicit AstLoad(Op op, const AstLoadStoreAddress &address)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr),
+        op_(op),
         address_(address)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     const AstLoadStoreAddress& address() const { return address_; }
 };
 
 class AstStore : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstLoadStoreAddress address_;
     AstExpr* value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Store;
-    explicit AstStore(Expr expr, const AstLoadStoreAddress &address,
-                          AstExpr* value)
+    explicit AstStore(Op op, const AstLoadStoreAddress &address, AstExpr* value)
       : AstExpr(Kind, ExprType::Void),
-        expr_(expr),
+        op_(op),
         address_(address),
         value_(value)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     const AstLoadStoreAddress& address() const { return address_; }
     AstExpr& value() const { return *value_; }
 };
 
 class AstCurrentMemory final : public AstExpr
 {
   public:
     static const AstExprKind Kind = AstExprKind::CurrentMemory;
     explicit AstCurrentMemory()
       : AstExpr(Kind, ExprType::I32)
     {}
 };
 
 class AstGrowMemory final : public AstExpr
 {
-    AstExpr* op_;
+    AstExpr* operand_;
 
   public:
     static const AstExprKind Kind = AstExprKind::GrowMemory;
-    explicit AstGrowMemory(AstExpr* op)
-      : AstExpr(Kind, ExprType::I32), op_(op)
+    explicit AstGrowMemory(AstExpr* operand)
+      : AstExpr(Kind, ExprType::I32), operand_(operand)
     {}
 
-    AstExpr* op() const { return op_; }
+    AstExpr* operand() const { return operand_; }
 };
 
 class AstBranchTable : public AstExpr
 {
     AstExpr& index_;
     AstRef default_;
     AstRefVector table_;
     AstExpr* value_;
@@ -912,100 +911,100 @@ class AstModule : public AstNode
     }
     const AstGlobalVector& globals() const {
         return globals_;
     }
 };
 
 class AstUnaryOperator final : public AstExpr
 {
-    Expr expr_;
-    AstExpr* op_;
+    Op op_;
+    AstExpr* operand_;
 
   public:
     static const AstExprKind Kind = AstExprKind::UnaryOperator;
-    explicit AstUnaryOperator(Expr expr, AstExpr* op)
+    explicit AstUnaryOperator(Op op, AstExpr* operand)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr), op_(op)
+        op_(op), operand_(operand)
     {}
 
-    Expr expr() const { return expr_; }
-    AstExpr* op() const { return op_; }
+    Op op() const { return op_; }
+    AstExpr* operand() const { return operand_; }
 };
 
 class AstBinaryOperator final : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstExpr* lhs_;
     AstExpr* rhs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::BinaryOperator;
-    explicit AstBinaryOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
+    explicit AstBinaryOperator(Op op, AstExpr* lhs, AstExpr* rhs)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr), lhs_(lhs), rhs_(rhs)
+        op_(op), lhs_(lhs), rhs_(rhs)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstExpr* lhs() const { return lhs_; }
     AstExpr* rhs() const { return rhs_; }
 };
 
 class AstTernaryOperator : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstExpr* op0_;
     AstExpr* op1_;
     AstExpr* op2_;
 
   public:
     static const AstExprKind Kind = AstExprKind::TernaryOperator;
-    AstTernaryOperator(Expr expr, AstExpr* op0, AstExpr* op1, AstExpr* op2)
+    AstTernaryOperator(Op op, AstExpr* op0, AstExpr* op1, AstExpr* op2)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr), op0_(op0), op1_(op1), op2_(op2)
+        op_(op), op0_(op0), op1_(op1), op2_(op2)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstExpr* op0() const { return op0_; }
     AstExpr* op1() const { return op1_; }
     AstExpr* op2() const { return op2_; }
 };
 
 class AstComparisonOperator final : public AstExpr
 {
-    Expr expr_;
+    Op op_;
     AstExpr* lhs_;
     AstExpr* rhs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::ComparisonOperator;
-    explicit AstComparisonOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
+    explicit AstComparisonOperator(Op op, AstExpr* lhs, AstExpr* rhs)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr), lhs_(lhs), rhs_(rhs)
+        op_(op), lhs_(lhs), rhs_(rhs)
     {}
 
-    Expr expr() const { return expr_; }
+    Op op() const { return op_; }
     AstExpr* lhs() const { return lhs_; }
     AstExpr* rhs() const { return rhs_; }
 };
 
 class AstConversionOperator final : public AstExpr
 {
-    Expr expr_;
-    AstExpr* op_;
+    Op op_;
+    AstExpr* operand_;
 
   public:
     static const AstExprKind Kind = AstExprKind::ConversionOperator;
-    explicit AstConversionOperator(Expr expr, AstExpr* op)
+    explicit AstConversionOperator(Op op, AstExpr* operand)
       : AstExpr(Kind, ExprType::Limit),
-        expr_(expr), op_(op)
+        op_(op), operand_(operand)
     {}
 
-    Expr expr() const { return expr_; }
-    AstExpr* op() const { return op_; }
+    Op op() const { return op_; }
+    AstExpr* operand() const { return operand_; }
 };
 
 // This is an artificial AST node which can fill operand slots in an AST
 // constructed from parsing or decoding stack-machine code that doesn't have
 // an inherent AST structure.
 class AstPop final : public AstExpr
 {
   public:
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -54,17 +54,17 @@
  *   this reduces register pressure and instruction count.
  *
  * - (Bug 1286816) Opportunities for cheaply folding in a constant rhs to
  *   conditionals.
  *
  * - (Bug 1286816) Boolean evaluation for control can be optimized by pushing a
  *   bool-generating operation onto the value stack in the same way that we now
  *   push latent constants and local lookups, or (easier) by remembering the
- *   operation in a side location if the next Expr will consume it.
+ *   operation in a side location if the next Op will consume it.
  *
  * - (Bug 1286816) brIf pessimizes by branching over code that performs stack
  *   cleanup and a branch.  If no cleanup is needed we can just branch
  *   conditionally to the target.
  *
  * - (Bug 1316804) brTable pessimizes by always dispatching to code that pops
  *   the stack and then jumps to the code for the target case.  If no cleanup is
  *   needed we could just branch conditionally to the target; if the same amount
@@ -128,33 +128,33 @@ using mozilla::IsPowerOfTwo;
 using mozilla::SpecificNaN;
 
 namespace js {
 namespace wasm {
 
 using namespace js::jit;
 using JS::GenericNaN;
 
-struct BaseCompilePolicy : ExprIterPolicy
+struct BaseCompilePolicy : OpIterPolicy
 {
     static const bool Output = true;
 
     // The baseline compiler tracks values on a stack of its own -- it
     // needs to scan that stack for spilling -- and thus has no need
     // for the values maintained by the iterator.
     //
     // The baseline compiler tracks control items on a stack of its
     // own as well.
     //
     // TODO / REDUNDANT (Bug 1316814): It would be nice if we could
     // make use of the iterator's ControlItems and not require our own
     // stack for that.
 };
 
-typedef ExprIter<BaseCompilePolicy> BaseExprIter;
+typedef OpIter<BaseCompilePolicy> BaseOpIter;
 
 typedef bool IsUnsigned;
 typedef bool IsSigned;
 typedef bool ZeroOnOverflow;
 typedef bool IsKnownNotZero;
 typedef bool HandleNaNSpecially;
 typedef unsigned ByteSize;
 typedef unsigned BitSize;
@@ -501,17 +501,17 @@ class BaseCompiler
         //
         // All other registers must be explicitly saved and restored
         // by the OOL code before being used.
 
         virtual void generate(MacroAssembler& masm) = 0;
     };
 
     const ModuleGeneratorData&  mg_;
-    BaseExprIter                iter_;
+    BaseOpIter                  iter_;
     const FuncBytes&            func_;
     size_t                      lastReadCallSite_;
     TempAllocator&              alloc_;
     const ValTypeVector&        locals_;         // Types of parameters and locals
     int32_t                     localSize_;      // Size of local area in bytes (stable after beginFunction)
     int32_t                     varLow_;         // Low byte offset of local area for true locals (not parameters)
     int32_t                     varHigh_;        // High byte offset + 1 of local area for true locals
     int32_t                     maxFramePushed_; // Max value of masm.framePushed() observed
@@ -6579,540 +6579,540 @@ BaseCompiler::emitBody()
             CHECK(stk_.reserve(stk_.length() + overhead * 2));
         }
 
         overhead--;
 
         if (done())
             return true;
 
-        uint16_t expr;
-        CHECK(iter_.readExpr(&expr));
-
-        switch (expr) {
+        uint16_t op;
+        CHECK(iter_.readOp(&op));
+
+        switch (op) {
           // Control opcodes
-          case uint16_t(Expr::Nop):
+          case uint16_t(Op::Nop):
             CHECK(iter_.readNop());
             NEXT();
-          case uint16_t(Expr::Drop):
+          case uint16_t(Op::Drop):
             CHECK_NEXT(emitDrop());
-          case uint16_t(Expr::Block):
+          case uint16_t(Op::Block):
             CHECK_NEXT(emitBlock());
-          case uint16_t(Expr::Loop):
+          case uint16_t(Op::Loop):
             CHECK_NEXT(emitLoop());
-          case uint16_t(Expr::If):
+          case uint16_t(Op::If):
             CHECK_NEXT(emitIf());
-          case uint16_t(Expr::Else):
+          case uint16_t(Op::Else):
             CHECK_NEXT(emitElse());
-          case uint16_t(Expr::End):
+          case uint16_t(Op::End):
             CHECK_NEXT(emitEnd());
-          case uint16_t(Expr::Br):
+          case uint16_t(Op::Br):
             CHECK_NEXT(emitBr());
-          case uint16_t(Expr::BrIf):
+          case uint16_t(Op::BrIf):
             CHECK_NEXT(emitBrIf());
-          case uint16_t(Expr::BrTable):
+          case uint16_t(Op::BrTable):
             CHECK_NEXT(emitBrTable());
-          case uint16_t(Expr::Return):
+          case uint16_t(Op::Return):
             CHECK_NEXT(emitReturn());
-          case uint16_t(Expr::Unreachable):
+          case uint16_t(Op::Unreachable):
             CHECK(iter_.readUnreachable());
             if (!deadCode_) {
                 unreachableTrap();
                 deadCode_ = true;
                 popValueStackTo(ctl_.back().stackSize);
             }
             NEXT();
 
           // Calls
-          case uint16_t(Expr::Call):
+          case uint16_t(Op::Call):
             CHECK_NEXT(emitCall());
-          case uint16_t(Expr::CallIndirect):
+          case uint16_t(Op::CallIndirect):
             CHECK_NEXT(emitCallIndirect(/* oldStyle = */ false));
-          case uint16_t(Expr::OldCallIndirect):
+          case uint16_t(Op::OldCallIndirect):
             CHECK_NEXT(emitCallIndirect(/* oldStyle = */ true));
 
           // Locals and globals
-          case uint16_t(Expr::GetLocal):
+          case uint16_t(Op::GetLocal):
             CHECK_NEXT(emitGetLocal());
-          case uint16_t(Expr::SetLocal):
+          case uint16_t(Op::SetLocal):
             CHECK_NEXT(emitSetLocal());
-          case uint16_t(Expr::TeeLocal):
+          case uint16_t(Op::TeeLocal):
             CHECK_NEXT(emitTeeLocal());
-          case uint16_t(Expr::GetGlobal):
+          case uint16_t(Op::GetGlobal):
             CHECK_NEXT(emitGetGlobal());
-          case uint16_t(Expr::SetGlobal):
+          case uint16_t(Op::SetGlobal):
             CHECK_NEXT(emitSetGlobal());
-          case uint16_t(Expr::TeeGlobal):
+          case uint16_t(Op::TeeGlobal):
             CHECK_NEXT(emitTeeGlobal());
 
           // Select
-          case uint16_t(Expr::Select):
+          case uint16_t(Op::Select):
             CHECK_NEXT(emitSelect());
 
           // I32
-          case uint16_t(Expr::I32Const): {
+          case uint16_t(Op::I32Const): {
             int32_t i32;
             CHECK(iter_.readI32Const(&i32));
             if (!deadCode_)
                 pushI32(i32);
             NEXT();
           }
-          case uint16_t(Expr::I32Add):
+          case uint16_t(Op::I32Add):
             CHECK_NEXT(emitBinary(emitAddI32, ValType::I32));
-          case uint16_t(Expr::I32Sub):
+          case uint16_t(Op::I32Sub):
             CHECK_NEXT(emitBinary(emitSubtractI32, ValType::I32));
-          case uint16_t(Expr::I32Mul):
+          case uint16_t(Op::I32Mul):
             CHECK_NEXT(emitBinary(emitMultiplyI32, ValType::I32));
-          case uint16_t(Expr::I32DivS):
+          case uint16_t(Op::I32DivS):
             CHECK_NEXT(emitBinary(emitQuotientI32, ValType::I32));
-          case uint16_t(Expr::I32DivU):
+          case uint16_t(Op::I32DivU):
             CHECK_NEXT(emitBinary(emitQuotientU32, ValType::I32));
-          case uint16_t(Expr::I32RemS):
+          case uint16_t(Op::I32RemS):
             CHECK_NEXT(emitBinary(emitRemainderI32, ValType::I32));
-          case uint16_t(Expr::I32RemU):
+          case uint16_t(Op::I32RemU):
             CHECK_NEXT(emitBinary(emitRemainderU32, ValType::I32));
-          case uint16_t(Expr::I32Min):
+          case uint16_t(Op::I32Min):
             CHECK_NEXT(emitBinary(emitMinI32, ValType::I32));
-          case uint16_t(Expr::I32Max):
+          case uint16_t(Op::I32Max):
             CHECK_NEXT(emitBinary(emitMaxI32, ValType::I32));
-          case uint16_t(Expr::I32Eqz):
+          case uint16_t(Op::I32Eqz):
             CHECK_NEXT(emitConversion(emitEqzI32, ValType::I32, ValType::I32));
-          case uint16_t(Expr::I32TruncSF32):
+          case uint16_t(Op::I32TruncSF32):
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<false>, ValType::F32, ValType::I32));
-          case uint16_t(Expr::I32TruncUF32):
+          case uint16_t(Op::I32TruncUF32):
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<true>, ValType::F32, ValType::I32));
-          case uint16_t(Expr::I32TruncSF64):
+          case uint16_t(Op::I32TruncSF64):
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<false>, ValType::F64, ValType::I32));
-          case uint16_t(Expr::I32TruncUF64):
+          case uint16_t(Op::I32TruncUF64):
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<true>, ValType::F64, ValType::I32));
-          case uint16_t(Expr::I32WrapI64):
+          case uint16_t(Op::I32WrapI64):
             CHECK_NEXT(emitConversion(emitWrapI64ToI32, ValType::I64, ValType::I32));
-          case uint16_t(Expr::I32ReinterpretF32):
+          case uint16_t(Op::I32ReinterpretF32):
             CHECK_NEXT(emitConversion(emitReinterpretF32AsI32, ValType::F32, ValType::I32));
-          case uint16_t(Expr::I32Clz):
+          case uint16_t(Op::I32Clz):
             CHECK_NEXT(emitUnary(emitClzI32, ValType::I32));
-          case uint16_t(Expr::I32Ctz):
+          case uint16_t(Op::I32Ctz):
             CHECK_NEXT(emitUnary(emitCtzI32, ValType::I32));
-          case uint16_t(Expr::I32Popcnt):
+          case uint16_t(Op::I32Popcnt):
             CHECK_NEXT(emitUnary(emitPopcntI32, ValType::I32));
-          case uint16_t(Expr::I32Abs):
+          case uint16_t(Op::I32Abs):
             CHECK_NEXT(emitUnary(emitAbsI32, ValType::I32));
-          case uint16_t(Expr::I32Neg):
+          case uint16_t(Op::I32Neg):
             CHECK_NEXT(emitUnary(emitNegateI32, ValType::I32));
-          case uint16_t(Expr::I32Or):
+          case uint16_t(Op::I32Or):
             CHECK_NEXT(emitBinary(emitOrI32, ValType::I32));
-          case uint16_t(Expr::I32And):
+          case uint16_t(Op::I32And):
             CHECK_NEXT(emitBinary(emitAndI32, ValType::I32));
-          case uint16_t(Expr::I32Xor):
+          case uint16_t(Op::I32Xor):
             CHECK_NEXT(emitBinary(emitXorI32, ValType::I32));
-          case uint16_t(Expr::I32Shl):
+          case uint16_t(Op::I32Shl):
             CHECK_NEXT(emitBinary(emitShlI32, ValType::I32));
-          case uint16_t(Expr::I32ShrS):
+          case uint16_t(Op::I32ShrS):
             CHECK_NEXT(emitBinary(emitShrI32, ValType::I32));
-          case uint16_t(Expr::I32ShrU):
+          case uint16_t(Op::I32ShrU):
             CHECK_NEXT(emitBinary(emitShrU32, ValType::I32));
-          case uint16_t(Expr::I32BitNot):
+          case uint16_t(Op::I32BitNot):
             CHECK_NEXT(emitUnary(emitBitNotI32, ValType::I32));
-          case uint16_t(Expr::I32Load8S):
+          case uint16_t(Op::I32Load8S):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int8));
-          case uint16_t(Expr::I32Load8U):
+          case uint16_t(Op::I32Load8U):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint8));
-          case uint16_t(Expr::I32Load16S):
+          case uint16_t(Op::I32Load16S):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int16));
-          case uint16_t(Expr::I32Load16U):
+          case uint16_t(Op::I32Load16U):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint16));
-          case uint16_t(Expr::I32Load):
+          case uint16_t(Op::I32Load):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int32));
-          case uint16_t(Expr::I32Store8):
+          case uint16_t(Op::I32Store8):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int8));
-          case uint16_t(Expr::I32TeeStore8):
+          case uint16_t(Op::I32TeeStore8):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int8));
-          case uint16_t(Expr::I32Store16):
+          case uint16_t(Op::I32Store16):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int16));
-          case uint16_t(Expr::I32TeeStore16):
+          case uint16_t(Op::I32TeeStore16):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int16));
-          case uint16_t(Expr::I32Store):
+          case uint16_t(Op::I32Store):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int32));
-          case uint16_t(Expr::I32TeeStore):
+          case uint16_t(Op::I32TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int32));
-          case uint16_t(Expr::I32Rotr):
+          case uint16_t(Op::I32Rotr):
             CHECK_NEXT(emitBinary(emitRotrI32, ValType::I32));
-          case uint16_t(Expr::I32Rotl):
+          case uint16_t(Op::I32Rotl):
             CHECK_NEXT(emitBinary(emitRotlI32, ValType::I32));
 
           // I64
-          case uint16_t(Expr::I64Const): {
+          case uint16_t(Op::I64Const): {
             int64_t i64;
             CHECK(iter_.readI64Const(&i64));
             if (!deadCode_)
                 pushI64(i64);
             NEXT();
           }
-          case uint16_t(Expr::I64Add):
+          case uint16_t(Op::I64Add):
             CHECK_NEXT(emitBinary(emitAddI64, ValType::I64));
-          case uint16_t(Expr::I64Sub):
+          case uint16_t(Op::I64Sub):
             CHECK_NEXT(emitBinary(emitSubtractI64, ValType::I64));
-          case uint16_t(Expr::I64Mul):
+          case uint16_t(Op::I64Mul):
             CHECK_NEXT(emitBinary(emitMultiplyI64, ValType::I64));
-          case uint16_t(Expr::I64DivS):
+          case uint16_t(Op::I64DivS):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::DivI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitQuotientI64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64DivU):
+          case uint16_t(Op::I64DivU):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UDivI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitQuotientU64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64RemS):
+          case uint16_t(Op::I64RemS):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::ModI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitRemainderI64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64RemU):
+          case uint16_t(Op::I64RemU):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UModI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitRemainderU64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64TruncSF32):
+          case uint16_t(Op::I64TruncSF32):
 #ifdef FLOAT_TO_I64_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
                                                 SymbolicAddress::TruncateDoubleToInt64,
                                                 ValType::F32, ValType::I64));
 #else
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI64<false>, ValType::F32, ValType::I64));
 #endif
-          case uint16_t(Expr::I64TruncUF32):
+          case uint16_t(Op::I64TruncUF32):
 #ifdef FLOAT_TO_I64_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
                                                 SymbolicAddress::TruncateDoubleToUint64,
                                                 ValType::F32, ValType::I64));
 #else
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI64<true>, ValType::F32, ValType::I64));
 #endif
-          case uint16_t(Expr::I64TruncSF64):
+          case uint16_t(Op::I64TruncSF64):
 #ifdef FLOAT_TO_I64_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
                                                 SymbolicAddress::TruncateDoubleToInt64,
                                                 ValType::F64, ValType::I64));
 #else
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI64<false>, ValType::F64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64TruncUF64):
+          case uint16_t(Op::I64TruncUF64):
 #ifdef FLOAT_TO_I64_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertFloatingToInt64Callout,
                                                 SymbolicAddress::TruncateDoubleToUint64,
                                                 ValType::F64, ValType::I64));
 #else
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI64<true>, ValType::F64, ValType::I64));
 #endif
-          case uint16_t(Expr::I64ExtendSI32):
+          case uint16_t(Op::I64ExtendSI32):
             CHECK_NEXT(emitConversion(emitExtendI32ToI64, ValType::I32, ValType::I64));
-          case uint16_t(Expr::I64ExtendUI32):
+          case uint16_t(Op::I64ExtendUI32):
             CHECK_NEXT(emitConversion(emitExtendU32ToI64, ValType::I32, ValType::I64));
-          case uint16_t(Expr::I64ReinterpretF64):
+          case uint16_t(Op::I64ReinterpretF64):
             CHECK_NEXT(emitConversion(emitReinterpretF64AsI64, ValType::F64, ValType::I64));
-          case uint16_t(Expr::I64Or):
+          case uint16_t(Op::I64Or):
             CHECK_NEXT(emitBinary(emitOrI64, ValType::I64));
-          case uint16_t(Expr::I64And):
+          case uint16_t(Op::I64And):
             CHECK_NEXT(emitBinary(emitAndI64, ValType::I64));
-          case uint16_t(Expr::I64Xor):
+          case uint16_t(Op::I64Xor):
             CHECK_NEXT(emitBinary(emitXorI64, ValType::I64));
-          case uint16_t(Expr::I64Shl):
+          case uint16_t(Op::I64Shl):
             CHECK_NEXT(emitBinary(emitShlI64, ValType::I64));
-          case uint16_t(Expr::I64ShrS):
+          case uint16_t(Op::I64ShrS):
             CHECK_NEXT(emitBinary(emitShrI64, ValType::I64));
-          case uint16_t(Expr::I64ShrU):
+          case uint16_t(Op::I64ShrU):
             CHECK_NEXT(emitBinary(emitShrU64, ValType::I64));
-          case uint16_t(Expr::I64Rotr):
+          case uint16_t(Op::I64Rotr):
             CHECK_NEXT(emitBinary(emitRotrI64, ValType::I64));
-          case uint16_t(Expr::I64Rotl):
+          case uint16_t(Op::I64Rotl):
             CHECK_NEXT(emitBinary(emitRotlI64, ValType::I64));
-          case uint16_t(Expr::I64Clz):
+          case uint16_t(Op::I64Clz):
             CHECK_NEXT(emitUnary(emitClzI64, ValType::I64));
-          case uint16_t(Expr::I64Ctz):
+          case uint16_t(Op::I64Ctz):
             CHECK_NEXT(emitUnary(emitCtzI64, ValType::I64));
-          case uint16_t(Expr::I64Popcnt):
+          case uint16_t(Op::I64Popcnt):
             CHECK_NEXT(emitUnary(emitPopcntI64, ValType::I64));
-          case uint16_t(Expr::I64Eqz):
+          case uint16_t(Op::I64Eqz):
             CHECK_NEXT(emitConversion(emitEqzI64, ValType::I64, ValType::I32));
-          case uint16_t(Expr::I64Load8S):
+          case uint16_t(Op::I64Load8S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int8));
-          case uint16_t(Expr::I64Load16S):
+          case uint16_t(Op::I64Load16S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int16));
-          case uint16_t(Expr::I64Load32S):
+          case uint16_t(Op::I64Load32S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int32));
-          case uint16_t(Expr::I64Load8U):
+          case uint16_t(Op::I64Load8U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint8));
-          case uint16_t(Expr::I64Load16U):
+          case uint16_t(Op::I64Load16U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint16));
-          case uint16_t(Expr::I64Load32U):
+          case uint16_t(Op::I64Load32U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint32));
-          case uint16_t(Expr::I64Load):
+          case uint16_t(Op::I64Load):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int64));
-          case uint16_t(Expr::I64Store8):
+          case uint16_t(Op::I64Store8):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int8));
-          case uint16_t(Expr::I64TeeStore8):
+          case uint16_t(Op::I64TeeStore8):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int8));
-          case uint16_t(Expr::I64Store16):
+          case uint16_t(Op::I64Store16):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int16));
-          case uint16_t(Expr::I64TeeStore16):
+          case uint16_t(Op::I64TeeStore16):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int16));
-          case uint16_t(Expr::I64Store32):
+          case uint16_t(Op::I64Store32):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int32));
-          case uint16_t(Expr::I64TeeStore32):
+          case uint16_t(Op::I64TeeStore32):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int32));
-          case uint16_t(Expr::I64Store):
+          case uint16_t(Op::I64Store):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int64));
-          case uint16_t(Expr::I64TeeStore):
+          case uint16_t(Op::I64TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int64));
 
           // F32
-          case uint16_t(Expr::F32Const): {
+          case uint16_t(Op::F32Const): {
             RawF32 f32;
             CHECK(iter_.readF32Const(&f32));
             if (!deadCode_)
                 pushF32(f32);
             NEXT();
           }
-          case uint16_t(Expr::F32Add):
+          case uint16_t(Op::F32Add):
             CHECK_NEXT(emitBinary(emitAddF32, ValType::F32));
-          case uint16_t(Expr::F32Sub):
+          case uint16_t(Op::F32Sub):
             CHECK_NEXT(emitBinary(emitSubtractF32, ValType::F32));
-          case uint16_t(Expr::F32Mul):
+          case uint16_t(Op::F32Mul):
             CHECK_NEXT(emitBinary(emitMultiplyF32, ValType::F32));
-          case uint16_t(Expr::F32Div):
+          case uint16_t(Op::F32Div):
             CHECK_NEXT(emitBinary(emitDivideF32, ValType::F32));
-          case uint16_t(Expr::F32Min):
+          case uint16_t(Op::F32Min):
             CHECK_NEXT(emitBinary(emitMinF32, ValType::F32));
-          case uint16_t(Expr::F32Max):
+          case uint16_t(Op::F32Max):
             CHECK_NEXT(emitBinary(emitMaxF32, ValType::F32));
-          case uint16_t(Expr::F32Neg):
+          case uint16_t(Op::F32Neg):
             CHECK_NEXT(emitUnary(emitNegateF32, ValType::F32));
-          case uint16_t(Expr::F32Abs):
+          case uint16_t(Op::F32Abs):
             CHECK_NEXT(emitUnary(emitAbsF32, ValType::F32));
-          case uint16_t(Expr::F32Sqrt):
+          case uint16_t(Op::F32Sqrt):
             CHECK_NEXT(emitUnary(emitSqrtF32, ValType::F32));
-          case uint16_t(Expr::F32Ceil):
+          case uint16_t(Op::F32Ceil):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilF, ValType::F32));
-          case uint16_t(Expr::F32Floor):
+          case uint16_t(Op::F32Floor):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorF, ValType::F32));
-          case uint16_t(Expr::F32DemoteF64):
+          case uint16_t(Op::F32DemoteF64):
             CHECK_NEXT(emitConversion(emitConvertF64ToF32, ValType::F64, ValType::F32));
-          case uint16_t(Expr::F32ConvertSI32):
+          case uint16_t(Op::F32ConvertSI32):
             CHECK_NEXT(emitConversion(emitConvertI32ToF32, ValType::I32, ValType::F32));
-          case uint16_t(Expr::F32ConvertUI32):
+          case uint16_t(Op::F32ConvertUI32):
             CHECK_NEXT(emitConversion(emitConvertU32ToF32, ValType::I32, ValType::F32));
-          case uint16_t(Expr::F32ConvertSI64):
+          case uint16_t(Op::F32ConvertSI64):
 #ifdef I64_TO_FLOAT_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
                                                 SymbolicAddress::Int64ToFloatingPoint,
                                                 ValType::I64, ValType::F32));
 #else
             CHECK_NEXT(emitConversion(emitConvertI64ToF32, ValType::I64, ValType::F32));
 #endif
-          case uint16_t(Expr::F32ConvertUI64):
+          case uint16_t(Op::F32ConvertUI64):
 #ifdef I64_TO_FLOAT_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
                                                 SymbolicAddress::Uint64ToFloatingPoint,
                                                 ValType::I64, ValType::F32));
 #else
             CHECK_NEXT(emitConversion(emitConvertU64ToF32, ValType::I64, ValType::F32));
 #endif
-          case uint16_t(Expr::F32ReinterpretI32):
+          case uint16_t(Op::F32ReinterpretI32):
             CHECK_NEXT(emitConversion(emitReinterpretI32AsF32, ValType::I32, ValType::F32));
-          case uint16_t(Expr::F32Load):
+          case uint16_t(Op::F32Load):
             CHECK_NEXT(emitLoad(ValType::F32, Scalar::Float32));
-          case uint16_t(Expr::F32Store):
+          case uint16_t(Op::F32Store):
             CHECK_NEXT(emitStore(ValType::F32, Scalar::Float32));
-          case uint16_t(Expr::F32TeeStore):
+          case uint16_t(Op::F32TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::F32, Scalar::Float32));
-          case uint16_t(Expr::F32TeeStoreF64):
+          case uint16_t(Op::F32TeeStoreF64):
             CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F32, Scalar::Float64));
-          case uint16_t(Expr::F32CopySign):
+          case uint16_t(Op::F32CopySign):
             CHECK_NEXT(emitBinary(emitCopysignF32, ValType::F32));
-          case uint16_t(Expr::F32Nearest):
+          case uint16_t(Op::F32Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntF, ValType::F32));
-          case uint16_t(Expr::F32Trunc):
+          case uint16_t(Op::F32Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncF, ValType::F32));
 
           // F64
-          case uint16_t(Expr::F64Const): {
+          case uint16_t(Op::F64Const): {
             RawF64 f64;
             CHECK(iter_.readF64Const(&f64));
             if (!deadCode_)
                 pushF64(f64);
             NEXT();
           }
-          case uint16_t(Expr::F64Add):
+          case uint16_t(Op::F64Add):
             CHECK_NEXT(emitBinary(emitAddF64, ValType::F64));
-          case uint16_t(Expr::F64Sub):
+          case uint16_t(Op::F64Sub):
             CHECK_NEXT(emitBinary(emitSubtractF64, ValType::F64));
-          case uint16_t(Expr::F64Mul):
+          case uint16_t(Op::F64Mul):
             CHECK_NEXT(emitBinary(emitMultiplyF64, ValType::F64));
-          case uint16_t(Expr::F64Div):
+          case uint16_t(Op::F64Div):
             CHECK_NEXT(emitBinary(emitDivideF64, ValType::F64));
-          case uint16_t(Expr::F64Mod):
+          case uint16_t(Op::F64Mod):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ModD, ValType::F64));
-          case uint16_t(Expr::F64Min):
+          case uint16_t(Op::F64Min):
             CHECK_NEXT(emitBinary(emitMinF64, ValType::F64));
-          case uint16_t(Expr::F64Max):
+          case uint16_t(Op::F64Max):
             CHECK_NEXT(emitBinary(emitMaxF64, ValType::F64));
-          case uint16_t(Expr::F64Neg):
+          case uint16_t(Op::F64Neg):
             CHECK_NEXT(emitUnary(emitNegateF64, ValType::F64));
-          case uint16_t(Expr::F64Abs):
+          case uint16_t(Op::F64Abs):
             CHECK_NEXT(emitUnary(emitAbsF64, ValType::F64));
-          case uint16_t(Expr::F64Sqrt):
+          case uint16_t(Op::F64Sqrt):
             CHECK_NEXT(emitUnary(emitSqrtF64, ValType::F64));
-          case uint16_t(Expr::F64Ceil):
+          case uint16_t(Op::F64Ceil):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilD, ValType::F64));
-          case uint16_t(Expr::F64Floor):
+          case uint16_t(Op::F64Floor):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorD, ValType::F64));
-          case uint16_t(Expr::F64Sin):
+          case uint16_t(Op::F64Sin):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::SinD, ValType::F64));
-          case uint16_t(Expr::F64Cos):
+          case uint16_t(Op::F64Cos):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CosD, ValType::F64));
-          case uint16_t(Expr::F64Tan):
+          case uint16_t(Op::F64Tan):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TanD, ValType::F64));
-          case uint16_t(Expr::F64Asin):
+          case uint16_t(Op::F64Asin):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ASinD, ValType::F64));
-          case uint16_t(Expr::F64Acos):
+          case uint16_t(Op::F64Acos):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ACosD, ValType::F64));
-          case uint16_t(Expr::F64Atan):
+          case uint16_t(Op::F64Atan):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ATanD, ValType::F64));
-          case uint16_t(Expr::F64Exp):
+          case uint16_t(Op::F64Exp):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ExpD, ValType::F64));
-          case uint16_t(Expr::F64Log):
+          case uint16_t(Op::F64Log):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::LogD, ValType::F64));
-          case uint16_t(Expr::F64Pow):
+          case uint16_t(Op::F64Pow):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::PowD, ValType::F64));
-          case uint16_t(Expr::F64Atan2):
+          case uint16_t(Op::F64Atan2):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ATan2D, ValType::F64));
-          case uint16_t(Expr::F64PromoteF32):
+          case uint16_t(Op::F64PromoteF32):
             CHECK_NEXT(emitConversion(emitConvertF32ToF64, ValType::F32, ValType::F64));
-          case uint16_t(Expr::F64ConvertSI32):
+          case uint16_t(Op::F64ConvertSI32):
             CHECK_NEXT(emitConversion(emitConvertI32ToF64, ValType::I32, ValType::F64));
-          case uint16_t(Expr::F64ConvertUI32):
+          case uint16_t(Op::F64ConvertUI32):
             CHECK_NEXT(emitConversion(emitConvertU32ToF64, ValType::I32, ValType::F64));
-          case uint16_t(Expr::F64ConvertSI64):
+          case uint16_t(Op::F64ConvertSI64):
 #ifdef I64_TO_FLOAT_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
                                                 SymbolicAddress::Int64ToFloatingPoint,
                                                 ValType::I64, ValType::F64));
 #else
             CHECK_NEXT(emitConversion(emitConvertI64ToF64, ValType::I64, ValType::F64));
 #endif
-          case uint16_t(Expr::F64ConvertUI64):
+          case uint16_t(Op::F64ConvertUI64):
 #ifdef I64_TO_FLOAT_CALLOUT
             CHECK_NEXT(emitCalloutConversionOOM(emitConvertInt64ToFloatingCallout,
                                                 SymbolicAddress::Uint64ToFloatingPoint,
                                                 ValType::I64, ValType::F64));
 #else
             CHECK_NEXT(emitConversion(emitConvertU64ToF64, ValType::I64, ValType::F64));
 #endif
-          case uint16_t(Expr::F64Load):
+          case uint16_t(Op::F64Load):
             CHECK_NEXT(emitLoad(ValType::F64, Scalar::Float64));
-          case uint16_t(Expr::F64Store):
+          case uint16_t(Op::F64Store):
             CHECK_NEXT(emitStore(ValType::F64, Scalar::Float64));
-          case uint16_t(Expr::F64TeeStore):
+          case uint16_t(Op::F64TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::F64, Scalar::Float64));
-          case uint16_t(Expr::F64TeeStoreF32):
+          case uint16_t(Op::F64TeeStoreF32):
             CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F64, Scalar::Float32));
-          case uint16_t(Expr::F64ReinterpretI64):
+          case uint16_t(Op::F64ReinterpretI64):
             CHECK_NEXT(emitConversion(emitReinterpretI64AsF64, ValType::I64, ValType::F64));
-          case uint16_t(Expr::F64CopySign):
+          case uint16_t(Op::F64CopySign):
             CHECK_NEXT(emitBinary(emitCopysignF64, ValType::F64));
-          case uint16_t(Expr::F64Nearest):
+          case uint16_t(Op::F64Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntD, ValType::F64));
-          case uint16_t(Expr::F64Trunc):
+          case uint16_t(Op::F64Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncD, ValType::F64));
 
           // Comparisons
-          case uint16_t(Expr::I32Eq):
+          case uint16_t(Op::I32Eq):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_EQ, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32Ne):
+          case uint16_t(Op::I32Ne):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_NE, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32LtS):
+          case uint16_t(Op::I32LtS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32LeS):
+          case uint16_t(Op::I32LeS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32GtS):
+          case uint16_t(Op::I32GtS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32GeS):
+          case uint16_t(Op::I32GeS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_Int32));
-          case uint16_t(Expr::I32LtU):
+          case uint16_t(Op::I32LtU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_UInt32));
-          case uint16_t(Expr::I32LeU):
+          case uint16_t(Op::I32LeU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_UInt32));
-          case uint16_t(Expr::I32GtU):
+          case uint16_t(Op::I32GtU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_UInt32));
-          case uint16_t(Expr::I32GeU):
+          case uint16_t(Op::I32GeU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_UInt32));
-          case uint16_t(Expr::I64Eq):
+          case uint16_t(Op::I64Eq):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_EQ, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64Ne):
+          case uint16_t(Op::I64Ne):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_NE, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64LtS):
+          case uint16_t(Op::I64LtS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64LeS):
+          case uint16_t(Op::I64LeS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64GtS):
+          case uint16_t(Op::I64GtS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64GeS):
+          case uint16_t(Op::I64GeS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_Int64));
-          case uint16_t(Expr::I64LtU):
+          case uint16_t(Op::I64LtU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_UInt64));
-          case uint16_t(Expr::I64LeU):
+          case uint16_t(Op::I64LeU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_UInt64));
-          case uint16_t(Expr::I64GtU):
+          case uint16_t(Op::I64GtU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_UInt64));
-          case uint16_t(Expr::I64GeU):
+          case uint16_t(Op::I64GeU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_UInt64));
-          case uint16_t(Expr::F32Eq):
+          case uint16_t(Op::F32Eq):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_EQ, MCompare::Compare_Float32));
-          case uint16_t(Expr::F32Ne):
+          case uint16_t(Op::F32Ne):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_NE, MCompare::Compare_Float32));
-          case uint16_t(Expr::F32Lt):
+          case uint16_t(Op::F32Lt):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LT, MCompare::Compare_Float32));
-          case uint16_t(Expr::F32Le):
+          case uint16_t(Op::F32Le):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LE, MCompare::Compare_Float32));
-          case uint16_t(Expr::F32Gt):
+          case uint16_t(Op::F32Gt):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GT, MCompare::Compare_Float32));
-          case uint16_t(Expr::F32Ge):
+          case uint16_t(Op::F32Ge):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GE, MCompare::Compare_Float32));
-          case uint16_t(Expr::F64Eq):
+          case uint16_t(Op::F64Eq):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_EQ, MCompare::Compare_Double));
-          case uint16_t(Expr::F64Ne):
+          case uint16_t(Op::F64Ne):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_NE, MCompare::Compare_Double));
-          case uint16_t(Expr::F64Lt):
+          case uint16_t(Op::F64Lt):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LT, MCompare::Compare_Double));
-          case uint16_t(Expr::F64Le):
+          case uint16_t(Op::F64Le):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LE, MCompare::Compare_Double));
-          case uint16_t(Expr::F64Gt):
+          case uint16_t(Op::F64Gt):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GT, MCompare::Compare_Double));
-          case uint16_t(Expr::F64Ge):
+          case uint16_t(Op::F64Ge):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GE, MCompare::Compare_Double));
 
           // SIMD
 #define CASE(TYPE, OP, SIGN) \
-          case uint16_t(Expr::TYPE##OP): \
+          case uint16_t(Op::TYPE##OP): \
             MOZ_CRASH("Unimplemented SIMD");
 #define I8x16CASE(OP) CASE(I8x16, OP, SimdSign::Signed)
 #define I16x8CASE(OP) CASE(I16x8, OP, SimdSign::Signed)
 #define I32x4CASE(OP) CASE(I32x4, OP, SimdSign::Signed)
 #define F32x4CASE(OP) CASE(F32x4, OP, SimdSign::NotApplicable)
 #define B8x16CASE(OP) CASE(B8x16, OP, SimdSign::NotApplicable)
 #define B16x8CASE(OP) CASE(B16x8, OP, SimdSign::NotApplicable)
 #define B32x4CASE(OP) CASE(B32x4, OP, SimdSign::NotApplicable)
 #define ENUMERATE(TYPE, FORALL, DO) \
-          case uint16_t(Expr::TYPE##Constructor): \
+          case uint16_t(Op::TYPE##Constructor): \
             FORALL(DO)
 
           ENUMERATE(I8x16, FORALL_INT8X16_ASMJS_OP, I8x16CASE)
           ENUMERATE(I16x8, FORALL_INT16X8_ASMJS_OP, I16x8CASE)
           ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32x4CASE)
           ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32x4CASE)
           ENUMERATE(B8x16, FORALL_BOOL_SIMD_OP, B8x16CASE)
           ENUMERATE(B16x8, FORALL_BOOL_SIMD_OP, B16x8CASE)
@@ -7123,59 +7123,59 @@ BaseCompiler::emitBody()
 #undef I16x8CASE
 #undef I32x4CASE
 #undef F32x4CASE
 #undef B8x16CASE
 #undef B16x8CASE
 #undef B32x4CASE
 #undef ENUMERATE
 
-          case uint16_t(Expr::I8x16Const):
-          case uint16_t(Expr::I16x8Const):
-          case uint16_t(Expr::I32x4Const):
-          case uint16_t(Expr::F32x4Const):
-          case uint16_t(Expr::B8x16Const):
-          case uint16_t(Expr::B16x8Const):
-          case uint16_t(Expr::B32x4Const):
-          case uint16_t(Expr::I32x4shiftRightByScalarU):
-          case uint16_t(Expr::I8x16addSaturateU):
-          case uint16_t(Expr::I8x16subSaturateU):
-          case uint16_t(Expr::I8x16shiftRightByScalarU):
-          case uint16_t(Expr::I8x16lessThanU):
-          case uint16_t(Expr::I8x16lessThanOrEqualU):
-          case uint16_t(Expr::I8x16greaterThanU):
-          case uint16_t(Expr::I8x16greaterThanOrEqualU):
-          case uint16_t(Expr::I8x16extractLaneU):
-          case uint16_t(Expr::I16x8addSaturateU):
-          case uint16_t(Expr::I16x8subSaturateU):
-          case uint16_t(Expr::I16x8shiftRightByScalarU):
-          case uint16_t(Expr::I16x8lessThanU):
-          case uint16_t(Expr::I16x8lessThanOrEqualU):
-          case uint16_t(Expr::I16x8greaterThanU):
-          case uint16_t(Expr::I16x8greaterThanOrEqualU):
-          case uint16_t(Expr::I16x8extractLaneU):
-          case uint16_t(Expr::I32x4lessThanU):
-          case uint16_t(Expr::I32x4lessThanOrEqualU):
-          case uint16_t(Expr::I32x4greaterThanU):
-          case uint16_t(Expr::I32x4greaterThanOrEqualU):
-          case uint16_t(Expr::I32x4fromFloat32x4U):
+          case uint16_t(Op::I8x16Const):
+          case uint16_t(Op::I16x8Const):
+          case uint16_t(Op::I32x4Const):
+          case uint16_t(Op::F32x4Const):
+          case uint16_t(Op::B8x16Const):
+          case uint16_t(Op::B16x8Const):
+          case uint16_t(Op::B32x4Const):
+          case uint16_t(Op::I32x4shiftRightByScalarU):
+          case uint16_t(Op::I8x16addSaturateU):
+          case uint16_t(Op::I8x16subSaturateU):
+          case uint16_t(Op::I8x16shiftRightByScalarU):
+          case uint16_t(Op::I8x16lessThanU):
+          case uint16_t(Op::I8x16lessThanOrEqualU):
+          case uint16_t(Op::I8x16greaterThanU):
+          case uint16_t(Op::I8x16greaterThanOrEqualU):
+          case uint16_t(Op::I8x16extractLaneU):
+          case uint16_t(Op::I16x8addSaturateU):
+          case uint16_t(Op::I16x8subSaturateU):
+          case uint16_t(Op::I16x8shiftRightByScalarU):
+          case uint16_t(Op::I16x8lessThanU):
+          case uint16_t(Op::I16x8lessThanOrEqualU):
+          case uint16_t(Op::I16x8greaterThanU):
+          case uint16_t(Op::I16x8greaterThanOrEqualU):
+          case uint16_t(Op::I16x8extractLaneU):
+          case uint16_t(Op::I32x4lessThanU):
+          case uint16_t(Op::I32x4lessThanOrEqualU):
+          case uint16_t(Op::I32x4greaterThanU):
+          case uint16_t(Op::I32x4greaterThanOrEqualU):
+          case uint16_t(Op::I32x4fromFloat32x4U):
             MOZ_CRASH("Unimplemented SIMD");
 
           // Atomics
-          case uint16_t(Expr::I32AtomicsLoad):
-          case uint16_t(Expr::I32AtomicsStore):
-          case uint16_t(Expr::I32AtomicsBinOp):
-          case uint16_t(Expr::I32AtomicsCompareExchange):
-          case uint16_t(Expr::I32AtomicsExchange):
+          case uint16_t(Op::I32AtomicsLoad):
+          case uint16_t(Op::I32AtomicsStore):
+          case uint16_t(Op::I32AtomicsBinOp):
+          case uint16_t(Op::I32AtomicsCompareExchange):
+          case uint16_t(Op::I32AtomicsExchange):
             MOZ_CRASH("Unimplemented Atomics");
 
           // Memory Related
-          case uint16_t(Expr::GrowMemory):
+          case uint16_t(Op::GrowMemory):
             CHECK_NEXT(emitGrowMemory());
-          case uint16_t(Expr::CurrentMemory):
+          case uint16_t(Op::CurrentMemory):
             CHECK_NEXT(emitCurrentMemory());
         }
 
         MOZ_CRASH("unexpected wasm opcode");
 
 #undef CHECK
 #undef NEXT
 #undef CHECK_NEXT
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -108,17 +108,17 @@ enum class GlobalFlags
     AllowedMask                          = 0x1
 };
 
 enum class MemoryTableFlags
 {
     Default                              = 0x0
 };
 
-enum class Expr
+enum class Op
 {
     // Control flow operators
     Unreachable                          = 0x00,
     Nop                                  = 0x01,
     Block                                = 0x02,
     Loop                                 = 0x03,
     If                                   = 0x04,
     Else                                 = 0x05,
--- a/js/src/wasm/WasmBinaryFormat.cpp
+++ b/js/src/wasm/WasmBinaryFormat.cpp
@@ -415,50 +415,50 @@ wasm::DecodeGlobalType(Decoder& d, ValTy
     *isMutable = flags & uint32_t(GlobalFlags::IsMutable);
     return true;
 }
 
 bool
 wasm::DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
                                   InitExpr* init)
 {
-    uint16_t expr;
-    if (!d.readExpr(&expr))
+    uint16_t op;
+    if (!d.readOp(&op))
         return d.fail("failed to read initializer type");
 
-    switch (expr) {
-      case uint16_t(Expr::I32Const): {
+    switch (op) {
+      case uint16_t(Op::I32Const): {
         int32_t i32;
         if (!d.readVarS32(&i32))
             return d.fail("failed to read initializer i32 expression");
         *init = InitExpr(Val(uint32_t(i32)));
         break;
       }
-      case uint16_t(Expr::I64Const): {
+      case uint16_t(Op::I64Const): {
         int64_t i64;
         if (!d.readVarS64(&i64))
             return d.fail("failed to read initializer i64 expression");
         *init = InitExpr(Val(uint64_t(i64)));
         break;
       }
-      case uint16_t(Expr::F32Const): {
+      case uint16_t(Op::F32Const): {
         RawF32 f32;
         if (!d.readFixedF32(&f32))
             return d.fail("failed to read initializer f32 expression");
         *init = InitExpr(Val(f32));
         break;
       }
-      case uint16_t(Expr::F64Const): {
+      case uint16_t(Op::F64Const): {
         RawF64 f64;
         if (!d.readFixedF64(&f64))
             return d.fail("failed to read initializer f64 expression");
         *init = InitExpr(Val(f64));
         break;
       }
-      case uint16_t(Expr::GetGlobal): {
+      case uint16_t(Op::GetGlobal): {
         uint32_t i;
         if (!d.readVarU32(&i))
             return d.fail("failed to read get_global index in initializer expression");
         if (i >= globals.length())
             return d.fail("global index out of range in initializer expression");
         if (!globals[i].isImport() || globals[i].isMutable())
             return d.fail("initializer expression must reference a global immutable import");
         *init = InitExpr(i, globals[i].type());
@@ -468,17 +468,17 @@ wasm::DecodeInitializerExpression(Decode
         return d.fail("unexpected initializer expression");
       }
     }
 
     if (expected != init->type())
         return d.fail("type mismatch: initializer type and expected type don't match");
 
     uint16_t end;
-    if (!d.readExpr(&end) || end != uint16_t(Expr::End))
+    if (!d.readOp(&end) || end != uint16_t(Op::End))
         return d.fail("failed to read end of initializer expression");
 
     return true;
 }
 
 bool
 wasm::DecodeLimits(Decoder& d, Limits* limits)
 {
--- a/js/src/wasm/WasmBinaryFormat.h
+++ b/js/src/wasm/WasmBinaryFormat.h
@@ -159,23 +159,23 @@ class Encoder
         MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
         return writeFixedU8(uint8_t(type));
     }
     MOZ_MUST_USE bool writeBlockType(ExprType type) {
         static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
         MOZ_ASSERT(size_t(type) < size_t(TypeCode::Limit));
         return writeFixedU8(uint8_t(type));
     }
-    MOZ_MUST_USE bool writeExpr(Expr expr) {
-        static_assert(size_t(Expr::Limit) <= 2 * UINT8_MAX, "fits");
-        MOZ_ASSERT(size_t(expr) < size_t(Expr::Limit));
-        if (size_t(expr) < UINT8_MAX)
-            return writeFixedU8(uint8_t(expr));
+    MOZ_MUST_USE bool writeOp(Op op) {
+        static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
+        MOZ_ASSERT(size_t(op) < size_t(Op::Limit));
+        if (size_t(op) < UINT8_MAX)
+            return writeFixedU8(uint8_t(op));
         return writeFixedU8(UINT8_MAX) &&
-               writeFixedU8(size_t(expr) - UINT8_MAX);
+               writeFixedU8(size_t(op) - UINT8_MAX);
     }
 
     // Fixed-length encodings that allow back-patching.
 
     MOZ_MUST_USE bool writePatchableFixedU7(size_t* offset) {
         *offset = bytes_.length();
         return writeFixedU8(UINT8_MAX);
     }
@@ -402,28 +402,28 @@ class Decoder
     MOZ_MUST_USE bool readValType(uint8_t* type) {
         static_assert(uint8_t(TypeCode::Limit) <= UINT8_MAX, "fits");
         return readFixedU8(type);
     }
     MOZ_MUST_USE bool readBlockType(uint8_t* type) {
         static_assert(size_t(TypeCode::Limit) <= UINT8_MAX, "fits");
         return readFixedU8(type);
     }
-    MOZ_MUST_USE bool readExpr(uint16_t* expr) {
-        static_assert(size_t(Expr::Limit) <= 2 * UINT8_MAX, "fits");
+    MOZ_MUST_USE bool readOp(uint16_t* op) {
+        static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
         uint8_t u8;
         if (!readFixedU8(&u8))
             return false;
         if (MOZ_LIKELY(u8 != UINT8_MAX)) {
-            *expr = u8;
+            *op = u8;
             return true;
         }
         if (!readFixedU8(&u8))
             return false;
-        *expr = uint16_t(u8) + UINT8_MAX;
+        *op = uint16_t(u8) + UINT8_MAX;
         return true;
     }
 
     // See writeBytes comment.
 
     MOZ_MUST_USE bool readBytes(uint32_t numBytes, const uint8_t** bytes = nullptr) {
         if (bytes)
             *bytes = cur_;
@@ -584,22 +584,22 @@ class Decoder
     int64_t uncheckedReadVarS64() {
         int64_t i64 = 0;
         MOZ_ALWAYS_TRUE(readVarS64(&i64));
         return i64;
     }
     ValType uncheckedReadValType() {
         return (ValType)uncheckedReadFixedU8();
     }
-    Expr uncheckedReadExpr() {
-        static_assert(size_t(Expr::Limit) <= 2 * UINT8_MAX, "fits");
+    Op uncheckedReadOp() {
+        static_assert(size_t(Op::Limit) <= 2 * UINT8_MAX, "fits");
         uint8_t u8 = uncheckedReadFixedU8();
         return u8 != UINT8_MAX
-               ? Expr(u8)
-               : Expr(uncheckedReadFixedU8() + UINT8_MAX);
+               ? Op(u8)
+               : Op(uncheckedReadFixedU8() + UINT8_MAX);
     }
     void uncheckedReadFixedI8x16(I8x16* i8x16) {
         struct T { I8x16 v; };
         T t = uncheckedRead<T>();
         memcpy(i8x16, &t, sizeof(t));
     }
     void uncheckedReadFixedI16x8(I16x8* i16x8) {
         struct T { I16x8 v; };
--- a/js/src/wasm/WasmBinaryIterator.cpp
+++ b/js/src/wasm/WasmBinaryIterator.cpp
@@ -18,481 +18,481 @@
 
 #include "wasm/WasmBinaryIterator.h"
 
 using namespace js;
 using namespace js::jit;
 using namespace js::wasm;
 
 #ifdef DEBUG
-ExprKind
-wasm::Classify(Expr expr)
+OpKind
+wasm::Classify(Op op)
 {
-    switch (expr) {
-      case Expr::Block:
-        return ExprKind::Block;
-      case Expr::Loop:
-        return ExprKind::Loop;
-      case Expr::Unreachable:
-        return ExprKind::Unreachable;
-      case Expr::Drop:
-        return ExprKind::Drop;
-      case Expr::I32Const:
-        return ExprKind::I32;
-      case Expr::I64Const:
-        return ExprKind::I64;
-      case Expr::F32Const:
-        return ExprKind::F32;
-      case Expr::F64Const:
-        return ExprKind::F64;
-      case Expr::I8x16Const:
-        return ExprKind::I8x16;
-      case Expr::I16x8Const:
-        return ExprKind::I16x8;
-      case Expr::I32x4Const:
-        return ExprKind::I32x4;
-      case Expr::B8x16Const:
-        return ExprKind::B8x16;
-      case Expr::B16x8Const:
-        return ExprKind::B16x8;
-      case Expr::B32x4Const:
-        return ExprKind::B32x4;
-      case Expr::F32x4Const:
-        return ExprKind::F32x4;
-      case Expr::Br:
-        return ExprKind::Br;
-      case Expr::BrIf:
-        return ExprKind::BrIf;
-      case Expr::BrTable:
-        return ExprKind::BrTable;
-      case Expr::Nop:
-        return ExprKind::Nop;
-      case Expr::I32Clz:
-      case Expr::I32Ctz:
-      case Expr::I32Popcnt:
-      case Expr::I64Clz:
-      case Expr::I64Ctz:
-      case Expr::I64Popcnt:
-      case Expr::F32Abs:
-      case Expr::F32Neg:
-      case Expr::F32Ceil:
-      case Expr::F32Floor:
-      case Expr::F32Trunc:
-      case Expr::F32Nearest:
-      case Expr::F32Sqrt:
-      case Expr::F64Abs:
-      case Expr::F64Neg:
-      case Expr::F64Ceil:
-      case Expr::F64Floor:
-      case Expr::F64Trunc:
-      case Expr::F64Nearest:
-      case Expr::F64Sqrt:
-      case Expr::I32BitNot:
-      case Expr::I32Abs:
-      case Expr::F64Sin:
-      case Expr::F64Cos:
-      case Expr::F64Tan:
-      case Expr::F64Asin:
-      case Expr::F64Acos:
-      case Expr::F64Atan:
-      case Expr::F64Exp:
-      case Expr::F64Log:
-      case Expr::I32Neg:
-      case Expr::I8x16neg:
-      case Expr::I8x16not:
-      case Expr::I16x8neg:
-      case Expr::I16x8not:
-      case Expr::I32x4neg:
-      case Expr::I32x4not:
-      case Expr::F32x4neg:
-      case Expr::F32x4sqrt:
-      case Expr::F32x4abs:
-      case Expr::F32x4reciprocalApproximation:
-      case Expr::F32x4reciprocalSqrtApproximation:
-      case Expr::B8x16not:
-      case Expr::B16x8not:
-      case Expr::B32x4not:
-        return ExprKind::Unary;
-      case Expr::I32Add:
-      case Expr::I32Sub:
-      case Expr::I32Mul:
-      case Expr::I32DivS:
-      case Expr::I32DivU:
-      case Expr::I32RemS:
-      case Expr::I32RemU:
-      case Expr::I32And:
-      case Expr::I32Or:
-      case Expr::I32Xor:
-      case Expr::I32Shl:
-      case Expr::I32ShrS:
-      case Expr::I32ShrU:
-      case Expr::I32Rotl:
-      case Expr::I32Rotr:
-      case Expr::I64Add:
-      case Expr::I64Sub:
-      case Expr::I64Mul:
-      case Expr::I64DivS:
-      case Expr::I64DivU:
-      case Expr::I64RemS:
-      case Expr::I64RemU:
-      case Expr::I64And:
-      case Expr::I64Or:
-      case Expr::I64Xor:
-      case Expr::I64Shl:
-      case Expr::I64ShrS:
-      case Expr::I64ShrU:
-      case Expr::I64Rotl:
-      case Expr::I64Rotr:
-      case Expr::F32Add:
-      case Expr::F32Sub:
-      case Expr::F32Mul:
-      case Expr::F32Div:
-      case Expr::F32Min:
-      case Expr::F32Max:
-      case Expr::F32CopySign:
-      case Expr::F64Add:
-      case Expr::F64Sub:
-      case Expr::F64Mul:
-      case Expr::F64Div:
-      case Expr::F64Min:
-      case Expr::F64Max:
-      case Expr::F64CopySign:
-      case Expr::I32Min:
-      case Expr::I32Max:
-      case Expr::F64Mod:
-      case Expr::F64Pow:
-      case Expr::F64Atan2:
-      case Expr::I8x16add:
-      case Expr::I8x16sub:
-      case Expr::I8x16mul:
-      case Expr::I8x16addSaturate:
-      case Expr::I8x16subSaturate:
-      case Expr::I8x16addSaturateU:
-      case Expr::I8x16subSaturateU:
-      case Expr::I8x16and:
-      case Expr::I8x16or:
-      case Expr::I8x16xor:
-      case Expr::I16x8add:
-      case Expr::I16x8sub:
-      case Expr::I16x8mul:
-      case Expr::I16x8addSaturate:
-      case Expr::I16x8subSaturate:
-      case Expr::I16x8addSaturateU:
-      case Expr::I16x8subSaturateU:
-      case Expr::I16x8and:
-      case Expr::I16x8or:
-      case Expr::I16x8xor:
-      case Expr::I32x4add:
-      case Expr::I32x4sub:
-      case Expr::I32x4mul:
-      case Expr::I32x4and:
-      case Expr::I32x4or:
-      case Expr::I32x4xor:
-      case Expr::F32x4add:
-      case Expr::F32x4sub:
-      case Expr::F32x4mul:
-      case Expr::F32x4div:
-      case Expr::F32x4min:
-      case Expr::F32x4max:
-      case Expr::F32x4minNum:
-      case Expr::F32x4maxNum:
-      case Expr::B8x16and:
-      case Expr::B8x16or:
-      case Expr::B8x16xor:
-      case Expr::B16x8and:
-      case Expr::B16x8or:
-      case Expr::B16x8xor:
-      case Expr::B32x4and:
-      case Expr::B32x4or:
-      case Expr::B32x4xor:
-        return ExprKind::Binary;
-      case Expr::I32Eq:
-      case Expr::I32Ne:
-      case Expr::I32LtS:
-      case Expr::I32LtU:
-      case Expr::I32LeS:
-      case Expr::I32LeU:
-      case Expr::I32GtS:
-      case Expr::I32GtU:
-      case Expr::I32GeS:
-      case Expr::I32GeU:
-      case Expr::I64Eq:
-      case Expr::I64Ne:
-      case Expr::I64LtS:
-      case Expr::I64LtU:
-      case Expr::I64LeS:
-      case Expr::I64LeU:
-      case Expr::I64GtS:
-      case Expr::I64GtU:
-      case Expr::I64GeS:
-      case Expr::I64GeU:
-      case Expr::F32Eq:
-      case Expr::F32Ne:
-      case Expr::F32Lt:
-      case Expr::F32Le:
-      case Expr::F32Gt:
-      case Expr::F32Ge:
-      case Expr::F64Eq:
-      case Expr::F64Ne:
-      case Expr::F64Lt:
-      case Expr::F64Le:
-      case Expr::F64Gt:
-      case Expr::F64Ge:
-        return ExprKind::Comparison;
-      case Expr::I32Eqz:
-      case Expr::I32WrapI64:
-      case Expr::I32TruncSF32:
-      case Expr::I32TruncUF32:
-      case Expr::I32ReinterpretF32:
-      case Expr::I32TruncSF64:
-      case Expr::I32TruncUF64:
-      case Expr::I64ExtendSI32:
-      case Expr::I64ExtendUI32:
-      case Expr::I64TruncSF32:
-      case Expr::I64TruncUF32:
-      case Expr::I64TruncSF64:
-      case Expr::I64TruncUF64:
-      case Expr::I64ReinterpretF64:
-      case Expr::I64Eqz:
-      case Expr::F32ConvertSI32:
-      case Expr::F32ConvertUI32:
-      case Expr::F32ReinterpretI32:
-      case Expr::F32ConvertSI64:
-      case Expr::F32ConvertUI64:
-      case Expr::F32DemoteF64:
-      case Expr::F64ConvertSI32:
-      case Expr::F64ConvertUI32:
-      case Expr::F64ConvertSI64:
-      case Expr::F64ConvertUI64:
-      case Expr::F64ReinterpretI64:
-      case Expr::F64PromoteF32:
-      case Expr::I32x4fromFloat32x4:
-      case Expr::I32x4fromFloat32x4U:
-      case Expr::F32x4fromInt32x4:
-      case Expr::F32x4fromUint32x4:
-      case Expr::I32x4fromFloat32x4Bits:
-      case Expr::I32x4fromInt8x16Bits:
-      case Expr::I32x4fromInt16x8Bits:
-      case Expr::I16x8fromInt8x16Bits:
-      case Expr::I16x8fromInt32x4Bits:
-      case Expr::I16x8fromFloat32x4Bits:
-      case Expr::I8x16fromInt16x8Bits:
-      case Expr::I8x16fromInt32x4Bits:
-      case Expr::I8x16fromFloat32x4Bits:
-      case Expr::F32x4fromInt8x16Bits:
-      case Expr::F32x4fromInt16x8Bits:
-      case Expr::F32x4fromInt32x4Bits:
-        return ExprKind::Conversion;
-      case Expr::I32Load8S:
-      case Expr::I32Load8U:
-      case Expr::I32Load16S:
-      case Expr::I32Load16U:
-      case Expr::I64Load8S:
-      case Expr::I64Load8U:
-      case Expr::I64Load16S:
-      case Expr::I64Load16U:
-      case Expr::I64Load32S:
-      case Expr::I64Load32U:
-      case Expr::I32Load:
-      case Expr::I64Load:
-      case Expr::F32Load:
-      case Expr::F64Load:
-      case Expr::I8x16load:
-      case Expr::I16x8load:
-      case Expr::I32x4load:
-      case Expr::I32x4load1:
-      case Expr::I32x4load2:
-      case Expr::I32x4load3:
-      case Expr::F32x4load:
-      case Expr::F32x4load1:
-      case Expr::F32x4load2:
-      case Expr::F32x4load3:
-        return ExprKind::Load;
-      case Expr::I32Store8:
-      case Expr::I32Store16:
-      case Expr::I64Store8:
-      case Expr::I64Store16:
-      case Expr::I64Store32:
-      case Expr::I32Store:
-      case Expr::I64Store:
-      case Expr::F32Store:
-      case Expr::F64Store:
-        return ExprKind::Store;
-      case Expr::I32TeeStore8:
-      case Expr::I32TeeStore16:
-      case Expr::I64TeeStore8:
-      case Expr::I64TeeStore16:
-      case Expr::I64TeeStore32:
-      case Expr::I32TeeStore:
-      case Expr::I64TeeStore:
-      case Expr::F32TeeStore:
-      case Expr::F64TeeStore:
-      case Expr::F32TeeStoreF64:
-      case Expr::F64TeeStoreF32:
-      case Expr::I8x16store:
-      case Expr::I16x8store:
-      case Expr::I32x4store:
-      case Expr::I32x4store1:
-      case Expr::I32x4store2:
-      case Expr::I32x4store3:
-      case Expr::F32x4store:
-      case Expr::F32x4store1:
-      case Expr::F32x4store2:
-      case Expr::F32x4store3:
-        return ExprKind::TeeStore;
-      case Expr::Select:
-        return ExprKind::Select;
-      case Expr::GetLocal:
-        return ExprKind::GetLocal;
-      case Expr::SetLocal:
-        return ExprKind::SetLocal;
-      case Expr::TeeLocal:
-        return ExprKind::TeeLocal;
-      case Expr::GetGlobal:
-        return ExprKind::GetGlobal;
-      case Expr::SetGlobal:
-        return ExprKind::SetGlobal;
-      case Expr::TeeGlobal:
-        return ExprKind::TeeGlobal;
-      case Expr::Call:
-        return ExprKind::Call;
-      case Expr::CallIndirect:
-        return ExprKind::CallIndirect;
-      case Expr::OldCallIndirect:
-        return ExprKind::OldCallIndirect;
-      case Expr::Return:
-      case Expr::Limit:
+    switch (op) {
+      case Op::Block:
+        return OpKind::Block;
+      case Op::Loop:
+        return OpKind::Loop;
+      case Op::Unreachable:
+        return OpKind::Unreachable;
+      case Op::Drop:
+        return OpKind::Drop;
+      case Op::I32Const:
+        return OpKind::I32;
+      case Op::I64Const:
+        return OpKind::I64;
+      case Op::F32Const:
+        return OpKind::F32;
+      case Op::F64Const:
+        return OpKind::F64;
+      case Op::I8x16Const:
+        return OpKind::I8x16;
+      case Op::I16x8Const:
+        return OpKind::I16x8;
+      case Op::I32x4Const:
+        return OpKind::I32x4;
+      case Op::B8x16Const:
+        return OpKind::B8x16;
+      case Op::B16x8Const:
+        return OpKind::B16x8;
+      case Op::B32x4Const:
+        return OpKind::B32x4;
+      case Op::F32x4Const:
+        return OpKind::F32x4;
+      case Op::Br:
+        return OpKind::Br;
+      case Op::BrIf:
+        return OpKind::BrIf;
+      case Op::BrTable:
+        return OpKind::BrTable;
+      case Op::Nop:
+        return OpKind::Nop;
+      case Op::I32Clz:
+      case Op::I32Ctz:
+      case Op::I32Popcnt:
+      case Op::I64Clz:
+      case Op::I64Ctz:
+      case Op::I64Popcnt:
+      case Op::F32Abs:
+      case Op::F32Neg:
+      case Op::F32Ceil:
+      case Op::F32Floor:
+      case Op::F32Trunc:
+      case Op::F32Nearest:
+      case Op::F32Sqrt:
+      case Op::F64Abs:
+      case Op::F64Neg:
+      case Op::F64Ceil:
+      case Op::F64Floor:
+      case Op::F64Trunc:
+      case Op::F64Nearest:
+      case Op::F64Sqrt:
+      case Op::I32BitNot:
+      case Op::I32Abs:
+      case Op::F64Sin:
+      case Op::F64Cos:
+      case Op::F64Tan:
+      case Op::F64Asin:
+      case Op::F64Acos:
+      case Op::F64Atan:
+      case Op::F64Exp:
+      case Op::F64Log:
+      case Op::I32Neg:
+      case Op::I8x16neg:
+      case Op::I8x16not:
+      case Op::I16x8neg:
+      case Op::I16x8not:
+      case Op::I32x4neg:
+      case Op::I32x4not:
+      case Op::F32x4neg:
+      case Op::F32x4sqrt:
+      case Op::F32x4abs:
+      case Op::F32x4reciprocalApproximation:
+      case Op::F32x4reciprocalSqrtApproximation:
+      case Op::B8x16not:
+      case Op::B16x8not:
+      case Op::B32x4not:
+        return OpKind::Unary;
+      case Op::I32Add:
+      case Op::I32Sub:
+      case Op::I32Mul:
+      case Op::I32DivS:
+      case Op::I32DivU:
+      case Op::I32RemS:
+      case Op::I32RemU:
+      case Op::I32And:
+      case Op::I32Or:
+      case Op::I32Xor:
+      case Op::I32Shl:
+      case Op::I32ShrS:
+      case Op::I32ShrU:
+      case Op::I32Rotl:
+      case Op::I32Rotr:
+      case Op::I64Add:
+      case Op::I64Sub:
+      case Op::I64Mul:
+      case Op::I64DivS:
+      case Op::I64DivU:
+      case Op::I64RemS:
+      case Op::I64RemU:
+      case Op::I64And:
+      case Op::I64Or:
+      case Op::I64Xor:
+      case Op::I64Shl:
+      case Op::I64ShrS:
+      case Op::I64ShrU:
+      case Op::I64Rotl:
+      case Op::I64Rotr:
+      case Op::F32Add:
+      case Op::F32Sub:
+      case Op::F32Mul:
+      case Op::F32Div:
+      case Op::F32Min:
+      case Op::F32Max:
+      case Op::F32CopySign:
+      case Op::F64Add:
+      case Op::F64Sub:
+      case Op::F64Mul:
+      case Op::F64Div:
+      case Op::F64Min:
+      case Op::F64Max:
+      case Op::F64CopySign:
+      case Op::I32Min:
+      case Op::I32Max:
+      case Op::F64Mod:
+      case Op::F64Pow:
+      case Op::F64Atan2:
+      case Op::I8x16add:
+      case Op::I8x16sub:
+      case Op::I8x16mul:
+      case Op::I8x16addSaturate:
+      case Op::I8x16subSaturate:
+      case Op::I8x16addSaturateU:
+      case Op::I8x16subSaturateU:
+      case Op::I8x16and:
+      case Op::I8x16or:
+      case Op::I8x16xor:
+      case Op::I16x8add:
+      case Op::I16x8sub:
+      case Op::I16x8mul:
+      case Op::I16x8addSaturate:
+      case Op::I16x8subSaturate:
+      case Op::I16x8addSaturateU:
+      case Op::I16x8subSaturateU:
+      case Op::I16x8and:
+      case Op::I16x8or:
+      case Op::I16x8xor:
+      case Op::I32x4add:
+      case Op::I32x4sub:
+      case Op::I32x4mul:
+      case Op::I32x4and:
+      case Op::I32x4or:
+      case Op::I32x4xor:
+      case Op::F32x4add:
+      case Op::F32x4sub:
+      case Op::F32x4mul:
+      case Op::F32x4div:
+      case Op::F32x4min:
+      case Op::F32x4max:
+      case Op::F32x4minNum:
+      case Op::F32x4maxNum:
+      case Op::B8x16and:
+      case Op::B8x16or:
+      case Op::B8x16xor:
+      case Op::B16x8and:
+      case Op::B16x8or:
+      case Op::B16x8xor:
+      case Op::B32x4and:
+      case Op::B32x4or:
+      case Op::B32x4xor:
+        return OpKind::Binary;
+      case Op::I32Eq:
+      case Op::I32Ne:
+      case Op::I32LtS:
+      case Op::I32LtU:
+      case Op::I32LeS:
+      case Op::I32LeU:
+      case Op::I32GtS:
+      case Op::I32GtU:
+      case Op::I32GeS:
+      case Op::I32GeU:
+      case Op::I64Eq:
+      case Op::I64Ne:
+      case Op::I64LtS:
+      case Op::I64LtU:
+      case Op::I64LeS:
+      case Op::I64LeU:
+      case Op::I64GtS:
+      case Op::I64GtU:
+      case Op::I64GeS:
+      case Op::I64GeU:
+      case Op::F32Eq:
+      case Op::F32Ne:
+      case Op::F32Lt:
+      case Op::F32Le:
+      case Op::F32Gt:
+      case Op::F32Ge:
+      case Op::F64Eq:
+      case Op::F64Ne:
+      case Op::F64Lt:
+      case Op::F64Le:
+      case Op::F64Gt:
+      case Op::F64Ge:
+        return OpKind::Comparison;
+      case Op::I32Eqz:
+      case Op::I32WrapI64:
+      case Op::I32TruncSF32:
+      case Op::I32TruncUF32:
+      case Op::I32ReinterpretF32:
+      case Op::I32TruncSF64:
+      case Op::I32TruncUF64:
+      case Op::I64ExtendSI32:
+      case Op::I64ExtendUI32:
+      case Op::I64TruncSF32:
+      case Op::I64TruncUF32:
+      case Op::I64TruncSF64:
+      case Op::I64TruncUF64:
+      case Op::I64ReinterpretF64:
+      case Op::I64Eqz:
+      case Op::F32ConvertSI32:
+      case Op::F32ConvertUI32:
+      case Op::F32ReinterpretI32:
+      case Op::F32ConvertSI64:
+      case Op::F32ConvertUI64:
+      case Op::F32DemoteF64:
+      case Op::F64ConvertSI32:
+      case Op::F64ConvertUI32:
+      case Op::F64ConvertSI64:
+      case Op::F64ConvertUI64:
+      case Op::F64ReinterpretI64:
+      case Op::F64PromoteF32:
+      case Op::I32x4fromFloat32x4:
+      case Op::I32x4fromFloat32x4U:
+      case Op::F32x4fromInt32x4:
+      case Op::F32x4fromUint32x4:
+      case Op::I32x4fromFloat32x4Bits:
+      case Op::I32x4fromInt8x16Bits:
+      case Op::I32x4fromInt16x8Bits:
+      case Op::I16x8fromInt8x16Bits:
+      case Op::I16x8fromInt32x4Bits:
+      case Op::I16x8fromFloat32x4Bits:
+      case Op::I8x16fromInt16x8Bits:
+      case Op::I8x16fromInt32x4Bits:
+      case Op::I8x16fromFloat32x4Bits:
+      case Op::F32x4fromInt8x16Bits:
+      case Op::F32x4fromInt16x8Bits:
+      case Op::F32x4fromInt32x4Bits:
+        return OpKind::Conversion;
+      case Op::I32Load8S:
+      case Op::I32Load8U:
+      case Op::I32Load16S:
+      case Op::I32Load16U:
+      case Op::I64Load8S:
+      case Op::I64Load8U:
+      case Op::I64Load16S:
+      case Op::I64Load16U:
+      case Op::I64Load32S:
+      case Op::I64Load32U:
+      case Op::I32Load:
+      case Op::I64Load:
+      case Op::F32Load:
+      case Op::F64Load:
+      case Op::I8x16load:
+      case Op::I16x8load:
+      case Op::I32x4load:
+      case Op::I32x4load1:
+      case Op::I32x4load2:
+      case Op::I32x4load3:
+      case Op::F32x4load:
+      case Op::F32x4load1:
+      case Op::F32x4load2:
+      case Op::F32x4load3:
+        return OpKind::Load;
+      case Op::I32Store8:
+      case Op::I32Store16:
+      case Op::I64Store8:
+      case Op::I64Store16:
+      case Op::I64Store32:
+      case Op::I32Store:
+      case Op::I64Store:
+      case Op::F32Store:
+      case Op::F64Store:
+        return OpKind::Store;
+      case Op::I32TeeStore8:
+      case Op::I32TeeStore16:
+      case Op::I64TeeStore8:
+      case Op::I64TeeStore16:
+      case Op::I64TeeStore32:
+      case Op::I32TeeStore:
+      case Op::I64TeeStore:
+      case Op::F32TeeStore:
+      case Op::F64TeeStore:
+      case Op::F32TeeStoreF64:
+      case Op::F64TeeStoreF32:
+      case Op::I8x16store:
+      case Op::I16x8store:
+      case Op::I32x4store:
+      case Op::I32x4store1:
+      case Op::I32x4store2:
+      case Op::I32x4store3:
+      case Op::F32x4store:
+      case Op::F32x4store1:
+      case Op::F32x4store2:
+      case Op::F32x4store3:
+        return OpKind::TeeStore;
+      case Op::Select:
+        return OpKind::Select;
+      case Op::GetLocal:
+        return OpKind::GetLocal;
+      case Op::SetLocal:
+        return OpKind::SetLocal;
+      case Op::TeeLocal:
+        return OpKind::TeeLocal;
+      case Op::GetGlobal:
+        return OpKind::GetGlobal;
+      case Op::SetGlobal:
+        return OpKind::SetGlobal;
+      case Op::TeeGlobal:
+        return OpKind::TeeGlobal;
+      case Op::Call:
+        return OpKind::Call;
+      case Op::CallIndirect:
+        return OpKind::CallIndirect;
+      case Op::OldCallIndirect:
+        return OpKind::OldCallIndirect;
+      case Op::Return:
+      case Op::Limit:
         // Accept Limit, for use in decoding the end of a function after the body.
-        return ExprKind::Return;
-      case Expr::If:
-        return ExprKind::If;
-      case Expr::Else:
-        return ExprKind::Else;
-      case Expr::End:
-        return ExprKind::End;
-      case Expr::I32AtomicsLoad:
-        return ExprKind::AtomicLoad;
-      case Expr::I32AtomicsStore:
-        return ExprKind::AtomicStore;
-      case Expr::I32AtomicsBinOp:
-        return ExprKind::AtomicBinOp;
-      case Expr::I32AtomicsCompareExchange:
-        return ExprKind::AtomicCompareExchange;
-      case Expr::I32AtomicsExchange:
-        return ExprKind::AtomicExchange;
-      case Expr::I8x16extractLane:
-      case Expr::I8x16extractLaneU:
-      case Expr::I16x8extractLane:
-      case Expr::I16x8extractLaneU:
-      case Expr::I32x4extractLane:
-      case Expr::F32x4extractLane:
-      case Expr::B8x16extractLane:
-      case Expr::B16x8extractLane:
-      case Expr::B32x4extractLane:
-        return ExprKind::ExtractLane;
-      case Expr::I8x16replaceLane:
-      case Expr::I16x8replaceLane:
-      case Expr::I32x4replaceLane:
-      case Expr::F32x4replaceLane:
-      case Expr::B8x16replaceLane:
-      case Expr::B16x8replaceLane:
-      case Expr::B32x4replaceLane:
-        return ExprKind::ReplaceLane;
-      case Expr::I8x16swizzle:
-      case Expr::I16x8swizzle:
-      case Expr::I32x4swizzle:
-      case Expr::F32x4swizzle:
-        return ExprKind::Swizzle;
-      case Expr::I8x16shuffle:
-      case Expr::I16x8shuffle:
-      case Expr::I32x4shuffle:
-      case Expr::F32x4shuffle:
-        return ExprKind::Shuffle;
-      case Expr::I16x8check:
-      case Expr::I16x8splat:
-      case Expr::I32x4check:
-      case Expr::I32x4splat:
-      case Expr::I8x16check:
-      case Expr::I8x16splat:
-      case Expr::F32x4check:
-      case Expr::F32x4splat:
-      case Expr::B16x8check:
-      case Expr::B16x8splat:
-      case Expr::B32x4check:
-      case Expr::B32x4splat:
-      case Expr::B8x16check:
-      case Expr::B8x16splat:
-        return ExprKind::Splat;
-      case Expr::I8x16select:
-      case Expr::I16x8select:
-      case Expr::I32x4select:
-      case Expr::F32x4select:
-        return ExprKind::SimdSelect;
-      case Expr::I8x16Constructor:
-      case Expr::I16x8Constructor:
-      case Expr::I32x4Constructor:
-      case Expr::F32x4Constructor:
-      case Expr::B8x16Constructor:
-      case Expr::B16x8Constructor:
-      case Expr::B32x4Constructor:
-        return ExprKind::SimdCtor;
-      case Expr::B8x16allTrue:
-      case Expr::B8x16anyTrue:
-      case Expr::B16x8allTrue:
-      case Expr::B16x8anyTrue:
-      case Expr::B32x4allTrue:
-      case Expr::B32x4anyTrue:
-        return ExprKind::SimdBooleanReduction;
-      case Expr::I8x16shiftLeftByScalar:
-      case Expr::I8x16shiftRightByScalar:
-      case Expr::I8x16shiftRightByScalarU:
-      case Expr::I16x8shiftLeftByScalar:
-      case Expr::I16x8shiftRightByScalar:
-      case Expr::I16x8shiftRightByScalarU:
-      case Expr::I32x4shiftLeftByScalar:
-      case Expr::I32x4shiftRightByScalar:
-      case Expr::I32x4shiftRightByScalarU:
-        return ExprKind::SimdShiftByScalar;
-      case Expr::I8x16equal:
-      case Expr::I8x16notEqual:
-      case Expr::I8x16greaterThan:
-      case Expr::I8x16greaterThanOrEqual:
-      case Expr::I8x16lessThan:
-      case Expr::I8x16lessThanOrEqual:
-      case Expr::I8x16greaterThanU:
-      case Expr::I8x16greaterThanOrEqualU:
-      case Expr::I8x16lessThanU:
-      case Expr::I8x16lessThanOrEqualU:
-      case Expr::I16x8equal:
-      case Expr::I16x8notEqual:
-      case Expr::I16x8greaterThan:
-      case Expr::I16x8greaterThanOrEqual:
-      case Expr::I16x8lessThan:
-      case Expr::I16x8lessThanOrEqual:
-      case Expr::I16x8greaterThanU:
-      case Expr::I16x8greaterThanOrEqualU:
-      case Expr::I16x8lessThanU:
-      case Expr::I16x8lessThanOrEqualU:
-      case Expr::I32x4equal:
-      case Expr::I32x4notEqual:
-      case Expr::I32x4greaterThan:
-      case Expr::I32x4greaterThanOrEqual:
-      case Expr::I32x4lessThan:
-      case Expr::I32x4lessThanOrEqual:
-      case Expr::I32x4greaterThanU:
-      case Expr::I32x4greaterThanOrEqualU:
-      case Expr::I32x4lessThanU:
-      case Expr::I32x4lessThanOrEqualU:
-      case Expr::F32x4equal:
-      case Expr::F32x4notEqual:
-      case Expr::F32x4greaterThan:
-      case Expr::F32x4greaterThanOrEqual:
-      case Expr::F32x4lessThan:
-      case Expr::F32x4lessThanOrEqual:
-        return ExprKind::SimdComparison;
-      case Expr::CurrentMemory:
-        return ExprKind::CurrentMemory;
-      case Expr::GrowMemory:
-        return ExprKind::GrowMemory;
+        return OpKind::Return;
+      case Op::If:
+        return OpKind::If;
+      case Op::Else:
+        return OpKind::Else;
+      case Op::End:
+        return OpKind::End;
+      case Op::I32AtomicsLoad:
+        return OpKind::AtomicLoad;
+      case Op::I32AtomicsStore:
+        return OpKind::AtomicStore;
+      case Op::I32AtomicsBinOp:
+        return OpKind::AtomicBinOp;
+      case Op::I32AtomicsCompareExchange:
+        return OpKind::AtomicCompareExchange;
+      case Op::I32AtomicsExchange:
+        return OpKind::AtomicExchange;
+      case Op::I8x16extractLane:
+      case Op::I8x16extractLaneU:
+      case Op::I16x8extractLane:
+      case Op::I16x8extractLaneU:
+      case Op::I32x4extractLane:
+      case Op::F32x4extractLane:
+      case Op::B8x16extractLane:
+      case Op::B16x8extractLane:
+      case Op::B32x4extractLane:
+        return OpKind::ExtractLane;
+      case Op::I8x16replaceLane:
+      case Op::I16x8replaceLane:
+      case Op::I32x4replaceLane:
+      case Op::F32x4replaceLane:
+      case Op::B8x16replaceLane:
+      case Op::B16x8replaceLane:
+      case Op::B32x4replaceLane:
+        return OpKind::ReplaceLane;
+      case Op::I8x16swizzle:
+      case Op::I16x8swizzle:
+      case Op::I32x4swizzle:
+      case Op::F32x4swizzle:
+        return OpKind::Swizzle;
+      case Op::I8x16shuffle:
+      case Op::I16x8shuffle:
+      case Op::I32x4shuffle:
+      case Op::F32x4shuffle:
+        return OpKind::Shuffle;
+      case Op::I16x8check:
+      case Op::I16x8splat:
+      case Op::I32x4check:
+      case Op::I32x4splat:
+      case Op::I8x16check:
+      case Op::I8x16splat:
+      case Op::F32x4check:
+      case Op::F32x4splat:
+      case Op::B16x8check:
+      case Op::B16x8splat:
+      case Op::B32x4check:
+      case Op::B32x4splat:
+      case Op::B8x16check:
+      case Op::B8x16splat:
+        return OpKind::Splat;
+      case Op::I8x16select:
+      case Op::I16x8select:
+      case Op::I32x4select:
+      case Op::F32x4select:
+        return OpKind::SimdSelect;
+      case Op::I8x16Constructor:
+      case Op::I16x8Constructor:
+      case Op::I32x4Constructor:
+      case Op::F32x4Constructor:
+      case Op::B8x16Constructor:
+      case Op::B16x8Constructor:
+      case Op::B32x4Constructor:
+        return OpKind::SimdCtor;
+      case Op::B8x16allTrue:
+      case Op::B8x16anyTrue:
+      case Op::B16x8allTrue:
+      case Op::B16x8anyTrue:
+      case Op::B32x4allTrue:
+      case Op::B32x4anyTrue:
+        return OpKind::SimdBooleanReduction;
+      case Op::I8x16shiftLeftByScalar:
+      case Op::I8x16shiftRightByScalar:
+      case Op::I8x16shiftRightByScalarU:
+      case Op::I16x8shiftLeftByScalar:
+      case Op::I16x8shiftRightByScalar:
+      case Op::I16x8shiftRightByScalarU:
+      case Op::I32x4shiftLeftByScalar:
+      case Op::I32x4shiftRightByScalar:
+      case Op::I32x4shiftRightByScalarU:
+        return OpKind::SimdShiftByScalar;
+      case Op::I8x16equal:
+      case Op::I8x16notEqual:
+      case Op::I8x16greaterThan:
+      case Op::I8x16greaterThanOrEqual:
+      case Op::I8x16lessThan:
+      case Op::I8x16lessThanOrEqual:
+      case Op::I8x16greaterThanU:
+      case Op::I8x16greaterThanOrEqualU:
+      case Op::I8x16lessThanU:
+      case Op::I8x16lessThanOrEqualU:
+      case Op::I16x8equal:
+      case Op::I16x8notEqual:
+      case Op::I16x8greaterThan:
+      case Op::I16x8greaterThanOrEqual:
+      case Op::I16x8lessThan:
+      case Op::I16x8lessThanOrEqual:
+      case Op::I16x8greaterThanU:
+      case Op::I16x8greaterThanOrEqualU:
+      case Op::I16x8lessThanU:
+      case Op::I16x8lessThanOrEqualU:
+      case Op::I32x4equal:
+      case Op::I32x4notEqual:
+      case Op::I32x4greaterThan:
+      case Op::I32x4greaterThanOrEqual:
+      case Op::I32x4lessThan:
+      case Op::I32x4lessThanOrEqual:
+      case Op::I32x4greaterThanU:
+      case Op::I32x4greaterThanOrEqualU:
+      case Op::I32x4lessThanU:
+      case Op::I32x4lessThanOrEqualU:
+      case Op::F32x4equal:
+      case Op::F32x4notEqual:
+      case Op::F32x4greaterThan:
+      case Op::F32x4greaterThanOrEqual:
+      case Op::F32x4lessThan:
+      case Op::F32x4lessThanOrEqual:
+        return OpKind::SimdComparison;
+      case Op::CurrentMemory:
+        return OpKind::CurrentMemory;
+      case Op::GrowMemory:
+        return OpKind::GrowMemory;
     }
     MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("unimplemented opcode");
 }
 #endif
--- a/js/src/wasm/WasmBinaryIterator.h
+++ b/js/src/wasm/WasmBinaryIterator.h
@@ -35,17 +35,17 @@ enum class LabelKind : uint8_t {
     Loop,
     Then,
     UnreachableThen, // like Then, but not reachable
     Else
 };
 
 #ifdef DEBUG
 // Families of opcodes that share a signature and validation logic.
-enum class ExprKind {
+enum class OpKind {
     Block,
     Loop,
     Unreachable,
     Drop,
     I32,
     I64,
     F32,
     F64,
@@ -96,20 +96,20 @@ enum class ExprKind {
     Splat,
     SimdSelect,
     SimdCtor,
     SimdBooleanReduction,
     SimdShiftByScalar,
     SimdComparison,
 };
 
-// Return the ExprKind for a given Expr. This is used for sanity-checking that
-// API users use the correct read function for a given Expr.
-ExprKind
-Classify(Expr expr);
+// Return the OpKind for a given Op. This is used for sanity-checking that
+// API users use the correct read function for a given Op.
+OpKind
+Classify(Op op);
 #endif
 
 // Common fields for linear memory access.
 template <typename Value>
 struct LinearMemoryAddress
 {
     Value base;
     uint32_t offset;
@@ -225,19 +225,19 @@ class TypeAndValue<Nothing>
       : type_(type)
     {}
 
     ValType type() const { return type_; }
     Nothing value() const { return Nothing(); }
     void setValue(Nothing value) {}
 };
 
-// A policy class for configuring ExprIter. Clients can use this as a
+// A policy class for configuring OpIter. Clients can use this as a
 // base class, and override the behavior as needed.
-struct ExprIterPolicy
+struct OpIterPolicy
 {
     // Should the iterator perform validation, such as type checking and
     // validity checking?
     static const bool Validate = false;
 
     // Should the iterator produce output values?
     static const bool Output = false;
 
@@ -250,31 +250,31 @@ struct ExprIterPolicy
 
 // An iterator over the bytes of a function body. It performs validation
 // (if Policy::Validate is true) and unpacks the data into a usable form.
 //
 // The MOZ_STACK_CLASS attribute here is because of the use of DebugOnly.
 // There's otherwise nothing inherent in this class which would require
 // it to be used on the stack.
 template <typename Policy>
-class MOZ_STACK_CLASS ExprIter : private Policy
+class MOZ_STACK_CLASS OpIter : private Policy
 {
     static const bool Validate = Policy::Validate;
     static const bool Output = Policy::Output;
     typedef typename Policy::Value Value;
     typedef typename Policy::ControlItem ControlItem;
 
     Decoder& d_;
     const size_t offsetInModule_;
 
     Vector<TypeAndValue<Value>, 0, SystemAllocPolicy> valueStack_;
     Vector<ControlStackEntry<ControlItem>, 0, SystemAllocPolicy> controlStack_;
     bool reachable_;
 
-    DebugOnly<Expr> expr_;
+    DebugOnly<Op> op_;
     size_t offsetOfExpr_;
 
     MOZ_MUST_USE bool readFixedU8(uint8_t* out) {
         if (Validate)
             return d_.readFixedU8(out);
         *out = d_.uncheckedReadFixedU8();
         return true;
     }
@@ -498,25 +498,25 @@ class MOZ_STACK_CLASS ExprIter : private
         valueStack_.shrinkTo(controlStack_.back().valueStackStart());
         reachable_ = false;
     }
 
     bool checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value);
     bool checkBrIfValues(uint32_t relativeDepth, Value* condition, ExprType* type, Value* value);
 
   public:
-    explicit ExprIter(Decoder& decoder, uint32_t offsetInModule = 0)
+    explicit OpIter(Decoder& decoder, uint32_t offsetInModule = 0)
       : d_(decoder), offsetInModule_(offsetInModule), reachable_(true),
-        expr_(Expr::Limit), offsetOfExpr_(0)
+        op_(Op::Limit), offsetOfExpr_(0)
     {}
 
     // Return the decoding byte offset.
     uint32_t currentOffset() const { return d_.currentOffset(); }
 
-    // Returning the offset within the entire module of the last-read Expr.
+    // Returning the offset within the entire module of the last-read Op.
     TrapOffset trapOffset() const {
         return TrapOffset(offsetInModule_ + offsetOfExpr_);
     }
 
     // Test whether the iterator has reached the end of the buffer.
     bool done() const { return d_.done(); }
 
     // Report a general failure.
@@ -529,17 +529,17 @@ class MOZ_STACK_CLASS ExprIter : private
     MOZ_MUST_USE bool unrecognizedOpcode(uint32_t expr) MOZ_COLD;
 
     // Test whether the iterator is currently in "reachable" code.
     bool inReachableCode() const { return reachable_; }
 
     // ------------------------------------------------------------------------
     // Decoding and validation interface.
 
-    MOZ_MUST_USE bool readExpr(uint16_t* expr);
+    MOZ_MUST_USE bool readOp(uint16_t* op);
     MOZ_MUST_USE bool readFunctionStart(ExprType ret);
     MOZ_MUST_USE bool readFunctionEnd();
     MOZ_MUST_USE bool readReturn(Value* value);
     MOZ_MUST_USE bool readBlock();
     MOZ_MUST_USE bool readLoop();
     MOZ_MUST_USE bool readIf(Value* condition);
     MOZ_MUST_USE bool readElse(ExprType* thenType, Value* thenValue);
     MOZ_MUST_USE bool readEnd(LabelKind* kind, ExprType* type, Value* value);
@@ -658,92 +658,92 @@ class MOZ_STACK_CLASS ExprIter : private
     // end of the function body.
     bool controlStackEmpty() const {
         return controlStack_.empty();
     }
 };
 
 template <typename Policy>
 bool
-ExprIter<Policy>::typeMismatch(ExprType actual, ExprType expected)
+OpIter<Policy>::typeMismatch(ExprType actual, ExprType expected)
 {
     MOZ_ASSERT(Validate);
     MOZ_ASSERT(reachable_);
 
     UniqueChars error(JS_smprintf("type mismatch: expression has type %s but expected %s",
                                   ToCString(actual), ToCString(expected)));
     if (!error)
         return false;
 
     return fail(error.get());
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::checkType(ValType actual, ValType expected)
+OpIter<Policy>::checkType(ValType actual, ValType expected)
 {
     return checkType(ToExprType(actual), ToExprType(expected));
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::checkType(ExprType actual, ExprType expected)
+OpIter<Policy>::checkType(ExprType actual, ExprType expected)
 {
     MOZ_ASSERT(reachable_);
 
     if (!Validate) {
         MOZ_ASSERT(actual == expected, "type mismatch");
         return true;
     }
 
     if (MOZ_LIKELY(actual == expected))
         return true;
 
     return typeMismatch(actual, expected);
 }
 
 template <typename Policy>
 bool
-ExprIter<Policy>::notYetImplemented(const char* what)
+OpIter<Policy>::notYetImplemented(const char* what)
 {
     UniqueChars error(JS_smprintf("not yet implemented: %s", what));
     if (!error)
         return false;
 
     return fail(error.get());
 }
 
 template <typename Policy>
 bool
-ExprIter<Policy>::unrecognizedOpcode(uint32_t expr)
+OpIter<Policy>::unrecognizedOpcode(uint32_t expr)
 {
     UniqueChars error(JS_smprintf("unrecognized opcode: %x", expr));
     if (!error)
         return false;
 
     return fail(error.get());
 }
 
 template <typename Policy>
 bool
-ExprIter<Policy>::fail(const char* msg)
+OpIter<Policy>::fail(const char* msg)
 {
     return d_.fail("%s", msg);
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::pushControl(LabelKind kind, ExprType type, bool reachable)
+OpIter<Policy>::pushControl(LabelKind kind, ExprType type, bool reachable)
 {
     return controlStack_.emplaceBack(kind, type, reachable, valueStack_.length());
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::mergeControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::mergeControl(LabelKind* kind, ExprType* type, Value* value)
 {
     MOZ_ASSERT(!controlStack_.empty());
 
     ControlStackEntry<ControlItem>& controlItem = controlStack_.back();
     *kind = controlItem.kind();
 
     if (reachable_) {
         // Unlike branching, exiting a scope via fallthrough does not implicitly
@@ -781,17 +781,17 @@ ExprIter<Policy>::mergeControl(LabelKind
             *value = Value();
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::popControl(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::popControl(LabelKind* kind, ExprType* type, Value* value)
 {
     if (!mergeControl(kind, type, value))
         return false;
 
     if (*kind == LabelKind::Then) {
         // A reachable If without an Else. Forbid a result value.
         if (reachable_) {
             if (Validate && !IsVoid(*type))
@@ -805,17 +805,17 @@ ExprIter<Policy>::popControl(LabelKind* 
     if (!reachable_ && !controlStack_.empty())
         valueStack_.shrinkTo(controlStack_.back().valueStackStart());
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBlockType(ExprType* type)
+OpIter<Policy>::readBlockType(ExprType* type)
 {
     uint8_t unchecked;
     if (!d_.readBlockType(&unchecked))
         return fail("unable to read block signature");
 
     if (Validate) {
         switch (unchecked) {
           case uint8_t(ExprType::Void):
@@ -837,65 +837,65 @@ ExprIter<Policy>::readBlockType(ExprType
     }
 
     *type = ExprType(unchecked);
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readExpr(uint16_t* expr)
+OpIter<Policy>::readOp(uint16_t* op)
 {
     offsetOfExpr_ = d_.currentOffset();
 
     if (Validate) {
-        if (MOZ_UNLIKELY(!d_.readExpr(expr)))
+        if (MOZ_UNLIKELY(!d_.readOp(op)))
             return fail("unable to read opcode");
     } else {
-        *expr = uint16_t(d_.uncheckedReadExpr());
+        *op = uint16_t(d_.uncheckedReadOp());
     }
 
-    expr_ = Expr(*expr);  // debug-only
+    op_ = Op(*op);  // debug-only
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readFunctionStart(ExprType ret)
+OpIter<Policy>::readFunctionStart(ExprType ret)
 {
     MOZ_ASSERT(valueStack_.empty());
     MOZ_ASSERT(controlStack_.empty());
-    MOZ_ASSERT(Expr(expr_) == Expr::Limit);
+    MOZ_ASSERT(Op(op_) == Op::Limit);
     MOZ_ASSERT(reachable_);
 
     return pushControl(LabelKind::Block, ret, false);
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readFunctionEnd()
+OpIter<Policy>::readFunctionEnd()
 {
     if (Validate) {
         if (!controlStack_.empty())
             return fail("unbalanced function body control flow");
     } else {
         MOZ_ASSERT(controlStack_.empty());
     }
 
-    expr_ = Expr::Limit;
+    op_ = Op::Limit;
     valueStack_.clear();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readReturn(Value* value)
+OpIter<Policy>::readReturn(Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Return);
+    MOZ_ASSERT(Classify(op_) == OpKind::Return);
 
     if (MOZ_LIKELY(reachable_)) {
         ControlStackEntry<ControlItem>& controlItem = controlStack_[0];
         MOZ_ASSERT(controlItem.kind() == LabelKind::Block);
 
         controlItem.setReachable();
 
         if (!IsVoid(controlItem.type())) {
@@ -905,45 +905,45 @@ ExprIter<Policy>::readReturn(Value* valu
     }
 
     enterUnreachableCode();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBlock()
+OpIter<Policy>::readBlock()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Block);
+    MOZ_ASSERT(Classify(op_) == OpKind::Block);
 
     ExprType type = ExprType::Limit;
     if (!readBlockType(&type))
         return false;
 
     return pushControl(LabelKind::Block, type, false);
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readLoop()
+OpIter<Policy>::readLoop()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Loop);
+    MOZ_ASSERT(Classify(op_) == OpKind::Loop);
 
     ExprType type = ExprType::Limit;
     if (!readBlockType(&type))
         return false;
 
     return pushControl(LabelKind::Loop, type, reachable_);
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readIf(Value* condition)
+OpIter<Policy>::readIf(Value* condition)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::If);
+    MOZ_ASSERT(Classify(op_) == OpKind::If);
 
     ExprType type = ExprType::Limit;
     if (!readBlockType(&type))
         return false;
 
     if (MOZ_LIKELY(reachable_)) {
         if (!popWithType(ValType::I32, condition))
             return false;
@@ -951,19 +951,19 @@ ExprIter<Policy>::readIf(Value* conditio
         return pushControl(LabelKind::Then, type, false);
     }
 
     return pushControl(LabelKind::UnreachableThen, type, false);
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readElse(ExprType* thenType, Value* thenValue)
+OpIter<Policy>::readElse(ExprType* thenType, Value* thenValue)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Else);
+    MOZ_ASSERT(Classify(op_) == OpKind::Else);
 
     // Finish up the then arm.
     ExprType type = ExprType::Limit;
     LabelKind kind;
     if (!mergeControl(&kind, &type, thenValue))
         return false;
 
     if (Output)
@@ -983,36 +983,36 @@ ExprIter<Policy>::readElse(ExprType* the
 
     MOZ_ASSERT(valueStack_.length() == controlStack_.back().valueStackStart());
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readEnd(LabelKind* kind, ExprType* type, Value* value)
+OpIter<Policy>::readEnd(LabelKind* kind, ExprType* type, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::End);
+    MOZ_ASSERT(Classify(op_) == OpKind::End);
 
     LabelKind validateKind = static_cast<LabelKind>(-1);
     ExprType validateType = ExprType::Limit;
     if (!popControl(&validateKind, &validateType, value))
         return false;
 
     if (Output) {
         *kind = validateKind;
         *type = validateType;
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value)
+OpIter<Policy>::checkBrValue(uint32_t relativeDepth, ExprType* type, Value* value)
 {
     if (MOZ_LIKELY(reachable_)) {
         ControlStackEntry<ControlItem>* controlItem = nullptr;
         if (!getControl(relativeDepth, &controlItem))
             return false;
 
         if (controlItem->kind() != LabelKind::Loop) {
             controlItem->setReachable();
@@ -1031,19 +1031,19 @@ ExprIter<Policy>::checkBrValue(uint32_t 
         *value = Value();
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBr(uint32_t* relativeDepth, ExprType* type, Value* value)
+OpIter<Policy>::readBr(uint32_t* relativeDepth, ExprType* type, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Br);
+    MOZ_ASSERT(Classify(op_) == OpKind::Br);
 
     uint32_t validateRelativeDepth;
     if (!readVarU32(&validateRelativeDepth))
         return fail("unable to read br depth");
 
     if (!checkBrValue(validateRelativeDepth, type, value))
         return false;
 
@@ -1051,17 +1051,17 @@ ExprIter<Policy>::readBr(uint32_t* relat
         *relativeDepth = validateRelativeDepth;
 
     enterUnreachableCode();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::checkBrIfValues(uint32_t relativeDepth, Value* condition,
+OpIter<Policy>::checkBrIfValues(uint32_t relativeDepth, Value* condition,
                                   ExprType* type, Value* value)
 {
     if (MOZ_LIKELY(reachable_)) {
         if (!popWithType(ValType::I32, condition))
             return false;
 
         ControlStackEntry<ControlItem>* controlItem = nullptr;
         if (!getControl(relativeDepth, &controlItem))
@@ -1084,39 +1084,39 @@ ExprIter<Policy>::checkBrIfValues(uint32
         *value = Value();
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBrIf(uint32_t* relativeDepth, ExprType* type, Value* value, Value* condition)
+OpIter<Policy>::readBrIf(uint32_t* relativeDepth, ExprType* type, Value* value, Value* condition)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::BrIf);
+    MOZ_ASSERT(Classify(op_) == OpKind::BrIf);
 
     uint32_t validateRelativeDepth;
     if (!readVarU32(&validateRelativeDepth))
         return fail("unable to read br_if depth");
 
     if (!checkBrIfValues(validateRelativeDepth, condition, type, value))
         return false;
 
     if (Output)
         *relativeDepth = validateRelativeDepth;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBrTable(uint32_t* tableLength, ExprType* type,
+OpIter<Policy>::readBrTable(uint32_t* tableLength, ExprType* type,
                               Value* value, Value* index)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::BrTable);
+    MOZ_ASSERT(Classify(op_) == OpKind::BrTable);
 
     if (!readVarU32(tableLength))
         return fail("unable to read br_table table length");
 
     if (MOZ_LIKELY(reachable_)) {
         if (!popWithType(ValType::I32, index))
             return false;
     }
@@ -1126,19 +1126,19 @@ ExprIter<Policy>::readBrTable(uint32_t* 
     if (Output)
         *value = Value();
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBrTableEntry(ExprType* type, Value* value, uint32_t* depth)
+OpIter<Policy>::readBrTableEntry(ExprType* type, Value* value, uint32_t* depth)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::BrTable);
+    MOZ_ASSERT(Classify(op_) == OpKind::BrTable);
 
     if (!readVarU32(depth))
         return false;
 
     ExprType knownType = *type;
 
     if (MOZ_LIKELY(reachable_)) {
         ControlStackEntry<ControlItem>* controlItem = nullptr;
@@ -1168,114 +1168,114 @@ ExprIter<Policy>::readBrTableEntry(ExprT
     *type = ExprType::Void;
     if (Output)
         *value = Value();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBrTableDefault(ExprType* type, Value* value, uint32_t* depth)
+OpIter<Policy>::readBrTableDefault(ExprType* type, Value* value, uint32_t* depth)
 {
     if (!readBrTableEntry(type, value, depth))
         return false;
 
     MOZ_ASSERT(!reachable_ || *type != ExprType::Limit);
 
     enterUnreachableCode();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readUnreachable()
+OpIter<Policy>::readUnreachable()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Unreachable);
+    MOZ_ASSERT(Classify(op_) == OpKind::Unreachable);
 
     enterUnreachableCode();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readDrop()
+OpIter<Policy>::readDrop()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Drop);
+    MOZ_ASSERT(Classify(op_) == OpKind::Drop);
 
     if (!pop())
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readUnary(ValType operandType, Value* input)
+OpIter<Policy>::readUnary(ValType operandType, Value* input)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Unary);
+    MOZ_ASSERT(Classify(op_) == OpKind::Unary);
 
     if (!popWithType(operandType, input))
         return false;
 
     infalliblePush(operandType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readConversion(ValType operandType, ValType resultType, Value* input)
+OpIter<Policy>::readConversion(ValType operandType, ValType resultType, Value* input)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Conversion);
+    MOZ_ASSERT(Classify(op_) == OpKind::Conversion);
 
     if (!popWithType(operandType, input))
         return false;
 
     infalliblePush(resultType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readBinary(ValType operandType, Value* lhs, Value* rhs)
+OpIter<Policy>::readBinary(ValType operandType, Value* lhs, Value* rhs)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Binary);
+    MOZ_ASSERT(Classify(op_) == OpKind::Binary);
 
     if (!popWithType(operandType, rhs))
         return false;
 
     if (!popWithType(operandType, lhs))
         return false;
 
     infalliblePush(operandType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readComparison(ValType operandType, Value* lhs, Value* rhs)
+OpIter<Policy>::readComparison(ValType operandType, Value* lhs, Value* rhs)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Comparison);
+    MOZ_ASSERT(Classify(op_) == OpKind::Comparison);
 
     if (!popWithType(operandType, rhs))
         return false;
 
     if (!popWithType(operandType, lhs))
         return false;
 
     infalliblePush(ValType::I32);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readLinearMemoryAddress(uint32_t byteSize, LinearMemoryAddress<Value>* addr)
+OpIter<Policy>::readLinearMemoryAddress(uint32_t byteSize, LinearMemoryAddress<Value>* addr)
 {
     uint8_t alignLog2;
     if (!readFixedU8(&alignLog2))
         return fail("unable to read load alignment");
 
     uint32_t unusedOffset;
     if (!readVarU32(Output ? &addr->offset : &unusedOffset))
         return fail("unable to read load offset");
@@ -1290,96 +1290,95 @@ ExprIter<Policy>::readLinearMemoryAddres
     if (Output)
         addr->align = uint32_t(1) << alignLog2;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readLoad(ValType resultType, uint32_t byteSize,
-                           LinearMemoryAddress<Value>* addr)
+OpIter<Policy>::readLoad(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Load);
+    MOZ_ASSERT(Classify(op_) == OpKind::Load);
 
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
 
     infalliblePush(resultType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readStore(ValType resultType, uint32_t byteSize,
-                            LinearMemoryAddress<Value>* addr, Value* value)
+OpIter<Policy>::readStore(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr,
+                          Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Store);
+    MOZ_ASSERT(Classify(op_) == OpKind::Store);
 
     if (!popWithType(resultType, value))
         return false;
 
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readTeeStore(ValType resultType, uint32_t byteSize,
-                               LinearMemoryAddress<Value>* addr, Value* value)
+OpIter<Policy>::readTeeStore(ValType resultType, uint32_t byteSize, LinearMemoryAddress<Value>* addr,
+                             Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::TeeStore);
+    MOZ_ASSERT(Classify(op_) == OpKind::TeeStore);
 
     if (!popWithType(resultType, value))
         return false;
 
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
 
     infalliblePush(TypeAndValue<Value>(resultType, Output ? *value : Value()));
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readNop()
+OpIter<Policy>::readNop()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Nop);
+    MOZ_ASSERT(Classify(op_) == OpKind::Nop);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCurrentMemory()
+OpIter<Policy>::readCurrentMemory()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::CurrentMemory);
+    MOZ_ASSERT(Classify(op_) == OpKind::CurrentMemory);
 
     uint32_t flags;
     if (!readVarU32(&flags))
         return false;
 
     if (Validate && flags != uint32_t(MemoryTableFlags::Default))
         return fail("unexpected flags");
 
     if (!push(ValType::I32))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readGrowMemory(Value* input)
+OpIter<Policy>::readGrowMemory(Value* input)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::GrowMemory);
+    MOZ_ASSERT(Classify(op_) == OpKind::GrowMemory);
 
     uint32_t flags;
     if (!readVarU32(&flags))
         return false;
 
     if (Validate && flags != uint32_t(MemoryTableFlags::Default))
         return fail("unexpected flags");
 
@@ -1388,19 +1387,19 @@ ExprIter<Policy>::readGrowMemory(Value* 
 
     infalliblePush(ValType::I32);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSelect(ValType* type, Value* trueValue, Value* falseValue, Value* condition)
+OpIter<Policy>::readSelect(ValType* type, Value* trueValue, Value* falseValue, Value* condition)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Select);
+    MOZ_ASSERT(Classify(op_) == OpKind::Select);
 
     if (!popWithType(ValType::I32, condition))
         return false;
 
     TypeAndValue<Value> false_;
     if (!pop(&false_))
         return false;
 
@@ -1420,19 +1419,19 @@ ExprIter<Policy>::readSelect(ValType* ty
         *falseValue = false_.value();
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readGetLocal(const ValTypeVector& locals, uint32_t* id)
+OpIter<Policy>::readGetLocal(const ValTypeVector& locals, uint32_t* id)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::GetLocal);
+    MOZ_ASSERT(Classify(op_) == OpKind::GetLocal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= locals.length())
         return fail("get_local index out of range");
 
@@ -1442,19 +1441,19 @@ ExprIter<Policy>::readGetLocal(const Val
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSetLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
+OpIter<Policy>::readSetLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SetLocal);
+    MOZ_ASSERT(Classify(op_) == OpKind::SetLocal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= locals.length())
         return fail("set_local index out of range");
 
@@ -1464,19 +1463,19 @@ ExprIter<Policy>::readSetLocal(const Val
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
+OpIter<Policy>::readTeeLocal(const ValTypeVector& locals, uint32_t* id, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::TeeLocal);
+    MOZ_ASSERT(Classify(op_) == OpKind::TeeLocal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= locals.length())
         return fail("set_local index out of range");
 
@@ -1486,19 +1485,19 @@ ExprIter<Policy>::readTeeLocal(const Val
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readGetGlobal(const GlobalDescVector& globals, uint32_t* id)
+OpIter<Policy>::readGetGlobal(const GlobalDescVector& globals, uint32_t* id)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::GetGlobal);
+    MOZ_ASSERT(Classify(op_) == OpKind::GetGlobal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= globals.length())
         return fail("get_global index out of range");
 
@@ -1508,19 +1507,19 @@ ExprIter<Policy>::readGetGlobal(const Gl
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSetGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
+OpIter<Policy>::readSetGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SetGlobal);
+    MOZ_ASSERT(Classify(op_) == OpKind::SetGlobal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= globals.length())
         return fail("set_global index out of range");
 
@@ -1533,19 +1532,19 @@ ExprIter<Policy>::readSetGlobal(const Gl
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readTeeGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
+OpIter<Policy>::readTeeGlobal(const GlobalDescVector& globals, uint32_t* id, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::TeeGlobal);
+    MOZ_ASSERT(Classify(op_) == OpKind::TeeGlobal);
 
     uint32_t validateId;
     if (!readVarU32(&validateId))
         return false;
 
     if (Validate && validateId >= globals.length())
         return fail("set_global index out of range");
 
@@ -1558,207 +1557,207 @@ ExprIter<Policy>::readTeeGlobal(const Gl
     if (Output)
         *id = validateId;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readI32Const(int32_t* i32)
+OpIter<Policy>::readI32Const(int32_t* i32)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::I32);
+    MOZ_ASSERT(Classify(op_) == OpKind::I32);
 
     int32_t unused;
     if (!readVarS32(Output ? i32 : &unused))
         return false;
 
     if (!push(ValType::I32))
        return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readI64Const(int64_t* i64)
+OpIter<Policy>::readI64Const(int64_t* i64)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::I64);
+    MOZ_ASSERT(Classify(op_) == OpKind::I64);
 
     int64_t unused;
     if (!readVarS64(Output ? i64 : &unused))
         return false;
 
     if (!push(ValType::I64))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readF32Const(RawF32* f32)
+OpIter<Policy>::readF32Const(RawF32* f32)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::F32);
+    MOZ_ASSERT(Classify(op_) == OpKind::F32);
 
     RawF32 unused;
     if (!readFixedF32(Output ? f32 : &unused))
         return false;
 
     if (!push(ValType::F32))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readF64Const(RawF64* f64)
+OpIter<Policy>::readF64Const(RawF64* f64)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::F64);
+    MOZ_ASSERT(Classify(op_) == OpKind::F64);
 
     RawF64 unused;
     if (!readFixedF64(Output ? f64 : &unused))
        return false;
 
     if (!push(ValType::F64))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readI8x16Const(I8x16* i8x16)
+OpIter<Policy>::readI8x16Const(I8x16* i8x16)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::I8x16);
+    MOZ_ASSERT(Classify(op_) == OpKind::I8x16);
 
     I8x16 unused;
     if (!readFixedI8x16(Output ? i8x16 : &unused))
         return false;
 
     if (!push(ValType::I8x16))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readI16x8Const(I16x8* i16x8)
+OpIter<Policy>::readI16x8Const(I16x8* i16x8)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::I16x8);
+    MOZ_ASSERT(Classify(op_) == OpKind::I16x8);
 
     I16x8 unused;
     if (!readFixedI16x8(Output ? i16x8 : &unused))
         return false;
 
     if (!push(ValType::I16x8))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readI32x4Const(I32x4* i32x4)
+OpIter<Policy>::readI32x4Const(I32x4* i32x4)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::I32x4);
+    MOZ_ASSERT(Classify(op_) == OpKind::I32x4);
 
     I32x4 unused;
     if (!readFixedI32x4(Output ? i32x4 : &unused))
         return false;
 
     if (!push(ValType::I32x4))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readF32x4Const(F32x4* f32x4)
+OpIter<Policy>::readF32x4Const(F32x4* f32x4)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::F32x4);
+    MOZ_ASSERT(Classify(op_) == OpKind::F32x4);
 
     F32x4 unused;
     if (!readFixedF32x4(Output ? f32x4 : &unused))
         return false;
 
     if (!push(ValType::F32x4))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readB8x16Const(I8x16* i8x16)
+OpIter<Policy>::readB8x16Const(I8x16* i8x16)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::B8x16);
+    MOZ_ASSERT(Classify(op_) == OpKind::B8x16);
 
     I8x16 unused;
     if (!readFixedI8x16(Output ? i8x16 : &unused))
         return false;
 
     if (!push(ValType::B8x16))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readB16x8Const(I16x8* i16x8)
+OpIter<Policy>::readB16x8Const(I16x8* i16x8)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::B16x8);
+    MOZ_ASSERT(Classify(op_) == OpKind::B16x8);
 
     I16x8 unused;
     if (!readFixedI16x8(Output ? i16x8 : &unused))
         return false;
 
     if (!push(ValType::B16x8))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readB32x4Const(I32x4* i32x4)
+OpIter<Policy>::readB32x4Const(I32x4* i32x4)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::B32x4);
+    MOZ_ASSERT(Classify(op_) == OpKind::B32x4);
 
     I32x4 unused;
     if (!readFixedI32x4(Output ? i32x4 : &unused))
         return false;
 
     if (!push(ValType::B32x4))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCall(uint32_t* calleeIndex)
+OpIter<Policy>::readCall(uint32_t* calleeIndex)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Call);
+    MOZ_ASSERT(Classify(op_) == OpKind::Call);
 
     if (!readVarU32(calleeIndex))
         return fail("unable to read call function index");
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCallIndirect(uint32_t* sigIndex, Value* callee)
+OpIter<Policy>::readCallIndirect(uint32_t* sigIndex, Value* callee)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::CallIndirect);
+    MOZ_ASSERT(Classify(op_) == OpKind::CallIndirect);
 
     if (!readVarU32(sigIndex))
         return fail("unable to read call_indirect signature index");
 
     uint32_t flags;
     if (!readVarU32(&flags))
         return false;
 
@@ -1770,29 +1769,29 @@ ExprIter<Policy>::readCallIndirect(uint3
             return false;
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readOldCallIndirect(uint32_t* sigIndex)
+OpIter<Policy>::readOldCallIndirect(uint32_t* sigIndex)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::OldCallIndirect);
+    MOZ_ASSERT(Classify(op_) == OpKind::OldCallIndirect);
 
     if (!readVarU32(sigIndex))
         return fail("unable to read call_indirect signature index");
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCallArg(ValType type, uint32_t numArgs, uint32_t argIndex, Value* arg)
+OpIter<Policy>::readCallArg(ValType type, uint32_t numArgs, uint32_t argIndex, Value* arg)
 {
     MOZ_ASSERT(reachable_);
 
     TypeAndValue<Value> tv;
 
     if (!peek(numArgs - argIndex, &tv))
         return false;
     if (!checkType(tv.type(), type))
@@ -1801,58 +1800,58 @@ ExprIter<Policy>::readCallArg(ValType ty
     if (Output)
         *arg = tv.value();
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCallArgsEnd(uint32_t numArgs)
+OpIter<Policy>::readCallArgsEnd(uint32_t numArgs)
 {
     MOZ_ASSERT(reachable_);
     MOZ_ASSERT(numArgs <= valueStack_.length());
 
     valueStack_.shrinkBy(numArgs);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readOldCallIndirectCallee(Value* callee)
+OpIter<Policy>::readOldCallIndirectCallee(Value* callee)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::OldCallIndirect);
+    MOZ_ASSERT(Classify(op_) == OpKind::OldCallIndirect);
     MOZ_ASSERT(reachable_);
 
     if (!popWithType(ValType::I32, callee))
         return false;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readCallReturn(ExprType ret)
+OpIter<Policy>::readCallReturn(ExprType ret)
 {
     MOZ_ASSERT(reachable_);
 
     if (!IsVoid(ret)) {
         if (!push(NonVoidToValType(ret)))
             return false;
     }
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readAtomicLoad(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType)
+OpIter<Policy>::readAtomicLoad(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::AtomicLoad);
+    MOZ_ASSERT(Classify(op_) == OpKind::AtomicLoad);
 
     Scalar::Type validateViewType;
     if (!readAtomicViewType(&validateViewType))
         return false;
 
     uint32_t byteSize = Scalar::byteSize(validateViewType);
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
@@ -1862,20 +1861,20 @@ ExprIter<Policy>::readAtomicLoad(LinearM
     if (Output)
         *viewType = validateViewType;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readAtomicStore(LinearMemoryAddress<Value>* addr,
-                                  Scalar::Type* viewType, Value* value)
+OpIter<Policy>::readAtomicStore(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType,
+                                Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::AtomicStore);
+    MOZ_ASSERT(Classify(op_) == OpKind::AtomicStore);
 
     Scalar::Type validateViewType;
     if (!readAtomicViewType(&validateViewType))
         return false;
 
     uint32_t byteSize = Scalar::byteSize(validateViewType);
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
@@ -1888,20 +1887,20 @@ ExprIter<Policy>::readAtomicStore(Linear
     if (Output)
         *viewType = validateViewType;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readAtomicBinOp(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType,
-                                  jit::AtomicOp* op, Value* value)
+OpIter<Policy>::readAtomicBinOp(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType,
+                                jit::AtomicOp* op, Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::AtomicBinOp);
+    MOZ_ASSERT(Classify(op_) == OpKind::AtomicBinOp);
 
     Scalar::Type validateViewType;
     if (!readAtomicViewType(&validateViewType))
         return false;
 
     if (!readAtomicBinOpOp(op))
         return false;
 
@@ -1917,21 +1916,20 @@ ExprIter<Policy>::readAtomicBinOp(Linear
     if (Output)
         *viewType = validateViewType;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readAtomicCompareExchange(LinearMemoryAddress<Value>* addr,
-                                            Scalar::Type* viewType,
-                                            Value* oldValue, Value* newValue)
+OpIter<Policy>::readAtomicCompareExchange(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType,
+                                          Value* oldValue, Value* newValue)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::AtomicCompareExchange);
+    MOZ_ASSERT(Classify(op_) == OpKind::AtomicCompareExchange);
 
     Scalar::Type validateViewType;
     if (!readAtomicViewType(&validateViewType))
         return false;
 
     uint32_t byteSize = Scalar::byteSize(validateViewType);
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
@@ -1947,21 +1945,20 @@ ExprIter<Policy>::readAtomicCompareExcha
     if (Output)
         *viewType = validateViewType;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readAtomicExchange(LinearMemoryAddress<Value>* addr,
-                                     Scalar::Type* viewType,
-                                     Value* value)
+OpIter<Policy>::readAtomicExchange(LinearMemoryAddress<Value>* addr, Scalar::Type* viewType,
+                                   Value* value)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::AtomicExchange);
+    MOZ_ASSERT(Classify(op_) == OpKind::AtomicExchange);
 
     Scalar::Type validateViewType;
     if (!readAtomicViewType(&validateViewType))
         return false;
 
     uint32_t byteSize = Scalar::byteSize(validateViewType);
     if (!readLinearMemoryAddress(byteSize, addr))
         return false;
@@ -1974,67 +1971,67 @@ ExprIter<Policy>::readAtomicExchange(Lin
     if (Output)
         *viewType = validateViewType;
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdComparison(ValType simdType, Value* lhs, Value* rhs)
+OpIter<Policy>::readSimdComparison(ValType simdType, Value* lhs, Value* rhs)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdComparison);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdComparison);
 
     if (!popWithType(simdType, rhs))
         return false;
 
     if (!popWithType(simdType, lhs))
         return false;
 
     infalliblePush(SimdBoolType(simdType));
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdShiftByScalar(ValType simdType, Value* lhs, Value* rhs)
+OpIter<Policy>::readSimdShiftByScalar(ValType simdType, Value* lhs, Value* rhs)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdShiftByScalar);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdShiftByScalar);
 
     if (!popWithType(ValType::I32, rhs))
         return false;
 
     if (!popWithType(simdType, lhs))
         return false;
 
     infalliblePush(simdType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdBooleanReduction(ValType simdType, Value* input)
+OpIter<Policy>::readSimdBooleanReduction(ValType simdType, Value* input)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdBooleanReduction);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdBooleanReduction);
 
     if (!popWithType(simdType, input))
         return false;
 
     infalliblePush(ValType::I32);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readExtractLane(ValType simdType, uint8_t* lane, Value* vector)
+OpIter<Policy>::readExtractLane(ValType simdType, uint8_t* lane, Value* vector)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::ExtractLane);
+    MOZ_ASSERT(Classify(op_) == OpKind::ExtractLane);
 
     uint32_t laneBits;
     if (!readVarU32(&laneBits))
         return false;
 
     if (Validate && laneBits >= NumSimdElements(simdType))
         return fail("simd lane out of bounds for simd type");
 
@@ -2046,19 +2043,19 @@ ExprIter<Policy>::readExtractLane(ValTyp
     if (Output)
         *lane = uint8_t(laneBits);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readReplaceLane(ValType simdType, uint8_t* lane, Value* vector, Value* scalar)
+OpIter<Policy>::readReplaceLane(ValType simdType, uint8_t* lane, Value* vector, Value* scalar)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::ReplaceLane);
+    MOZ_ASSERT(Classify(op_) == OpKind::ReplaceLane);
 
     uint32_t laneBits;
     if (!readVarU32(&laneBits))
         return false;
 
     if (Validate && laneBits >= NumSimdElements(simdType))
         return fail("simd lane out of bounds for simd type");
 
@@ -2073,33 +2070,33 @@ ExprIter<Policy>::readReplaceLane(ValTyp
     if (Output)
         *lane = uint8_t(laneBits);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSplat(ValType simdType, Value* scalar)
+OpIter<Policy>::readSplat(ValType simdType, Value* scalar)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Splat);
+    MOZ_ASSERT(Classify(op_) == OpKind::Splat);
 
     if (!popWithType(SimdElementType(simdType), scalar))
         return false;
 
     infalliblePush(simdType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSwizzle(ValType simdType, uint8_t (* lanes)[16], Value* vector)
+OpIter<Policy>::readSwizzle(ValType simdType, uint8_t (* lanes)[16], Value* vector)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Swizzle);
+    MOZ_ASSERT(Classify(op_) == OpKind::Swizzle);
 
     uint32_t numSimdLanes = NumSimdElements(simdType);
     MOZ_ASSERT(numSimdLanes <= mozilla::ArrayLength(*lanes));
     for (uint32_t i = 0; i < numSimdLanes; ++i) {
         uint8_t validateLane;
         if (!readFixedU8(Output ? &(*lanes)[i] : &validateLane))
             return fail("unable to read swizzle lane");
         if (Validate && (Output ? (*lanes)[i] : validateLane) >= numSimdLanes)
@@ -2111,19 +2108,19 @@ ExprIter<Policy>::readSwizzle(ValType si
 
     infalliblePush(simdType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readShuffle(ValType simdType, uint8_t (* lanes)[16], Value* lhs, Value* rhs)
+OpIter<Policy>::readShuffle(ValType simdType, uint8_t (* lanes)[16], Value* lhs, Value* rhs)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::Shuffle);
+    MOZ_ASSERT(Classify(op_) == OpKind::Shuffle);
 
     uint32_t numSimdLanes = NumSimdElements(simdType);
     MOZ_ASSERT(numSimdLanes <= mozilla::ArrayLength(*lanes));
     for (uint32_t i = 0; i < numSimdLanes; ++i) {
         uint8_t validateLane;
         if (!readFixedU8(Output ? &(*lanes)[i] : &validateLane))
             return fail("unable to read shuffle lane");
         if (Validate && (Output ? (*lanes)[i] : validateLane) >= numSimdLanes * 2)
@@ -2138,78 +2135,78 @@ ExprIter<Policy>::readShuffle(ValType si
 
     infalliblePush(simdType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdSelect(ValType simdType, Value* trueValue, Value* falseValue,
-                                 Value* condition)
+OpIter<Policy>::readSimdSelect(ValType simdType, Value* trueValue, Value* falseValue,
+                               Value* condition)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdSelect);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdSelect);
 
     if (!popWithType(simdType, falseValue))
         return false;
     if (!popWithType(simdType, trueValue))
         return false;
     if (!popWithType(SimdBoolType(simdType), condition))
         return false;
 
     infalliblePush(simdType);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdCtor()
+OpIter<Policy>::readSimdCtor()
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdCtor);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdCtor);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdCtorArg(ValType elementType, uint32_t numElements, uint32_t index,
-                                  Value* arg)
+OpIter<Policy>::readSimdCtorArg(ValType elementType, uint32_t numElements, uint32_t index,
+                                Value* arg)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdCtor);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdCtor);
     MOZ_ASSERT(numElements > 0);
 
     TypeAndValue<Value> tv;
 
     if (!peek(numElements - index, &tv))
         return false;
     if (!checkType(tv.type(), elementType))
         return false;
 
     *arg = tv.value();
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdCtorArgsEnd(uint32_t numElements)
+OpIter<Policy>::readSimdCtorArgsEnd(uint32_t numElements)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdCtor);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdCtor);
     MOZ_ASSERT(numElements <= valueStack_.length());
 
     valueStack_.shrinkBy(numElements);
 
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readSimdCtorReturn(ValType simdType)
+OpIter<Policy>::readSimdCtorReturn(ValType simdType)
 {
-    MOZ_ASSERT(Classify(expr_) == ExprKind::SimdCtor);
+    MOZ_ASSERT(Classify(op_) == OpKind::SimdCtor);
 
     infalliblePush(simdType);
 
     return true;
 }
 
 } // namespace wasm
 } // namespace js
--- a/js/src/wasm/WasmBinaryToAST.cpp
+++ b/js/src/wasm/WasmBinaryToAST.cpp
@@ -58,47 +58,47 @@ struct AstDecodeStackItem
     {}
     explicit AstDecodeStackItem(AstExpr* expr)
      : expr(expr),
        terminationKind(AstDecodeTerminationKind::Unknown),
        type(ExprType::Limit)
     {}
 };
 
-// We don't define a Value type because ExprIter doesn't push void values, which
+// We don't define a Value type because OpIter doesn't push void values, which
 // we actually need here because we're building an AST, so we maintain our own
 // stack.
-struct AstDecodePolicy : ExprIterPolicy
+struct AstDecodePolicy : OpIterPolicy
 {
     // Enable validation because we can be called from wasmBinaryToText on bytes
     // which are not necessarily valid, and we shouldn't run the decoder in
     // non-validating mode on invalid code.
     static const bool Validate = true;
 
     static const bool Output = true;
 };
 
-typedef ExprIter<AstDecodePolicy> AstDecodeExprIter;
+typedef OpIter<AstDecodePolicy> AstDecodeOpIter;
 
 class AstDecodeContext
 {
   public:
     typedef AstVector<uint32_t> AstIndexVector;
     typedef AstVector<AstDecodeStackItem> AstDecodeStack;
     typedef AstVector<uint32_t> DepthStack;
 
     JSContext* cx;
     LifoAlloc& lifo;
     Decoder& d;
     bool generateNames;
 
   private:
     AstModule& module_;
     AstIndexVector funcDefSigs_;
-    AstDecodeExprIter *iter_;
+    AstDecodeOpIter *iter_;
     AstDecodeStack exprs_;
     DepthStack depths_;
     const ValTypeVector* locals_;
     GlobalDescVector globals_;
     AstNameVector blockLabels_;
     uint32_t currentLabelIndex_;
     ExprType retType_;
 
@@ -117,17 +117,17 @@ class AstDecodeContext
        locals_(nullptr),
        blockLabels_(lifo),
        currentLabelIndex_(0),
        retType_(ExprType::Limit)
     {}
 
     AstModule& module() { return module_; }
     AstIndexVector& funcDefSigs() { return funcDefSigs_; }
-    AstDecodeExprIter& iter() { return *iter_; }
+    AstDecodeOpIter& iter() { return *iter_; }
     AstDecodeStack& exprs() { return exprs_; }
     DepthStack& depths() { return depths_; }
 
     AstNameVector& blockLabels() { return blockLabels_; }
 
     ExprType retType() const { return retType_; }
     const ValTypeVector& locals() const { return *locals_; }
 
@@ -184,17 +184,17 @@ class AstDecodeContext
                 return nullptr;
 
             return new(lifo) AstFirst(Move(exprs));
         }
 
         return voidNode;
     }
 
-    void startFunction(AstDecodeExprIter *iter, const ValTypeVector* locals, ExprType retType)
+    void startFunction(AstDecodeOpIter* iter, const ValTypeVector* locals, ExprType retType)
     {
         iter_ = iter;
         locals_ = locals;
         currentLabelIndex_ = 0;
         retType_ = retType;
     }
     void endFunction()
     {
@@ -350,17 +350,17 @@ AstDecodeCall(AstDecodeContext& c)
 
     AstExprVector args(c.lifo);
     if (!AstDecodeCallArgs(c, *sig, &args))
         return false;
 
     if (!AstDecodeCallReturn(c, *sig))
         return false;
 
-    AstCall* call = new(c.lifo) AstCall(Expr::Call, sig->ret(), funcRef, Move(args));
+    AstCall* call = new(c.lifo) AstCall(Op::Call, sig->ret(), funcRef, Move(args));
     if (!call)
         return false;
 
     AstExpr* result = call;
     if (IsVoid(sig->ret()))
         result = c.handleVoidExpr(call);
 
     if (!c.push(AstDecodeStackItem(result)))
@@ -470,57 +470,57 @@ AstDecodeBrTable(AstDecodeContext& c)
 
     if (!c.push(AstDecodeStackItem(branchTable)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeBlock(AstDecodeContext& c, Expr expr)
+AstDecodeBlock(AstDecodeContext& c, Op op)
 {
-    MOZ_ASSERT(expr == Expr::Block || expr == Expr::Loop);
+    MOZ_ASSERT(op == Op::Block || op == Op::Loop);
 
     if (!c.blockLabels().append(AstName()))
         return false;
 
-    if (expr == Expr::Loop) {
+    if (op == Op::Loop) {
       if (!c.iter().readLoop())
           return false;
     } else {
       if (!c.iter().readBlock())
           return false;
     }
 
     if (!c.depths().append(c.exprs().length()))
         return false;
 
     ExprType type;
     while (true) {
         if (!AstDecodeExpr(c))
             return false;
 
         const AstDecodeStackItem& item = c.top();
-        if (!item.expr) { // Expr::End was found
+        if (!item.expr) { // Op::End was found
             type = item.type;
             c.popBack();
             break;
         }
     }
 
     AstExprVector exprs(c.lifo);
     for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
          i != e; ++i) {
         if (!exprs.append(i->expr))
             return false;
     }
     c.exprs().shrinkTo(c.depths().popCopy());
 
     AstName name = c.blockLabels().popCopy();
-    AstBlock* block = new(c.lifo) AstBlock(expr, type, name, Move(exprs));
+    AstBlock* block = new(c.lifo) AstBlock(op, type, name, Move(exprs));
     if (!block)
         return false;
 
     AstExpr* result = block;
     if (IsVoid(type))
         result = c.handleVoidExpr(block);
 
     if (!c.push(AstDecodeStackItem(result)))
@@ -546,17 +546,17 @@ AstDecodeIf(AstDecodeContext& c)
         return false;
 
     ExprType type;
     while (true) {
         if (!AstDecodeExpr(c))
             return false;
 
         const AstDecodeStackItem& item = c.top();
-        if (!item.expr) { // Expr::End was found
+        if (!item.expr) { // Op::End was found
             hasElse = item.terminationKind == AstDecodeTerminationKind::Else;
             type = item.type;
             c.popBack();
             break;
         }
     }
 
     AstExprVector thenExprs(c.lifo);
@@ -569,17 +569,17 @@ AstDecodeIf(AstDecodeContext& c)
 
     AstExprVector elseExprs(c.lifo);
     if (hasElse) {
         while (true) {
             if (!AstDecodeExpr(c))
                 return false;
 
             const AstDecodeStackItem& item = c.top();
-            if (!item.expr) { // Expr::End was found
+            if (!item.expr) { // Op::End was found
                 c.popBack();
                 break;
             }
         }
 
         for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
              i != e; ++i) {
             if (!elseExprs.append(i->expr))
@@ -650,43 +650,43 @@ AstDecodeNop(AstDecodeContext& c)
 
     if (!c.push(AstDecodeStackItem(tmp)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeUnary(AstDecodeContext& c, ValType type, Expr expr)
+AstDecodeUnary(AstDecodeContext& c, ValType type, Op op)
 {
     if (!c.iter().readUnary(type, nullptr))
         return false;
 
-    AstDecodeStackItem op = c.popCopy();
+    AstDecodeStackItem operand = c.popCopy();
 
-    AstUnaryOperator* unary = new(c.lifo) AstUnaryOperator(expr, op.expr);
+    AstUnaryOperator* unary = new(c.lifo) AstUnaryOperator(op, operand.expr);
     if (!unary)
         return false;
 
     if (!c.push(AstDecodeStackItem(unary)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeBinary(AstDecodeContext& c, ValType type, Expr expr)
+AstDecodeBinary(AstDecodeContext& c, ValType type, Op op)
 {
     if (!c.iter().readBinary(type, nullptr, nullptr))
         return false;
 
     AstDecodeStackItem rhs = c.popCopy();
     AstDecodeStackItem lhs = c.popCopy();
 
-    AstBinaryOperator* binary = new(c.lifo) AstBinaryOperator(expr, lhs.expr, rhs.expr);
+    AstBinaryOperator* binary = new(c.lifo) AstBinaryOperator(op, lhs.expr, rhs.expr);
     if (!binary)
         return false;
 
     if (!c.push(AstDecodeStackItem(binary)))
         return false;
 
     return true;
 }
@@ -697,54 +697,54 @@ AstDecodeSelect(AstDecodeContext& c)
     ValType type;
     if (!c.iter().readSelect(&type, nullptr, nullptr, nullptr))
         return false;
 
     AstDecodeStackItem selectFalse = c.popCopy();
     AstDecodeStackItem selectTrue = c.popCopy();
     AstDecodeStackItem cond = c.popCopy();
 
-    AstTernaryOperator* ternary = new(c.lifo) AstTernaryOperator(Expr::Select, cond.expr, selectTrue.expr, selectFalse.expr);
+    AstTernaryOperator* ternary = new(c.lifo) AstTernaryOperator(Op::Select, cond.expr, selectTrue.expr, selectFalse.expr);
     if (!ternary)
         return false;
 
     if (!c.push(AstDecodeStackItem(ternary)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeComparison(AstDecodeContext& c, ValType type, Expr expr)
+AstDecodeComparison(AstDecodeContext& c, ValType type, Op op)
 {
     if (!c.iter().readComparison(type, nullptr, nullptr))
         return false;
 
     AstDecodeStackItem rhs = c.popCopy();
     AstDecodeStackItem lhs = c.popCopy();
 
-    AstComparisonOperator* comparison = new(c.lifo) AstComparisonOperator(expr, lhs.expr, rhs.expr);
+    AstComparisonOperator* comparison = new(c.lifo) AstComparisonOperator(op, lhs.expr, rhs.expr);
     if (!comparison)
         return false;
 
     if (!c.push(AstDecodeStackItem(comparison)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeConversion(AstDecodeContext& c, ValType fromType, ValType toType, Expr expr)
+AstDecodeConversion(AstDecodeContext& c, ValType fromType, ValType toType, Op op)
 {
     if (!c.iter().readConversion(fromType, toType, nullptr))
         return false;
 
-    AstDecodeStackItem op = c.popCopy();
+    AstDecodeStackItem operand = c.popCopy();
 
-    AstConversionOperator* conversion = new(c.lifo) AstConversionOperator(expr, op.expr);
+    AstConversionOperator* conversion = new(c.lifo) AstConversionOperator(op, operand.expr);
     if (!conversion)
         return false;
 
     if (!c.push(AstDecodeStackItem(conversion)))
         return false;
 
     return true;
 }
@@ -752,45 +752,45 @@ AstDecodeConversion(AstDecodeContext& c,
 static AstLoadStoreAddress
 AstDecodeLoadStoreAddress(const LinearMemoryAddress<Nothing>& addr, const AstDecodeStackItem& item)
 {
     uint32_t flags = FloorLog2(addr.align);
     return AstLoadStoreAddress(item.expr, flags, addr.offset);
 }
 
 static bool
-AstDecodeLoad(AstDecodeContext& c, ValType type, uint32_t byteSize, Expr expr)
+AstDecodeLoad(AstDecodeContext& c, ValType type, uint32_t byteSize, Op op)
 {
     LinearMemoryAddress<Nothing> addr;
     if (!c.iter().readLoad(type, byteSize, &addr))
         return false;
 
     AstDecodeStackItem item = c.popCopy();
 
-    AstLoad* load = new(c.lifo) AstLoad(expr, AstDecodeLoadStoreAddress(addr, item));
+    AstLoad* load = new(c.lifo) AstLoad(op, AstDecodeLoadStoreAddress(addr, item));
     if (!load)
         return false;
 
     if (!c.push(AstDecodeStackItem(load)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeStore(AstDecodeContext& c, ValType type, uint32_t byteSize, Expr expr)
+AstDecodeStore(AstDecodeContext& c, ValType type, uint32_t byteSize, Op op)
 {
     LinearMemoryAddress<Nothing> addr;
     if (!c.iter().readStore(type, byteSize, &addr, nullptr))
         return false;
 
     AstDecodeStackItem value = c.popCopy();
     AstDecodeStackItem item = c.popCopy();
 
-    AstStore* store = new(c.lifo) AstStore(expr, AstDecodeLoadStoreAddress(addr, item), value.expr);
+    AstStore* store = new(c.lifo) AstStore(op, AstDecodeLoadStoreAddress(addr, item), value.expr);
     if (!store)
         return false;
 
     AstExpr* wrapped = c.handleVoidExpr(store);
     if (!wrapped)
         return false;
 
     if (!c.push(AstDecodeStackItem(wrapped)))
@@ -816,57 +816,57 @@ AstDecodeCurrentMemory(AstDecodeContext&
 }
 
 static bool
 AstDecodeGrowMemory(AstDecodeContext& c)
 {
     if (!c.iter().readGrowMemory(nullptr))
         return false;
 
-    AstDecodeStackItem op = c.popCopy();
+    AstDecodeStackItem operand = c.popCopy();
 
-    AstGrowMemory* gm = new(c.lifo) AstGrowMemory(op.expr);
+    AstGrowMemory* gm = new(c.lifo) AstGrowMemory(operand.expr);
     if (!gm)
         return false;
 
     if (!c.push(AstDecodeStackItem(gm)))
         return false;
 
     return true;
 }
 
 static bool
-AstDecodeBranch(AstDecodeContext& c, Expr expr)
+AstDecodeBranch(AstDecodeContext& c, Op op)
 {
-    MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf);
+    MOZ_ASSERT(op == Op::Br || op == Op::BrIf);
 
     uint32_t depth;
     ExprType type;
     AstDecodeStackItem value;
     AstDecodeStackItem cond;
-    if (expr == Expr::Br) {
+    if (op == Op::Br) {
         if (!c.iter().readBr(&depth, &type, nullptr))
             return false;
         if (!IsVoid(type))
             value = c.popCopy();
     } else {
         if (!c.iter().readBrIf(&depth, &type, nullptr, nullptr))
             return false;
         if (!IsVoid(type))
             value = c.popCopy();
         cond = c.popCopy();
     }
 
     AstRef depthRef;
     if (!AstDecodeGetBlockRef(c, depth, &depthRef))
         return false;
 
-    if (expr == Expr::Br || !value.expr)
+    if (op == Op::Br || !value.expr)
         type = ExprType::Void;
-    AstBranch* branch = new(c.lifo) AstBranch(expr, type, cond.expr, depthRef, value.expr);
+    AstBranch* branch = new(c.lifo) AstBranch(op, type, cond.expr, depthRef, value.expr);
     if (!branch)
         return false;
 
     if (!c.push(AstDecodeStackItem(branch)))
         return false;
 
     return true;
 }
@@ -1009,420 +1009,420 @@ AstDecodeReturn(AstDecodeContext& c)
 
     return true;
 }
 
 static bool
 AstDecodeExpr(AstDecodeContext& c)
 {
     uint32_t exprOffset = c.iter().currentOffset();
-    uint16_t expr;
-    if (!c.iter().readExpr(&expr))
+    uint16_t op;
+    if (!c.iter().readOp(&op))
         return false;
 
     AstExpr* tmp;
-    switch (expr) {
-      case uint16_t(Expr::Nop):
+    switch (op) {
+      case uint16_t(Op::Nop):
         if (!AstDecodeNop(c))
             return false;
         break;
-      case uint16_t(Expr::Drop):
+      case uint16_t(Op::Drop):
         if (!AstDecodeDrop(c))
             return false;
         break;
-      case uint16_t(Expr::Call):
+      case uint16_t(Op::Call):
         if (!AstDecodeCall(c))
             return false;
         break;
-      case uint16_t(Expr::CallIndirect):
+      case uint16_t(Op::CallIndirect):
         if (!AstDecodeCallIndirect(c))
             return false;
         break;
-      case uint16_t(Expr::I32Const):
+      case uint16_t(Op::I32Const):
         int32_t i32;
         if (!c.iter().readI32Const(&i32))
             return false;
         tmp = new(c.lifo) AstConst(Val((uint32_t)i32));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
-      case uint16_t(Expr::I64Const):
+      case uint16_t(Op::I64Const):
         int64_t i64;
         if (!c.iter().readI64Const(&i64))
             return false;
         tmp = new(c.lifo) AstConst(Val((uint64_t)i64));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
-      case uint16_t(Expr::F32Const): {
+      case uint16_t(Op::F32Const): {
         RawF32 f32;
         if (!c.iter().readF32Const(&f32))
             return false;
         tmp = new(c.lifo) AstConst(Val(f32));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       }
-      case uint16_t(Expr::F64Const): {
+      case uint16_t(Op::F64Const): {
         RawF64 f64;
         if (!c.iter().readF64Const(&f64))
             return false;
         tmp = new(c.lifo) AstConst(Val(f64));
         if (!tmp || !c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       }
-      case uint16_t(Expr::GetLocal):
+      case uint16_t(Op::GetLocal):
         if (!AstDecodeGetLocal(c))
             return false;
         break;
-      case uint16_t(Expr::SetLocal):
+      case uint16_t(Op::SetLocal):
         if (!AstDecodeSetLocal(c))
             return false;
         break;
-      case uint16_t(Expr::TeeLocal):
+      case uint16_t(Op::TeeLocal):
         if (!AstDecodeTeeLocal(c))
             return false;
         break;
-      case uint16_t(Expr::Select):
+      case uint16_t(Op::Select):
         if (!AstDecodeSelect(c))
             return false;
         break;
-      case uint16_t(Expr::Block):
-      case uint16_t(Expr::Loop):
-        if (!AstDecodeBlock(c, Expr(expr)))
+      case uint16_t(Op::Block):
+      case uint16_t(Op::Loop):
+        if (!AstDecodeBlock(c, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::If):
+      case uint16_t(Op::If):
         if (!AstDecodeIf(c))
             return false;
         break;
-      case uint16_t(Expr::Else):
+      case uint16_t(Op::Else):
         if (!AstDecodeElse(c))
             return false;
         break;
-      case uint16_t(Expr::End):
+      case uint16_t(Op::End):
         if (!AstDecodeEnd(c))
             return false;
         break;
-      case uint16_t(Expr::I32Clz):
-      case uint16_t(Expr::I32Ctz):
-      case uint16_t(Expr::I32Popcnt):
-        if (!AstDecodeUnary(c, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32Clz):
+      case uint16_t(Op::I32Ctz):
+      case uint16_t(Op::I32Popcnt):
+        if (!AstDecodeUnary(c, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Clz):
-      case uint16_t(Expr::I64Ctz):
-      case uint16_t(Expr::I64Popcnt):
-        if (!AstDecodeUnary(c, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64Clz):
+      case uint16_t(Op::I64Ctz):
+      case uint16_t(Op::I64Popcnt):
+        if (!AstDecodeUnary(c, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32Abs):
-      case uint16_t(Expr::F32Neg):
-      case uint16_t(Expr::F32Ceil):
-      case uint16_t(Expr::F32Floor):
-      case uint16_t(Expr::F32Sqrt):
-      case uint16_t(Expr::F32Trunc):
-      case uint16_t(Expr::F32Nearest):
-        if (!AstDecodeUnary(c, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32Abs):
+      case uint16_t(Op::F32Neg):
+      case uint16_t(Op::F32Ceil):
+      case uint16_t(Op::F32Floor):
+      case uint16_t(Op::F32Sqrt):
+      case uint16_t(Op::F32Trunc):
+      case uint16_t(Op::F32Nearest):
+        if (!AstDecodeUnary(c, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64Abs):
-      case uint16_t(Expr::F64Neg):
-      case uint16_t(Expr::F64Ceil):
-      case uint16_t(Expr::F64Floor):
-      case uint16_t(Expr::F64Sqrt):
-      case uint16_t(Expr::F64Trunc):
-      case uint16_t(Expr::F64Nearest):
-        if (!AstDecodeUnary(c, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64Abs):
+      case uint16_t(Op::F64Neg):
+      case uint16_t(Op::F64Ceil):
+      case uint16_t(Op::F64Floor):
+      case uint16_t(Op::F64Sqrt):
+      case uint16_t(Op::F64Trunc):
+      case uint16_t(Op::F64Nearest):
+        if (!AstDecodeUnary(c, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Add):
-      case uint16_t(Expr::I32Sub):
-      case uint16_t(Expr::I32Mul):
-      case uint16_t(Expr::I32DivS):
-      case uint16_t(Expr::I32DivU):
-      case uint16_t(Expr::I32RemS):
-      case uint16_t(Expr::I32RemU):
-      case uint16_t(Expr::I32And):
-      case uint16_t(Expr::I32Or):
-      case uint16_t(Expr::I32Xor):
-      case uint16_t(Expr::I32Shl):
-      case uint16_t(Expr::I32ShrS):
-      case uint16_t(Expr::I32ShrU):
-      case uint16_t(Expr::I32Rotl):
-      case uint16_t(Expr::I32Rotr):
-        if (!AstDecodeBinary(c, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32Add):
+      case uint16_t(Op::I32Sub):
+      case uint16_t(Op::I32Mul):
+      case uint16_t(Op::I32DivS):
+      case uint16_t(Op::I32DivU):
+      case uint16_t(Op::I32RemS):
+      case uint16_t(Op::I32RemU):
+      case uint16_t(Op::I32And):
+      case uint16_t(Op::I32Or):
+      case uint16_t(Op::I32Xor):
+      case uint16_t(Op::I32Shl):
+      case uint16_t(Op::I32ShrS):
+      case uint16_t(Op::I32ShrU):
+      case uint16_t(Op::I32Rotl):
+      case uint16_t(Op::I32Rotr):
+        if (!AstDecodeBinary(c, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Add):
-      case uint16_t(Expr::I64Sub):
-      case uint16_t(Expr::I64Mul):
-      case uint16_t(Expr::I64DivS):
-      case uint16_t(Expr::I64DivU):
-      case uint16_t(Expr::I64RemS):
-      case uint16_t(Expr::I64RemU):
-      case uint16_t(Expr::I64And):
-      case uint16_t(Expr::I64Or):
-      case uint16_t(Expr::I64Xor):
-      case uint16_t(Expr::I64Shl):
-      case uint16_t(Expr::I64ShrS):
-      case uint16_t(Expr::I64ShrU):
-      case uint16_t(Expr::I64Rotl):
-      case uint16_t(Expr::I64Rotr):
-        if (!AstDecodeBinary(c, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64Add):
+      case uint16_t(Op::I64Sub):
+      case uint16_t(Op::I64Mul):
+      case uint16_t(Op::I64DivS):
+      case uint16_t(Op::I64DivU):
+      case uint16_t(Op::I64RemS):
+      case uint16_t(Op::I64RemU):
+      case uint16_t(Op::I64And):
+      case uint16_t(Op::I64Or):
+      case uint16_t(Op::I64Xor):
+      case uint16_t(Op::I64Shl):
+      case uint16_t(Op::I64ShrS):
+      case uint16_t(Op::I64ShrU):
+      case uint16_t(Op::I64Rotl):
+      case uint16_t(Op::I64Rotr):
+        if (!AstDecodeBinary(c, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32Add):
-      case uint16_t(Expr::F32Sub):
-      case uint16_t(Expr::F32Mul):
-      case uint16_t(Expr::F32Div):
-      case uint16_t(Expr::F32Min):
-      case uint16_t(Expr::F32Max):
-      case uint16_t(Expr::F32CopySign):
-        if (!AstDecodeBinary(c, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32Add):
+      case uint16_t(Op::F32Sub):
+      case uint16_t(Op::F32Mul):
+      case uint16_t(Op::F32Div):
+      case uint16_t(Op::F32Min):
+      case uint16_t(Op::F32Max):
+      case uint16_t(Op::F32CopySign):
+        if (!AstDecodeBinary(c, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64Add):
-      case uint16_t(Expr::F64Sub):
-      case uint16_t(Expr::F64Mul):
-      case uint16_t(Expr::F64Div):
-      case uint16_t(Expr::F64Min):
-      case uint16_t(Expr::F64Max):
-      case uint16_t(Expr::F64CopySign):
-        if (!AstDecodeBinary(c, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64Add):
+      case uint16_t(Op::F64Sub):
+      case uint16_t(Op::F64Mul):
+      case uint16_t(Op::F64Div):
+      case uint16_t(Op::F64Min):
+      case uint16_t(Op::F64Max):
+      case uint16_t(Op::F64CopySign):
+        if (!AstDecodeBinary(c, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Eq):
-      case uint16_t(Expr::I32Ne):
-      case uint16_t(Expr::I32LtS):
-      case uint16_t(Expr::I32LtU):
-      case uint16_t(Expr::I32LeS):
-      case uint16_t(Expr::I32LeU):
-      case uint16_t(Expr::I32GtS):
-      case uint16_t(Expr::I32GtU):
-      case uint16_t(Expr::I32GeS):
-      case uint16_t(Expr::I32GeU):
-        if (!AstDecodeComparison(c, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32Eq):
+      case uint16_t(Op::I32Ne):
+      case uint16_t(Op::I32LtS):
+      case uint16_t(Op::I32LtU):
+      case uint16_t(Op::I32LeS):
+      case uint16_t(Op::I32LeU):
+      case uint16_t(Op::I32GtS):
+      case uint16_t(Op::I32GtU):
+      case uint16_t(Op::I32GeS):
+      case uint16_t(Op::I32GeU):
+        if (!AstDecodeComparison(c, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Eq):
-      case uint16_t(Expr::I64Ne):
-      case uint16_t(Expr::I64LtS):
-      case uint16_t(Expr::I64LtU):
-      case uint16_t(Expr::I64LeS):
-      case uint16_t(Expr::I64LeU):
-      case uint16_t(Expr::I64GtS):
-      case uint16_t(Expr::I64GtU):
-      case uint16_t(Expr::I64GeS):
-      case uint16_t(Expr::I64GeU):
-        if (!AstDecodeComparison(c, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64Eq):
+      case uint16_t(Op::I64Ne):
+      case uint16_t(Op::I64LtS):
+      case uint16_t(Op::I64LtU):
+      case uint16_t(Op::I64LeS):
+      case uint16_t(Op::I64LeU):
+      case uint16_t(Op::I64GtS):
+      case uint16_t(Op::I64GtU):
+      case uint16_t(Op::I64GeS):
+      case uint16_t(Op::I64GeU):
+        if (!AstDecodeComparison(c, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32Eq):
-      case uint16_t(Expr::F32Ne):
-      case uint16_t(Expr::F32Lt):
-      case uint16_t(Expr::F32Le):
-      case uint16_t(Expr::F32Gt):
-      case uint16_t(Expr::F32Ge):
-        if (!AstDecodeComparison(c, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32Eq):
+      case uint16_t(Op::F32Ne):
+      case uint16_t(Op::F32Lt):
+      case uint16_t(Op::F32Le):
+      case uint16_t(Op::F32Gt):
+      case uint16_t(Op::F32Ge):
+        if (!AstDecodeComparison(c, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64Eq):
-      case uint16_t(Expr::F64Ne):
-      case uint16_t(Expr::F64Lt):
-      case uint16_t(Expr::F64Le):
-      case uint16_t(Expr::F64Gt):
-      case uint16_t(Expr::F64Ge):
-        if (!AstDecodeComparison(c, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64Eq):
+      case uint16_t(Op::F64Ne):
+      case uint16_t(Op::F64Lt):
+      case uint16_t(Op::F64Le):
+      case uint16_t(Op::F64Gt):
+      case uint16_t(Op::F64Ge):
+        if (!AstDecodeComparison(c, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Eqz):
-        if (!AstDecodeConversion(c, ValType::I32, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32Eqz):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Eqz):
-      case uint16_t(Expr::I32WrapI64):
-        if (!AstDecodeConversion(c, ValType::I64, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I64Eqz):
+      case uint16_t(Op::I32WrapI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32TruncSF32):
-      case uint16_t(Expr::I32TruncUF32):
-      case uint16_t(Expr::I32ReinterpretF32):
-        if (!AstDecodeConversion(c, ValType::F32, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32TruncSF32):
+      case uint16_t(Op::I32TruncUF32):
+      case uint16_t(Op::I32ReinterpretF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32TruncSF64):
-      case uint16_t(Expr::I32TruncUF64):
-        if (!AstDecodeConversion(c, ValType::F64, ValType::I32, Expr(expr)))
+      case uint16_t(Op::I32TruncSF64):
+      case uint16_t(Op::I32TruncUF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::I32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64ExtendSI32):
-      case uint16_t(Expr::I64ExtendUI32):
-        if (!AstDecodeConversion(c, ValType::I32, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64ExtendSI32):
+      case uint16_t(Op::I64ExtendUI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64TruncSF32):
-      case uint16_t(Expr::I64TruncUF32):
-        if (!AstDecodeConversion(c, ValType::F32, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64TruncSF32):
+      case uint16_t(Op::I64TruncUF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64TruncSF64):
-      case uint16_t(Expr::I64TruncUF64):
-      case uint16_t(Expr::I64ReinterpretF64):
-        if (!AstDecodeConversion(c, ValType::F64, ValType::I64, Expr(expr)))
+      case uint16_t(Op::I64TruncSF64):
+      case uint16_t(Op::I64TruncUF64):
+      case uint16_t(Op::I64ReinterpretF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::I64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32ConvertSI32):
-      case uint16_t(Expr::F32ConvertUI32):
-      case uint16_t(Expr::F32ReinterpretI32):
-        if (!AstDecodeConversion(c, ValType::I32, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32ConvertSI32):
+      case uint16_t(Op::F32ConvertUI32):
+      case uint16_t(Op::F32ReinterpretI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32ConvertSI64):
-      case uint16_t(Expr::F32ConvertUI64):
-        if (!AstDecodeConversion(c, ValType::I64, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32ConvertSI64):
+      case uint16_t(Op::F32ConvertUI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32DemoteF64):
-        if (!AstDecodeConversion(c, ValType::F64, ValType::F32, Expr(expr)))
+      case uint16_t(Op::F32DemoteF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::F32, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64ConvertSI32):
-      case uint16_t(Expr::F64ConvertUI32):
-        if (!AstDecodeConversion(c, ValType::I32, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64ConvertSI32):
+      case uint16_t(Op::F64ConvertUI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64ConvertSI64):
-      case uint16_t(Expr::F64ConvertUI64):
-      case uint16_t(Expr::F64ReinterpretI64):
-        if (!AstDecodeConversion(c, ValType::I64, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64ConvertSI64):
+      case uint16_t(Op::F64ConvertUI64):
+      case uint16_t(Op::F64ReinterpretI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64PromoteF32):
-        if (!AstDecodeConversion(c, ValType::F32, ValType::F64, Expr(expr)))
+      case uint16_t(Op::F64PromoteF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::F64, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Load8S):
-      case uint16_t(Expr::I32Load8U):
-        if (!AstDecodeLoad(c, ValType::I32, 1, Expr(expr)))
+      case uint16_t(Op::I32Load8S):
+      case uint16_t(Op::I32Load8U):
+        if (!AstDecodeLoad(c, ValType::I32, 1, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Load16S):
-      case uint16_t(Expr::I32Load16U):
-        if (!AstDecodeLoad(c, ValType::I32, 2, Expr(expr)))
+      case uint16_t(Op::I32Load16S):
+      case uint16_t(Op::I32Load16U):
+        if (!AstDecodeLoad(c, ValType::I32, 2, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Load):
-        if (!AstDecodeLoad(c, ValType::I32, 4, Expr(expr)))
+      case uint16_t(Op::I32Load):
+        if (!AstDecodeLoad(c, ValType::I32, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Load8S):
-      case uint16_t(Expr::I64Load8U):
-        if (!AstDecodeLoad(c, ValType::I64, 1, Expr(expr)))
+      case uint16_t(Op::I64Load8S):
+      case uint16_t(Op::I64Load8U):
+        if (!AstDecodeLoad(c, ValType::I64, 1, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Load16S):
-      case uint16_t(Expr::I64Load16U):
-        if (!AstDecodeLoad(c, ValType::I64, 2, Expr(expr)))
+      case uint16_t(Op::I64Load16S):
+      case uint16_t(Op::I64Load16U):
+        if (!AstDecodeLoad(c, ValType::I64, 2, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Load32S):
-      case uint16_t(Expr::I64Load32U):
-        if (!AstDecodeLoad(c, ValType::I64, 4, Expr(expr)))
+      case uint16_t(Op::I64Load32S):
+      case uint16_t(Op::I64Load32U):
+        if (!AstDecodeLoad(c, ValType::I64, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Load):
-        if (!AstDecodeLoad(c, ValType::I64, 8, Expr(expr)))
+      case uint16_t(Op::I64Load):
+        if (!AstDecodeLoad(c, ValType::I64, 8, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32Load):
-        if (!AstDecodeLoad(c, ValType::F32, 4, Expr(expr)))
+      case uint16_t(Op::F32Load):
+        if (!AstDecodeLoad(c, ValType::F32, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64Load):
-        if (!AstDecodeLoad(c, ValType::F64, 8, Expr(expr)))
+      case uint16_t(Op::F64Load):
+        if (!AstDecodeLoad(c, ValType::F64, 8, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Store8):
-        if (!AstDecodeStore(c, ValType::I32, 1, Expr(expr)))
+      case uint16_t(Op::I32Store8):
+        if (!AstDecodeStore(c, ValType::I32, 1, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Store16):
-        if (!AstDecodeStore(c, ValType::I32, 2, Expr(expr)))
+      case uint16_t(Op::I32Store16):
+        if (!AstDecodeStore(c, ValType::I32, 2, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I32Store):
-        if (!AstDecodeStore(c, ValType::I32, 4, Expr(expr)))
+      case uint16_t(Op::I32Store):
+        if (!AstDecodeStore(c, ValType::I32, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Store8):
-        if (!AstDecodeStore(c, ValType::I64, 1, Expr(expr)))
+      case uint16_t(Op::I64Store8):
+        if (!AstDecodeStore(c, ValType::I64, 1, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Store16):
-        if (!AstDecodeStore(c, ValType::I64, 2, Expr(expr)))
+      case uint16_t(Op::I64Store16):
+        if (!AstDecodeStore(c, ValType::I64, 2, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Store32):
-        if (!AstDecodeStore(c, ValType::I64, 4, Expr(expr)))
+      case uint16_t(Op::I64Store32):
+        if (!AstDecodeStore(c, ValType::I64, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::I64Store):
-        if (!AstDecodeStore(c, ValType::I64, 8, Expr(expr)))
+      case uint16_t(Op::I64Store):
+        if (!AstDecodeStore(c, ValType::I64, 8, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F32Store):
-        if (!AstDecodeStore(c, ValType::F32, 4, Expr(expr)))
+      case uint16_t(Op::F32Store):
+        if (!AstDecodeStore(c, ValType::F32, 4, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::F64Store):
-        if (!AstDecodeStore(c, ValType::F64, 8, Expr(expr)))
+      case uint16_t(Op::F64Store):
+        if (!AstDecodeStore(c, ValType::F64, 8, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::CurrentMemory):
+      case uint16_t(Op::CurrentMemory):
         if (!AstDecodeCurrentMemory(c))
             return false;
         break;
-      case uint16_t(Expr::GrowMemory):
+      case uint16_t(Op::GrowMemory):
         if (!AstDecodeGrowMemory(c))
             return false;
         break;
-      case uint16_t(Expr::SetGlobal):
+      case uint16_t(Op::SetGlobal):
         if (!AstDecodeSetGlobal(c))
             return false;
         break;
-      case uint16_t(Expr::GetGlobal):
+      case uint16_t(Op::GetGlobal):
         if (!AstDecodeGetGlobal(c))
             return false;
         break;
-      case uint16_t(Expr::Br):
-      case uint16_t(Expr::BrIf):
-        if (!AstDecodeBranch(c, Expr(expr)))
+      case uint16_t(Op::Br):
+      case uint16_t(Op::BrIf):
+        if (!AstDecodeBranch(c, Op(op)))
             return false;
         break;
-      case uint16_t(Expr::BrTable):
+      case uint16_t(Op::BrTable):
         if (!AstDecodeBrTable(c))
             return false;
         break;
-      case uint16_t(Expr::Return):
+      case uint16_t(Op::Return):
         if (!AstDecodeReturn(c))
             return false;
         break;
-      case uint16_t(Expr::Unreachable):
+      case uint16_t(Op::Unreachable):
         if (!c.iter().readUnreachable())
             return false;
         tmp = new(c.lifo) AstUnreachable();
         if (!tmp)
             return false;
         if (!c.push(AstDecodeStackItem(tmp)))
             return false;
         break;
       default:
-        return c.iter().unrecognizedOpcode(expr);
+        return c.iter().unrecognizedOpcode(op);
     }
 
     AstExpr* lastExpr = c.top().expr;
     if (lastExpr)
         lastExpr->setOffset(exprOffset);
     return true;
 }
 
@@ -1787,17 +1787,17 @@ AstDecodeFunctionBody(AstDecodeContext &
         return c.d.fail("expected number of function body bytes");
 
     if (c.d.bytesRemain() < bodySize)
         return c.d.fail("function body length too big");
 
     const uint8_t* bodyBegin = c.d.currentPosition();
     const uint8_t* bodyEnd = bodyBegin + bodySize;
 
-    AstDecodeExprIter iter(c.d);
+    AstDecodeOpIter iter(c.d);
 
     uint32_t sigIndex = c.funcDefSigs()[funcDefIndex];
     const AstSig* sig = c.module().sigs()[sigIndex];
 
     AstValTypeVector vars(c.lifo);
     AstNameVector localsNames(c.lifo);
     AstExprVector body(c.lifo);
 
@@ -1834,17 +1834,17 @@ AstDecodeFunctionBody(AstDecodeContext &
     if (!c.depths().append(c.exprs().length()))
         return false;
 
     while (c.d.currentPosition() < bodyEnd) {
         if (!AstDecodeExpr(c))
             return false;
 
         const AstDecodeStackItem& item = c.top();
-        if (!item.expr) { // Expr::End was found
+        if (!item.expr) { // Op::End was found
             c.popBack();
             break;
         }
     }
 
     for (auto i = c.exprs().begin() + c.depths().back(), e = c.exprs().end();
          i != e; ++i) {
         if (!body.append(i->expr))
--- a/js/src/wasm/WasmBinaryToExperimentalText.cpp
+++ b/js/src/wasm/WasmBinaryToExperimentalText.cpp
@@ -358,17 +358,17 @@ PrintCallArgs(WasmPrintContext& c, const
 
     c.currentPrecedence = lastPrecedence;
     return true;
 }
 
 static bool
 PrintCall(WasmPrintContext& c, AstCall& call)
 {
-    if (call.expr() == Expr::Call) {
+    if (call.op() == Op::Call) {
         if (!c.buffer.append("call "))
             return false;
     } else {
         return false;
     }
 
     if (!PrintRef(c, call.func()))
         return false;
@@ -590,40 +590,41 @@ PrintBlockName(WasmPrintContext& c, cons
         return false;
     return c.buffer.append(":\n");
 }
 
 static bool
 PrintBlock(WasmPrintContext& c, AstBlock& block)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
-    if (block.expr() == Expr::Block) {
+    if (block.op() == Op::Block) {
         if (!c.buffer.append("{\n"))
             return false;
-    } else if (block.expr() == Expr::Loop) {
+    } else if (block.op() == Op::Loop) {
         if (!c.buffer.append("loop"))
             return false;
         if (!block.name().empty()) {
             if (!c.buffer.append(" "))
                 return false;
             if (!PrintName(c, block.name()))
                 return false;
         }
         if (!c.buffer.append(" {\n"))
             return false;
     } else
         return false;
 
     c.currentPrecedence = ExpressionPrecedence;
 
     bool skip = 0;
-    if (c.f.groupBlocks && block.expr() == Expr::Block &&
-        block.exprs().length() > 0 && block.exprs()[0]->kind() == AstExprKind::Block) {
+    if (c.f.groupBlocks && block.op() == Op::Block &&
+        block.exprs().length() > 0 && block.exprs()[0]->kind() == AstExprKind::Block)
+    {
         AstBlock* innerBlock = static_cast<AstBlock*>(block.exprs()[0]);
-        if (innerBlock->expr() == Expr::Block) {
+        if (innerBlock->op() == Op::Block) {
             if (!PrintGroupedBlock(c, *innerBlock))
                 return false;
             skip = 1;
             if (block.exprs().length() == 1 && block.name().empty()) {
               // Special case to resolve ambiguity in parsing of optional end block label.
               if (!PrintIndent(c))
                   return false;
               if (!c.buffer.append("$exit$:\n"))
@@ -633,373 +634,373 @@ PrintBlock(WasmPrintContext& c, AstBlock
     }
 
     c.indent++;
     if (!PrintExprList(c, block.exprs(), skip))
         return false;
     c.indent--;
     c.currentPrecedence = lastPrecedence;
 
-    if (block.expr() != Expr::Loop) {
+    if (block.op() != Op::Loop) {
         if (!PrintBlockName(c, block.name()))
           return false;
     }
 
     if (!PrintIndent(c))
         return false;
 
     return c.buffer.append("}");
 }
 
 static bool
-PrintUnaryOperator(WasmPrintContext& c, AstUnaryOperator& op)
+PrintUnaryOperator(WasmPrintContext& c, AstUnaryOperator& unary)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
 
     const char* opStr;
     const char* prefixStr = nullptr;
     PrintOperatorPrecedence precedence = OperatorPrecedence;
-    switch (op.expr()) {
-      case Expr::I32Clz:     opStr = "i32.clz"; break;
-      case Expr::I32Ctz:     opStr = "i32.ctz"; break;
-      case Expr::I32Popcnt:  opStr = "i32.popcnt"; break;
-      case Expr::I64Clz:     opStr = "i64.clz"; break;
-      case Expr::I64Ctz:     opStr = "i64.ctz"; break;
-      case Expr::I64Popcnt:  opStr = "i64.popcnt"; break;
-      case Expr::F32Abs:     opStr = "f32.abs"; break;
-      case Expr::F32Neg:     opStr = "f32.neg"; prefixStr = "-"; precedence = NegatePrecedence; break;
-      case Expr::F32Ceil:    opStr = "f32.ceil"; break;
-      case Expr::F32Floor:   opStr = "f32.floor"; break;
-      case Expr::F32Sqrt:    opStr = "f32.sqrt"; break;
-      case Expr::F32Trunc:   opStr = "f32.trunc"; break;
-      case Expr::F32Nearest: opStr = "f32.nearest"; break;
-      case Expr::F64Abs:     opStr = "f64.abs"; break;
-      case Expr::F64Neg:     opStr = "f64.neg"; prefixStr = "-"; precedence = NegatePrecedence; break;
-      case Expr::F64Ceil:    opStr = "f64.ceil"; break;
-      case Expr::F64Floor:   opStr = "f64.floor"; break;
-      case Expr::F64Sqrt:    opStr = "f64.sqrt"; break;
+    switch (unary.op()) {
+      case Op::I32Clz:     opStr = "i32.clz"; break;
+      case Op::I32Ctz:     opStr = "i32.ctz"; break;
+      case Op::I32Popcnt:  opStr = "i32.popcnt"; break;
+      case Op::I64Clz:     opStr = "i64.clz"; break;
+      case Op::I64Ctz:     opStr = "i64.ctz"; break;
+      case Op::I64Popcnt:  opStr = "i64.popcnt"; break;
+      case Op::F32Abs:     opStr = "f32.abs"; break;
+      case Op::F32Neg:     opStr = "f32.neg"; prefixStr = "-"; precedence = NegatePrecedence; break;
+      case Op::F32Ceil:    opStr = "f32.ceil"; break;
+      case Op::F32Floor:   opStr = "f32.floor"; break;
+      case Op::F32Sqrt:    opStr = "f32.sqrt"; break;
+      case Op::F32Trunc:   opStr = "f32.trunc"; break;
+      case Op::F32Nearest: opStr = "f32.nearest"; break;
+      case Op::F64Abs:     opStr = "f64.abs"; break;
+      case Op::F64Neg:     opStr = "f64.neg"; prefixStr = "-"; precedence = NegatePrecedence; break;
+      case Op::F64Ceil:    opStr = "f64.ceil"; break;
+      case Op::F64Floor:   opStr = "f64.floor"; break;
+      case Op::F64Sqrt:    opStr = "f64.sqrt"; break;
       default: return false;
     }
 
     if (c.f.allowAsciiOperators && prefixStr) {
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append("("))
                 return false;
         }
 
         c.currentPrecedence = precedence;
         if (!c.buffer.append(prefixStr, strlen(prefixStr)))
             return false;
-        if (!PrintExpr(c, *op.op()))
+        if (!PrintExpr(c, *unary.operand()))
             return false;
 
         if (!c.f.reduceParens || lastPrecedence > precedence) {
           if (!c.buffer.append(")"))
               return false;
         }
     } else {
         if (!c.buffer.append(opStr, strlen(opStr)))
             return false;
         if (!c.buffer.append("("))
             return false;
 
         c.currentPrecedence = ExpressionPrecedence;
-        if (!PrintExpr(c, *op.op()))
+        if (!PrintExpr(c, *unary.operand()))
             return false;
 
         if (!c.buffer.append(")"))
             return false;
     }
     c.currentPrecedence = lastPrecedence;
 
     return true;
 }
 
 static bool
-PrintBinaryOperator(WasmPrintContext& c, AstBinaryOperator& op)
+PrintBinaryOperator(WasmPrintContext& c, AstBinaryOperator& binary)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
 
     const char* opStr;
     const char* infixStr = nullptr;
     PrintOperatorPrecedence precedence;
-    switch (op.expr()) {
-      case Expr::I32Add:      opStr = "i32.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
-      case Expr::I32Sub:      opStr = "i32.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
-      case Expr::I32Mul:      opStr = "i32.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
-      case Expr::I32DivS:     opStr = "i32.div_s"; infixStr = "/s"; precedence = MultiplicationPrecedence; break;
-      case Expr::I32DivU:     opStr = "i32.div_u"; infixStr = "/u"; precedence = MultiplicationPrecedence; break;
-      case Expr::I32RemS:     opStr = "i32.rem_s"; infixStr = "%s"; precedence = MultiplicationPrecedence; break;
-      case Expr::I32RemU:     opStr = "i32.rem_u"; infixStr = "%u"; precedence = MultiplicationPrecedence; break;
-      case Expr::I32And:      opStr = "i32.and"; infixStr = "&"; precedence = BitwiseAndPrecedence; break;
-      case Expr::I32Or:       opStr = "i32.or"; infixStr = "|"; precedence = BitwiseOrPrecedence; break;
-      case Expr::I32Xor:      opStr = "i32.xor"; infixStr = "^"; precedence = BitwiseXorPrecedence; break;
-      case Expr::I32Shl:      opStr = "i32.shl"; infixStr = "<<"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::I32ShrS:     opStr = "i32.shr_s"; infixStr = ">>s"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::I32ShrU:     opStr = "i32.shr_u"; infixStr = ">>u"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::I64Add:      opStr = "i64.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
-      case Expr::I64Sub:      opStr = "i64.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
-      case Expr::I64Mul:      opStr = "i64.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
-      case Expr::I64DivS:     opStr = "i64.div_s"; infixStr = "/s"; precedence = MultiplicationPrecedence; break;
-      case Expr::I64DivU:     opStr = "i64.div_u"; infixStr = "/u"; precedence = MultiplicationPrecedence; break;
-      case Expr::I64RemS:     opStr = "i64.rem_s"; infixStr = "%s"; precedence = MultiplicationPrecedence; break;
-      case Expr::I64RemU:     opStr = "i64.rem_u"; infixStr = "%u"; precedence = MultiplicationPrecedence; break;
-      case Expr::I64And:      opStr = "i64.and"; infixStr = "&"; precedence = BitwiseAndPrecedence; break;
-      case Expr::I64Or:       opStr = "i64.or"; infixStr = "|"; precedence = BitwiseOrPrecedence; break;
-      case Expr::I64Xor:      opStr = "i64.xor"; infixStr = "^"; precedence = BitwiseXorPrecedence; break;
-      case Expr::I64Shl:      opStr = "i64.shl"; infixStr = "<<"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::I64ShrS:     opStr = "i64.shr_s"; infixStr = ">>s"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::I64ShrU:     opStr = "i64.shr_u"; infixStr = ">>u"; precedence = BitwiseShiftPrecedence; break;
-      case Expr::F32Add:      opStr = "f32.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
-      case Expr::F32Sub:      opStr = "f32.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
-      case Expr::F32Mul:      opStr = "f32.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
-      case Expr::F32Div:      opStr = "f32.div"; infixStr = "/"; precedence = MultiplicationPrecedence; break;
-      case Expr::F32Min:      opStr = "f32.min"; precedence = OperatorPrecedence; break;
-      case Expr::F32Max:      opStr = "f32.max"; precedence = OperatorPrecedence; break;
-      case Expr::F32CopySign: opStr = "f32.copysign"; precedence = OperatorPrecedence; break;
-      case Expr::F64Add:      opStr = "f64.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
-      case Expr::F64Sub:      opStr = "f64.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
-      case Expr::F64Mul:      opStr = "f64.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
-      case Expr::F64Div:      opStr = "f64.div"; infixStr = "/"; precedence = MultiplicationPrecedence; break;
-      case Expr::F64Min:      opStr = "f64.min"; precedence = OperatorPrecedence; break;
-      case Expr::F64Max:      opStr = "f64.max"; precedence = OperatorPrecedence; break;
-      case Expr::F64CopySign: opStr = "f64.copysign"; precedence = OperatorPrecedence; break;
+    switch (binary.op()) {
+      case Op::I32Add:      opStr = "i32.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
+      case Op::I32Sub:      opStr = "i32.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
+      case Op::I32Mul:      opStr = "i32.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
+      case Op::I32DivS:     opStr = "i32.div_s"; infixStr = "/s"; precedence = MultiplicationPrecedence; break;
+      case Op::I32DivU:     opStr = "i32.div_u"; infixStr = "/u"; precedence = MultiplicationPrecedence; break;
+      case Op::I32RemS:     opStr = "i32.rem_s"; infixStr = "%s"; precedence = MultiplicationPrecedence; break;
+      case Op::I32RemU:     opStr = "i32.rem_u"; infixStr = "%u"; precedence = MultiplicationPrecedence; break;
+      case Op::I32And:      opStr = "i32.and"; infixStr = "&"; precedence = BitwiseAndPrecedence; break;
+      case Op::I32Or:       opStr = "i32.or"; infixStr = "|"; precedence = BitwiseOrPrecedence; break;
+      case Op::I32Xor:      opStr = "i32.xor"; infixStr = "^"; precedence = BitwiseXorPrecedence; break;
+      case Op::I32Shl:      opStr = "i32.shl"; infixStr = "<<"; precedence = BitwiseShiftPrecedence; break;
+      case Op::I32ShrS:     opStr = "i32.shr_s"; infixStr = ">>s"; precedence = BitwiseShiftPrecedence; break;
+      case Op::I32ShrU:     opStr = "i32.shr_u"; infixStr = ">>u"; precedence = BitwiseShiftPrecedence; break;
+      case Op::I64Add:      opStr = "i64.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
+      case Op::I64Sub:      opStr = "i64.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
+      case Op::I64Mul:      opStr = "i64.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
+      case Op::I64DivS:     opStr = "i64.div_s"; infixStr = "/s"; precedence = MultiplicationPrecedence; break;
+      case Op::I64DivU:     opStr = "i64.div_u"; infixStr = "/u"; precedence = MultiplicationPrecedence; break;
+      case Op::I64RemS:     opStr = "i64.rem_s"; infixStr = "%s"; precedence = MultiplicationPrecedence; break;
+      case Op::I64RemU:     opStr = "i64.rem_u"; infixStr = "%u"; precedence = MultiplicationPrecedence; break;
+      case Op::I64And:      opStr = "i64.and"; infixStr = "&"; precedence = BitwiseAndPrecedence; break;
+      case Op::I64Or:       opStr = "i64.or"; infixStr = "|"; precedence = BitwiseOrPrecedence; break;
+      case Op::I64Xor:      opStr = "i64.xor"; infixStr = "^"; precedence = BitwiseXorPrecedence; break;
+      case Op::I64Shl:      opStr = "i64.shl"; infixStr = "<<"; precedence = BitwiseShiftPrecedence; break;
+      case Op::I64ShrS:     opStr = "i64.shr_s"; infixStr = ">>s"; precedence = BitwiseShiftPrecedence; break;
+      case Op::I64ShrU:     opStr = "i64.shr_u"; infixStr = ">>u"; precedence = BitwiseShiftPrecedence; break;
+      case Op::F32Add:      opStr = "f32.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
+      case Op::F32Sub:      opStr = "f32.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
+      case Op::F32Mul:      opStr = "f32.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
+      case Op::F32Div:      opStr = "f32.div"; infixStr = "/"; precedence = MultiplicationPrecedence; break;
+      case Op::F32Min:      opStr = "f32.min"; precedence = OperatorPrecedence; break;
+      case Op::F32Max:      opStr = "f32.max"; precedence = OperatorPrecedence; break;
+      case Op::F32CopySign: opStr = "f32.copysign"; precedence = OperatorPrecedence; break;
+      case Op::F64Add:      opStr = "f64.add"; infixStr = "+"; precedence = AdditionPrecedence; break;
+      case Op::F64Sub:      opStr = "f64.sub"; infixStr = "-"; precedence = AdditionPrecedence; break;
+      case Op::F64Mul:      opStr = "f64.mul"; infixStr = "*"; precedence = MultiplicationPrecedence; break;
+      case Op::F64Div:      opStr = "f64.div"; infixStr = "/"; precedence = MultiplicationPrecedence; break;
+      case Op::F64Min:      opStr = "f64.min"; precedence = OperatorPrecedence; break;
+      case Op::F64Max:      opStr = "f64.max"; precedence = OperatorPrecedence; break;
+      case Op::F64CopySign: opStr = "f64.copysign"; precedence = OperatorPrecedence; break;
       default: return false;
     }
 
     if (c.f.allowAsciiOperators && infixStr) {
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append("("))
                 return false;
         }
 
         c.currentPrecedence = precedence;
-        if (!PrintExpr(c, *op.lhs()))
+        if (!PrintExpr(c, *binary.lhs()))
             return false;
         if (!c.buffer.append(" "))
             return false;
         if (!c.buffer.append(infixStr, strlen(infixStr)))
             return false;
         if (!c.buffer.append(" "))
             return false;
         // case of  A / (B / C)
         c.currentPrecedence = (PrintOperatorPrecedence)(precedence + 1);
 
-        if (!PrintExpr(c, *op.rhs()))
+        if (!PrintExpr(c, *binary.rhs()))
             return false;
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append(")"))
                 return false;
         }
     } else {
         if (!c.buffer.append(opStr, strlen(opStr)))
             return false;
         if (!c.buffer.append("("))
             return false;
 
         c.currentPrecedence = ExpressionPrecedence;
-        if (!PrintExpr(c, *op.lhs()))
+        if (!PrintExpr(c, *binary.lhs()))
             return false;
         if (!c.buffer.append(", "))
             return false;
-        if (!PrintExpr(c, *op.rhs()))
+        if (!PrintExpr(c, *binary.rhs()))
             return false;
 
         if (!c.buffer.append(")"))
             return false;
     }
     c.currentPrecedence = lastPrecedence;
 
     return true;
 }
 
 static bool
-PrintTernaryOperator(WasmPrintContext& c, AstTernaryOperator& op)
+PrintTernaryOperator(WasmPrintContext& c, AstTernaryOperator& ternary)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
 
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::Select: opStr = "select"; break;
+    switch (ternary.op()) {
+      case Op::Select: opStr = "select"; break;
       default: return false;
     }
 
     if (!c.buffer.append(opStr, strlen(opStr)))
         return false;
     if (!c.buffer.append("("))
         return false;
 
     c.currentPrecedence = ExpressionPrecedence;
-    if (!PrintExpr(c, *op.op0()))
+    if (!PrintExpr(c, *ternary.op0()))
         return false;
     if (!c.buffer.append(", "))
         return false;
-    if (!PrintExpr(c, *op.op1()))
+    if (!PrintExpr(c, *ternary.op1()))
         return false;
     if (!c.buffer.append(", "))
         return false;
-    if (!PrintExpr(c, *op.op2()))
+    if (!PrintExpr(c, *ternary.op2()))
         return false;
 
     if (!c.buffer.append(")"))
         return false;
     c.currentPrecedence = lastPrecedence;
 
     return true;
 }
 
 static bool
-PrintComparisonOperator(WasmPrintContext& c, AstComparisonOperator& op)
+PrintComparisonOperator(WasmPrintContext& c, AstComparisonOperator& comp)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
 
     const char* opStr;
     const char* infixStr = nullptr;
     PrintOperatorPrecedence precedence;
-    switch (op.expr()) {
-      case Expr::I32Eq:  opStr = "i32.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
-      case Expr::I32Ne:  opStr = "i32.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
-      case Expr::I32LtS: opStr = "i32.lt_s"; infixStr = "<s"; precedence = ComparisonPrecedence; break;
-      case Expr::I32LtU: opStr = "i32.lt_u"; infixStr = "<u"; precedence = ComparisonPrecedence; break;
-      case Expr::I32LeS: opStr = "i32.le_s"; infixStr = "<=s"; precedence = ComparisonPrecedence; break;
-      case Expr::I32LeU: opStr = "i32.le_u"; infixStr = "<=u"; precedence = ComparisonPrecedence; break;
-      case Expr::I32GtS: opStr = "i32.gt_s"; infixStr = ">s"; precedence = ComparisonPrecedence; break;
-      case Expr::I32GtU: opStr = "i32.gt_u"; infixStr = ">u"; precedence = ComparisonPrecedence; break;
-      case Expr::I32GeS: opStr = "i32.ge_s"; infixStr = ">=s"; precedence = ComparisonPrecedence; break;
-      case Expr::I32GeU: opStr = "i32.ge_u"; infixStr = ">=u"; precedence = ComparisonPrecedence; break;
-      case Expr::I64Eq:  opStr = "i64.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
-      case Expr::I64Ne:  opStr = "i64.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
-      case Expr::I64LtS: opStr = "i64.lt_s"; infixStr = "<s"; precedence = ComparisonPrecedence; break;
-      case Expr::I64LtU: opStr = "i64.lt_u"; infixStr = "<u"; precedence = ComparisonPrecedence; break;
-      case Expr::I64LeS: opStr = "i64.le_s"; infixStr = "<=s"; precedence = ComparisonPrecedence; break;
-      case Expr::I64LeU: opStr = "i64.le_u"; infixStr = "<=u"; precedence = ComparisonPrecedence; break;
-      case Expr::I64GtS: opStr = "i64.gt_s"; infixStr = ">s"; precedence = ComparisonPrecedence; break;
-      case Expr::I64GtU: opStr = "i64.gt_u"; infixStr = ">u"; precedence = ComparisonPrecedence; break;
-      case Expr::I64GeS: opStr = "i64.ge_s"; infixStr = ">=s"; precedence = ComparisonPrecedence; break;
-      case Expr::I64GeU: opStr = "i64.ge_u"; infixStr = ">=u"; precedence = ComparisonPrecedence; break;
-      case Expr::F32Eq:  opStr = "f32.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
-      case Expr::F32Ne:  opStr = "f32.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
-      case Expr::F32Lt:  opStr = "f32.lt"; infixStr = "<"; precedence = ComparisonPrecedence; break;
-      case Expr::F32Le:  opStr = "f32.le"; infixStr = "<="; precedence = ComparisonPrecedence; break;
-      case Expr::F32Gt:  opStr = "f32.gt"; infixStr = ">"; precedence = ComparisonPrecedence; break;
-      case Expr::F32Ge:  opStr = "f32.ge"; infixStr = ">="; precedence = ComparisonPrecedence; break;
-      case Expr::F64Eq:  opStr = "f64.eq"; infixStr = "=="; precedence = ComparisonPrecedence; break;
-      case Expr::F64Ne:  opStr = "f64.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
-      case Expr::F64Lt:  opStr = "f64.lt"; infixStr = "<"; precedence = EqualityPrecedence; break;
-      case Expr::F64Le:  opStr = "f64.le"; infixStr = "<="; precedence = ComparisonPrecedence; break;
-      case Expr::F64Gt:  opStr = "f64.gt"; infixStr = ">"; precedence = ComparisonPrecedence; break;
-      case Expr::F64Ge:  opStr = "f64.ge"; infixStr = ">="; precedence = ComparisonPrecedence; break;
+    switch (comp.op()) {
+      case Op::I32Eq:  opStr = "i32.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
+      case Op::I32Ne:  opStr = "i32.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
+      case Op::I32LtS: opStr = "i32.lt_s"; infixStr = "<s"; precedence = ComparisonPrecedence; break;
+      case Op::I32LtU: opStr = "i32.lt_u"; infixStr = "<u"; precedence = ComparisonPrecedence; break;
+      case Op::I32LeS: opStr = "i32.le_s"; infixStr = "<=s"; precedence = ComparisonPrecedence; break;
+      case Op::I32LeU: opStr = "i32.le_u"; infixStr = "<=u"; precedence = ComparisonPrecedence; break;
+      case Op::I32GtS: opStr = "i32.gt_s"; infixStr = ">s"; precedence = ComparisonPrecedence; break;
+      case Op::I32GtU: opStr = "i32.gt_u"; infixStr = ">u"; precedence = ComparisonPrecedence; break;
+      case Op::I32GeS: opStr = "i32.ge_s"; infixStr = ">=s"; precedence = ComparisonPrecedence; break;
+      case Op::I32GeU: opStr = "i32.ge_u"; infixStr = ">=u"; precedence = ComparisonPrecedence; break;
+      case Op::I64Eq:  opStr = "i64.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
+      case Op::I64Ne:  opStr = "i64.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
+      case Op::I64LtS: opStr = "i64.lt_s"; infixStr = "<s"; precedence = ComparisonPrecedence; break;
+      case Op::I64LtU: opStr = "i64.lt_u"; infixStr = "<u"; precedence = ComparisonPrecedence; break;
+      case Op::I64LeS: opStr = "i64.le_s"; infixStr = "<=s"; precedence = ComparisonPrecedence; break;
+      case Op::I64LeU: opStr = "i64.le_u"; infixStr = "<=u"; precedence = ComparisonPrecedence; break;
+      case Op::I64GtS: opStr = "i64.gt_s"; infixStr = ">s"; precedence = ComparisonPrecedence; break;
+      case Op::I64GtU: opStr = "i64.gt_u"; infixStr = ">u"; precedence = ComparisonPrecedence; break;
+      case Op::I64GeS: opStr = "i64.ge_s"; infixStr = ">=s"; precedence = ComparisonPrecedence; break;
+      case Op::I64GeU: opStr = "i64.ge_u"; infixStr = ">=u"; precedence = ComparisonPrecedence; break;
+      case Op::F32Eq:  opStr = "f32.eq"; infixStr = "=="; precedence = EqualityPrecedence; break;
+      case Op::F32Ne:  opStr = "f32.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
+      case Op::F32Lt:  opStr = "f32.lt"; infixStr = "<"; precedence = ComparisonPrecedence; break;
+      case Op::F32Le:  opStr = "f32.le"; infixStr = "<="; precedence = ComparisonPrecedence; break;
+      case Op::F32Gt:  opStr = "f32.gt"; infixStr = ">"; precedence = ComparisonPrecedence; break;
+      case Op::F32Ge:  opStr = "f32.ge"; infixStr = ">="; precedence = ComparisonPrecedence; break;
+      case Op::F64Eq:  opStr = "f64.eq"; infixStr = "=="; precedence = ComparisonPrecedence; break;
+      case Op::F64Ne:  opStr = "f64.ne"; infixStr = "!="; precedence = EqualityPrecedence; break;
+      case Op::F64Lt:  opStr = "f64.lt"; infixStr = "<"; precedence = EqualityPrecedence; break;
+      case Op::F64Le:  opStr = "f64.le"; infixStr = "<="; precedence = ComparisonPrecedence; break;
+      case Op::F64Gt:  opStr = "f64.gt"; infixStr = ">"; precedence = ComparisonPrecedence; break;
+      case Op::F64Ge:  opStr = "f64.ge"; infixStr = ">="; precedence = ComparisonPrecedence; break;
       default: return false;
     }
 
     if (c.f.allowAsciiOperators && infixStr) {
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append("("))
                 return false;
         }
         c.currentPrecedence = precedence;
-        if (!PrintExpr(c, *op.lhs()))
+        if (!PrintExpr(c, *comp.lhs()))
             return false;
         if (!c.buffer.append(" "))
             return false;
         if (!c.buffer.append(infixStr, strlen(infixStr)))
             return false;
         if (!c.buffer.append(" "))
             return false;
         // case of  A == (B == C)
         c.currentPrecedence = (PrintOperatorPrecedence)(precedence + 1);
-        if (!PrintExpr(c, *op.rhs()))
+        if (!PrintExpr(c, *comp.rhs()))
             return false;
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append(")"))
                 return false;
         }
     } else {
         if (!c.buffer.append(opStr, strlen(opStr)))
             return false;
         c.currentPrecedence = ExpressionPrecedence;
         if (!c.buffer.append("("))
             return false;
-        if (!PrintExpr(c, *op.lhs()))
+        if (!PrintExpr(c, *comp.lhs()))
             return false;
         if (!c.buffer.append(", "))
             return false;
-        if (!PrintExpr(c, *op.rhs()))
+        if (!PrintExpr(c, *comp.rhs()))
             return false;
         if (!c.buffer.append(")"))
             return false;
     }
     c.currentPrecedence = lastPrecedence;
 
     return true;
 }
 
 static bool
-PrintConversionOperator(WasmPrintContext& c, AstConversionOperator& op)
+PrintConversionOperator(WasmPrintContext& c, AstConversionOperator& conv)
 {
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
 
     const char* opStr;
     const char* prefixStr = nullptr;
     PrintOperatorPrecedence precedence = ExpressionPrecedence;
-    switch (op.expr()) {
-      case Expr::I32Eqz:            opStr = "i32.eqz"; prefixStr = "!"; precedence = EqzPrecedence; break;
-      case Expr::I32WrapI64:        opStr = "i32.wrap/i64"; break;
-      case Expr::I32TruncSF32:      opStr = "i32.trunc_s/f32"; break;
-      case Expr::I32TruncUF32:      opStr = "i32.trunc_u/f32"; break;
-      case Expr::I32ReinterpretF32: opStr = "i32.reinterpret/f32"; break;
-      case Expr::I32TruncSF64:      opStr = "i32.trunc_s/f64"; break;
-      case Expr::I32TruncUF64:      opStr = "i32.trunc_u/f64"; break;
-      case Expr::I64Eqz:            opStr = "i64.eqz"; prefixStr = "!"; precedence = EqzPrecedence; break;
-      case Expr::I64ExtendSI32:     opStr = "i64.extend_s/i32"; break;
-      case Expr::I64ExtendUI32:     opStr = "i64.extend_u/i32"; break;
-      case Expr::I64TruncSF32:      opStr = "i64.trunc_s/f32"; break;
-      case Expr::I64TruncUF32:      opStr = "i64.trunc_u/f32"; break;
-      case Expr::I64TruncSF64:      opStr = "i64.trunc_s/f64"; break;
-      case Expr::I64TruncUF64:      opStr = "i64.trunc_u/f64"; break;
-      case Expr::I64ReinterpretF64: opStr = "i64.reinterpret/f64"; break;
-      case Expr::F32ConvertSI32:    opStr = "f32.convert_s/i32"; break;
-      case Expr::F32ConvertUI32:    opStr = "f32.convert_u/i32"; break;
-      case Expr::F32ReinterpretI32: opStr = "f32.reinterpret/i32"; break;
-      case Expr::F32ConvertSI64:    opStr = "f32.convert_s/i64"; break;
-      case Expr::F32ConvertUI64:    opStr = "f32.convert_u/i64"; break;
-      case Expr::F32DemoteF64:      opStr = "f32.demote/f64"; break;
-      case Expr::F64ConvertSI32:    opStr = "f64.convert_s/i32"; break;
-      case Expr::F64ConvertUI32:    opStr = "f64.convert_u/i32"; break;
-      case Expr::F64ConvertSI64:    opStr = "f64.convert_s/i64"; break;
-      case Expr::F64ConvertUI64:    opStr = "f64.convert_u/i64"; break;
-      case Expr::F64ReinterpretI64: opStr = "f64.reinterpret/i64"; break;
-      case Expr::F64PromoteF32:     opStr = "f64.promote/f32"; break;
+    switch (conv.op()) {
+      case Op::I32Eqz:            opStr = "i32.eqz"; prefixStr = "!"; precedence = EqzPrecedence; break;
+      case Op::I32WrapI64:        opStr = "i32.wrap/i64"; break;
+      case Op::I32TruncSF32:      opStr = "i32.trunc_s/f32"; break;
+      case Op::I32TruncUF32:      opStr = "i32.trunc_u/f32"; break;
+      case Op::I32ReinterpretF32: opStr = "i32.reinterpret/f32"; break;
+      case Op::I32TruncSF64:      opStr = "i32.trunc_s/f64"; break;
+      case Op::I32TruncUF64:      opStr = "i32.trunc_u/f64"; break;
+      case Op::I64Eqz:            opStr = "i64.eqz"; prefixStr = "!"; precedence = EqzPrecedence; break;
+      case Op::I64ExtendSI32:     opStr = "i64.extend_s/i32"; break;
+      case Op::I64ExtendUI32:     opStr = "i64.extend_u/i32"; break;
+      case Op::I64TruncSF32:      opStr = "i64.trunc_s/f32"; break;
+      case Op::I64TruncUF32:      opStr = "i64.trunc_u/f32"; break;
+      case Op::I64TruncSF64:      opStr = "i64.trunc_s/f64"; break;
+      case Op::I64TruncUF64:      opStr = "i64.trunc_u/f64"; break;
+      case Op::I64ReinterpretF64: opStr = "i64.reinterpret/f64"; break;
+      case Op::F32ConvertSI32:    opStr = "f32.convert_s/i32"; break;
+      case Op::F32ConvertUI32:    opStr = "f32.convert_u/i32"; break;
+      case Op::F32ReinterpretI32: opStr = "f32.reinterpret/i32"; break;
+      case Op::F32ConvertSI64:    opStr = "f32.convert_s/i64"; break;
+      case Op::F32ConvertUI64:    opStr = "f32.convert_u/i64"; break;
+      case Op::F32DemoteF64:      opStr = "f32.demote/f64"; break;
+      case Op::F64ConvertSI32:    opStr = "f64.convert_s/i32"; break;
+      case Op::F64ConvertUI32:    opStr = "f64.convert_u/i32"; break;
+      case Op::F64ConvertSI64:    opStr = "f64.convert_s/i64"; break;
+      case Op::F64ConvertUI64:    opStr = "f64.convert_u/i64"; break;
+      case Op::F64ReinterpretI64: opStr = "f64.reinterpret/i64"; break;
+      case Op::F64PromoteF32:     opStr = "f64.promote/f32"; break;
       default: return false;
     }
 
     if (c.f.allowAsciiOperators && prefixStr) {
         if (!c.f.reduceParens || lastPrecedence > precedence) {
             if (!c.buffer.append("("))
                 return false;
         }
 
         c.currentPrecedence = precedence;
         if (!c.buffer.append(prefixStr, strlen(prefixStr)))
             return false;
-        if (!PrintExpr(c, *op.op()))
+        if (!PrintExpr(c, *conv.operand()))
             return false;
 
         if (!c.f.reduceParens || lastPrecedence > precedence) {
           if (!c.buffer.append(")"))
               return false;
         }
     } else {
         if (!c.buffer.append(opStr, strlen(opStr)))
             return false;
         if (!c.buffer.append("("))
             return false;
 
         c.currentPrecedence = ExpressionPrecedence;
-        if (!PrintExpr(c, *op.op()))
+        if (!PrintExpr(c, *conv.operand()))
             return false;
 
         if (!c.buffer.append(")"))
             return false;
     }
     c.currentPrecedence = lastPrecedence;
 
     return true;
@@ -1089,83 +1090,83 @@ PrintLoad(WasmPrintContext& c, AstLoad& 
 
     c.currentPrecedence = LoadOperatorPrecedence;
     if (!c.f.reduceParens || lastPrecedence > LoadOperatorPrecedence) {
         if (!c.buffer.append("("))
             return false;
     }
 
     uint32_t defaultAlignLog2;
-    switch (load.expr()) {
-      case Expr::I32Load8S:
+    switch (load.op()) {
+      case Op::I32Load8S:
         if (!c.buffer.append("i32:8s"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Load8S:
+      case Op::I64Load8S:
         if (!c.buffer.append("i64:8s"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Load8U:
+      case Op::I32Load8U:
         if (!c.buffer.append("i32:8u"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Load8U:
+      case Op::I64Load8U:
         if (!c.buffer.append("i64:8u"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Load16S:
+      case Op::I32Load16S:
         if (!c.buffer.append("i32:16s"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load16S:
+      case Op::I64Load16S:
         if (!c.buffer.append("i64:16s"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I32Load16U:
+      case Op::I32Load16U:
         if (!c.buffer.append("i32:16u"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load16U:
+      case Op::I64Load16U:
         if (!c.buffer.append("i64:16u"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load32S:
+      case Op::I64Load32S:
         if (!c.buffer.append("i64:32s"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Load32U:
+      case Op::I64Load32U:
         if (!c.buffer.append("i64:32u"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I32Load:
+      case Op::I32Load:
         if (!c.buffer.append("i32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Load:
+      case Op::I64Load:
         if (!c.buffer.append("i64"))
             return false;
         defaultAlignLog2 = 3;
         break;
-      case Expr::F32Load:
+      case Op::F32Load:
         if (!c.buffer.append("f32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::F64Load:
+      case Op::F64Load:
         if (!c.buffer.append("f64"))
             return false;
         defaultAlignLog2 = 3;
         break;
       default:
         return false;
     }
 
@@ -1188,58 +1189,58 @@ PrintStore(WasmPrintContext& c, AstStore
 
     c.currentPrecedence = StoreOperatorPrecedence;
     if (!c.f.reduceParens || lastPrecedence > StoreOperatorPrecedence) {
         if (!c.buffer.append("("))
             return false;
     }
 
     uint32_t defaultAlignLog2;
-    switch (store.expr()) {
-      case Expr::I32Store8:
+    switch (store.op()) {
+      case Op::I32Store8:
         if (!c.buffer.append("i32:8"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Store8:
+      case Op::I64Store8:
         if (!c.buffer.append("i64:8"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Store16:
+      case Op::I32Store16:
         if (!c.buffer.append("i32:16"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Store16:
+      case Op::I64Store16:
         if (!c.buffer.append("i64:16"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Store32:
+      case Op::I64Store32:
         if (!c.buffer.append("i64:32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I32Store:
+      case Op::I32Store:
         if (!c.buffer.append("i32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Store:
+      case Op::I64Store:
         if (!c.buffer.append("i64"))
             return false;
         defaultAlignLog2 = 3;
         break;
-      case Expr::F32Store:
+      case Op::F32Store:
         if (!c.buffer.append("f32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::F64Store:
+      case Op::F64Store:
         if (!c.buffer.append("f64"))
             return false;
         defaultAlignLog2 = 3;
         break;
       default:
         return false;
     }
 
@@ -1259,41 +1260,41 @@ PrintStore(WasmPrintContext& c, AstStore
 
     c.currentPrecedence = lastPrecedence;
     return true;
 }
 
 static bool
 PrintBranch(WasmPrintContext& c, AstBranch& branch)
 {
-    Expr expr = branch.expr();
-    MOZ_ASSERT(expr == Expr::BrIf || expr == Expr::Br);
+    Op op = branch.op();
+    MOZ_ASSERT(op == Op::BrIf || op == Op::Br);
 
-    if (expr == Expr::BrIf ? !c.buffer.append("br_if ") : !c.buffer.append("br "))
+    if (op == Op::BrIf ? !c.buffer.append("br_if ") : !c.buffer.append("br "))
         return false;
 
-    if (expr == Expr::BrIf || branch.maybeValue()) {
+    if (op == Op::BrIf || branch.maybeValue()) {
         if (!c.buffer.append('('))
             return false;
     }
 
-    if (expr == Expr::BrIf) {
+    if (op == Op::BrIf) {
         if (!PrintExpr(c, branch.cond()))
             return false;
     }
 
     if (branch.maybeValue()) {
         if (!c.buffer.append(", "))
             return false;
 
         if (!PrintExpr(c, *(branch.maybeValue())))
             return false;
     }
 
-    if (expr == Expr::BrIf || branch.maybeValue()) {
+    if (op == Op::BrIf || branch.maybeValue()) {
         if (!c.buffer.append(") "))
             return false;
     }
 
     if (!PrintRef(c, branch.target()))
         return false;
 
     return true;
@@ -1392,17 +1393,17 @@ static bool
 PrintGrowMemory(WasmPrintContext& c, AstGrowMemory& gm)
 {
     if (!c.buffer.append("grow_memory("))
         return false;
 
     PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
     c.currentPrecedence = ExpressionPrecedence;
 
-    if (!PrintExpr(c, *gm.op()))
+    if (!PrintExpr(c, *gm.operand()))
         return false;
 
     if (!c.buffer.append(")"))
         return false;
 
     c.currentPrecedence = lastPrecedence;
     return true;
 }
--- a/js/src/wasm/WasmBinaryToText.cpp
+++ b/js/src/wasm/WasmBinaryToText.cpp
@@ -297,17 +297,17 @@ RenderCall(WasmRenderContext& c, AstCall
 {
     if (!RenderCallArgs(c, call.args()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, call);
-    if (call.expr() == Expr::Call) {
+    if (call.op() == Op::Call) {
         if (!c.buffer.append("call "))
             return false;
     } else {
         return Fail(c, "unexpected operator");
     }
 
     return RenderRef(c, call.func());
 }
@@ -439,20 +439,20 @@ RenderExprList(WasmRenderContext& c, con
 
 static bool
 RenderBlock(WasmRenderContext& c, AstBlock& block)
 {
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, block);
-    if (block.expr() == Expr::Block) {
+    if (block.op() == Op::Block) {
         if (!c.buffer.append("block"))
             return false;
-    } else if (block.expr() == Expr::Loop) {
+    } else if (block.op() == Op::Loop) {
         if (!c.buffer.append("loop"))
             return false;
     } else {
         return Fail(c, "unexpected block kind");
     }
 
     if (!RenderBlockNameAndSignature(c, block.name(), block.type()))
         return false;
@@ -484,243 +484,243 @@ RenderCurrentMemory(WasmRenderContext& c
         return false;
 
     return c.buffer.append("current_memory\n");
 }
 
 static bool
 RenderGrowMemory(WasmRenderContext& c, AstGrowMemory& gm)
 {
-    if (!RenderExpr(c, *gm.op()))
+    if (!RenderExpr(c, *gm.operand()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, gm);
     return c.buffer.append("grow_memory\n");
 }
 
 static bool
-RenderUnaryOperator(WasmRenderContext& c, AstUnaryOperator& op)
+RenderUnaryOperator(WasmRenderContext& c, AstUnaryOperator& unary)
 {
-    if (!RenderExpr(c, *op.op()))
+    if (!RenderExpr(c, *unary.operand()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
-    MAP_AST_EXPR(c, op);
+    MAP_AST_EXPR(c, unary);
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::I32Eqz:     opStr = "i32.eqz"; break;
-      case Expr::I32Clz:     opStr = "i32.clz"; break;
-      case Expr::I32Ctz:     opStr = "i32.ctz"; break;
-      case Expr::I32Popcnt:  opStr = "i32.popcnt"; break;
-      case Expr::I64Clz:     opStr = "i64.clz"; break;
-      case Expr::I64Ctz:     opStr = "i64.ctz"; break;
-      case Expr::I64Popcnt:  opStr = "i64.popcnt"; break;
-      case Expr::F32Abs:     opStr = "f32.abs"; break;
-      case Expr::F32Neg:     opStr = "f32.neg"; break;
-      case Expr::F32Ceil:    opStr = "f32.ceil"; break;
-      case Expr::F32Floor:   opStr = "f32.floor"; break;
-      case Expr::F32Sqrt:    opStr = "f32.sqrt"; break;
-      case Expr::F32Trunc:   opStr = "f32.trunc"; break;
-      case Expr::F32Nearest: opStr = "f32.nearest"; break;
-      case Expr::F64Abs:     opStr = "f64.abs"; break;
-      case Expr::F64Neg:     opStr = "f64.neg"; break;
-      case Expr::F64Ceil:    opStr = "f64.ceil"; break;
-      case Expr::F64Floor:   opStr = "f64.floor"; break;
-      case Expr::F64Nearest: opStr = "f64.nearest"; break;
-      case Expr::F64Sqrt:    opStr = "f64.sqrt"; break;
-      case Expr::F64Trunc:   opStr = "f64.trunc"; break;
+    switch (unary.op()) {
+      case Op::I32Eqz:     opStr = "i32.eqz"; break;
+      case Op::I32Clz:     opStr = "i32.clz"; break;
+      case Op::I32Ctz:     opStr = "i32.ctz"; break;
+      case Op::I32Popcnt:  opStr = "i32.popcnt"; break;
+      case Op::I64Clz:     opStr = "i64.clz"; break;
+      case Op::I64Ctz:     opStr = "i64.ctz"; break;
+      case Op::I64Popcnt:  opStr = "i64.popcnt"; break;
+      case Op::F32Abs:     opStr = "f32.abs"; break;
+      case Op::F32Neg:     opStr = "f32.neg"; break;
+      case Op::F32Ceil:    opStr = "f32.ceil"; break;
+      case Op::F32Floor:   opStr = "f32.floor"; break;
+      case Op::F32Sqrt:    opStr = "f32.sqrt"; break;
+      case Op::F32Trunc:   opStr = "f32.trunc"; break;
+      case Op::F32Nearest: opStr = "f32.nearest"; break;
+      case Op::F64Abs:     opStr = "f64.abs"; break;
+      case Op::F64Neg:     opStr = "f64.neg"; break;
+      case Op::F64Ceil:    opStr = "f64.ceil"; break;
+      case Op::F64Floor:   opStr = "f64.floor"; break;
+      case Op::F64Nearest: opStr = "f64.nearest"; break;
+      case Op::F64Sqrt:    opStr = "f64.sqrt"; break;
+      case Op::F64Trunc:   opStr = "f64.trunc"; break;
       default:               return Fail(c, "unexpected unary operator");
     }
 
     return c.buffer.append(opStr, strlen(opStr));
 }
 
 static bool
-RenderBinaryOperator(WasmRenderContext& c, AstBinaryOperator& op)
+RenderBinaryOperator(WasmRenderContext& c, AstBinaryOperator& binary)
 {
-    if (!RenderExpr(c, *op.lhs()))
+    if (!RenderExpr(c, *binary.lhs()))
         return false;
-    if (!RenderExpr(c, *op.rhs()))
+    if (!RenderExpr(c, *binary.rhs()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
-    MAP_AST_EXPR(c, op);
+    MAP_AST_EXPR(c, binary);
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::I32Add:      opStr = "i32.add"; break;
-      case Expr::I32Sub:      opStr = "i32.sub"; break;
-      case Expr::I32Mul:      opStr = "i32.mul"; break;
-      case Expr::I32DivS:     opStr = "i32.div_s"; break;
-      case Expr::I32DivU:     opStr = "i32.div_u"; break;
-      case Expr::I32RemS:     opStr = "i32.rem_s"; break;
-      case Expr::I32RemU:     opStr = "i32.rem_u"; break;
-      case Expr::I32And:      opStr = "i32.and"; break;
-      case Expr::I32Or:       opStr = "i32.or"; break;
-      case Expr::I32Xor:      opStr = "i32.xor"; break;
-      case Expr::I32Shl:      opStr = "i32.shl"; break;
-      case Expr::I32ShrS:     opStr = "i32.shr_s"; break;
-      case Expr::I32ShrU:     opStr = "i32.shr_u"; break;
-      case Expr::I32Rotl:     opStr = "i32.rotl"; break;
-      case Expr::I32Rotr:     opStr = "i32.rotr"; break;
-      case Expr::I64Add:      opStr = "i64.add"; break;
-      case Expr::I64Sub:      opStr = "i64.sub"; break;
-      case Expr::I64Mul:      opStr = "i64.mul"; break;
-      case Expr::I64DivS:     opStr = "i64.div_s"; break;
-      case Expr::I64DivU:     opStr = "i64.div_u"; break;
-      case Expr::I64RemS:     opStr = "i64.rem_s"; break;
-      case Expr::I64RemU:     opStr = "i64.rem_u"; break;
-      case Expr::I64And:      opStr = "i64.and"; break;
-      case Expr::I64Or:       opStr = "i64.or"; break;
-      case Expr::I64Xor:      opStr = "i64.xor"; break;
-      case Expr::I64Shl:      opStr = "i64.shl"; break;
-      case Expr::I64ShrS:     opStr = "i64.shr_s"; break;
-      case Expr::I64ShrU:     opStr = "i64.shr_u"; break;
-      case Expr::I64Rotl:     opStr = "i64.rotl"; break;
-      case Expr::I64Rotr:     opStr = "i64.rotr"; break;
-      case Expr::F32Add:      opStr = "f32.add"; break;
-      case Expr::F32Sub:      opStr = "f32.sub"; break;
-      case Expr::F32Mul:      opStr = "f32.mul"; break;
-      case Expr::F32Div:      opStr = "f32.div"; break;
-      case Expr::F32Min:      opStr = "f32.min"; break;
-      case Expr::F32Max:      opStr = "f32.max"; break;
-      case Expr::F32CopySign: opStr = "f32.copysign"; break;
-      case Expr::F64Add:      opStr = "f64.add"; break;
-      case Expr::F64Sub:      opStr = "f64.sub"; break;
-      case Expr::F64Mul:      opStr = "f64.mul"; break;
-      case Expr::F64Div:      opStr = "f64.div"; break;
-      case Expr::F64Min:      opStr = "f64.min"; break;
-      case Expr::F64Max:      opStr = "f64.max"; break;
-      case Expr::F64CopySign: opStr = "f64.copysign"; break;
+    switch (binary.op()) {
+      case Op::I32Add:      opStr = "i32.add"; break;
+      case Op::I32Sub:      opStr = "i32.sub"; break;
+      case Op::I32Mul:      opStr = "i32.mul"; break;
+      case Op::I32DivS:     opStr = "i32.div_s"; break;
+      case Op::I32DivU:     opStr = "i32.div_u"; break;
+      case Op::I32RemS:     opStr = "i32.rem_s"; break;
+      case Op::I32RemU:     opStr = "i32.rem_u"; break;
+      case Op::I32And:      opStr = "i32.and"; break;
+      case Op::I32Or:       opStr = "i32.or"; break;
+      case Op::I32Xor:      opStr = "i32.xor"; break;
+      case Op::I32Shl:      opStr = "i32.shl"; break;
+      case Op::I32ShrS:     opStr = "i32.shr_s"; break;
+      case Op::I32ShrU:     opStr = "i32.shr_u"; break;
+      case Op::I32Rotl:     opStr = "i32.rotl"; break;
+      case Op::I32Rotr:     opStr = "i32.rotr"; break;
+      case Op::I64Add:      opStr = "i64.add"; break;
+      case Op::I64Sub:      opStr = "i64.sub"; break;
+      case Op::I64Mul:      opStr = "i64.mul"; break;
+      case Op::I64DivS:     opStr = "i64.div_s"; break;
+      case Op::I64DivU:     opStr = "i64.div_u"; break;
+      case Op::I64RemS:     opStr = "i64.rem_s"; break;
+      case Op::I64RemU:     opStr = "i64.rem_u"; break;
+      case Op::I64And:      opStr = "i64.and"; break;
+      case Op::I64Or:       opStr = "i64.or"; break;
+      case Op::I64Xor:      opStr = "i64.xor"; break;
+      case Op::I64Shl:      opStr = "i64.shl"; break;
+      case Op::I64ShrS:     opStr = "i64.shr_s"; break;
+      case Op::I64ShrU:     opStr = "i64.shr_u"; break;
+      case Op::I64Rotl:     opStr = "i64.rotl"; break;
+      case Op::I64Rotr:     opStr = "i64.rotr"; break;
+      case Op::F32Add:      opStr = "f32.add"; break;
+      case Op::F32Sub:      opStr = "f32.sub"; break;
+      case Op::F32Mul:      opStr = "f32.mul"; break;
+      case Op::F32Div:      opStr = "f32.div"; break;
+      case Op::F32Min:      opStr = "f32.min"; break;
+      case Op::F32Max:      opStr = "f32.max"; break;
+      case Op::F32CopySign: opStr = "f32.copysign"; break;
+      case Op::F64Add:      opStr = "f64.add"; break;
+      case Op::F64Sub:      opStr = "f64.sub"; break;
+      case Op::F64Mul:      opStr = "f64.mul"; break;
+      case Op::F64Div:      opStr = "f64.div"; break;
+      case Op::F64Min:      opStr = "f64.min"; break;
+      case Op::F64Max:      opStr = "f64.max"; break;
+      case Op::F64CopySign: opStr = "f64.copysign"; break;
       default:                return Fail(c, "unexpected binary operator");
     }
 
     return c.buffer.append(opStr, strlen(opStr));
 }
 
 static bool
-RenderTernaryOperator(WasmRenderContext& c, AstTernaryOperator& op)
+RenderTernaryOperator(WasmRenderContext& c, AstTernaryOperator& ternary)
 {
-    if (!RenderExpr(c, *op.op0()))
+    if (!RenderExpr(c, *ternary.op0()))
         return false;
-    if (!RenderExpr(c, *op.op1()))
+    if (!RenderExpr(c, *ternary.op1()))
         return false;
-    if (!RenderExpr(c, *op.op2()))
+    if (!RenderExpr(c, *ternary.op2()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
-    MAP_AST_EXPR(c, op);
+    MAP_AST_EXPR(c, ternary);
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::Select: opStr = "select"; break;
+    switch (ternary.op()) {
+      case Op::Select: opStr = "select"; break;
       default:           return Fail(c, "unexpected ternary operator");
     }
 
     return c.buffer.append(opStr, strlen(opStr));
 }
 
 static bool
-RenderComparisonOperator(WasmRenderContext& c, AstComparisonOperator& op)
+RenderComparisonOperator(WasmRenderContext& c, AstComparisonOperator& comp)
 {
-    if (!RenderExpr(c, *op.lhs()))
+    if (!RenderExpr(c, *comp.lhs()))
         return false;
-    if (!RenderExpr(c, *op.rhs()))
+    if (!RenderExpr(c, *comp.rhs()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
-    MAP_AST_EXPR(c, op);
+    MAP_AST_EXPR(c, comp);
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::I32Eq:  opStr = "i32.eq"; break;
-      case Expr::I32Ne:  opStr = "i32.ne"; break;
-      case Expr::I32LtS: opStr = "i32.lt_s"; break;
-      case Expr::I32LtU: opStr = "i32.lt_u"; break;
-      case Expr::I32LeS: opStr = "i32.le_s"; break;
-      case Expr::I32LeU: opStr = "i32.le_u"; break;
-      case Expr::I32GtS: opStr = "i32.gt_s"; break;
-      case Expr::I32GtU: opStr = "i32.gt_u"; break;
-      case Expr::I32GeS: opStr = "i32.ge_s"; break;
-      case Expr::I32GeU: opStr = "i32.ge_u"; break;
-      case Expr::I64Eq:  opStr = "i64.eq"; break;
-      case Expr::I64Ne:  opStr = "i64.ne"; break;
-      case Expr::I64LtS: opStr = "i64.lt_s"; break;
-      case Expr::I64LtU: opStr = "i64.lt_u"; break;
-      case Expr::I64LeS: opStr = "i64.le_s"; break;
-      case Expr::I64LeU: opStr = "i64.le_u"; break;
-      case Expr::I64GtS: opStr = "i64.gt_s"; break;
-      case Expr::I64GtU: opStr = "i64.gt_u"; break;
-      case Expr::I64GeS: opStr = "i64.ge_s"; break;
-      case Expr::I64GeU: opStr = "i64.ge_u"; break;
-      case Expr::F32Eq:  opStr = "f32.eq"; break;
-      case Expr::F32Ne:  opStr = "f32.ne"; break;
-      case Expr::F32Lt:  opStr = "f32.lt"; break;
-      case Expr::F32Le:  opStr = "f32.le"; break;
-      case Expr::F32Gt:  opStr = "f32.gt"; break;
-      case Expr::F32Ge:  opStr = "f32.ge"; break;
-      case Expr::F64Eq:  opStr = "f64.eq"; break;
-      case Expr::F64Ne:  opStr = "f64.ne"; break;
-      case Expr::F64Lt:  opStr = "f64.lt"; break;
-      case Expr::F64Le:  opStr = "f64.le"; break;
-      case Expr::F64Gt:  opStr = "f64.gt"; break;
-      case Expr::F64Ge:  opStr = "f64.ge"; break;
+    switch (comp.op()) {
+      case Op::I32Eq:  opStr = "i32.eq"; break;
+      case Op::I32Ne:  opStr = "i32.ne"; break;
+      case Op::I32LtS: opStr = "i32.lt_s"; break;
+      case Op::I32LtU: opStr = "i32.lt_u"; break;
+      case Op::I32LeS: opStr = "i32.le_s"; break;
+      case Op::I32LeU: opStr = "i32.le_u"; break;
+      case Op::I32GtS: opStr = "i32.gt_s"; break;
+      case Op::I32GtU: opStr = "i32.gt_u"; break;
+      case Op::I32GeS: opStr = "i32.ge_s"; break;
+      case Op::I32GeU: opStr = "i32.ge_u"; break;
+      case Op::I64Eq:  opStr = "i64.eq"; break;
+      case Op::I64Ne:  opStr = "i64.ne"; break;
+      case Op::I64LtS: opStr = "i64.lt_s"; break;
+      case Op::I64LtU: opStr = "i64.lt_u"; break;
+      case Op::I64LeS: opStr = "i64.le_s"; break;
+      case Op::I64LeU: opStr = "i64.le_u"; break;
+      case Op::I64GtS: opStr = "i64.gt_s"; break;
+      case Op::I64GtU: opStr = "i64.gt_u"; break;
+      case Op::I64GeS: opStr = "i64.ge_s"; break;
+      case Op::I64GeU: opStr = "i64.ge_u"; break;
+      case Op::F32Eq:  opStr = "f32.eq"; break;
+      case Op::F32Ne:  opStr = "f32.ne"; break;
+      case Op::F32Lt:  opStr = "f32.lt"; break;
+      case Op::F32Le:  opStr = "f32.le"; break;
+      case Op::F32Gt:  opStr = "f32.gt"; break;
+      case Op::F32Ge:  opStr = "f32.ge"; break;
+      case Op::F64Eq:  opStr = "f64.eq"; break;
+      case Op::F64Ne:  opStr = "f64.ne"; break;
+      case Op::F64Lt:  opStr = "f64.lt"; break;
+      case Op::F64Le:  opStr = "f64.le"; break;
+      case Op::F64Gt:  opStr = "f64.gt"; break;
+      case Op::F64Ge:  opStr = "f64.ge"; break;
       default:           return Fail(c, "unexpected comparison operator");
     }
 
     return c.buffer.append(opStr, strlen(opStr));
 }
 
 static bool
-RenderConversionOperator(WasmRenderContext& c, AstConversionOperator& op)
+RenderConversionOperator(WasmRenderContext& c, AstConversionOperator& conv)
 {
-    if (!RenderExpr(c, *op.op()))
+    if (!RenderExpr(c, *conv.operand()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
-    MAP_AST_EXPR(c, op);
+    MAP_AST_EXPR(c, conv);
     const char* opStr;
-    switch (op.expr()) {
-      case Expr::I32WrapI64:        opStr = "i32.wrap/i64"; break;
-      case Expr::I32TruncSF32:      opStr = "i32.trunc_s/f32"; break;
-      case Expr::I32TruncUF32:      opStr = "i32.trunc_u/f32"; break;
-      case Expr::I32ReinterpretF32: opStr = "i32.reinterpret/f32"; break;
-      case Expr::I32TruncSF64:      opStr = "i32.trunc_s/f64"; break;
-      case Expr::I32TruncUF64:      opStr = "i32.trunc_u/f64"; break;
-      case Expr::I64ExtendSI32:     opStr = "i64.extend_s/i32"; break;
-      case Expr::I64ExtendUI32:     opStr = "i64.extend_u/i32"; break;
-      case Expr::I64TruncSF32:      opStr = "i64.trunc_s/f32"; break;
-      case Expr::I64TruncUF32:      opStr = "i64.trunc_u/f32"; break;
-      case Expr::I64TruncSF64:      opStr = "i64.trunc_s/f64"; break;
-      case Expr::I64TruncUF64:      opStr = "i64.trunc_u/f64"; break;
-      case Expr::I64ReinterpretF64: opStr = "i64.reinterpret/f64"; break;
-      case Expr::F32ConvertSI32:    opStr = "f32.convert_s/i32"; break;
-      case Expr::F32ConvertUI32:    opStr = "f32.convert_u/i32"; break;
-      case Expr::F32ReinterpretI32: opStr = "f32.reinterpret/i32"; break;
-      case Expr::F32ConvertSI64:    opStr = "f32.convert_s/i64"; break;
-      case Expr::F32ConvertUI64:    opStr = "f32.convert_u/i64"; break;
-      case Expr::F32DemoteF64:      opStr = "f32.demote/f64"; break;
-      case Expr::F64ConvertSI32:    opStr = "f64.convert_s/i32"; break;
-      case Expr::F64ConvertUI32:    opStr = "f64.convert_u/i32"; break;
-      case Expr::F64ConvertSI64:    opStr = "f64.convert_s/i64"; break;
-      case Expr::F64ConvertUI64:    opStr = "f64.convert_u/i64"; break;
-      case Expr::F64ReinterpretI64: opStr = "f64.reinterpret/i64"; break;
-      case Expr::F64PromoteF32:     opStr = "f64.promote/f32"; break;
-      case Expr::I32Eqz:            opStr = "i32.eqz"; break;
-      case Expr::I64Eqz:            opStr = "i64.eqz"; break;
+    switch (conv.op()) {
+      case Op::I32WrapI64:        opStr = "i32.wrap/i64"; break;
+      case Op::I32TruncSF32:      opStr = "i32.trunc_s/f32"; break;
+      case Op::I32TruncUF32:      opStr = "i32.trunc_u/f32"; break;
+      case Op::I32ReinterpretF32: opStr = "i32.reinterpret/f32"; break;
+      case Op::I32TruncSF64:      opStr = "i32.trunc_s/f64"; break;
+      case Op::I32TruncUF64:      opStr = "i32.trunc_u/f64"; break;
+      case Op::I64ExtendSI32:     opStr = "i64.extend_s/i32"; break;
+      case Op::I64ExtendUI32:     opStr = "i64.extend_u/i32"; break;
+      case Op::I64TruncSF32:      opStr = "i64.trunc_s/f32"; break;
+      case Op::I64TruncUF32:      opStr = "i64.trunc_u/f32"; break;
+      case Op::I64TruncSF64:      opStr = "i64.trunc_s/f64"; break;
+      case Op::I64TruncUF64:      opStr = "i64.trunc_u/f64"; break;
+      case Op::I64ReinterpretF64: opStr = "i64.reinterpret/f64"; break;
+      case Op::F32ConvertSI32:    opStr = "f32.convert_s/i32"; break;
+      case Op::F32ConvertUI32:    opStr = "f32.convert_u/i32"; break;
+      case Op::F32ReinterpretI32: opStr = "f32.reinterpret/i32"; break;
+      case Op::F32ConvertSI64:    opStr = "f32.convert_s/i64"; break;
+      case Op::F32ConvertUI64:    opStr = "f32.convert_u/i64"; break;
+      case Op::F32DemoteF64:      opStr = "f32.demote/f64"; break;
+      case Op::F64ConvertSI32:    opStr = "f64.convert_s/i32"; break;
+      case Op::F64ConvertUI32:    opStr = "f64.convert_u/i32"; break;
+      case Op::F64ConvertSI64:    opStr = "f64.convert_s/i64"; break;
+      case Op::F64ConvertUI64:    opStr = "f64.convert_u/i64"; break;
+      case Op::F64ReinterpretI64: opStr = "f64.reinterpret/i64"; break;
+      case Op::F64PromoteF32:     opStr = "f64.promote/f32"; break;
+      case Op::I32Eqz:            opStr = "i32.eqz"; break;
+      case Op::I64Eqz:            opStr = "i64.eqz"; break;
       default:                      return Fail(c, "unexpected conversion operator");
     }
     return c.buffer.append(opStr, strlen(opStr));
 }
 
 static bool
 RenderIf(WasmRenderContext& c, AstIf& if_)
 {
@@ -795,83 +795,83 @@ RenderLoad(WasmRenderContext& c, AstLoad
     if (!RenderLoadStoreBase(c, load.address()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, load);
     uint32_t defaultAlignLog2;
-    switch (load.expr()) {
-      case Expr::I32Load8S:
+    switch (load.op()) {
+      case Op::I32Load8S:
         if (!c.buffer.append("i32.load8_s"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Load8S:
+      case Op::I64Load8S:
         if (!c.buffer.append("i64.load8_s"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Load8U:
+      case Op::I32Load8U:
         if (!c.buffer.append("i32.load8_u"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Load8U:
+      case Op::I64Load8U:
         if (!c.buffer.append("i64.load8_u"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Load16S:
+      case Op::I32Load16S:
         if (!c.buffer.append("i32.load16_s"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load16S:
+      case Op::I64Load16S:
         if (!c.buffer.append("i64.load16_s"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I32Load16U:
+      case Op::I32Load16U:
         if (!c.buffer.append("i32.load16_u"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load16U:
+      case Op::I64Load16U:
         if (!c.buffer.append("i64.load16_u"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Load32S:
+      case Op::I64Load32S:
         if (!c.buffer.append("i64.load32_s"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Load32U:
+      case Op::I64Load32U:
         if (!c.buffer.append("i64.load32_u"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I32Load:
+      case Op::I32Load:
         if (!c.buffer.append("i32.load"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Load:
+      case Op::I64Load:
         if (!c.buffer.append("i64.load"))
             return false;
         defaultAlignLog2 = 3;
         break;
-      case Expr::F32Load:
+      case Op::F32Load:
         if (!c.buffer.append("f32.load"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::F64Load:
+      case Op::F64Load:
         if (!c.buffer.append("f64.load"))
             return false;
         defaultAlignLog2 = 3;
         break;
       default:
         return Fail(c, "unexpected load operator");
     }
 
@@ -887,90 +887,90 @@ RenderStore(WasmRenderContext& c, AstSto
     if (!RenderExpr(c, store.value()))
         return false;
 
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, store);
     uint32_t defaultAlignLog2;
-    switch (store.expr()) {
-      case Expr::I32Store8:
+    switch (store.op()) {
+      case Op::I32Store8:
         if (!c.buffer.append("i32.store8"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I64Store8:
+      case Op::I64Store8:
         if (!c.buffer.append("i64.store8"))
             return false;
         defaultAlignLog2 = 0;
         break;
-      case Expr::I32Store16:
+      case Op::I32Store16:
         if (!c.buffer.append("i32.store16"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Store16:
+      case Op::I64Store16:
         if (!c.buffer.append("i64.store16"))
             return false;
         defaultAlignLog2 = 1;
         break;
-      case Expr::I64Store32:
+      case Op::I64Store32:
         if (!c.buffer.append("i64.store32"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I32Store:
+      case Op::I32Store:
         if (!c.buffer.append("i32.store"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::I64Store:
+      case Op::I64Store:
         if (!c.buffer.append("i64.store"))
             return false;
         defaultAlignLog2 = 3;
         break;
-      case Expr::F32Store:
+      case Op::F32Store:
         if (!c.buffer.append("f32.store"))
             return false;
         defaultAlignLog2 = 2;
         break;
-      case Expr::F64Store:
+      case Op::F64Store:
         if (!c.buffer.append("f64.store"))
             return false;
         defaultAlignLog2 = 3;
         break;
       default:
         return Fail(c, "unexpected store operator");
     }
 
     return RenderLoadStoreAddress(c, store.address(), defaultAlignLog2);
 }
 
 static bool
 RenderBranch(WasmRenderContext& c, AstBranch& branch)
 {
-    Expr expr = branch.expr();
-    MOZ_ASSERT(expr == Expr::BrIf || expr == Expr::Br);
+    Op op = branch.op();
+    MOZ_ASSERT(op == Op::BrIf || op == Op::Br);
 
-    if (expr == Expr::BrIf) {
+    if (op == Op::BrIf) {
         if (!RenderExpr(c, branch.cond()))
             return false;
     }
 
     if (branch.maybeValue()) {
         if (!RenderExpr(c, *(branch.maybeValue())))
             return false;
     }
 
     if (!RenderIndent(c))
         return false;
 
     MAP_AST_EXPR(c, branch);
-    if (expr == Expr::BrIf ? !c.buffer.append("br_if ") : !c.buffer.append("br "))
+    if (op == Op::BrIf ? !c.buffer.append("br_if ") : !c.buffer.append("br "))
         return false;
 
     return RenderRef(c, branch.target());
 }
 
 static bool
 RenderBrTable(WasmRenderContext& c, AstBranchTable& table)
 {
--- a/js/src/wasm/WasmCompile.cpp
+++ b/js/src/wasm/WasmCompile.cpp
@@ -28,36 +28,36 @@
 using namespace js;
 using namespace js::jit;
 using namespace js::wasm;
 
 using mozilla::IsNaN;
 
 namespace {
 
-struct ValidatingPolicy : ExprIterPolicy
+struct ValidatingPolicy : OpIterPolicy
 {
     // Validation is what we're all about here.
     static const bool Validate = true;
 };
 
-typedef ExprIter<ValidatingPolicy> ValidatingExprIter;
+typedef OpIter<ValidatingPolicy> ValidatingOpIter;
 
 class FunctionDecoder
 {
     const ModuleGenerator& mg_;
     const ValTypeVector& locals_;
-    ValidatingExprIter iter_;
+    ValidatingOpIter iter_;
 
   public:
     FunctionDecoder(const ModuleGenerator& mg, const ValTypeVector& locals, Decoder& d)
       : mg_(mg), locals_(locals), iter_(d)
     {}
     const ModuleGenerator& mg() const { return mg_; }
-    ValidatingExprIter& iter() { return iter_; }
+    ValidatingOpIter& iter() { return iter_; }
     const ValTypeVector& locals() const { return locals_; }
 
     bool checkHasMemory() {
         if (!mg().usesMemory())
             return iter().fail("can't touch memory without memory");
         return true;
     }
 };
@@ -145,268 +145,268 @@ DecodeBrTable(FunctionDecoder& f)
 }
 
 static bool
 DecodeFunctionBodyExprs(FunctionDecoder& f)
 {
 #define CHECK(c) if (!(c)) return false; break
 
     while (true) {
-        uint16_t expr;
-        if (!f.iter().readExpr(&expr))
+        uint16_t op;
+        if (!f.iter().readOp(&op))
             return false;
 
-        switch (expr) {
-          case uint16_t(Expr::End):
+        switch (op) {
+          case uint16_t(Op::End):
             if (!f.iter().readEnd(nullptr, nullptr, nullptr))
                 return false;
             if (f.iter().controlStackEmpty())
                 return true;
             break;
-          case uint16_t(Expr::Nop):
+          case uint16_t(Op::Nop):
             CHECK(f.iter().readNop());
-          case uint16_t(Expr::Drop):
+          case uint16_t(Op::Drop):
             CHECK(f.iter().readDrop());
-          case uint16_t(Expr::Call):
+          case uint16_t(Op::Call):
             CHECK(DecodeCall(f));
-          case uint16_t(Expr::CallIndirect):
+          case uint16_t(Op::CallIndirect):
             CHECK(DecodeCallIndirect(f));
-          case uint16_t(Expr::I32Const):
+          case uint16_t(Op::I32Const):
             CHECK(f.iter().readI32Const(nullptr));
-          case uint16_t(Expr::I64Const):
+          case uint16_t(Op::I64Const):
             CHECK(f.iter().readI64Const(nullptr));
-          case uint16_t(Expr::F32Const):
+          case uint16_t(Op::F32Const):
             CHECK(f.iter().readF32Const(nullptr));
-          case uint16_t(Expr::F64Const):
+          case uint16_t(Op::F64Const):
             CHECK(f.iter().readF64Const(nullptr));
-          case uint16_t(Expr::GetLocal):
+          case uint16_t(Op::GetLocal):
             CHECK(f.iter().readGetLocal(f.locals(), nullptr));
-          case uint16_t(Expr::SetLocal):
+          case uint16_t(Op::SetLocal):
             CHECK(f.iter().readSetLocal(f.locals(), nullptr, nullptr));
-          case uint16_t(Expr::TeeLocal):
+          case uint16_t(Op::TeeLocal):
             CHECK(f.iter().readTeeLocal(f.locals(), nullptr, nullptr));
-          case uint16_t(Expr::GetGlobal):
+          case uint16_t(Op::GetGlobal):
             CHECK(f.iter().readGetGlobal(f.mg().globals(), nullptr));
-          case uint16_t(Expr::SetGlobal):
+          case uint16_t(Op::SetGlobal):
             CHECK(f.iter().readSetGlobal(f.mg().globals(), nullptr, nullptr));
-          case uint16_t(Expr::Select):
+          case uint16_t(Op::Select):
             CHECK(f.iter().readSelect(nullptr, nullptr, nullptr, nullptr));
-          case uint16_t(Expr::Block):
+          case uint16_t(Op::Block):
             CHECK(f.iter().readBlock());
-          case uint16_t(Expr::Loop):
+          case uint16_t(Op::Loop):
             CHECK(f.iter().readLoop());
-          case uint16_t(Expr::If):
+          case uint16_t(Op::If):
             CHECK(f.iter().readIf(nullptr));
-          case uint16_t(Expr::Else):
+          case uint16_t(Op::Else):
             CHECK(f.iter().readElse(nullptr, nullptr));
-          case uint16_t(Expr::I32Clz):
-          case uint16_t(Expr::I32Ctz):
-          case uint16_t(Expr::I32Popcnt):
+          case uint16_t(Op::I32Clz):
+          case uint16_t(Op::I32Ctz):
+          case uint16_t(Op::I32Popcnt):
             CHECK(f.iter().readUnary(ValType::I32, nullptr));
-          case uint16_t(Expr::I64Clz):
-          case uint16_t(Expr::I64Ctz):
-          case uint16_t(Expr::I64Popcnt):
+          case uint16_t(Op::I64Clz):
+          case uint16_t(Op::I64Ctz):
+          case uint16_t(Op::I64Popcnt):
             CHECK(f.iter().readUnary(ValType::I64, nullptr));
-          case uint16_t(Expr::F32Abs):
-          case uint16_t(Expr::F32Neg):
-          case uint16_t(Expr::F32Ceil):
-          case uint16_t(Expr::F32Floor):
-          case uint16_t(Expr::F32Sqrt):
-          case uint16_t(Expr::F32Trunc):
-          case uint16_t(Expr::F32Nearest):
+          case uint16_t(Op::F32Abs):
+          case uint16_t(Op::F32Neg):
+          case uint16_t(Op::F32Ceil):
+          case uint16_t(Op::F32Floor):
+          case uint16_t(Op::F32Sqrt):
+          case uint16_t(Op::F32Trunc):
+          case uint16_t(Op::F32Nearest):
             CHECK(f.iter().readUnary(ValType::F32, nullptr));
-          case uint16_t(Expr::F64Abs):
-          case uint16_t(Expr::F64Neg):
-          case uint16_t(Expr::F64Ceil):
-          case uint16_t(Expr::F64Floor):
-          case uint16_t(Expr::F64Sqrt):
-          case uint16_t(Expr::F64Trunc):
-          case uint16_t(Expr::F64Nearest):
+          case uint16_t(Op::F64Abs):
+          case uint16_t(Op::F64Neg):
+          case uint16_t(Op::F64Ceil):
+          case uint16_t(Op::F64Floor):
+          case uint16_t(Op::F64Sqrt):
+          case uint16_t(Op::F64Trunc):
+          case uint16_t(Op::F64Nearest):
             CHECK(f.iter().readUnary(ValType::F64, nullptr));
-          case uint16_t(Expr::I32Add):
-          case uint16_t(Expr::I32Sub):
-          case uint16_t(Expr::I32Mul):
-          case uint16_t(Expr::I32DivS):
-          case uint16_t(Expr::I32DivU):
-          case uint16_t(Expr::I32RemS):
-          case uint16_t(Expr::I32RemU):
-          case uint16_t(Expr::I32And):
-          case uint16_t(Expr::I32Or):
-          case uint16_t(Expr::I32Xor):
-          case uint16_t(Expr::I32Shl):
-          case uint16_t(Expr::I32ShrS):
-          case uint16_t(Expr::I32ShrU):
-          case uint16_t(Expr::I32Rotl):
-          case uint16_t(Expr::I32Rotr):
+          case uint16_t(Op::I32Add):
+          case uint16_t(Op::I32Sub):
+          case uint16_t(Op::I32Mul):
+          case uint16_t(Op::I32DivS):
+          case uint16_t(Op::I32DivU):
+          case uint16_t(Op::I32RemS):
+          case uint16_t(Op::I32RemU):
+          case uint16_t(Op::I32And):
+          case uint16_t(Op::I32Or):
+          case uint16_t(Op::I32Xor):
+          case uint16_t(Op::I32Shl):
+          case uint16_t(Op::I32ShrS):
+          case uint16_t(Op::I32ShrU):
+          case uint16_t(Op::I32Rotl):
+          case uint16_t(Op::I32Rotr):
             CHECK(f.iter().readBinary(ValType::I32, nullptr, nullptr));
-          case uint16_t(Expr::I64Add):
-          case uint16_t(Expr::I64Sub):
-          case uint16_t(Expr::I64Mul):
-          case uint16_t(Expr::I64DivS):
-          case uint16_t(Expr::I64DivU):
-          case uint16_t(Expr::I64RemS):
-          case uint16_t(Expr::I64RemU):
-          case uint16_t(Expr::I64And):
-          case uint16_t(Expr::I64Or):
-          case uint16_t(Expr::I64Xor):
-          case uint16_t(Expr::I64Shl):
-          case uint16_t(Expr::I64ShrS):
-          case uint16_t(Expr::I64ShrU):
-          case uint16_t(Expr::I64Rotl):
-          case uint16_t(Expr::I64Rotr):
+          case uint16_t(Op::I64Add):
+          case uint16_t(Op::I64Sub):
+          case uint16_t(Op::I64Mul):
+          case uint16_t(Op::I64DivS):
+          case uint16_t(Op::I64DivU):
+          case uint16_t(Op::I64RemS):
+          case uint16_t(Op::I64RemU):
+          case uint16_t(Op::I64And):
+          case uint16_t(Op::I64Or):
+          case uint16_t(Op::I64Xor):
+          case uint16_t(Op::I64Shl):
+          case uint16_t(Op::I64ShrS):
+          case uint16_t(Op::I64ShrU):
+          case uint16_t(Op::I64Rotl):
+          case uint16_t(Op::I64Rotr):
             CHECK(f.iter().readBinary(ValType::I64, nullptr, nullptr));
-          case uint16_t(Expr::F32Add):
-          case uint16_t(Expr::F32Sub):
-          case uint16_t(Expr::F32Mul):
-          case uint16_t(Expr::F32Div):
-          case uint16_t(Expr::F32Min):
-          case uint16_t(Expr::F32Max):
-          case uint16_t(Expr::F32CopySign):
+          case uint16_t(Op::F32Add):
+          case uint16_t(Op::F32Sub):
+          case uint16_t(Op::F32Mul):
+          case uint16_t(Op::F32Div):
+          case uint16_t(Op::F32Min):
+          case uint16_t(Op::F32Max):
+          case uint16_t(Op::F32CopySign):
             CHECK(f.iter().readBinary(ValType::F32, nullptr, nullptr));
-          case uint16_t(Expr::F64Add):
-          case uint16_t(Expr::F64Sub):
-          case uint16_t(Expr::F64Mul):
-          case uint16_t(Expr::F64Div):
-          case uint16_t(Expr::F64Min):
-          case uint16_t(Expr::F64Max):
-          case uint16_t(Expr::F64CopySign):
+          case uint16_t(Op::F64Add):
+          case uint16_t(Op::F64Sub):
+          case uint16_t(Op::F64Mul):
+          case uint16_t(Op::F64Div):
+          case uint16_t(Op::F64Min):
+          case uint16_t(Op::F64Max):
+          case uint16_t(Op::F64CopySign):
             CHECK(f.iter().readBinary(ValType::F64, nullptr, nullptr));
-          case uint16_t(Expr::I32Eq):
-          case uint16_t(Expr::I32Ne):
-          case uint16_t(Expr::I32LtS):
-          case uint16_t(Expr::I32LtU):
-          case uint16_t(Expr::I32LeS):
-          case uint16_t(Expr::I32LeU):
-          case uint16_t(Expr::I32GtS):
-          case uint16_t(Expr::I32GtU):
-          case uint16_t(Expr::I32GeS):
-          case uint16_t(Expr::I32GeU):
+          case uint16_t(Op::I32Eq):
+          case uint16_t(Op::I32Ne):
+          case uint16_t(Op::I32LtS):
+          case uint16_t(Op::I32LtU):
+          case uint16_t(Op::I32LeS):
+          case uint16_t(Op::I32LeU):
+          case uint16_t(Op::I32GtS):
+          case uint16_t(Op::I32GtU):
+          case uint16_t(Op::I32GeS):
+          case uint16_t(Op::I32GeU):
             CHECK(f.iter().readComparison(ValType::I32, nullptr, nullptr));
-          case uint16_t(Expr::I64Eq):
-          case uint16_t(Expr::I64Ne):
-          case uint16_t(Expr::I64LtS):
-          case uint16_t(Expr::I64LtU):
-          case uint16_t(Expr::I64LeS):
-          case uint16_t(Expr::I64LeU):
-          case uint16_t(Expr::I64GtS):
-          case uint16_t(Expr::I64GtU):
-          case uint16_t(Expr::I64GeS):
-          case uint16_t(Expr::I64GeU):
+          case uint16_t(Op::I64Eq):
+          case uint16_t(Op::I64Ne):
+          case uint16_t(Op::I64LtS):
+          case uint16_t(Op::I64LtU):
+          case uint16_t(Op::I64LeS):
+          case uint16_t(Op::I64LeU):
+          case uint16_t(Op::I64GtS):
+          case uint16_t(Op::I64GtU):
+          case uint16_t(Op::I64GeS):
+          case uint16_t(Op::I64GeU):
             CHECK(f.iter().readComparison(ValType::I64, nullptr, nullptr));
-          case uint16_t(Expr::F32Eq):
-          case uint16_t(Expr::F32Ne):
-          case uint16_t(Expr::F32Lt):
-          case uint16_t(Expr::F32Le):
-          case uint16_t(Expr::F32Gt):
-          case uint16_t(Expr::F32Ge):
+          case uint16_t(Op::F32Eq):
+          case uint16_t(Op::F32Ne):
+          case uint16_t(Op::F32Lt):
+          case uint16_t(Op::F32Le):
+          case uint16_t(Op::F32Gt):
+          case uint16_t(Op::F32Ge):
             CHECK(f.iter().readComparison(ValType::F32, nullptr, nullptr));
-          case uint16_t(Expr::F64Eq):
-          case uint16_t(Expr::F64Ne):
-          case uint16_t(Expr::F64Lt):
-          case uint16_t(Expr::F64Le):
-          case uint16_t(Expr::F64Gt):
-          case uint16_t(Expr::F64Ge):
+          case uint16_t(Op::F64Eq):
+          case uint16_t(Op::F64Ne):
+          case uint16_t(Op::F64Lt):
+          case uint16_t(Op::F64Le):
+          case uint16_t(Op::F64Gt):
+          case uint16_t(Op::F64Ge):
             CHECK(f.iter().readComparison(ValType::F64, nullptr, nullptr));
-          case uint16_t(Expr::I32Eqz):
+          case uint16_t(Op::I32Eqz):
             CHECK(f.iter().readConversion(ValType::I32, ValType::I32, nullptr));
-          case uint16_t(Expr::I64Eqz):
-          case uint16_t(Expr::I32WrapI64):
+          case uint16_t(Op::I64Eqz):
+          case uint16_t(Op::I32WrapI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::I32, nullptr));
-          case uint16_t(Expr::I32TruncSF32):
-          case uint16_t(Expr::I32TruncUF32):
-          case uint16_t(Expr::I32ReinterpretF32):
+          case uint16_t(Op::I32TruncSF32):
+          case uint16_t(Op::I32TruncUF32):
+          case uint16_t(Op::I32ReinterpretF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::I32, nullptr));
-          case uint16_t(Expr::I32TruncSF64):
-          case uint16_t(Expr::I32TruncUF64):
+          case uint16_t(Op::I32TruncSF64):
+          case uint16_t(Op::I32TruncUF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::I32, nullptr));
-          case uint16_t(Expr::I64ExtendSI32):
-          case uint16_t(Expr::I64ExtendUI32):
+          case uint16_t(Op::I64ExtendSI32):
+          case uint16_t(Op::I64ExtendUI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::I64, nullptr));
-          case uint16_t(Expr::I64TruncSF32):
-          case uint16_t(Expr::I64TruncUF32):
+          case uint16_t(Op::I64TruncSF32):
+          case uint16_t(Op::I64TruncUF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::I64, nullptr));
-          case uint16_t(Expr::I64TruncSF64):
-          case uint16_t(Expr::I64TruncUF64):
-          case uint16_t(Expr::I64ReinterpretF64):
+          case uint16_t(Op::I64TruncSF64):
+          case uint16_t(Op::I64TruncUF64):
+          case uint16_t(Op::I64ReinterpretF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::I64, nullptr));
-          case uint16_t(Expr::F32ConvertSI32):
-          case uint16_t(Expr::F32ConvertUI32):
-          case uint16_t(Expr::F32ReinterpretI32):
+          case uint16_t(Op::F32ConvertSI32):
+          case uint16_t(Op::F32ConvertUI32):
+          case uint16_t(Op::F32ReinterpretI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::F32, nullptr));
-          case uint16_t(Expr::F32ConvertSI64):
-          case uint16_t(Expr::F32ConvertUI64):
+          case uint16_t(Op::F32ConvertSI64):
+          case uint16_t(Op::F32ConvertUI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::F32, nullptr));
-          case uint16_t(Expr::F32DemoteF64):
+          case uint16_t(Op::F32DemoteF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::F32, nullptr));
-          case uint16_t(Expr::F64ConvertSI32):
-          case uint16_t(Expr::F64ConvertUI32):
+          case uint16_t(Op::F64ConvertSI32):
+          case uint16_t(Op::F64ConvertUI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::F64, nullptr));
-          case uint16_t(Expr::F64ConvertSI64):
-          case uint16_t(Expr::F64ConvertUI64):
-          case uint16_t(Expr::F64ReinterpretI64):
+          case uint16_t(Op::F64ConvertSI64):
+          case uint16_t(Op::F64ConvertUI64):
+          case uint16_t(Op::F64ReinterpretI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::F64, nullptr));
-          case uint16_t(Expr::F64PromoteF32):
+          case uint16_t(Op::F64PromoteF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::F64, nullptr));
-          case uint16_t(Expr::I32Load8S):
-          case uint16_t(Expr::I32Load8U):
+          case uint16_t(Op::I32Load8S):
+          case uint16_t(Op::I32Load8U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 1, nullptr));
-          case uint16_t(Expr::I32Load16S):
-          case uint16_t(Expr::I32Load16U):
+          case uint16_t(Op::I32Load16S):
+          case uint16_t(Op::I32Load16U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 2, nullptr));
-          case uint16_t(Expr::I32Load):
+          case uint16_t(Op::I32Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 4, nullptr));
-          case uint16_t(Expr::I64Load8S):
-          case uint16_t(Expr::I64Load8U):
+          case uint16_t(Op::I64Load8S):
+          case uint16_t(Op::I64Load8U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 1, nullptr));
-          case uint16_t(Expr::I64Load16S):
-          case uint16_t(Expr::I64Load16U):
+          case uint16_t(Op::I64Load16S):
+          case uint16_t(Op::I64Load16U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 2, nullptr));
-          case uint16_t(Expr::I64Load32S):
-          case uint16_t(Expr::I64Load32U):
+          case uint16_t(Op::I64Load32S):
+          case uint16_t(Op::I64Load32U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 4, nullptr));
-          case uint16_t(Expr::I64Load):
+          case uint16_t(Op::I64Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 8, nullptr));
-          case uint16_t(Expr::F32Load):
+          case uint16_t(Op::F32Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::F32, 4, nullptr));
-          case uint16_t(Expr::F64Load):
+          case uint16_t(Op::F64Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::F64, 8, nullptr));
-          case uint16_t(Expr::I32Store8):
+          case uint16_t(Op::I32Store8):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 1, nullptr, nullptr));
-          case uint16_t(Expr::I32Store16):
+          case uint16_t(Op::I32Store16):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 2, nullptr, nullptr));
-          case uint16_t(Expr::I32Store):
+          case uint16_t(Op::I32Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 4, nullptr, nullptr));
-          case uint16_t(Expr::I64Store8):
+          case uint16_t(Op::I64Store8):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 1, nullptr, nullptr));
-          case uint16_t(Expr::I64Store16):
+          case uint16_t(Op::I64Store16):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 2, nullptr, nullptr));
-          case uint16_t(Expr::I64Store32):
+          case uint16_t(Op::I64Store32):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 4, nullptr, nullptr));
-          case uint16_t(Expr::I64Store):
+          case uint16_t(Op::I64Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 8, nullptr, nullptr));
-          case uint16_t(Expr::F32Store):
+          case uint16_t(Op::F32Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::F32, 4, nullptr, nullptr));
-          case uint16_t(Expr::F64Store):
+          case uint16_t(Op::F64Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::F64, 8, nullptr, nullptr));
-          case uint16_t(Expr::GrowMemory):
+          case uint16_t(Op::GrowMemory):
             CHECK(f.checkHasMemory() && f.iter().readGrowMemory(nullptr));
-          case uint16_t(Expr::CurrentMemory):
+          case uint16_t(Op::CurrentMemory):
             CHECK(f.checkHasMemory() && f.iter().readCurrentMemory());
-          case uint16_t(Expr::Br):
+          case uint16_t(Op::Br):
             CHECK(f.iter().readBr(nullptr, nullptr, nullptr));
-          case uint16_t(Expr::BrIf):
+          case uint16_t(Op::BrIf):
             CHECK(f.iter().readBrIf(nullptr, nullptr, nullptr, nullptr));
-          case uint16_t(Expr::BrTable):
+          case uint16_t(Op::BrTable):
             CHECK(DecodeBrTable(f));
-          case uint16_t(Expr::Return):
+          case uint16_t(Op::Return):
             CHECK(f.iter().readReturn(nullptr));
-          case uint16_t(Expr::Unreachable):
+          case uint16_t(Op::Unreachable):
             CHECK(f.iter().readUnreachable());
           default:
-            return f.iter().unrecognizedOpcode(expr);
+            return f.iter().unrecognizedOpcode(op);
         }
     }
 
     MOZ_CRASH("unreachable");
 
 #undef CHECK
 }
 
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -37,29 +37,29 @@ using mozilla::IsPowerOfTwo;
 using mozilla::Maybe;
 using mozilla::Nothing;
 using mozilla::Some;
 
 namespace {
 
 typedef Vector<MBasicBlock*, 8, SystemAllocPolicy> BlockVector;
 
-struct IonCompilePolicy : ExprIterPolicy
+struct IonCompilePolicy : OpIterPolicy
 {
     // Producing output is what we're all about here.
     static const bool Output = true;
 
     // We store SSA definitions in the value stack.
     typedef MDefinition* Value;
 
     // We store loop headers and then/else blocks in the control flow stack.
     typedef MBasicBlock* ControlItem;
 };
 
-typedef ExprIter<IonCompilePolicy> IonExprIter;
+typedef OpIter<IonCompilePolicy> IonOpIter;
 
 class FunctionCompiler;
 
 // TlsUsage describes how the TLS register is used during a function call.
 
 enum class TlsUsage {
     Unused,     // No particular action is taken with respect to the TLS register.
     Need,       // The TLS register must be reloaded just before the call.
@@ -143,17 +143,17 @@ class FunctionCompiler
         {}
     };
 
     typedef Vector<ControlFlowPatch, 0, SystemAllocPolicy> ControlFlowPatchVector;
     typedef Vector<ControlFlowPatchVector, 0, SystemAllocPolicy> ControlFlowPatchsVector;
     typedef Vector<CallCompileState*, 0, SystemAllocPolicy> CallCompileStateVector;
 
     const ModuleGeneratorData& mg_;
-    IonExprIter                iter_;
+    IonOpIter                  iter_;
     const FuncBytes&           func_;
     const ValTypeVector&       locals_;
     size_t                     lastReadCallSite_;
 
     TempAllocator&             alloc_;
     MIRGraph&                  graph_;
     const CompileInfo&         info_;
     MIRGenerator&              mirGen_;
@@ -194,17 +194,17 @@ class FunctionCompiler
         maxStackArgBytes_(0),
         loopDepth_(0),
         blockDepth_(0),
         compileResults_(compileResults),
         tlsPointer_(nullptr)
     {}
 
     const ModuleGeneratorData& mg() const    { return mg_; }
-    IonExprIter&               iter()        { return iter_; }
+    IonOpIter&                 iter()        { return iter_; }
     TempAllocator&             alloc() const { return alloc_; }
     MacroAssembler&            masm() const  { return compileResults_.masm(); }
     const Sig&                 sig() const   { return func_.sig(); }
 
     TrapOffset trapOffset() const {
         return iter_.trapOffset();
     }
     Maybe<TrapOffset> trapIfNotAsmJS() const {
@@ -1108,22 +1108,22 @@ class FunctionCompiler
     }
 
     /*********************************************** Control flow generation */
 
     inline bool inDeadCode() const {
         return curBlock_ == nullptr;
     }
 
-    void returnExpr(MDefinition* expr)
+    void returnExpr(MDefinition* operand)
     {
         if (inDeadCode())
             return;
 
-        MWasmReturn* ins = MWasmReturn::New(alloc(), expr, tlsPointer_);
+        MWasmReturn* ins = MWasmReturn::New(alloc(), operand, tlsPointer_);
         curBlock_->end(ins);
         curBlock_ = nullptr;
     }
 
     void returnVoid()
     {
         if (inDeadCode())
             return;
@@ -1401,17 +1401,17 @@ class FunctionCompiler
             MOZ_ASSERT(inDeadCode());
             MOZ_ASSERT(headerLabel >= blockPatches_.length() || blockPatches_[headerLabel].empty());
             blockDepth_--;
             loopDepth_--;
             *loopResult = nullptr;
             return true;
         }
 
-        // Expr::Loop doesn't have an implicit backedge so temporarily set
+        // Op::Loop doesn't have an implicit backedge so temporarily set
         // aside the end of the loop body to bind backedges.
         MBasicBlock* loopBody = curBlock_;
         curBlock_ = nullptr;
 
         // As explained in bug 1253544, Ion apparently has an invariant that
         // there is only one backedge to loop headers. To handle wasm's ability
         // to have multiple backedges to the same loop header, we bind all those
         // branches as forward jumps to a single backward jump. This is
@@ -1492,27 +1492,27 @@ class FunctionCompiler
 
         pushDef(maybeValue);
 
         curBlock_->end(test);
         curBlock_ = joinBlock;
         return true;
     }
 
-    bool brTable(MDefinition* expr, uint32_t defaultDepth, const Uint32Vector& depths,
+    bool brTable(MDefinition* operand, uint32_t defaultDepth, const Uint32Vector& depths,
                  MDefinition* maybeValue)
     {
         if (inDeadCode())
             return true;
 
         size_t numCases = depths.length();
         MOZ_ASSERT(numCases <= INT32_MAX);
         MOZ_ASSERT(numCases);
 
-        MTableSwitch* table = MTableSwitch::New(alloc(), expr, 0, int32_t(numCases - 1));
+        MTableSwitch* table = MTableSwitch::New(alloc(), operand, 0, int32_t(numCases - 1));
 
         size_t defaultIndex;
         if (!table->addDefault(nullptr, &defaultIndex))
             return false;
         if (!addControlFlowPatch(table, defaultDepth, defaultIndex))
             return false;
 
         typedef HashMap<uint32_t, uint32_t, DefaultHasher<uint32_t>, SystemAllocPolicy>
@@ -3096,463 +3096,463 @@ EmitCurrentMemory(FunctionCompiler& f)
 
 static bool
 EmitExpr(FunctionCompiler& f)
 {
     if (!f.mirGen().ensureBallast())
         return false;
 
     uint16_t u16;
-    MOZ_ALWAYS_TRUE(f.iter().readExpr(&u16));
-    Expr expr = Expr(u16);
-
-    switch (expr) {
+    MOZ_ALWAYS_TRUE(f.iter().readOp(&u16));
+    Op op = Op(u16);
+
+    switch (op) {
       // Control opcodes
-      case Expr::Nop:
+      case Op::Nop:
         return f.iter().readNop();
-      case Expr::Drop:
+      case Op::Drop:
         return f.iter().readDrop();
-      case Expr::Block:
+      case Op::Block:
         return EmitBlock(f);
-      case Expr::Loop:
+      case Op::Loop:
         return EmitLoop(f);
-      case Expr::If:
+      case Op::If:
         return EmitIf(f);
-      case Expr::Else:
+      case Op::Else:
         return EmitElse(f);
-      case Expr::End:
+      case Op::End:
         return EmitEnd(f);
-      case Expr::Br:
+      case Op::Br:
         return EmitBr(f);
-      case Expr::BrIf:
+      case Op::BrIf:
         return EmitBrIf(f);
-      case Expr::BrTable:
+      case Op::BrTable:
         return EmitBrTable(f);
-      case Expr::Return:
+      case Op::Return:
         return EmitReturn(f);
-      case Expr::Unreachable:
+      case Op::Unreachable:
         if (!f.iter().readUnreachable())
             return false;
         f.unreachableTrap();
         return true;
 
       // Calls
-      case Expr::Call:
+      case Op::Call:
         return EmitCall(f);
-      case Expr::CallIndirect:
+      case Op::CallIndirect:
         return EmitCallIndirect(f, /* oldStyle = */ false);
-      case Expr::OldCallIndirect:
+      case Op::OldCallIndirect:
         return EmitCallIndirect(f, /* oldStyle = */ true);
 
       // Locals and globals
-      case Expr::GetLocal:
+      case Op::GetLocal:
         return EmitGetLocal(f);
-      case Expr::SetLocal:
+      case Op::SetLocal:
         return EmitSetLocal(f);
-      case Expr::TeeLocal:
+      case Op::TeeLocal:
         return EmitTeeLocal(f);
-      case Expr::GetGlobal:
+      case Op::GetGlobal:
         return EmitGetGlobal(f);
-      case Expr::SetGlobal:
+      case Op::SetGlobal:
         return EmitSetGlobal(f);
-      case Expr::TeeGlobal:
+      case Op::TeeGlobal:
         return EmitTeeGlobal(f);
 
       // Select
-      case Expr::Select:
+      case Op::Select:
         return EmitSelect(f);
 
       // I32
-      case Expr::I32Const: {
+      case Op::I32Const: {
         int32_t i32;
         if (!f.iter().readI32Const(&i32))
             return false;
 
         f.iter().setResult(f.constant(Int32Value(i32), MIRType::Int32));
         return true;
       }
-      case Expr::I32Add:
+      case Op::I32Add:
         return EmitAdd(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Sub:
+      case Op::I32Sub:
         return EmitSub(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Mul:
+      case Op::I32Mul:
         return EmitMul(f, ValType::I32, MIRType::Int32);
-      case Expr::I32DivS:
-      case Expr::I32DivU:
-        return EmitDiv(f, ValType::I32, MIRType::Int32, expr == Expr::I32DivU);
-      case Expr::I32RemS:
-      case Expr::I32RemU:
-        return EmitRem(f, ValType::I32, MIRType::Int32, expr == Expr::I32RemU);
-      case Expr::I32Min:
-      case Expr::I32Max:
-        return EmitMinMax(f, ValType::I32, MIRType::Int32, expr == Expr::I32Max);
-      case Expr::I32Eqz:
+      case Op::I32DivS:
+      case Op::I32DivU:
+        return EmitDiv(f, ValType::I32, MIRType::Int32, op == Op::I32DivU);
+      case Op::I32RemS:
+      case Op::I32RemU:
+        return EmitRem(f, ValType::I32, MIRType::Int32, op == Op::I32RemU);
+      case Op::I32Min:
+      case Op::I32Max:
+        return EmitMinMax(f, ValType::I32, MIRType::Int32, op == Op::I32Max);
+      case Op::I32Eqz:
         return EmitConversion<MNot>(f, ValType::I32, ValType::I32);
-      case Expr::I32TruncSF32:
-      case Expr::I32TruncUF32:
-        return EmitTruncate(f, ValType::F32, ValType::I32, expr == Expr::I32TruncUF32);
-      case Expr::I32TruncSF64:
-      case Expr::I32TruncUF64:
-        return EmitTruncate(f, ValType::F64, ValType::I32, expr == Expr::I32TruncUF64);
-      case Expr::I32WrapI64:
+      case Op::I32TruncSF32:
+      case Op::I32TruncUF32:
+        return EmitTruncate(f, ValType::F32, ValType::I32, op == Op::I32TruncUF32);
+      case Op::I32TruncSF64:
+      case Op::I32TruncUF64:
+        return EmitTruncate(f, ValType::F64, ValType::I32, op == Op::I32TruncUF64);
+      case Op::I32WrapI64:
         return EmitConversion<MWrapInt64ToInt32>(f, ValType::I64, ValType::I32);
-      case Expr::I32ReinterpretF32:
+      case Op::I32ReinterpretF32:
         return EmitReinterpret(f, ValType::I32, ValType::F32, MIRType::Int32);
-      case Expr::I32Clz:
+      case Op::I32Clz:
         return EmitUnaryWithType<MClz>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Ctz:
+      case Op::I32Ctz:
         return EmitUnaryWithType<MCtz>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Popcnt:
+      case Op::I32Popcnt:
         return EmitUnaryWithType<MPopcnt>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Abs:
+      case Op::I32Abs:
         return EmitUnaryWithType<MAbs>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Neg:
+      case Op::I32Neg:
         return EmitUnaryWithType<MAsmJSNeg>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Or:
+      case Op::I32Or:
         return EmitBitwise<MBitOr>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32And:
+      case Op::I32And:
         return EmitBitwise<MBitAnd>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Xor:
+      case Op::I32Xor:
         return EmitBitwise<MBitXor>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32Shl:
+      case Op::I32Shl:
         return EmitBitwise<MLsh>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32ShrS:
+      case Op::I32ShrS:
         return EmitBitwise<MRsh>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32ShrU:
+      case Op::I32ShrU:
         return EmitBitwise<MUrsh>(f, ValType::I32, MIRType::Int32);
-      case Expr::I32BitNot:
+      case Op::I32BitNot:
         return EmitBitNot(f, ValType::I32);
-      case Expr::I32Load8S:
+      case Op::I32Load8S:
         return EmitLoad(f, ValType::I32, Scalar::Int8);
-      case Expr::I32Load8U:
+      case Op::I32Load8U:
         return EmitLoad(f, ValType::I32, Scalar::Uint8);
-      case Expr::I32Load16S:
+      case Op::I32Load16S:
         return EmitLoad(f, ValType::I32, Scalar::Int16);
-      case Expr::I32Load16U:
+      case Op::I32Load16U:
         return EmitLoad(f, ValType::I32, Scalar::Uint16);
-      case Expr::I32Load:
+      case Op::I32Load:
         return EmitLoad(f, ValType::I32, Scalar::Int32);
-      case Expr::I32Store8:
+      case Op::I32Store8:
         return EmitStore(f, ValType::I32, Scalar::Int8);
-      case Expr::I32TeeStore8:
+      case Op::I32TeeStore8:
         return EmitTeeStore(f, ValType::I32, Scalar::Int8);
-      case Expr::I32Store16:
+      case Op::I32Store16:
         return EmitStore(f, ValType::I32, Scalar::Int16);
-      case Expr::I32TeeStore16:
+      case Op::I32TeeStore16:
         return EmitTeeStore(f, ValType::I32, Scalar::Int16);
-      case Expr::I32Store:
+      case Op::I32Store:
         return EmitStore(f, ValType::I32, Scalar::Int32);
-      case Expr::I32TeeStore:
+      case Op::I32TeeStore:
         return EmitTeeStore(f, ValType::I32, Scalar::Int32);
-      case Expr::I32Rotr:
-      case Expr::I32Rotl:
-        return EmitRotate(f, ValType::I32, expr == Expr::I32Rotl);
+      case Op::I32Rotr:
+      case Op::I32Rotl:
+        return EmitRotate(f, ValType::I32, op == Op::I32Rotl);
 
       // I64
-      case Expr::I64Const: {
+      case Op::I64Const: {
         int64_t i64;
         if (!f.iter().readI64Const(&i64))
             return false;
 
         f.iter().setResult(f.constant(i64));
         return true;
       }
-      case Expr::I64Add:
+      case Op::I64Add:
         return EmitAdd(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Sub:
+      case Op::I64Sub:
         return EmitSub(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Mul:
+      case Op::I64Mul:
         return EmitMul(f, ValType::I64, MIRType::Int64);
-      case Expr::I64DivS:
-      case Expr::I64DivU:
-        return EmitDiv(f, ValType::I64, MIRType::Int64, expr == Expr::I64DivU);
-      case Expr::I64RemS:
-      case Expr::I64RemU:
-        return EmitRem(f, ValType::I64, MIRType::Int64, expr == Expr::I64RemU);
-      case Expr::I64TruncSF32:
-      case Expr::I64TruncUF32:
-        return EmitTruncate(f, ValType::F32, ValType::I64, expr == Expr::I64TruncUF32);
-      case Expr::I64TruncSF64:
-      case Expr::I64TruncUF64:
-        return EmitTruncate(f, ValType::F64, ValType::I64, expr == Expr::I64TruncUF64);
-      case Expr::I64ExtendSI32:
-      case Expr::I64ExtendUI32:
-        return EmitExtendI32(f, expr == Expr::I64ExtendUI32);
-      case Expr::I64ReinterpretF64:
+      case Op::I64DivS:
+      case Op::I64DivU:
+        return EmitDiv(f, ValType::I64, MIRType::Int64, op == Op::I64DivU);
+      case Op::I64RemS:
+      case Op::I64RemU:
+        return EmitRem(f, ValType::I64, MIRType::Int64, op == Op::I64RemU);
+      case Op::I64TruncSF32:
+      case Op::I64TruncUF32:
+        return EmitTruncate(f, ValType::F32, ValType::I64, op == Op::I64TruncUF32);
+      case Op::I64TruncSF64:
+      case Op::I64TruncUF64:
+        return EmitTruncate(f, ValType::F64, ValType::I64, op == Op::I64TruncUF64);
+      case Op::I64ExtendSI32:
+      case Op::I64ExtendUI32:
+        return EmitExtendI32(f, op == Op::I64ExtendUI32);
+      case Op::I64ReinterpretF64:
         return EmitReinterpret(f, ValType::I64, ValType::F64, MIRType::Int64);
-      case Expr::I64Or:
+      case Op::I64Or:
         return EmitBitwise<MBitOr>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64And:
+      case Op::I64And:
         return EmitBitwise<MBitAnd>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Xor:
+      case Op::I64Xor:
         return EmitBitwise<MBitXor>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Shl:
+      case Op::I64Shl:
         return EmitBitwise<MLsh>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64ShrS:
+      case Op::I64ShrS:
         return EmitBitwise<MRsh>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64ShrU:
+      case Op::I64ShrU:
         return EmitBitwise<MUrsh>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Rotr:
-      case Expr::I64Rotl:
-        return EmitRotate(f, ValType::I64, expr == Expr::I64Rotl);
-      case Expr::I64Eqz:
+      case Op::I64Rotr:
+      case Op::I64Rotl:
+        return EmitRotate(f, ValType::I64, op == Op::I64Rotl);
+      case Op::I64Eqz:
         return EmitConversion<MNot>(f, ValType::I64, ValType::I32);
-      case Expr::I64Clz:
+      case Op::I64Clz:
         return EmitUnaryWithType<MClz>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Ctz:
+      case Op::I64Ctz:
         return EmitUnaryWithType<MCtz>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Popcnt:
+      case Op::I64Popcnt:
         return EmitUnaryWithType<MPopcnt>(f, ValType::I64, MIRType::Int64);
-      case Expr::I64Load8S:
+      case Op::I64Load8S:
         return EmitLoad(f, ValType::I64, Scalar::Int8);
-      case Expr::I64Load8U:
+      case Op::I64Load8U:
         return EmitLoad(f, ValType::I64, Scalar::Uint8);
-      case Expr::I64Load16S:
+      case Op::I64Load16S:
         return EmitLoad(f, ValType::I64, Scalar::Int16);
-      case Expr::I64Load16U:
+      case Op::I64Load16U:
         return EmitLoad(f, ValType::I64, Scalar::Uint16);
-      case Expr::I64Load32S:
+      case Op::I64Load32S:
         return EmitLoad(f, ValType::I64, Scalar::Int32);
-      case Expr::I64Load32U:
+      case Op::I64Load32U:
         return EmitLoad(f, ValType::I64, Scalar::Uint32);
-      case Expr::I64Load:
+      case Op::I64Load:
         return EmitLoad(f, ValType::I64, Scalar::Int64);
-      case Expr::I64Store8:
+      case Op::I64Store8:
         return EmitStore(f, ValType::I64, Scalar::Int8);
-      case Expr::I64TeeStore8:
+      case Op::I64TeeStore8:
         return EmitTeeStore(f, ValType::I64, Scalar::Int8);
-      case Expr::I64Store16:
+      case Op::I64Store16:
         return EmitStore(f, ValType::I64, Scalar::Int16);
-      case Expr::I64TeeStore16:
+      case Op::I64TeeStore16:
         return EmitTeeStore(f, ValType::I64, Scalar::Int16);
-      case Expr::I64Store32:
+      case Op::I64Store32:
         return EmitStore(f, ValType::I64, Scalar::Int32);
-      case Expr::I64TeeStore32:
+      case Op::I64TeeStore32:
         return EmitTeeStore(f, ValType::I64, Scalar::Int32);
-      case Expr::I64Store:
+      case Op::I64Store:
         return EmitStore(f, ValType::I64, Scalar::Int64);
-      case Expr::I64TeeStore:
+      case Op::I64TeeStore:
         return EmitTeeStore(f, ValType::I64, Scalar::Int64);
 
       // F32
-      case Expr::F32Const: {
+      case Op::F32Const: {
         RawF32 f32;
         if (!f.iter().readF32Const(&f32))
             return false;
 
         f.iter().setResult(f.constant(f32));
         return true;
       }
-      case Expr::F32Add:
+      case Op::F32Add:
         return EmitAdd(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Sub:
+      case Op::F32Sub:
         return EmitSub(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Mul:
+      case Op::F32Mul:
         return EmitMul(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Div:
+      case Op::F32Div:
         return EmitDiv(f, ValType::F32, MIRType::Float32, /* isUnsigned = */ false);
-      case Expr::F32Min:
-      case Expr::F32Max:
-        return EmitMinMax(f, ValType::F32, MIRType::Float32, expr == Expr::F32Max);
-      case Expr::F32CopySign:
+      case Op::F32Min:
+      case Op::F32Max:
+        return EmitMinMax(f, ValType::F32, MIRType::Float32, op == Op::F32Max);
+      case Op::F32CopySign:
         return EmitCopySign(f, ValType::F32);
-      case Expr::F32Neg:
+      case Op::F32Neg:
         return EmitUnaryWithType<MAsmJSNeg>(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Abs:
+      case Op::F32Abs:
         return EmitUnaryWithType<MAbs>(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Sqrt:
+      case Op::F32Sqrt:
         return EmitUnaryWithType<MSqrt>(f, ValType::F32, MIRType::Float32);
-      case Expr::F32Ceil:
+      case Op::F32Ceil:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::CeilF, ValType::F32);
-      case Expr::F32Floor:
+      case Op::F32Floor:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::FloorF, ValType::F32);
-      case Expr::F32Trunc:
+      case Op::F32Trunc:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::TruncF, ValType::F32);
-      case Expr::F32Nearest:
+      case Op::F32Nearest:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::NearbyIntF, ValType::F32);
-      case Expr::F32DemoteF64:
+      case Op::F32DemoteF64:
         return EmitConversion<MToFloat32>(f, ValType::F64, ValType::F32);
-      case Expr::F32ConvertSI32:
+      case Op::F32ConvertSI32:
         return EmitConversion<MToFloat32>(f, ValType::I32, ValType::F32);
-      case Expr::F32ConvertUI32:
+      case Op::F32ConvertUI32:
         return EmitConversion<MWasmUnsignedToFloat32>(f, ValType::I32, ValType::F32);
-      case Expr::F32ConvertSI64:
-      case Expr::F32ConvertUI64:
+      case Op::F32ConvertSI64:
+      case Op::F32ConvertUI64:
         return EmitConvertI64ToFloatingPoint(f, ValType::F32, MIRType::Float32,
-                                             expr == Expr::F32ConvertUI64);
-      case Expr::F32ReinterpretI32:
+                                             op == Op::F32ConvertUI64);
+      case Op::F32ReinterpretI32:
         return EmitReinterpret(f, ValType::F32, ValType::I32, MIRType::Float32);
 
-      case Expr::F32Load:
+      case Op::F32Load:
         return EmitLoad(f, ValType::F32, Scalar::Float32);
-      case Expr::F32Store:
+      case Op::F32Store:
         return EmitStore(f, ValType::F32, Scalar::Float32);
-      case Expr::F32TeeStore:
+      case Op::F32TeeStore:
         return EmitTeeStore(f, ValType::F32, Scalar::Float32);
-      case Expr::F32TeeStoreF64:
+      case Op::F32TeeStoreF64:
         return EmitTeeStoreWithCoercion(f, ValType::F32, Scalar::Float64);
 
       // F64
-      case Expr::F64Const: {
+      case Op::F64Const: {
         RawF64 f64;
         if (!f.iter().readF64Const(&f64))
             return false;
 
         f.iter().setResult(f.constant(f64));
         return true;
       }
-      case Expr::F64Add:
+      case Op::F64Add:
         return EmitAdd(f, ValType::F64, MIRType::Double);
-      case Expr::F64Sub:
+      case Op::F64Sub:
         return EmitSub(f, ValType::F64, MIRType::Double);
-      case Expr::F64Mul:
+      case Op::F64Mul:
         return EmitMul(f, ValType::F64, MIRType::Double);
-      case Expr::F64Div:
+      case Op::F64Div:
         return EmitDiv(f, ValType::F64, MIRType::Double, /* isUnsigned = */ false);
-      case Expr::F64Mod:
+      case Op::F64Mod:
         return EmitRem(f, ValType::F64, MIRType::Double, /* isUnsigned = */ false);
-      case Expr::F64Min:
-      case Expr::F64Max:
-        return EmitMinMax(f, ValType::F64, MIRType::Double, expr == Expr::F64Max);
-      case Expr::F64CopySign:
+      case Op::F64Min:
+      case Op::F64Max:
+        return EmitMinMax(f, ValType::F64, MIRType::Double, op == Op::F64Max);
+      case Op::F64CopySign:
         return EmitCopySign(f, ValType::F64);
-      case Expr::F64Neg:
+      case Op::F64Neg:
         return EmitUnaryWithType<MAsmJSNeg>(f, ValType::F64, MIRType::Double);
-      case Expr::F64Abs:
+      case Op::F64Abs:
         return EmitUnaryWithType<MAbs>(f, ValType::F64, MIRType::Double);
-      case Expr::F64Sqrt:
+      case Op::F64Sqrt:
         return EmitUnaryWithType<MSqrt>(f, ValType::F64, MIRType::Double);
-      case Expr::F64Ceil:
+      case Op::F64Ceil:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::CeilD, ValType::F64);
-      case Expr::F64Floor:
+      case Op::F64Floor:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::FloorD, ValType::F64);
-      case Expr::F64Trunc:
+      case Op::F64Trunc:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::TruncD, ValType::F64);
-      case Expr::F64Nearest:
+      case Op::F64Nearest:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::NearbyIntD, ValType::F64);
-      case Expr::F64Sin:
+      case Op::F64Sin:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::SinD, ValType::F64);
-      case Expr::F64Cos:
+      case Op::F64Cos:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::CosD, ValType::F64);
-      case Expr::F64Tan:
+      case Op::F64Tan:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::TanD, ValType::F64);
-      case Expr::F64Asin:
+      case Op::F64Asin:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::ASinD, ValType::F64);
-      case Expr::F64Acos:
+      case Op::F64Acos:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::ACosD, ValType::F64);
-      case Expr::F64Atan:
+      case Op::F64Atan:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::ATanD, ValType::F64);
-      case Expr::F64Exp:
+      case Op::F64Exp:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::ExpD, ValType::F64);
-      case Expr::F64Log:
+      case Op::F64Log:
         return EmitUnaryMathBuiltinCall(f, SymbolicAddress::LogD, ValType::F64);
-      case Expr::F64Pow:
+      case Op::F64Pow:
         return EmitBinaryMathBuiltinCall(f, SymbolicAddress::PowD, ValType::F64);
-      case Expr::F64Atan2:
+      case Op::F64Atan2:
         return EmitBinaryMathBuiltinCall(f, SymbolicAddress::ATan2D, ValType::F64);
-      case Expr::F64PromoteF32:
+      case Op::F64PromoteF32:
         return EmitConversion<MToDouble>(f, ValType::F32, ValType::F64);
-      case Expr::F64ConvertSI32:
+      case Op::F64ConvertSI32:
         return EmitConversion<MToDouble>(f, ValType::I32, ValType::F64);
-      case Expr::F64ConvertUI32:
+      case Op::F64ConvertUI32:
         return EmitConversion<MWasmUnsignedToDouble>(f, ValType::I32, ValType::F64);
-      case Expr::F64ConvertSI64:
-      case Expr::F64ConvertUI64:
+      case Op::F64ConvertSI64:
+      case Op::F64ConvertUI64:
         return EmitConvertI64ToFloatingPoint(f, ValType::F64, MIRType::Double,
-                                             expr == Expr::F64ConvertUI64);
-      case Expr::F64Load:
+                                             op == Op::F64ConvertUI64);
+      case Op::F64Load:
         return EmitLoad(f, ValType::F64, Scalar::Float64);
-      case Expr::F64Store:
+      case Op::F64Store:
         return EmitStore(f, ValType::F64, Scalar::Float64);
-      case Expr::F64TeeStore:
+      case Op::F64TeeStore:
         return EmitTeeStore(f, ValType::F64, Scalar::Float64);
-      case Expr::F64TeeStoreF32:
+      case Op::F64TeeStoreF32:
         return EmitTeeStoreWithCoercion(f, ValType::F64, Scalar::Float32);
-      case Expr::F64ReinterpretI64:
+      case Op::F64ReinterpretI64:
         return EmitReinterpret(f, ValType::F64, ValType::I64, MIRType::Double);
 
       // Comparisons
-      case Expr::I32Eq:
+      case Op::I32Eq:
         return EmitComparison(f, ValType::I32, JSOP_EQ, MCompare::Compare_Int32);
-      case Expr::I32Ne:
+      case Op::I32Ne:
         return EmitComparison(f, ValType::I32, JSOP_NE, MCompare::Compare_Int32);
-      case Expr::I32LtS:
+      case Op::I32LtS:
         return EmitComparison(f, ValType::I32, JSOP_LT, MCompare::Compare_Int32);
-      case Expr::I32LeS:
+      case Op::I32LeS:
         return EmitComparison(f, ValType::I32, JSOP_LE, MCompare::Compare_Int32);
-      case Expr::I32GtS:
+      case Op::I32GtS:
         return EmitComparison(f, ValType::I32, JSOP_GT, MCompare::Compare_Int32);
-      case Expr::I32GeS:
+      case Op::I32GeS:
         return EmitComparison(f, ValType::I32, JSOP_GE, MCompare::Compare_Int32);
-      case Expr::I32LtU:
+      case Op::I32LtU:
         return EmitComparison(f, ValType::I32, JSOP_LT, MCompare::Compare_UInt32);
-      case Expr::I32LeU:
+      case Op::I32LeU:
         return EmitComparison(f, ValType::I32, JSOP_LE, MCompare::Compare_UInt32);
-      case Expr::I32GtU:
+      case Op::I32GtU:
         return EmitComparison(f, ValType::I32, JSOP_GT, MCompare::Compare_UInt32);
-      case Expr::I32GeU:
+      case Op::I32GeU:
         return EmitComparison(f, ValType::I32, JSOP_GE, MCompare::Compare_UInt32);
-      case Expr::I64Eq:
+      case Op::I64Eq:
         return EmitComparison(f, ValType::I64, JSOP_EQ, MCompare::Compare_Int64);
-      case Expr::I64Ne:
+      case Op::I64Ne:
         return EmitComparison(f, ValType::I64, JSOP_NE, MCompare::Compare_Int64);
-      case Expr::I64LtS:
+      case Op::I64LtS:
         return EmitComparison(f, ValType::I64, JSOP_LT, MCompare::Compare_Int64);
-      case Expr::I64LeS:
+      case Op::I64LeS:
         return EmitComparison(f, ValType::I64, JSOP_LE, MCompare::Compare_Int64);
-      case Expr::I64GtS:
+      case Op::I64GtS:
         return EmitComparison(f, ValType::I64, JSOP_GT, MCompare::Compare_Int64);
-      case Expr::I64GeS:
+      case Op::I64GeS:
         return EmitComparison(f, ValType::I64, JSOP_GE, MCompare::Compare_Int64);
-      case Expr::I64LtU:
+      case Op::I64LtU:
         return EmitComparison(f, ValType::I64, JSOP_LT, MCompare::Compare_UInt64);
-      case Expr::I64LeU:
+      case Op::I64LeU:
         return EmitComparison(f, ValType::I64, JSOP_LE, MCompare::Compare_UInt64);
-      case Expr::I64GtU:
+      case Op::I64GtU:
         return EmitComparison(f, ValType::I64, JSOP_GT, MCompare::Compare_UInt64);
-      case Expr::I64GeU:
+      case Op::I64GeU:
         return EmitComparison(f, ValType::I64, JSOP_GE, MCompare::Compare_UInt64);
-      case Expr::F32Eq:
+      case Op::F32Eq:
         return EmitComparison(f, ValType::F32, JSOP_EQ, MCompare::Compare_Float32);
-      case Expr::F32Ne:
+      case Op::F32Ne:
         return EmitComparison(f, ValType::F32, JSOP_NE, MCompare::Compare_Float32);
-      case Expr::F32Lt:
+      case Op::F32Lt:
         return EmitComparison(f, ValType::F32, JSOP_LT, MCompare::Compare_Float32);
-      case Expr::F32Le:
+      case Op::F32Le:
         return EmitComparison(f, ValType::F32, JSOP_LE, MCompare::Compare_Float32);
-      case Expr::F32Gt:
+      case Op::F32Gt:
         return EmitComparison(f, ValType::F32, JSOP_GT, MCompare::Compare_Float32);
-      case Expr::F32Ge:
+      case Op::F32Ge:
         return EmitComparison(f, ValType::F32, JSOP_GE, MCompare::Compare_Float32);
-      case Expr::F64Eq:
+      case Op::F64Eq:
         return EmitComparison(f, ValType::F64, JSOP_EQ, MCompare::Compare_Double);
-      case Expr::F64Ne:
+      case Op::F64Ne:
         return EmitComparison(f, ValType::F64, JSOP_NE, MCompare::Compare_Double);
-      case Expr::F64Lt:
+      case Op::F64Lt:
         return EmitComparison(f, ValType::F64, JSOP_LT, MCompare::Compare_Double);
-      case Expr::F64Le:
+      case Op::F64Le:
         return EmitComparison(f, ValType::F64, JSOP_LE, MCompare::Compare_Double);
-      case Expr::F64Gt:
+      case Op::F64Gt:
         return EmitComparison(f, ValType::F64, JSOP_GT, MCompare::Compare_Double);
-      case Expr::F64Ge:
+      case Op::F64Ge:
         return EmitComparison(f, ValType::F64, JSOP_GE, MCompare::Compare_Double);
 
       // SIMD
 #define CASE(TYPE, OP, SIGN)                                                    \
-      case Expr::TYPE##OP:                                                      \
+      case Op::TYPE##OP:                                                      \
         return EmitSimdOp(f, ValType::TYPE, SimdOperation::Fn_##OP, SIGN);
 #define I8x16CASE(OP) CASE(I8x16, OP, SimdSign::Signed)
 #define I16x8CASE(OP) CASE(I16x8, OP, SimdSign::Signed)
 #define I32x4CASE(OP) CASE(I32x4, OP, SimdSign::Signed)
 #define F32x4CASE(OP) CASE(F32x4, OP, SimdSign::NotApplicable)
 #define B8x16CASE(OP) CASE(B8x16, OP, SimdSign::NotApplicable)
 #define B16x8CASE(OP) CASE(B16x8, OP, SimdSign::NotApplicable)
 #define B32x4CASE(OP) CASE(B32x4, OP, SimdSign::NotApplicable)
 #define ENUMERATE(TYPE, FORALL, DO)                                             \
-      case Expr::TYPE##Constructor:                                             \
+      case Op::TYPE##Constructor:                                             \
         return EmitSimdOp(f, ValType::TYPE, SimdOperation::Constructor, SimdSign::NotApplicable); \
       FORALL(DO)
 
       ENUMERATE(I8x16, FORALL_INT8X16_ASMJS_OP, I8x16CASE)
       ENUMERATE(I16x8, FORALL_INT16X8_ASMJS_OP, I16x8CASE)
       ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32x4CASE)
       ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32x4CASE)
       ENUMERATE(B8x16, FORALL_BOOL_SIMD_OP, B8x16CASE)
@@ -3564,138 +3564,138 @@ EmitExpr(FunctionCompiler& f)
 #undef I16x8CASE
 #undef I32x4CASE
 #undef F32x4CASE
 #undef B8x16CASE
 #undef B16x8CASE
 #undef B32x4CASE
 #undef ENUMERATE
 
-      case Expr::I8x16Const: {
+      case Op::I8x16Const: {
         I8x16 i8x16;
         if (!f.iter().readI8x16Const(&i8x16))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX16(i8x16), MIRType::Int8x16));
         return true;
       }
-      case Expr::I16x8Const: {
+      case Op::I16x8Const: {
         I16x8 i16x8;
         if (!f.iter().readI16x8Const(&i16x8))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX8(i16x8), MIRType::Int16x8));
         return true;
       }
-      case Expr::I32x4Const: {
+      case Op::I32x4Const: {
         I32x4 i32x4;
         if (!f.iter().readI32x4Const(&i32x4))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX4(i32x4), MIRType::Int32x4));
         return true;
       }
-      case Expr::F32x4Const: {
+      case Op::F32x4Const: {
         F32x4 f32x4;
         if (!f.iter().readF32x4Const(&f32x4))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX4(f32x4), MIRType::Float32x4));
         return true;
       }
-      case Expr::B8x16Const: {
+      case Op::B8x16Const: {
         I8x16 i8x16;
         if (!f.iter().readB8x16Const(&i8x16))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX16(i8x16), MIRType::Bool8x16));
         return true;
       }
-      case Expr::B16x8Const: {
+      case Op::B16x8Const: {
         I16x8 i16x8;
         if (!f.iter().readB16x8Const(&i16x8))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX8(i16x8), MIRType::Bool16x8));
         return true;
       }
-      case Expr::B32x4Const: {
+      case Op::B32x4Const: {
         I32x4 i32x4;
         if (!f.iter().readB32x4Const(&i32x4))
             return false;
 
         f.iter().setResult(f.constant(SimdConstant::CreateX4(i32x4), MIRType::Bool32x4));
         return true;
       }
 
       // SIMD unsigned integer operations.
-      case Expr::I8x16addSaturateU:
+      case Op::I8x16addSaturateU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_addSaturate, SimdSign::Unsigned);
-      case Expr::I8x16subSaturateU:
+      case Op::I8x16subSaturateU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_subSaturate, SimdSign::Unsigned);
-      case Expr::I8x16shiftRightByScalarU:
+      case Op::I8x16shiftRightByScalarU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_shiftRightByScalar, SimdSign::Unsigned);
-      case Expr::I8x16lessThanU:
+      case Op::I8x16lessThanU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_lessThan, SimdSign::Unsigned);
-      case Expr::I8x16lessThanOrEqualU:
+      case Op::I8x16lessThanOrEqualU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_lessThanOrEqual, SimdSign::Unsigned);
-      case Expr::I8x16greaterThanU:
+      case Op::I8x16greaterThanU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_greaterThan, SimdSign::Unsigned);
-      case Expr::I8x16greaterThanOrEqualU:
+      case Op::I8x16greaterThanOrEqualU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_greaterThanOrEqual, SimdSign::Unsigned);
-      case Expr::I8x16extractLaneU:
+      case Op::I8x16extractLaneU:
         return EmitSimdOp(f, ValType::I8x16, SimdOperation::Fn_extractLane, SimdSign::Unsigned);
 
-      case Expr::I16x8addSaturateU:
+      case Op::I16x8addSaturateU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_addSaturate, SimdSign::Unsigned);
-      case Expr::I16x8subSaturateU:
+      case Op::I16x8subSaturateU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_subSaturate, SimdSign::Unsigned);
-      case Expr::I16x8shiftRightByScalarU:
+      case Op::I16x8shiftRightByScalarU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_shiftRightByScalar, SimdSign::Unsigned);
-      case Expr::I16x8lessThanU:
+      case Op::I16x8lessThanU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_lessThan, SimdSign::Unsigned);
-      case Expr::I16x8lessThanOrEqualU:
+      case Op::I16x8lessThanOrEqualU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_lessThanOrEqual, SimdSign::Unsigned);
-      case Expr::I16x8greaterThanU:
+      case Op::I16x8greaterThanU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_greaterThan, SimdSign::Unsigned);
-      case Expr::I16x8greaterThanOrEqualU:
+      case Op::I16x8greaterThanOrEqualU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_greaterThanOrEqual, SimdSign::Unsigned);
-      case Expr::I16x8extractLaneU:
+      case Op::I16x8extractLaneU:
         return EmitSimdOp(f, ValType::I16x8, SimdOperation::Fn_extractLane, SimdSign::Unsigned);
 
-      case Expr::I32x4shiftRightByScalarU:
+      case Op::I32x4shiftRightByScalarU:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_shiftRightByScalar, SimdSign::Unsigned);
-      case Expr::I32x4lessThanU:
+      case Op::I32x4lessThanU:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_lessThan, SimdSign::Unsigned);
-      case Expr::I32x4lessThanOrEqualU:
+      case Op::I32x4lessThanOrEqualU:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_lessThanOrEqual, SimdSign::Unsigned);
-      case Expr::I32x4greaterThanU:
+      case Op::I32x4greaterThanU:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_greaterThan, SimdSign::Unsigned);
-      case Expr::I32x4greaterThanOrEqualU:
+      case Op::I32x4greaterThanOrEqualU:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_greaterThanOrEqual, SimdSign::Unsigned);
-      case Expr::I32x4fromFloat32x4U:
+      case Op::I32x4fromFloat32x4U:
         return EmitSimdOp(f, ValType::I32x4, SimdOperation::Fn_fromFloat32x4, SimdSign::Unsigned);
 
       // Atomics
-      case Expr::I32AtomicsLoad:
+      case Op::I32AtomicsLoad:
         return EmitAtomicsLoad(f);
-      case Expr::I32AtomicsStore:
+      case Op::I32AtomicsStore:
         return EmitAtomicsStore(f);
-      case Expr::I32AtomicsBinOp:
+      case Op::I32AtomicsBinOp:
         return EmitAtomicsBinOp(f);
-      case Expr::I32AtomicsCompareExchange:
+      case Op::I32AtomicsCompareExchange:
         return EmitAtomicsCompareExchange(f);
-      case Expr::I32AtomicsExchange:
+      case Op::I32AtomicsExchange:
         return EmitAtomicsExchange(f);
       // Memory Operators
-      case Expr::GrowMemory:
+      case Op::GrowMemory:
         return EmitGrowMemory(f);
-      case Expr::CurrentMemory:
+      case Op::CurrentMemory:
         return EmitCurrentMemory(f);
-      case Expr::Limit:;
+      case Op::Limit:;
     }
 
     MOZ_CRASH("unexpected wasm opcode");
 }
 
 bool
 wasm::IonCompileFunction(IonCompileTask* task)
 {
--- a/js/src/wasm/WasmTextToBinary.cpp
+++ b/js/src/wasm/WasmTextToBinary.cpp
@@ -132,17 +132,17 @@ class WasmToken
     const char16_t* begin_;
     const char16_t* end_;
     union {
         uint32_t index_;
         uint64_t uint_;
         int64_t sint_;
         FloatLiteralKind floatLiteralKind_;
         ValType valueType_;
-        Expr expr_;
+        Op op_;
     } u;
   public:
     WasmToken()
       : kind_(Kind(-1)),
         begin_(nullptr),
         end_(nullptr),
         u()
     { }
@@ -191,26 +191,26 @@ class WasmToken
       : kind_(kind),
         begin_(begin),
         end_(end)
     {
         MOZ_ASSERT(begin != end);
         MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
         u.valueType_ = valueType;
     }
-    explicit WasmToken(Kind kind, Expr expr, const char16_t* begin, const char16_t* end)
+    explicit WasmToken(Kind kind, Op op, const char16_t* begin, const char16_t* end)
       : kind_(kind),
         begin_(begin),
         end_(end)
     {
         MOZ_ASSERT(begin != end);
         MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
                    kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
                    kind_ == Load || kind_ == Store);
-        u.expr_ = expr;
+        u.op_ = op;
     }
     explicit WasmToken(const char16_t* begin)
       : kind_(Error),
         begin_(begin),
         end_(begin)
     {}
     Kind kind() const {
         MOZ_ASSERT(kind_ != Kind(-1));
@@ -247,21 +247,21 @@ class WasmToken
     FloatLiteralKind floatLiteralKind() const {
         MOZ_ASSERT(kind_ == Float);
         return u.floatLiteralKind_;
     }
     ValType valueType() const {
         MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
         return u.valueType_;
     }
-    Expr expr() const {
+    Op op() const {
         MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == TernaryOpcode ||
                    kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
                    kind_ == Load || kind_ == Store);
-        return u.expr_;
+        return u.op_;
     }
     bool isOpcode() const {
         switch (kind_) {
           case BinaryOpcode:
           case Block:
           case Br:
           case BrIf:
           case BrTable:
@@ -883,207 +883,207 @@ WasmTokenStream::next()
 
         if (consume(u"f32")) {
             if (!consume(u"."))
                 return WasmToken(WasmToken::ValueType, ValType::F32, begin, cur_);
 
             switch (*cur_) {
               case 'a':
                 if (consume(u"abs"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Abs, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Abs, begin, cur_);
                 if (consume(u"add"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Add, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Add, begin, cur_);
                 break;
               case 'c':
                 if (consume(u"ceil"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Ceil, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Ceil, begin, cur_);
                 if (consume(u"const"))
                     return WasmToken(WasmToken::Const, ValType::F32, begin, cur_);
                 if (consume(u"convert_s/i32")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertSI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI32,
                                      begin, cur_);
                 }
                 if (consume(u"convert_u/i32")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertUI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI32,
                                      begin, cur_);
                 }
                 if (consume(u"convert_s/i64")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertSI64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertSI64,
                                      begin, cur_);
                 }
                 if (consume(u"convert_u/i64")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertUI64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32ConvertUI64,
                                      begin, cur_);
                 }
                 if (consume(u"copysign"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32CopySign, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32CopySign, begin, cur_);
                 break;
               case 'd':
                 if (consume(u"demote/f64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32DemoteF64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32DemoteF64,
                                      begin, cur_);
                 if (consume(u"div"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Div, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Div, begin, cur_);
                 break;
               case 'e':
                 if (consume(u"eq"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Eq, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Eq, begin, cur_);
                 break;
               case 'f':
                 if (consume(u"floor"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Floor, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Floor, begin, cur_);
                 break;
               case 'g':
                 if (consume(u"ge"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Ge, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Ge, begin, cur_);
                 if (consume(u"gt"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Gt, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Gt, begin, cur_);
                 break;
               case 'l':
                 if (consume(u"le"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Le, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Le, begin, cur_);
                 if (consume(u"lt"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Lt, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Lt, begin, cur_);
                 if (consume(u"load"))
-                    return WasmToken(WasmToken::Load, Expr::F32Load, begin, cur_);
+                    return WasmToken(WasmToken::Load, Op::F32Load, begin, cur_);
                 break;
               case 'm':
                 if (consume(u"max"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Max, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Max, begin, cur_);
                 if (consume(u"min"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Min, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Min, begin, cur_);
                 if (consume(u"mul"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Mul, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Mul, begin, cur_);
                 break;
               case 'n':
                 if (consume(u"nearest"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Nearest, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Nearest, begin, cur_);
                 if (consume(u"neg"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Neg, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Neg, begin, cur_);
                 if (consume(u"ne"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Ne, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F32Ne, begin, cur_);
                 break;
               case 'r':
                 if (consume(u"reinterpret/i32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F32ReinterpretI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F32ReinterpretI32,
                                      begin, cur_);
                 break;
               case 's':
                 if (consume(u"sqrt"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Sqrt, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Sqrt, begin, cur_);
                 if (consume(u"sub"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F32Sub, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F32Sub, begin, cur_);
                 if (consume(u"store"))
-                    return WasmToken(WasmToken::Store, Expr::F32Store, begin, cur_);
+                    return WasmToken(WasmToken::Store, Op::F32Store, begin, cur_);
                 break;
               case 't':
                 if (consume(u"trunc"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F32Trunc, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F32Trunc, begin, cur_);
                 break;
             }
             break;
         }
         if (consume(u"f64")) {
             if (!consume(u"."))
                 return WasmToken(WasmToken::ValueType, ValType::F64, begin, cur_);
 
             switch (*cur_) {
               case 'a':
                 if (consume(u"abs"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Abs, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Abs, begin, cur_);
                 if (consume(u"add"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Add, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Add, begin, cur_);
                 break;
               case 'c':
                 if (consume(u"ceil"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Ceil, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Ceil, begin, cur_);
                 if (consume(u"const"))
                     return WasmToken(WasmToken::Const, ValType::F64, begin, cur_);
                 if (consume(u"convert_s/i32")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertSI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI32,
                                      begin, cur_);
                 }
                 if (consume(u"convert_u/i32")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertUI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI32,
                                      begin, cur_);
                 }
                 if (consume(u"convert_s/i64")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertSI64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertSI64,
                                      begin, cur_);
                 }
                 if (consume(u"convert_u/i64")) {
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertUI64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F64ConvertUI64,
                                      begin, cur_);
                 }
                 if (consume(u"copysign"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64CopySign, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64CopySign, begin, cur_);
                 break;
               case 'd':
                 if (consume(u"div"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Div, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Div, begin, cur_);
                 break;
               case 'e':
                 if (consume(u"eq"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Eq, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Eq, begin, cur_);
                 break;
               case 'f':
                 if (consume(u"floor"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Floor, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Floor, begin, cur_);
                 break;
               case 'g':
                 if (consume(u"ge"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Ge, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Ge, begin, cur_);
                 if (consume(u"gt"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Gt, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Gt, begin, cur_);
                 break;
               case 'l':
                 if (consume(u"le"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Le, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Le, begin, cur_);
                 if (consume(u"lt"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Lt, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Lt, begin, cur_);
                 if (consume(u"load"))
-                    return WasmToken(WasmToken::Load, Expr::F64Load, begin, cur_);
+                    return WasmToken(WasmToken::Load, Op::F64Load, begin, cur_);
                 break;
               case 'm':
                 if (consume(u"max"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Max, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Max, begin, cur_);
                 if (consume(u"min"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Min, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Min, begin, cur_);
                 if (consume(u"mul"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Mul, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Mul, begin, cur_);
                 break;
               case 'n':
                 if (consume(u"nearest"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Nearest, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Nearest, begin, cur_);
                 if (consume(u"neg"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Neg, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Neg, begin, cur_);
                 if (consume(u"ne"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Ne, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::F64Ne, begin, cur_);
                 break;
               case 'p':
                 if (consume(u"promote/f32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::F64PromoteF32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::F64PromoteF32,
                                      begin, cur_);
                 break;
               case 'r':
                 if (consume(u"reinterpret/i64"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64ReinterpretI64,
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64ReinterpretI64,
                                      begin, cur_);
                 break;
               case 's':
                 if (consume(u"sqrt"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Sqrt, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Sqrt, begin, cur_);
                 if (consume(u"sub"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::F64Sub, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::F64Sub, begin, cur_);
                 if (consume(u"store"))
-                    return WasmToken(WasmToken::Store, Expr::F64Store, begin, cur_);
+                    return WasmToken(WasmToken::Store, Op::F64Store, begin, cur_);
                 break;
               case 't':
                 if (consume(u"trunc"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::F64Trunc, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::F64Trunc, begin, cur_);
                 break;
             }
             break;
         }
         break;
 
       case 'g':
         if (consume(u"get_global"))
@@ -1099,288 +1099,288 @@ WasmTokenStream::next()
       case 'i':
         if (consume(u"i32")) {
             if (!consume(u"."))
                 return WasmToken(WasmToken::ValueType, ValType::I32, begin, cur_);
 
             switch (*cur_) {
               case 'a':
                 if (consume(u"add"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Add, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Add, begin, cur_);
                 if (consume(u"and"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32And, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32And, begin, cur_);
                 break;
               case 'c':
                 if (consume(u"const"))
                     return WasmToken(WasmToken::Const, ValType::I32, begin, cur_);
                 if (consume(u"clz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I32Clz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I32Clz, begin, cur_);
                 if (consume(u"ctz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I32Ctz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I32Ctz, begin, cur_);
                 break;
               case 'd':
                 if (consume(u"div_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32DivS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32DivS, begin, cur_);
                 if (consume(u"div_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32DivU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32DivU, begin, cur_);
                 break;
               case 'e':
                 if (consume(u"eqz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I32Eqz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I32Eqz, begin, cur_);
                 if (consume(u"eq"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32Eq, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32Eq, begin, cur_);
                 break;
               case 'g':
                 if (consume(u"ge_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32GeS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32GeS, begin, cur_);
                 if (consume(u"ge_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32GeU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32GeU, begin, cur_);
                 if (consume(u"gt_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32GtS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32GtS, begin, cur_);
                 if (consume(u"gt_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32GtU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32GtU, begin, cur_);
                 break;
               case 'l':
                 if (consume(u"le_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32LeS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32LeS, begin, cur_);
                 if (consume(u"le_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32LeU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32LeU, begin, cur_);
                 if (consume(u"lt_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32LtS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32LtS, begin, cur_);
                 if (consume(u"lt_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32LtU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32LtU, begin, cur_);
                 if (consume(u"load")) {
                     if (IsWasmSpace(*cur_))
-                        return WasmToken(WasmToken::Load, Expr::I32Load, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I32Load, begin, cur_);
                     if (consume(u"8_s"))
-                        return WasmToken(WasmToken::Load, Expr::I32Load8S, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I32Load8S, begin, cur_);
                     if (consume(u"8_u"))
-                        return WasmToken(WasmToken::Load, Expr::I32Load8U, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I32Load8U, begin, cur_);
                     if (consume(u"16_s"))
-                        return WasmToken(WasmToken::Load, Expr::I32Load16S, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I32Load16S, begin, cur_);
                     if (consume(u"16_u"))
-                        return WasmToken(WasmToken::Load, Expr::I32Load16U, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I32Load16U, begin, cur_);
                     break;
                 }
                 break;
               case 'm':
                 if (consume(u"mul"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Mul, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Mul, begin, cur_);
                 break;
               case 'n':
                 if (consume(u"ne"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I32Ne, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I32Ne, begin, cur_);
                 break;
               case 'o':
                 if (consume(u"or"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Or, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Or, begin, cur_);
                 break;
               case 'p':
                 if (consume(u"popcnt"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I32Popcnt, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I32Popcnt, begin, cur_);
                 break;
               case 'r':
                 if (consume(u"reinterpret/f32"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I32ReinterpretF32,
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I32ReinterpretF32,
                                      begin, cur_);
                 if (consume(u"rem_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32RemS, begin, cur_);
                 if (consume(u"rem_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32RemU, begin, cur_);
                 if (consume(u"rotr"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Rotr, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Rotr, begin, cur_);
                 if (consume(u"rotl"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Rotl, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Rotl, begin, cur_);
                 break;
               case 's':
                 if (consume(u"sub"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Sub, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Sub, begin, cur_);
                 if (consume(u"shl"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Shl, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Shl, begin, cur_);
                 if (consume(u"shr_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32ShrS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32ShrS, begin, cur_);
                 if (consume(u"shr_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32ShrU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32ShrU, begin, cur_);
                 if (consume(u"store")) {
                     if (IsWasmSpace(*cur_))
-                        return WasmToken(WasmToken::Store, Expr::I32Store, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I32Store, begin, cur_);
                     if (consume(u"8"))
-                        return WasmToken(WasmToken::Store, Expr::I32Store8, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I32Store8, begin, cur_);
                     if (consume(u"16"))
-                        return WasmToken(WasmToken::Store, Expr::I32Store16, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I32Store16, begin, cur_);
                     break;
                 }
                 break;
               case 't':
                 if (consume(u"trunc_s/f32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncSF32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF32,
                                      begin, cur_);
                 if (consume(u"trunc_s/f64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncSF64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncSF64,
                                      begin, cur_);
                 if (consume(u"trunc_u/f32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncUF32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF32,
                                      begin, cur_);
                 if (consume(u"trunc_u/f64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncUF64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I32TruncUF64,
                                      begin, cur_);
                 break;
               case 'w':
                 if (consume(u"wrap/i64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I32WrapI64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I32WrapI64,
                                      begin, cur_);
                 break;
               case 'x':
                 if (consume(u"xor"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I32Xor, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I32Xor, begin, cur_);
                 break;
             }
             break;
         }
         if (consume(u"i64")) {
             if (!consume(u"."))
                 return WasmToken(WasmToken::ValueType, ValType::I64, begin, cur_);
 
             switch (*cur_) {
               case 'a':
                 if (consume(u"add"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Add, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Add, begin, cur_);
                 if (consume(u"and"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64And, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64And, begin, cur_);
                 break;
               case 'c':
                 if (consume(u"const"))
                     return WasmToken(WasmToken::Const, ValType::I64, begin, cur_);
                 if (consume(u"clz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I64Clz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I64Clz, begin, cur_);
                 if (consume(u"ctz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I64Ctz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I64Ctz, begin, cur_);
                 break;
               case 'd':
                 if (consume(u"div_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64DivS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64DivS, begin, cur_);
                 if (consume(u"div_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64DivU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64DivU, begin, cur_);
                 break;
               case 'e':
                 if (consume(u"eqz"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I64Eqz, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I64Eqz, begin, cur_);
                 if (consume(u"eq"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64Eq, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64Eq, begin, cur_);
                 if (consume(u"extend_s/i32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64ExtendSI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendSI32,
                                      begin, cur_);
                 if (consume(u"extend_u/i32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64ExtendUI32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64ExtendUI32,
                                      begin, cur_);
                 break;
               case 'g':
                 if (consume(u"ge_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64GeS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64GeS, begin, cur_);
                 if (consume(u"ge_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64GeU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64GeU, begin, cur_);
                 if (consume(u"gt_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64GtS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64GtS, begin, cur_);
                 if (consume(u"gt_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64GtU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64GtU, begin, cur_);
                 break;
               case 'l':
                 if (consume(u"le_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64LeS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64LeS, begin, cur_);
                 if (consume(u"le_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64LeU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64LeU, begin, cur_);
                 if (consume(u"lt_s"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64LtS, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64LtS, begin, cur_);
                 if (consume(u"lt_u"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64LtU, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64LtU, begin, cur_);
                 if (consume(u"load")) {
                     if (IsWasmSpace(*cur_))
-                        return WasmToken(WasmToken::Load, Expr::I64Load, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load, begin, cur_);
                     if (consume(u"8_s"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load8S, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load8S, begin, cur_);
                     if (consume(u"8_u"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load8U, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load8U, begin, cur_);
                     if (consume(u"16_s"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load16S, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load16S, begin, cur_);
                     if (consume(u"16_u"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load16U, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load16U, begin, cur_);
                     if (consume(u"32_s"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load32S, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load32S, begin, cur_);
                     if (consume(u"32_u"))
-                        return WasmToken(WasmToken::Load, Expr::I64Load32U, begin, cur_);
+                        return WasmToken(WasmToken::Load, Op::I64Load32U, begin, cur_);
                     break;
                 }
                 break;
               case 'm':
                 if (consume(u"mul"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Mul, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Mul, begin, cur_);
                 break;
               case 'n':
                 if (consume(u"ne"))
-                    return WasmToken(WasmToken::ComparisonOpcode, Expr::I64Ne, begin, cur_);
+                    return WasmToken(WasmToken::ComparisonOpcode, Op::I64Ne, begin, cur_);
                 break;
               case 'o':
                 if (consume(u"or"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Or, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Or, begin, cur_);
                 break;
               case 'p':
                 if (consume(u"popcnt"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I64Popcnt, begin, cur_);
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I64Popcnt, begin, cur_);
                 break;
               case 'r':
                 if (consume(u"reinterpret/f64"))
-                    return WasmToken(WasmToken::UnaryOpcode, Expr::I64ReinterpretF64,
+                    return WasmToken(WasmToken::UnaryOpcode, Op::I64ReinterpretF64,
                                      begin, cur_);
                 if (consume(u"rem_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64RemS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64RemS, begin, cur_);
                 if (consume(u"rem_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64RemU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64RemU, begin, cur_);
                 if (consume(u"rotr"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Rotr, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Rotr, begin, cur_);
                 if (consume(u"rotl"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Rotl, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Rotl, begin, cur_);
                 break;
               case 's':
                 if (consume(u"sub"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Sub, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Sub, begin, cur_);
                 if (consume(u"shl"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Shl, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Shl, begin, cur_);
                 if (consume(u"shr_s"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64ShrS, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64ShrS, begin, cur_);
                 if (consume(u"shr_u"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64ShrU, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64ShrU, begin, cur_);
                 if (consume(u"store")) {
                     if (IsWasmSpace(*cur_))
-                        return WasmToken(WasmToken::Store, Expr::I64Store, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I64Store, begin, cur_);
                     if (consume(u"8"))
-                        return WasmToken(WasmToken::Store, Expr::I64Store8, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I64Store8, begin, cur_);
                     if (consume(u"16"))
-                        return WasmToken(WasmToken::Store, Expr::I64Store16, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I64Store16, begin, cur_);
                     if (consume(u"32"))
-                        return WasmToken(WasmToken::Store, Expr::I64Store32, begin, cur_);
+                        return WasmToken(WasmToken::Store, Op::I64Store32, begin, cur_);
                     break;
                 }
                 break;
               case 't':
                 if (consume(u"trunc_s/f32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64TruncSF32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF32,
                                      begin, cur_);
                 if (consume(u"trunc_s/f64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64TruncSF64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncSF64,
                                      begin, cur_);
                 if (consume(u"trunc_u/f32"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64TruncUF32,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF32,
                                      begin, cur_);
                 if (consume(u"trunc_u/f64"))
-                    return WasmToken(WasmToken::ConversionOpcode, Expr::I64TruncUF64,
+                    return WasmToken(WasmToken::ConversionOpcode, Op::I64TruncUF64,
                                      begin, cur_);
                 break;
               case 'x':
                 if (consume(u"xor"))
-                    return WasmToken(WasmToken::BinaryOpcode, Expr::I64Xor, begin, cur_);
+                    return WasmToken(WasmToken::BinaryOpcode, Op::I64Xor, begin, cur_);
                 break;
             }
             break;
         }
         if (consume(u"import"))
             return WasmToken(WasmToken::Import, begin, cur_);
         if (consume(u"infinity"))
             return WasmToken(WasmToken::Infinity, begin, cur_);
@@ -1425,17 +1425,17 @@ WasmTokenStream::next()
         if (consume(u"result"))
             return WasmToken(WasmToken::Result, begin, cur_);
         if (consume(u"return"))
             return WasmToken(WasmToken::Return, begin, cur_);
         break;
 
       case 's':
         if (consume(u"select"))
-            return WasmToken(WasmToken::TernaryOpcode, Expr::Select, begin, cur_);
+            return WasmToken(WasmToken::TernaryOpcode, Op::Select, begin, cur_);
         if (consume(u"set_global"))
             return WasmToken(WasmToken::SetGlobal, begin, cur_);
         if (consume(u"set_local"))
             return WasmToken(WasmToken::SetLocal, begin, cur_);
         if (consume(u"start"))
             return WasmToken(WasmToken::Start, begin, cur_);
         break;
 
@@ -1558,26 +1558,26 @@ ParseBlockSignature(WasmParseContext& c,
         *type = ToExprType(token.valueType());
     else
         *type = ExprType::Void;
 
     return true;
 }
 
 static AstBlock*
-ParseBlock(WasmParseContext& c, Expr expr, bool inParens)
+ParseBlock(WasmParseContext& c, Op op, bool inParens)
 {
     AstExprVector exprs(c.lifo);
 
     AstName name = c.ts.getIfName();
 
     // Compatibility syntax sugar: If a second label is present, we'll wrap
     // this loop in a block.
     AstName otherName;
-    if (expr == Expr::Loop) {
+    if (op == Op::Loop) {
         AstName maybeName = c.ts.getIfName();
         if (!maybeName.empty()) {
             otherName = name;
             name = maybeName;
         }
     }
 
     ExprType type;
@@ -1587,31 +1587,31 @@ ParseBlock(WasmParseContext& c, Expr exp
     if (!ParseExprList(c, &exprs, inParens))
         return nullptr;
 
     if (!inParens) {
         if (!c.ts.match(WasmToken::End, c.error))
             return nullptr;
     }
 
-    AstBlock* result = new(c.lifo) AstBlock(expr, type, name, Move(exprs));
-
-    if (expr == Expr::Loop && !otherName.empty()) {
+    AstBlock* result = new(c.lifo) AstBlock(op, type, name, Move(exprs));
+
+    if (op == Op::Loop && !otherName.empty()) {
         if (!exprs.append(result))
             return nullptr;
-        result = new(c.lifo) AstBlock(Expr::Block, type, otherName, Move(exprs));
+        result = new(c.lifo) AstBlock(Op::Block, type, otherName, Move(exprs));
     }
 
     return result;
 }
 
 static AstBranch*
-ParseBranch(WasmParseContext& c, Expr expr, bool inParens)
+ParseBranch(WasmParseContext& c, Op op, bool inParens)
 {
-    MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf);
+    MOZ_ASSERT(op == Op::Br || op == Op::BrIf);
 
     AstRef target;
     if (!c.ts.matchRef(&target, c.error))
         return nullptr;
 
     AstExpr* value = nullptr;
     if (inParens) {
         if (c.ts.getIf(WasmToken::OpenParen)) {
@@ -1619,31 +1619,31 @@ ParseBranch(WasmParseContext& c, Expr ex
             if (!value)
                 return nullptr;
             if (!c.ts.match(WasmToken::CloseParen, c.error))
                 return nullptr;
         }
     }
 
     AstExpr* cond = nullptr;
-    if (expr == Expr::BrIf) {
+    if (op == Op::BrIf) {
         if (inParens && c.ts.getIf(WasmToken::OpenParen)) {
             cond = ParseExprInsideParens(c);
             if (!cond)
                 return nullptr;
             if (!c.ts.match(WasmToken::CloseParen, c.error))
                 return nullptr;
         } else {
             cond = new(c.lifo) AstPop();
             if (!cond)
                 return nullptr;
         }
     }
 
-    return new(c.lifo) AstBranch(expr, ExprType::Void, cond, target, value);
+    return new(c.lifo) AstBranch(op, ExprType::Void, cond, target, value);
 }
 
 static bool
 ParseArgs(WasmParseContext& c, AstExprVector* args)
 {
     while (c.ts.getIf(WasmToken::OpenParen)) {
         AstExpr* arg = ParseExprInsideParens(c);
         if (!arg || !args->append(arg))
@@ -1663,17 +1663,17 @@ ParseCall(WasmParseContext& c, bool inPa
         return nullptr;