Bug 1229399: Add list of wasm opcodes described in v8 design document; r=luke
authorBenjamin Bouvier <benj@benj.me>
Mon, 18 Jan 2016 18:48:25 +0100
changeset 280397 ac89d5bfe552b127a79008c130efd80695920fb1
parent 280396 7d298a714dd550d179cd9124dbdbbd1baab9da51
child 280398 1f3dd3fe9116c56a70ea718c0814c36d100e8aea
push id70428
push userbenj@benj.me
push dateMon, 18 Jan 2016 17:53:12 +0000
treeherdermozilla-inbound@ac89d5bfe552 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1229399
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1229399: Add list of wasm opcodes described in v8 design document; r=luke
js/src/asmjs/AsmJS.cpp
js/src/asmjs/WasmBinary.h
js/src/asmjs/WasmIonCompile.cpp
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -2708,37 +2708,37 @@ class MOZ_STACK_CLASS FunctionValidator
         return encoder().writeU32(u32);
     }
     MOZ_WARN_UNUSED_RESULT
     bool writeI32(int32_t i32) {
         return encoder().writeI32(i32);
     }
     MOZ_WARN_UNUSED_RESULT
     bool writeInt32Lit(int32_t i32) {
-        return writeOp(Expr::I32Literal) && encoder().writeI32(i32);
+        return writeOp(Expr::I32Const) && encoder().writeI32(i32);
     }
 
     MOZ_WARN_UNUSED_RESULT
     bool writeLit(NumLit lit) {
         switch (lit.which()) {
           case NumLit::Fixnum:
           case NumLit::NegativeInt:
           case NumLit::BigUnsigned:
             return writeInt32Lit(lit.toInt32());
           case NumLit::Float:
-            return writeOp(Expr::F32Literal) && encoder().writeF32(lit.toFloat());
+            return writeOp(Expr::F32Const) && encoder().writeF32(lit.toFloat());
           case NumLit::Double:
-            return writeOp(Expr::F64Literal) && encoder().writeF64(lit.toDouble());
+            return writeOp(Expr::F64Const) && encoder().writeF64(lit.toDouble());
           case NumLit::Int32x4:
-            return writeOp(Expr::I32X4Literal) && encoder().writeI32X4(lit.simdValue().asInt32x4());
+            return writeOp(Expr::I32X4Const) && encoder().writeI32X4(lit.simdValue().asInt32x4());
           case NumLit::Float32x4:
-            return writeOp(Expr::F32X4Literal) && encoder().writeF32X4(lit.simdValue().asFloat32x4());
+            return writeOp(Expr::F32X4Const) && encoder().writeF32X4(lit.simdValue().asFloat32x4());
           case NumLit::Bool32x4:
             // Boolean vectors use the Int32x4 memory representation.
-            return writeOp(Expr::B32X4Literal) && encoder().writeI32X4(lit.simdValue().asInt32x4());
+            return writeOp(Expr::B32X4Const) && encoder().writeI32X4(lit.simdValue().asInt32x4());
           case NumLit::OutOfRangeInt:
             break;
         }
         MOZ_CRASH("unexpected literal type");
     }
 
     void patchOp(size_t pos, Expr stmt) {
         static_assert(sizeof(Expr) == sizeof(uint8_t), "opcodes must be uint8");
@@ -2753,38 +2753,38 @@ class MOZ_STACK_CLASS FunctionValidator
         encoder().patch32(pos, val);
     }
     void patchSig(size_t pos, const LifoSig* ptr) {
         encoder().patchSig(pos, ptr);
     }
 
     MOZ_WARN_UNUSED_RESULT
     bool tempU8(size_t* offset) {
-        return encoder().writeU8(uint8_t(Expr::Bad), offset);
+        return encoder().writeU8(uint8_t(Expr::Unreachable), offset);
     }
     MOZ_WARN_UNUSED_RESULT
     bool tempOp(size_t* offset) {
         return tempU8(offset);
     }
     MOZ_WARN_UNUSED_RESULT
     bool temp32(size_t* offset) {
-        if (!encoder().writeU8(uint8_t(Expr::Bad), offset))
+        if (!encoder().writeU8(uint8_t(Expr::Unreachable), offset))
             return false;
         for (size_t i = 1; i < 4; i++) {
-            if (!encoder().writeU8(uint8_t(Expr::Bad)))
+            if (!encoder().writeU8(uint8_t(Expr::Unreachable)))
                 return false;
         }
         return true;
     }
     MOZ_WARN_UNUSED_RESULT
     bool tempPtr(size_t* offset) {
-        if (!encoder().writeU8(uint8_t(Expr::Bad), offset))
+        if (!encoder().writeU8(uint8_t(Expr::Unreachable), offset))
             return false;
         for (size_t i = 1; i < sizeof(intptr_t); i++) {
-            if (!encoder().writeU8(uint8_t(Expr::Bad)))
+            if (!encoder().writeU8(uint8_t(Expr::Unreachable)))
                 return false;
         }
         return true;
     }
     /************************************************** End of build helpers */
 };
 
 } /* anonymous namespace */
@@ -3387,24 +3387,24 @@ IsLiteralOrConst(FunctionValidator& f, P
     return true;
 }
 
 static bool
 CheckFinalReturn(FunctionValidator& f, ParseNode* lastNonEmptyStmt)
 {
     if (!f.hasAlreadyReturned()) {
         f.setReturnedType(ExprType::Void);
-        return f.writeOp(Expr::Ret);
+        return f.writeOp(Expr::Return);
     }
 
     if (!lastNonEmptyStmt->isKind(PNK_RETURN)) {
         if (!IsVoid(f.returnedType()))
             return f.fail(lastNonEmptyStmt, "void incompatible with previous return type");
 
-        return f.writeOp(Expr::Ret);
+        return f.writeOp(Expr::Return);
     }
 
     return true;
 }
 
 static bool
 SetLocal(FunctionValidator& f, Expr exprStmt, NumLit lit)
 {
@@ -3677,17 +3677,17 @@ CheckAndPrepareArrayAccess(FunctionValid
         return false;
 
     if (!CheckArrayAccess(f, viewName, indexExpr, viewType, needsBoundsCheck, mask))
         return false;
 
     // 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) {
-        f.patchOp(prepareAt, Expr::I32BitAnd);
+        f.patchOp(prepareAt, Expr::I32And);
         return f.writeInt32Lit(*mask);
     }
 
     f.patchOp(prepareAt, Expr::Id);
     return true;
 }
 
 static bool
@@ -3701,24 +3701,24 @@ CheckLoadArray(FunctionValidator& f, Par
     size_t needsBoundsCheckAt;
     if (!f.tempOp(&opcodeAt) || !f.tempU8(&needsBoundsCheckAt))
         return false;
 
     if (!CheckAndPrepareArrayAccess(f, ElemBase(elem), ElemIndex(elem), &viewType, &needsBoundsCheck, &mask))
         return false;
 
     switch (viewType) {
-      case Scalar::Int8:    f.patchOp(opcodeAt, Expr::I32SLoad8);  break;
-      case Scalar::Int16:   f.patchOp(opcodeAt, Expr::I32SLoad16); break;
-      case Scalar::Int32:   f.patchOp(opcodeAt, Expr::I32SLoad32); break;
-      case Scalar::Uint8:   f.patchOp(opcodeAt, Expr::I32ULoad8);  break;
-      case Scalar::Uint16:  f.patchOp(opcodeAt, Expr::I32ULoad16); break;
-      case Scalar::Uint32:  f.patchOp(opcodeAt, Expr::I32ULoad32); break;
-      case Scalar::Float32: f.patchOp(opcodeAt, Expr::F32Load);    break;
-      case Scalar::Float64: f.patchOp(opcodeAt, Expr::F64Load);    break;
+      case Scalar::Int8:    f.patchOp(opcodeAt, Expr::I32LoadMem8S);  break;
+      case Scalar::Uint8:   f.patchOp(opcodeAt, Expr::I32LoadMem8U);  break;
+      case Scalar::Int16:   f.patchOp(opcodeAt, Expr::I32LoadMem16S); break;
+      case Scalar::Uint16:  f.patchOp(opcodeAt, Expr::I32LoadMem16U); break;
+      case Scalar::Uint32:
+      case Scalar::Int32:   f.patchOp(opcodeAt, Expr::I32LoadMem);    break;
+      case Scalar::Float32: f.patchOp(opcodeAt, Expr::F32LoadMem);    break;
+      case Scalar::Float64: f.patchOp(opcodeAt, Expr::F64LoadMem);    break;
       default: MOZ_CRASH("unexpected scalar type");
     }
 
     f.patchU8(needsBoundsCheckAt, uint8_t(needsBoundsCheck));
 
     switch (viewType) {
       case Scalar::Int8:
       case Scalar::Int16:
@@ -3778,37 +3778,37 @@ CheckStoreArray(FunctionValidator& f, Pa
         break;
       default:
         MOZ_CRASH("Unexpected view type");
     }
 
     switch (viewType) {
       case Scalar::Int8:
       case Scalar::Uint8:
-        f.patchOp(opcodeAt, Expr::I32Store8);
+        f.patchOp(opcodeAt, Expr::I32StoreMem8);
         break;
       case Scalar::Int16:
       case Scalar::Uint16:
-        f.patchOp(opcodeAt, Expr::I32Store16);
+        f.patchOp(opcodeAt, Expr::I32StoreMem16);
         break;
       case Scalar::Int32:
       case Scalar::Uint32:
-        f.patchOp(opcodeAt, Expr::I32Store32);
+        f.patchOp(opcodeAt, Expr::I32StoreMem);
         break;
       case Scalar::Float32:
         if (rhsType.isFloatish())
-            f.patchOp(opcodeAt, Expr::F32StoreF32);
+            f.patchOp(opcodeAt, Expr::F32StoreMem);
         else
-            f.patchOp(opcodeAt, Expr::F64StoreF32);
+            f.patchOp(opcodeAt, Expr::F64StoreMemF32);
         break;
       case Scalar::Float64:
         if (rhsType.isFloatish())
-            f.patchOp(opcodeAt, Expr::F32StoreF64);
+            f.patchOp(opcodeAt, Expr::F32StoreMemF64);
         else
-            f.patchOp(opcodeAt, Expr::F64StoreF64);
+            f.patchOp(opcodeAt, Expr::F64StoreMem);
         break;
       default: MOZ_CRASH("unexpected scalar type");
     }
 
     f.patchU8(needsBoundsCheckAt, uint8_t(needsBoundsCheck));
 
     *type = rhsType;
     return true;
@@ -4386,26 +4386,18 @@ CheckIsVarType(FunctionValidator& f, Par
         return f.failf(argNode, "%s is not a subtype of int, float or double", type.toChars());
     return true;
 }
 
 static bool
 CheckInternalCall(FunctionValidator& f, ParseNode* callNode, PropertyName* calleeName,
                   ExprType ret, Type* type)
 {
-    switch (ret) {
-      case ExprType::Void:   if (!f.writeOp(Expr::CallInternal))      return false; break;
-      case ExprType::I32:    if (!f.writeOp(Expr::I32CallInternal))   return false; break;
-      case ExprType::I64:    MOZ_CRASH("no int64 in asm.js");
-      case ExprType::F32:    if (!f.writeOp(Expr::F32CallInternal))   return false; break;
-      case ExprType::F64:    if (!f.writeOp(Expr::F64CallInternal))   return false; break;
-      case ExprType::I32x4:  if (!f.writeOp(Expr::I32X4CallInternal)) return false; break;
-      case ExprType::F32x4:  if (!f.writeOp(Expr::F32X4CallInternal)) return false; break;
-      case ExprType::B32x4:  if (!f.writeOp(Expr::B32X4CallInternal)) return false; break;
-    }
+    if (!f.writeOp(Expr::CallInternal))
+        return false;
 
     // Function's index, to find out the function's entry
     size_t funcIndexAt;
     // Function's signature in lifo
     size_t sigAt;
     if (!f.temp32(&funcIndexAt) || !f.tempPtr(&sigAt))
         return false;
 
@@ -4479,26 +4471,18 @@ CheckFuncPtrCall(FunctionValidator& f, P
     ParseNode* indexNode = BitwiseLeft(indexExpr);
     ParseNode* maskNode = BitwiseRight(indexExpr);
 
     uint32_t mask;
     if (!IsLiteralInt(f.m(), maskNode, &mask) || mask == UINT32_MAX || !IsPowerOfTwo(mask + 1))
         return f.fail(maskNode, "function-pointer table index mask value must be a power of two minus 1");
 
     // Opcode
-    switch (ret) {
-      case ExprType::Void:   if (!f.writeOp(Expr::CallIndirect))  return false; break;
-      case ExprType::I32:    if (!f.writeOp(Expr::I32CallIndirect))   return false; break;
-      case ExprType::I64:    MOZ_CRASH("no in64 in asm.js");
-      case ExprType::F32:    if (!f.writeOp(Expr::F32CallIndirect))   return false; break;
-      case ExprType::F64:    if (!f.writeOp(Expr::F64CallIndirect))   return false; break;
-      case ExprType::I32x4:  if (!f.writeOp(Expr::I32X4CallIndirect)) return false; break;
-      case ExprType::F32x4:  if (!f.writeOp(Expr::F32X4CallIndirect)) return false; break;
-      case ExprType::B32x4:  if (!f.writeOp(Expr::B32X4CallIndirect)) return false; break;
-    }
+    if (!f.writeOp(Expr::CallIndirect))
+        return false;
     // Table's mask
     if (!f.writeU32(mask))
         return false;
     // Global data offset
     size_t globalDataOffsetAt;
     if (!f.temp32(&globalDataOffsetAt))
         return false;
     // Signature
@@ -4547,27 +4531,19 @@ CheckFFICall(FunctionValidator& f, Parse
 {
     PropertyName* calleeName = CallCallee(callNode)->name();
 
     if (ret == ExprType::F32)
         return f.fail(callNode, "FFI calls can't return float");
     if (IsSimdType(ret))
         return f.fail(callNode, "FFI calls can't return SIMD values");
 
-    switch (ret) {
-      case ExprType::Void:   if (!f.writeOp(Expr::CallImport))  return false; break;
-      case ExprType::I32:    if (!f.writeOp(Expr::I32CallImport))   return false; break;
-      case ExprType::I64:    MOZ_CRASH("no int64 in asm.js");
-      case ExprType::F32:    if (!f.writeOp(Expr::F32CallImport))   return false; break;
-      case ExprType::F64:    if (!f.writeOp(Expr::F64CallImport))   return false; break;
-      case ExprType::I32x4:  if (!f.writeOp(Expr::I32X4CallImport)) return false; break;
-      case ExprType::F32x4:  if (!f.writeOp(Expr::F32X4CallImport)) return false; break;
-      case ExprType::B32x4:  if (!f.writeOp(Expr::B32X4CallImport)) return false; break;
-    }
-
+    // Opcode
+    if (!f.writeOp(Expr::CallImport))
+        return false;
     // Global data offset
     size_t offsetAt;
     if (!f.temp32(&offsetAt))
         return false;
     // Pointer to the import's signature in the module's lifo
     size_t sigAt;
     if (!f.tempPtr(&sigAt))
         return false;
@@ -4684,28 +4660,28 @@ CheckMathBuiltinCall(FunctionValidator& 
     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::Bad;   break;
-      case AsmJSMathBuiltin_cos:    arity = 1; f64 = Expr::F64Cos;   f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_tan:    arity = 1; f64 = Expr::F64Tan;   f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_asin:   arity = 1; f64 = Expr::F64Asin;  f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_acos:   arity = 1; f64 = Expr::F64Acos;  f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_atan:   arity = 1; f64 = Expr::F64Atan;  f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_exp:    arity = 1; f64 = Expr::F64Exp;   f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_log:    arity = 1; f64 = Expr::F64Log;   f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_pow:    arity = 2; f64 = Expr::F64Pow;   f32 = Expr::Bad;   break;
-      case AsmJSMathBuiltin_atan2:  arity = 2; f64 = Expr::F64Atan2; f32 = Expr::Bad;   break;
+      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;
       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);
 
     size_t opcodeAt;
@@ -4719,17 +4695,17 @@ 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::Bad)
+    if (!opIsDouble && f32 == Expr::Unreachable)
         return f.fail(callNode, "math builtin cannot be used as float");
 
     if (opIsDouble)
         f.patchOp(opcodeAt, f64);
     else
         f.patchOp(opcodeAt, f32);
 
     if (arity == 2) {
@@ -5032,17 +5008,17 @@ CheckSimdBinary(FunctionValidator& f, Pa
     return SwitchPackOp(f, opType, Expr::I32X4Binary, Expr::F32X4Binary, Expr::B32X4Binary) &&
            CheckSimdBinaryGuts(f, call, opType, op, type);
 }
 
 static bool
 CheckSimdBinary(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType,
                 MSimdBinaryBitwise::Operation op, Type* type)
 {
-    return SwitchPackOp(f, opType, Expr::I32X4BinaryBitwise, Expr::Bad, Expr::B32X4BinaryBitwise) &&
+    return SwitchPackOp(f, opType, Expr::I32X4BinaryBitwise, Expr::Unreachable, Expr::B32X4BinaryBitwise) &&
            CheckSimdBinaryGuts(f, call, opType, op, type);
 }
 
 static bool
 CheckSimdBinary(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType,
                 MSimdBinaryComp::Operation op, Type* type)
 {
     switch (opType) {
@@ -5116,19 +5092,19 @@ typedef bool IsBitCast;
 namespace {
 // Include CheckSimdCast in unnamed namespace to avoid MSVC name lookup bug (due to the use of Type).
 
 static bool
 CheckSimdCast(FunctionValidator& f, ParseNode* call, AsmJSSimdType fromType, AsmJSSimdType toType,
               bool bitcast, Type* type)
 {
     if (!SwitchPackOp(f, toType,
-                 bitcast ? Expr::I32X4FromF32X4Bits : Expr::I32X4FromF32X4,
-                 bitcast ? Expr::F32X4FromI32X4Bits : Expr::F32X4FromI32X4,
-                 Expr::Bad))
+                      bitcast ? Expr::I32X4FromF32X4Bits : Expr::I32X4FromF32X4,
+                      bitcast ? Expr::F32X4FromI32X4Bits : Expr::F32X4FromI32X4,
+                      Expr::Unreachable))
     {
         return false;
     }
     if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(fromType)))
         return false;
     *type = toType;
     return true;
 }
@@ -5151,17 +5127,17 @@ CheckSimdShuffleSelectors(FunctionValida
 
 static bool
 CheckSimdSwizzle(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType, Type* type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 5)
         return f.failf(call, "expected 5 arguments to SIMD swizzle, got %u", numArgs);
 
-    if (!SwitchPackOp(f, opType, Expr::I32X4Swizzle, Expr::F32X4Swizzle, Expr::Bad))
+    if (!SwitchPackOp(f, opType, Expr::I32X4Swizzle, Expr::F32X4Swizzle, Expr::Unreachable))
         return false;
 
     Type retType = opType;
     ParseNode* vec = CallArgList(call);
     Type vecType;
     if (!CheckExpr(f, vec, &vecType))
         return false;
     if (!(vecType <= retType))
@@ -5182,17 +5158,17 @@ CheckSimdSwizzle(FunctionValidator& f, P
 
 static bool
 CheckSimdShuffle(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType, Type* type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 6)
         return f.failf(call, "expected 6 arguments to SIMD shuffle, got %u", numArgs);
 
-    if (!SwitchPackOp(f, opType, Expr::I32X4Shuffle, Expr::F32X4Shuffle, Expr::Bad))
+    if (!SwitchPackOp(f, opType, Expr::I32X4Shuffle, Expr::F32X4Shuffle, Expr::Unreachable))
         return false;
 
     Type retType = opType;
     ParseNode* arg = CallArgList(call);
     for (unsigned i = 0; i < 2; i++, arg = NextNode(arg)) {
         Type type;
         if (!CheckExpr(f, arg, &type))
             return false;
@@ -5260,17 +5236,17 @@ CheckSimdLoadStoreArgs(FunctionValidator
 static bool
 CheckSimdLoad(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType,
               unsigned numElems, Type* type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 2)
         return f.failf(call, "expected 2 arguments to SIMD load, got %u", numArgs);
 
-    if (!SwitchPackOp(f, opType, Expr::I32X4Load, Expr::F32X4Load, Expr::Bad))
+    if (!SwitchPackOp(f, opType, Expr::I32X4Load, Expr::F32X4Load, Expr::Unreachable))
         return false;
 
     size_t viewTypeAt;
     size_t needsBoundsCheckAt;
     if (!f.tempU8(&viewTypeAt) || !f.tempU8(&needsBoundsCheckAt) || !f.writeU8(numElems))
         return false;
 
     Scalar::Type viewType;
@@ -5288,17 +5264,17 @@ CheckSimdLoad(FunctionValidator& f, Pars
 static bool
 CheckSimdStore(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType,
                unsigned numElems, Type* type)
 {
     unsigned numArgs = CallArgListLength(call);
     if (numArgs != 3)
         return f.failf(call, "expected 3 arguments to SIMD store, got %u", numArgs);
 
-    if (!SwitchPackOp(f, opType, Expr::I32X4Store, Expr::F32X4Store, Expr::Bad))
+    if (!SwitchPackOp(f, opType, Expr::I32X4Store, Expr::F32X4Store, Expr::Unreachable))
         return false;
 
     size_t viewTypeAt;
     size_t needsBoundsCheckAt;
     if (!f.tempU8(&viewTypeAt) || !f.tempU8(&needsBoundsCheckAt) || !f.writeU8(numElems))
         return false;
 
     Scalar::Type viewType;
@@ -5319,17 +5295,17 @@ CheckSimdStore(FunctionValidator& f, Par
 
     *type = vecType;
     return true;
 }
 
 static bool
 CheckSimdSelect(FunctionValidator& f, ParseNode* call, AsmJSSimdType opType, Type* type)
 {
-    if (!SwitchPackOp(f, opType, Expr::I32X4Select, Expr::F32X4Select, Expr::Bad))
+    if (!SwitchPackOp(f, opType, Expr::I32X4Select, Expr::F32X4Select, Expr::Unreachable))
         return false;
     if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(opType)))
         return false;
     *type = opType;
     return true;
 }
 
 static bool
@@ -5796,17 +5772,18 @@ CheckCoerceToInt(FunctionValidator& f, P
     if (!f.tempOp(&opcodeAt))
         return false;
 
     Type operandType;
     if (!CheckExpr(f, operand, &operandType))
         return false;
 
     if (operandType.isMaybeDouble() || operandType.isMaybeFloat()) {
-        f.patchOp(opcodeAt, operandType.isMaybeDouble() ? Expr::I32FromF64 : Expr::I32FromF32);
+        Expr opcode = operandType.isMaybeDouble() ? Expr::I32SConvertF64 : Expr::I32SConvertF32;
+        f.patchOp(opcodeAt, opcode);
         *type = Type::Signed;
         return true;
     }
 
     if (!operandType.isIntish())
         return f.failf(operand, "%s is not a subtype of double?, float? or intish", operandType.toChars());
 
     f.patchOp(opcodeAt, Expr::Id);
@@ -5841,54 +5818,35 @@ static bool
 CheckAsExprStatement(FunctionValidator& f, ParseNode* exprStmt);
 
 static bool
 CheckComma(FunctionValidator& f, ParseNode* comma, Type* type)
 {
     MOZ_ASSERT(comma->isKind(PNK_COMMA));
     ParseNode* operands = ListHead(comma);
 
-    size_t commaAt;
-    if (!f.tempOp(&commaAt) || !f.writeU32(ListLength(comma)))
+    if (!f.writeOp(Expr::Block) || !f.writeU32(ListLength(comma)))
         return false;
 
     ParseNode* pn = operands;
     for (; NextNode(pn); pn = NextNode(pn)) {
         if (!CheckAsExprStatement(f, pn))
             return false;
     }
 
-    if (!CheckExpr(f, pn, type))
-        return false;
-
-    if (type->isIntish())
-        f.patchOp(commaAt, Expr::I32Comma);
-    else if (type->isFloatish())
-        f.patchOp(commaAt, Expr::F32Comma);
-    else if (type->isMaybeDouble())
-        f.patchOp(commaAt, Expr::F64Comma);
-    else if (type->isInt32x4())
-        f.patchOp(commaAt, Expr::I32X4Comma);
-    else if (type->isFloat32x4())
-        f.patchOp(commaAt, Expr::F32X4Comma);
-    else if (type->isBool32x4())
-        f.patchOp(commaAt, Expr::B32X4Comma);
-    else
-        MOZ_CRASH("unexpected or unimplemented expression statement");
-
-    return true;
+    return CheckExpr(f, pn, type) &&
+           f.writeDebugCheckPoint();
 }
 
 static bool
 CheckConditional(FunctionValidator& f, ParseNode* ternary, Type* type)
 {
     MOZ_ASSERT(ternary->isKind(PNK_CONDITIONAL));
 
-    size_t opcodeAt;
-    if (!f.tempOp(&opcodeAt))
+    if (!f.writeOp(Expr::Ternary))
         return false;
 
     ParseNode* cond = TernaryKid1(ternary);
     ParseNode* thenExpr = TernaryKid2(ternary);
     ParseNode* elseExpr = TernaryKid3(ternary);
 
     Type condType;
     if (!CheckExpr(f, cond, &condType))
@@ -5901,32 +5859,26 @@ CheckConditional(FunctionValidator& f, P
     if (!CheckExpr(f, thenExpr, &thenType))
         return false;
 
     Type elseType;
     if (!CheckExpr(f, elseExpr, &elseType))
         return false;
 
     if (thenType.isInt() && elseType.isInt()) {
-        f.patchOp(opcodeAt, Expr::I32Conditional);
         *type = Type::Int;
     } else if (thenType.isDouble() && elseType.isDouble()) {
-        f.patchOp(opcodeAt, Expr::F64Conditional);
         *type = Type::Double;
     } else if (thenType.isFloat() && elseType.isFloat()) {
-        f.patchOp(opcodeAt, Expr::F32Conditional);
         *type = Type::Float;
     } else if (elseType.isInt32x4() && thenType.isInt32x4()) {
-        f.patchOp(opcodeAt, Expr::I32X4Conditional);
         *type = Type::Int32x4;
     } else if (elseType.isFloat32x4() && thenType.isFloat32x4()) {
-        f.patchOp(opcodeAt, Expr::F32X4Conditional);
         *type = Type::Float32x4;
     } else if (elseType.isBool32x4() && thenType.isBool32x4()) {
-        f.patchOp(opcodeAt, Expr::B32X4Conditional);
         *type = Type::Bool32x4;
     } else {
         return f.failf(ternary, "then/else branches of conditional must both produce int, float, "
                        "double or SIMD types, current types are %s and %s",
                        thenType.toChars(), elseType.toChars());
     }
 
     return true;
@@ -6090,23 +6042,23 @@ CheckDivOrMod(FunctionValidator& f, Pars
             f.patchOp(opcodeAt, Expr::F32Div);
         else
             return f.fail(expr, "modulo cannot receive float arguments");
         *type = Type::Floatish;
         return true;
     }
 
     if (lhsType.isSigned() && rhsType.isSigned()) {
-        f.patchOp(opcodeAt, expr->isKind(PNK_DIV) ? Expr::I32SDiv : Expr::I32SMod);
+        f.patchOp(opcodeAt, expr->isKind(PNK_DIV) ? Expr::I32DivS : Expr::I32RemS);
         *type = Type::Intish;
         return true;
     }
 
     if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
-        f.patchOp(opcodeAt, expr->isKind(PNK_DIV) ? Expr::I32UDiv : Expr::I32UMod);
+        f.patchOp(opcodeAt, expr->isKind(PNK_DIV) ? Expr::I32DivU : Expr::I32RemU);
         *type = Type::Intish;
         return true;
     }
 
     return f.failf(expr, "arguments to / or %% must both be double?, float?, signed, or unsigned; "
                    "%s and %s are given", lhsType.toChars(), rhsType.toChars());
 }
 
@@ -6136,52 +6088,52 @@ CheckComparison(FunctionValidator& f, Pa
     {
         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;
     if (lhsType.isSigned() && rhsType.isSigned()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32EqI32;  break;
-          case JSOP_NE: stmt = Expr::I32NeI32;  break;
-          case JSOP_LT: stmt = Expr::I32SLtI32; break;
-          case JSOP_LE: stmt = Expr::I32SLeI32; break;
-          case JSOP_GT: stmt = Expr::I32SGtI32; break;
-          case JSOP_GE: stmt = Expr::I32SGeI32; break;
+          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;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isUnsigned() && rhsType.isUnsigned()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32EqI32;  break;
-          case JSOP_NE: stmt = Expr::I32NeI32;  break;
-          case JSOP_LT: stmt = Expr::I32ULtI32; break;
-          case JSOP_LE: stmt = Expr::I32ULeI32; break;
-          case JSOP_GT: stmt = Expr::I32UGtI32; break;
-          case JSOP_GE: stmt = Expr::I32UGeI32; break;
+          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;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isDouble()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32EqF64;  break;
-          case JSOP_NE: stmt = Expr::I32NeF64;  break;
-          case JSOP_LT: stmt = Expr::I32LtF64; break;
-          case JSOP_LE: stmt = Expr::I32LeF64; break;
-          case JSOP_GT: stmt = Expr::I32GtF64; break;
-          case JSOP_GE: stmt = Expr::I32GeF64; break;
+          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;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else if (lhsType.isFloat()) {
         switch (comp->getOp()) {
-          case JSOP_EQ: stmt = Expr::I32EqF32;  break;
-          case JSOP_NE: stmt = Expr::I32NeF32;  break;
-          case JSOP_LT: stmt = Expr::I32LtF32; break;
-          case JSOP_LE: stmt = Expr::I32LeF32; break;
-          case JSOP_GT: stmt = Expr::I32GtF32; break;
-          case JSOP_GE: stmt = Expr::I32GeF32; break;
+          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;
           default: MOZ_CRASH("unexpected comparison op");
         }
     } else {
         MOZ_CRASH("unexpected type");
     }
 
     f.patchOp(opcodeAt, stmt);
     *type = Type::Int;
@@ -6224,22 +6176,22 @@ CheckBitwise(FunctionValidator& f, Parse
         if (!CheckExpr(f, lhs, &lhsType))
             return false;
         if (!lhsType.isIntish())
             return f.failf(bitwise, "%s is not a subtype of intish", lhsType.toChars());
         return true;
     }
 
     switch (bitwise->getKind()) {
-      case PNK_BITOR:  if (!f.writeOp(Expr::I32BitOr))    return false; break;
-      case PNK_BITAND: if (!f.writeOp(Expr::I32BitAnd))   return false; break;
-      case PNK_BITXOR: if (!f.writeOp(Expr::I32BitXor))   return false; break;
-      case PNK_LSH:    if (!f.writeOp(Expr::I32Lsh))      return false; break;
-      case PNK_RSH:    if (!f.writeOp(Expr::I32ArithRsh)) return false; break;
-      case PNK_URSH:   if (!f.writeOp(Expr::I32LogicRsh)) return false; break;
+      case PNK_BITOR:  if (!f.writeOp(Expr::I32Ior))  return false; break;
+      case PNK_BITAND: if (!f.writeOp(Expr::I32And))  return false; break;
+      case PNK_BITXOR: if (!f.writeOp(Expr::I32Xor))  return false; break;
+      case PNK_LSH:    if (!f.writeOp(Expr::I32Shl))  return false; break;
+      case PNK_RSH:    if (!f.writeOp(Expr::I32ShrS)) return false; break;
+      case PNK_URSH:   if (!f.writeOp(Expr::I32ShrU)) return false; break;
       default: MOZ_CRASH("not a bitwise op");
     }
 
     Type lhsType;
     if (!CheckExpr(f, lhs, &lhsType))
         return false;
 
     Type rhsType;
@@ -6339,17 +6291,17 @@ CheckAsExprStatement(FunctionValidator& 
 }
 
 static bool
 CheckExprStatement(FunctionValidator& f, ParseNode* exprStmt)
 {
     MOZ_ASSERT(exprStmt->isKind(PNK_SEMI));
     ParseNode* expr = UnaryKid(exprStmt);
     if (!expr)
-        return f.writeOp(Expr::Noop);
+        return f.writeOp(Expr::Nop);
     return CheckAsExprStatement(f, expr);
 }
 
 enum class InterruptCheckPosition {
     Head,
     Loop
 };
 
@@ -6507,17 +6459,17 @@ CheckIf(FunctionValidator& f, ParseNode*
         return false;
     if (!condType.isInt())
         return f.failf(cond, "%s is not a subtype of int", condType.toChars());
 
     if (!CheckStatement(f, thenStmt))
         return false;
 
     if (!elseStmt) {
-        f.patchOp(opcodeAt, Expr::IfThen);
+        f.patchOp(opcodeAt, Expr::If);
     } else {
         f.patchOp(opcodeAt, Expr::IfElse);
 
         if (elseStmt->isKind(PNK_IF)) {
             ifStmt = elseStmt;
             goto recurse;
         }
 
@@ -6613,17 +6565,17 @@ PatchSwitch(FunctionValidator& f,
     f.patch32(numCasesAt, numCases);
 }
 
 static bool
 CheckSwitch(FunctionValidator& f, ParseNode* switchStmt)
 {
     MOZ_ASSERT(switchStmt->isKind(PNK_SWITCH));
 
-    if (!f.writeOp(Expr::Switch))
+    if (!f.writeOp(Expr::TableSwitch))
         return false;
 
     // Has default
     size_t hasDefaultAt;
     if (!f.tempU8(&hasDefaultAt))
         return false;
 
     // Low / High / Num cases
@@ -6712,17 +6664,17 @@ CheckReturnType(FunctionValidator& f, Pa
     return true;
 }
 
 static bool
 CheckReturn(FunctionValidator& f, ParseNode* returnStmt)
 {
     ParseNode* expr = ReturnExpr(returnStmt);
 
-    if (!f.writeOp(Expr::Ret))
+    if (!f.writeOp(Expr::Return))
         return false;
 
     if (!expr)
         return CheckReturnType(f, returnStmt, ExprType::Void);
 
     Type type;
     if (!CheckExpr(f, expr, &type))
         return false;
--- a/js/src/asmjs/WasmBinary.h
+++ b/js/src/asmjs/WasmBinary.h
@@ -24,335 +24,280 @@
 namespace js {
 
 class PropertyName;
 
 namespace wasm {
 
 enum class Expr : uint8_t
 {
-    Ret,
+    // Control opcodes
+    Nop,
+    Block,
+    Loop,
+    If,
+    IfElse,
+    Select,
+    Br,
+    BrIf,
+    TableSwitch,
+    Return,
+    Unreachable,
+
+    // Calls
+    CallInternal,
+    CallIndirect,
+    CallImport,
 
-    Block,
+    // Constants and calls
+    I8Const,
+    I32Const,
+    I64Const,
+    F64Const,
+    F32Const,
+    GetLocal,
+    SetLocal,
+    LoadGlobal,
+    StoreGlobal,
+
+    // I32 opcodes
+    I32Add,
+    I32Sub,
+    I32Mul,
+    I32DivS,
+    I32DivU,
+    I32RemS,
+    I32RemU,
+    I32Ior,
+    I32And,
+    I32Xor,
+    I32Shl,
+    I32ShrU,
+    I32ShrS,
+    I32Eq,
+    I32Ne,
+    I32LtS,
+    I32LeS,
+    I32LtU,
+    I32LeU,
+    I32GtS,
+    I32GeS,
+    I32GtU,
+    I32GeU,
+    I32Clz,
+    I32Ctz,
+    I32Popcnt,
 
-    IfThen,
-    IfElse,
-    Switch,
+    // F32 opcodes
+    F32Add,
+    F32Sub,
+    F32Mul,
+    F32Div,
+    F32Min,
+    F32Max,
+    F32Abs,
+    F32Neg,
+    F32CopySign,
+    F32Ceil,
+    F32Floor,
+    F32Trunc,
+    F32NearestInt,
+    F32Sqrt,
+    F32Eq,
+    F32Ne,
+    F32Lt,
+    F32Le,
+    F32Gt,
+    F32Ge,
+
+    // F64 opcodes
+    F64Add,
+    F64Sub,
+    F64Mul,
+    F64Div,
+    F64Min,
+    F64Max,
+    F64Abs,
+    F64Neg,
+    F64CopySign,
+    F64Ceil,
+    F64Floor,
+    F64Trunc,
+    F64NearestInt,
+    F64Sqrt,
+    F64Eq,
+    F64Ne,
+    F64Lt,
+    F64Le,
+    F64Gt,
+    F64Ge,
 
-    While,
+    // Conversions
+    I32SConvertF32,
+    I32SConvertF64,
+    I32UConvertF32,
+    I32UConvertF64,
+    I32ConvertI64,
+    I64SConvertF32,
+    I64SConvertF64,
+    I64UConvertF32,
+    I64UConvertF64,
+    I64SConvertI32,
+    I64UConvertI32,
+
+    // Load/store operations
+    I32LoadMem8S,
+    I32LoadMem8U,
+    I32LoadMem16S,
+    I32LoadMem16U,
+    I32LoadMem,
+    I64LoadMem8S,
+    I64LoadMem8U,
+    I64LoadMem16S,
+    I64LoadMem16U,
+    I64LoadMem32S,
+    I64LoadMem32U,
+    I64LoadMem,
+    F32LoadMem,
+    F64LoadMem,
+
+    I32StoreMem8,
+    I32StoreMem16,
+    I64StoreMem8,
+    I64StoreMem16,
+    I64StoreMem32,
+    I32StoreMem,
+    I64StoreMem,
+    F32StoreMem,
+    F64StoreMem,
+
+    // asm.js specific
+    Ternary,        // to be merged with IfElse
+
+    While,          // all CFG ops to be deleted in favor of Loop/Br/BrIf
     DoWhile,
 
     ForInitInc,
     ForInitNoInc,
     ForNoInitNoInc,
     ForNoInitInc,
 
     Label,
     Continue,
     ContinueLabel,
     Break,
     BreakLabel,
 
-    GetLocal,
-    SetLocal,
-
-    CallInternal,
-    CallIndirect,
-    CallImport,
-
-    AtomicsFence,
-
-    I32Expr,
+    I32Expr,        // to be removed
     F32Expr,
     F64Expr,
-    I32X4Expr,
-    F32X4Expr,
-    B32X4Expr,
 
-    // asm.js specific
     Id,
-    Noop,
-
-    LoadGlobal,
-    StoreGlobal,
 
     InterruptCheckHead,
     InterruptCheckLoop,
 
     DebugCheckPoint,
-    Bad,
 
-    // I32 opcodes
-    I32CallInternal,
-    I32CallIndirect,
-    I32CallImport,
-
-    I32Conditional,
-    I32Comma,
-
-    I32Literal,
-
-    // Binary arith opcodes
-    I32Add,
-    I32Sub,
-    I32Mul,
-    I32SDiv,
-    I32SMod,
-    I32UDiv,
-    I32UMod,
     I32Min,
     I32Max,
 
-    // Unary arith opcodes
-    I32Not,
-    I32Neg,
-
-    // Bitwise opcodes
-    I32BitOr,
-    I32BitAnd,
-    I32BitXor,
-    I32BitNot,
-
-    I32Lsh,
-    I32ArithRsh,
-    I32LogicRsh,
-
-    // Conversion opcodes
-    I32FromF32,
-    I32FromF64,
-
-    // Math builtin opcodes
-    I32Clz,
-    I32Abs,
-
-    // Comparison opcodes
-    // Ordering matters (EmitComparison expects signed opcodes to be placed
-    // before unsigned opcodes)
-    I32EqI32,
-    I32NeI32,
-    I32SLtI32,
-    I32SLeI32,
-    I32SGtI32,
-    I32SGeI32,
-    I32ULtI32,
-    I32ULeI32,
-    I32UGtI32,
-    I32UGeI32,
-
-    I32EqF32,
-    I32NeF32,
-    I32LtF32,
-    I32LeF32,
-    I32GtF32,
-    I32GeF32,
-
-    I32EqF64,
-    I32NeF64,
-    I32LtF64,
-    I32LeF64,
-    I32GtF64,
-    I32GeF64,
-
-    // Heap accesses opcodes
-    I32SLoad8,
-    I32SLoad16,
-    I32SLoad32,
-    I32ULoad8,
-    I32ULoad16,
-    I32ULoad32,
-    I32Store8,
-    I32Store16,
-    I32Store32,
-
-    // Atomics opcodes
+    // Atomics
+    AtomicsFence,
     I32AtomicsCompareExchange,
     I32AtomicsExchange,
     I32AtomicsLoad,
     I32AtomicsStore,
     I32AtomicsBinOp,
 
-    // SIMD opcodes
+    // SIMD
+    I32X4Const,
+    B32X4Const,
+    F32X4Const,
+
+    I32X4Expr,
+    F32X4Expr,
+    B32X4Expr,
+
     I32I32X4ExtractLane,
     I32B32X4ExtractLane,
     I32B32X4AllTrue,
     I32B32X4AnyTrue,
 
-    // F32 opcdoes
-    // Common opcodes
-    F32CallInternal,
-    F32CallIndirect,
-    F32CallImport,
+    F32F32X4ExtractLane,
 
-    F32Conditional,
-    F32Comma,
-
-    F32Literal,
+    I32X4Ctor,
+    I32X4Unary,
+    I32X4Binary,
+    I32X4BinaryBitwise,
+    I32X4BinaryShift,
+    I32X4ReplaceLane,
+    I32X4FromF32X4,
+    I32X4FromF32X4Bits,
+    I32X4Swizzle,
+    I32X4Shuffle,
+    I32X4Select,
+    I32X4Splat,
+    I32X4Load,
+    I32X4Store,
 
-    // Binary arith opcodes
-    F32Add,
-    F32Sub,
-    F32Mul,
-    F32Div,
-    F32Min,
-    F32Max,
-    F32Neg,
+    F32X4Ctor,
+    F32X4Unary,
+    F32X4Binary,
+    F32X4ReplaceLane,
+    F32X4FromI32X4,
+    F32X4FromI32X4Bits,
+    F32X4Swizzle,
+    F32X4Shuffle,
+    F32X4Select,
+    F32X4Splat,
+    F32X4Load,
+    F32X4Store,
 
-    // Math builtin opcodes
-    F32Abs,
-    F32Sqrt,
-    F32Ceil,
-    F32Floor,
+    B32X4Ctor,
+    B32X4Unary,
+    B32X4Binary,
+    B32X4BinaryCompI32X4,
+    B32X4BinaryCompF32X4,
+    B32X4BinaryBitwise,
+    B32X4ReplaceLane,
+    B32X4Splat,
 
-    // Conversion opcodes
+    // I32 asm.js opcodes
+    I32Not,
+    I32Neg,
+    I32BitNot,
+    I32Abs,
+
+    // F32 asm.js opcodes
     F32FromF64,
     F32FromS32,
     F32FromU32,
 
-    // Heap accesses opcodes
-    F32Load,
-    F32StoreF32,
-    F32StoreF64,
-
-    // SIMD opcodes
-    F32F32X4ExtractLane,
-
-    // F64 opcodes
-    // Common opcodes
-    F64CallInternal,
-    F64CallIndirect,
-    F64CallImport,
-
-    F64Conditional,
-    F64Comma,
+    F32StoreMemF64,
 
-    F64Literal,
+    // F64 asm.js opcodes
+    F64Mod,
 
-    // Binary arith opcodes
-    F64Add,
-    F64Sub,
-    F64Mul,
-    F64Div,
-    F64Min,
-    F64Max,
-    F64Mod,
-    F64Neg,
-
-    // Math builtin opcodes
-    F64Abs,
-    F64Sqrt,
-    F64Ceil,
-    F64Floor,
     F64Sin,
     F64Cos,
     F64Tan,
     F64Asin,
     F64Acos,
     F64Atan,
     F64Exp,
     F64Log,
     F64Pow,
     F64Atan2,
 
-    // Conversions opcodes
     F64FromF32,
     F64FromS32,
     F64FromU32,
 
-    // Heap accesses opcodes
-    F64Load,
-    F64StoreF32,
-    F64StoreF64,
-
-    // I32X4 opcodes
-    // Common opcodes
-    I32X4CallInternal,
-    I32X4CallIndirect,
-    I32X4CallImport,
-
-    I32X4Conditional,
-    I32X4Comma,
-
-    I32X4Literal,
-
-    // Specific opcodes
-    I32X4Ctor,
-
-    I32X4Unary,
-
-    I32X4Binary,
-    I32X4BinaryBitwise,
-    I32X4BinaryShift,
-
-    I32X4ReplaceLane,
-
-    I32X4FromF32X4,
-    I32X4FromF32X4Bits,
-
-    I32X4Swizzle,
-    I32X4Shuffle,
-    I32X4Select,
-    I32X4Splat,
-
-    I32X4Load,
-    I32X4Store,
-
-    // F32X4 opcodes
-    // Common opcodes
-    F32X4CallInternal,
-    F32X4CallIndirect,
-    F32X4CallImport,
-
-    F32X4Conditional,
-    F32X4Comma,
-
-    F32X4Literal,
-
-    // Specific opcodes
-    F32X4Ctor,
-
-    F32X4Unary,
-
-    F32X4Binary,
-
-    F32X4ReplaceLane,
-
-    F32X4FromI32X4,
-    F32X4FromI32X4Bits,
-    F32X4Swizzle,
-    F32X4Shuffle,
-    F32X4Select,
-    F32X4Splat,
-
-    F32X4Load,
-    F32X4Store,
-
-    // B32X4 opcodes
-    // Common opcodes
-    B32X4CallInternal,
-    B32X4CallIndirect,
-    B32X4CallImport,
-
-    B32X4Conditional,
-    B32X4Comma,
-
-    B32X4Literal,
-
-    // Specific opcodes
-    B32X4Ctor,
-
-    B32X4Unary,
-
-    B32X4Binary,
-    B32X4BinaryCompI32X4,
-    B32X4BinaryCompF32X4,
-    B32X4BinaryBitwise,
-
-    B32X4ReplaceLane,
-
-    B32X4Splat
+    F64StoreMemF32
 };
 
 enum NeedsBoundsCheck : uint8_t
 {
     NO_BOUNDS_CHECK,
     NEEDS_BOUNDS_CHECK
 };
 
@@ -443,17 +388,17 @@ class Encoder
         }
         return true;
     }
 
 #ifdef DEBUG
     bool pcIsPatchable(size_t pc, unsigned size) const {
         bool patchable = true;
         for (unsigned i = 0; patchable && i < size; i++)
-            patchable &= Expr((*bytecode_)[pc]) == Expr::Bad;
+            patchable &= Expr((*bytecode_)[pc]) == Expr::Unreachable;
         return patchable;
     }
 #endif
 
     void patchU8(size_t pc, uint8_t i) {
         MOZ_ASSERT(pcIsPatchable(pc, sizeof(uint8_t)));
         (*bytecode_)[pc] = i;
     }
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -2024,30 +2024,17 @@ EmitUnaryMir(FunctionCompiler& f, ExprTy
     MDefinition* in;
     if (!EmitExpr(f, type, &in))
         return false;
     *def = f.unary<T>(in, ToMIRType(type));
     return true;
 }
 
 static bool
-EmitComma(FunctionCompiler& f, ExprType type, MDefinition** def)
-{
-    uint32_t numExpr = f.readU32();
-    MOZ_ASSERT(numExpr > 0);
-    for (uint32_t i = 0; i < numExpr; i++) {
-        // Clobber def; we only want the latest use anyway
-        if (!EmitExpr(f, type, def))
-            return false;
-    }
-    return true;
-}
-
-static bool
-EmitConditional(FunctionCompiler& f, ExprType type, MDefinition** def)
+EmitTernary(FunctionCompiler& f, ExprType type, MDefinition** def)
 {
     MDefinition* cond;
     if (!EmitExpr(f, ExprType::I32, &cond))
         return false;
 
     MBasicBlock* thenBlock = nullptr;
     MBasicBlock* elseBlock = nullptr;
     if (!f.branchAndStartThen(cond, &thenBlock, &elseBlock))
@@ -2083,17 +2070,17 @@ EmitMultiply(FunctionCompiler& f, ExprTy
 {
     MDefinition* lhs;
     if (!EmitExpr(f, type, &lhs))
         return false;
     MDefinition* rhs;
     if (!EmitExpr(f, type, &rhs))
         return false;
     MIRType mirType = ToMIRType(type);
-    *def = f.mul(lhs, rhs, mirType, type == ExprType::I32 ? MMul::Integer : MMul::Normal);
+    *def = f.mul(lhs, rhs, mirType, mirType == MIRType_Int32 ? MMul::Integer : MMul::Normal);
     return true;
 }
 
 typedef bool IsAdd;
 
 static bool
 EmitAddOrSub(FunctionCompiler& f, ExprType type, bool isAdd, MDefinition** def)
 {
@@ -2134,91 +2121,95 @@ EmitDivOrMod(FunctionCompiler& f, ExprTy
 }
 
 static bool
 EmitComparison(FunctionCompiler& f, Expr expr, MDefinition** def)
 {
     MDefinition *lhs, *rhs;
     MCompare::CompareType compareType;
     switch (expr) {
-      case Expr::I32EqI32:
-      case Expr::I32NeI32:
-      case Expr::I32SLeI32:
-      case Expr::I32SLtI32:
-      case Expr::I32ULeI32:
-      case Expr::I32ULtI32:
-      case Expr::I32SGeI32:
-      case Expr::I32SGtI32:
-      case Expr::I32UGeI32:
-      case Expr::I32UGtI32:
+      case Expr::I32Eq:
+      case Expr::I32Ne:
+      case Expr::I32LeS:
+      case Expr::I32LtS:
+      case Expr::I32LeU:
+      case Expr::I32LtU:
+      case Expr::I32GeS:
+      case Expr::I32GtS:
+      case Expr::I32GeU:
+      case Expr::I32GtU:
         if (!EmitExpr(f, ExprType::I32, &lhs) || !EmitExpr(f, ExprType::I32, &rhs))
             return false;
-        // The list of opcodes is sorted such that all signed comparisons
-        // stand before ULtI32.
-        compareType = expr < Expr::I32ULtI32
-                      ? MCompare::Compare_Int32
-                      : MCompare::Compare_UInt32;
+
+        switch (expr) {
+          case Expr::I32LeS: case Expr::I32LtS: case Expr::I32GeS: case Expr::I32GtS:
+          case Expr::I32Eq: case Expr::I32Ne:
+            compareType = MCompare::Compare_Int32; break;
+          case Expr::I32GeU: case Expr::I32GtU: case Expr::I32LeU: case Expr::I32LtU:
+            compareType = MCompare::Compare_UInt32; break;
+          default: MOZ_CRASH("impossibru opcode");
+        }
         break;
-      case Expr::I32EqF32:
-      case Expr::I32NeF32:
-      case Expr::I32LeF32:
-      case Expr::I32LtF32:
-      case Expr::I32GeF32:
-      case Expr::I32GtF32:
+      case Expr::F32Eq:
+      case Expr::F32Ne:
+      case Expr::F32Le:
+      case Expr::F32Lt:
+      case Expr::F32Ge:
+      case Expr::F32Gt:
         if (!EmitExpr(f, ExprType::F32, &lhs) || !EmitExpr(f, ExprType::F32, &rhs))
             return false;
         compareType = MCompare::Compare_Float32;
         break;
-      case Expr::I32EqF64:
-      case Expr::I32NeF64:
-      case Expr::I32LeF64:
-      case Expr::I32LtF64:
-      case Expr::I32GeF64:
-      case Expr::I32GtF64:
+      case Expr::F64Eq:
+      case Expr::F64Ne:
+      case Expr::F64Le:
+      case Expr::F64Lt:
+      case Expr::F64Ge:
+      case Expr::F64Gt:
         if (!EmitExpr(f, ExprType::F64, &lhs) || !EmitExpr(f, ExprType::F64, &rhs))
             return false;
         compareType = MCompare::Compare_Double;
         break;
       default: MOZ_CRASH("unexpected comparison opcode");
     }
 
     JSOp compareOp;
     switch (expr) {
-      case Expr::I32EqI32:
-      case Expr::I32EqF32:
-      case Expr::I32EqF64:
+      case Expr::I32Eq:
+      case Expr::F32Eq:
+      case Expr::F64Eq:
         compareOp = JSOP_EQ;
         break;
-      case Expr::I32NeI32:
-      case Expr::I32NeF32:
-      case Expr::I32NeF64:
+      case Expr::I32Ne:
+      case Expr::F32Ne:
+      case Expr::F64Ne:
         compareOp = JSOP_NE;
         break;
-      case Expr::I32SLeI32:
-      case Expr::I32ULeI32:
-      case Expr::I32LeF32:
-      case Expr::I32LeF64:
+      case Expr::I32LeS:
+      case Expr::I32LeU:
+      case Expr::F32Le:
+      case Expr::F64Le:
         compareOp = JSOP_LE;
         break;
-      case Expr::I32SLtI32:
-      case Expr::I32ULtI32:
-      case Expr::I32LtF32:
-      case Expr::I32LtF64:
+      case Expr::I32LtS:
+      case Expr::I32LtU:
+      case Expr::F32Lt:
+      case Expr::F64Lt:
         compareOp = JSOP_LT;
         break;
-      case Expr::I32SGeI32:
-      case Expr::I32UGeI32:
-      case Expr::I32GeF32:
-      case Expr::I32GeF64:
+      case Expr::I32GeS:
+      case Expr::I32GeU:
+      case Expr::F32Ge:
+      case Expr::F64Ge:
         compareOp = JSOP_GE;
         break;
-      case Expr::I32SGtI32:
-      case Expr::I32UGtI32:
-      case Expr::I32GtF32:
-      case Expr::I32GtF64:
+      case Expr::I32GtS:
+      case Expr::I32GtU:
+      case Expr::F32Gt:
+      case Expr::F64Gt:
         compareOp = JSOP_GT;
         break;
       default: MOZ_CRASH("unexpected comparison opcode");
     }
 
     *def = f.compare(lhs, rhs, compareOp, compareType);
     return true;
 }
@@ -2422,17 +2413,17 @@ EmitIfElse(FunctionCompiler& f, bool has
 
     if (!f.appendThenBlock(&thenBlocks))
         return false;
 
     if (hasElse) {
         f.switchToElse(elseOrJoinBlock);
 
         Expr nextStmt(f.readOpcode());
-        if (nextStmt == Expr::IfThen) {
+        if (nextStmt == Expr::If) {
             hasElse = false;
             goto recurse;
         }
         if (nextStmt == Expr::IfElse) {
             hasElse = true;
             goto recurse;
         }
 
@@ -2442,17 +2433,17 @@ EmitIfElse(FunctionCompiler& f, bool has
 
         return f.joinIfElse(thenBlocks);
     } else {
         return f.joinIf(thenBlocks, elseOrJoinBlock);
     }
 }
 
 static bool
-EmitSwitch(FunctionCompiler& f)
+EmitTableSwitch(FunctionCompiler& f)
 {
     bool hasDefault = f.readU8();
     int32_t low = f.readI32();
     int32_t high = f.readI32();
     uint32_t numCases = f.readU32();
 
     MDefinition* exprDef;
     if (!EmitExpr(f, ExprType::I32, &exprDef))
@@ -2505,22 +2496,22 @@ EmitRet(FunctionCompiler& f)
     MDefinition *def = nullptr;
     if (!EmitExpr(f, ret, &def))
         return false;
     f.returnExpr(def);
     return true;
 }
 
 static bool
-EmitBlock(FunctionCompiler& f)
+EmitBlock(FunctionCompiler& f, ExprType type, MDefinition** def)
 {
     size_t numStmt = f.readU32();
     for (size_t i = 0; i < numStmt; i++) {
-        MDefinition* _;
-        if (!EmitExpr(f, ExprType::Void, &_))
+        // Fine to clobber def, we only want the last use.
+        if (!EmitExpr(f, type, def))
             return false;
     }
     f.assertDebugCheckPoint();
     return true;
 }
 
 typedef bool HasLabel;
 
@@ -2544,25 +2535,27 @@ EmitBreak(FunctionCompiler& f, bool hasL
 
 static bool
 EmitExpr(FunctionCompiler& f, ExprType type, Expr op, MDefinition** def, LabelVector* maybeLabels)
 {
     if (!f.mirGen().ensureBallast())
         return false;
 
     switch (op) {
-      // Statements
+      case Expr::Nop:
+        return true;
       case Expr::Block:
-        return EmitBlock(f);
-      case Expr::IfThen:
-        return EmitIfElse(f, HasElseBlock(false));
+        return EmitBlock(f, type, def);
+      case Expr::If:
       case Expr::IfElse:
-        return EmitIfElse(f, HasElseBlock(true));
-      case Expr::Switch:
-        return EmitSwitch(f);
+        return EmitIfElse(f, HasElseBlock(op == Expr::IfElse));
+      case Expr::TableSwitch:
+        return EmitTableSwitch(f);
+      case Expr::Ternary:
+        return EmitTernary(f, type, def);
       case Expr::While:
         return EmitWhile(f, maybeLabels);
       case Expr::DoWhile:
         return EmitDoWhile(f, maybeLabels);
       case Expr::ForInitInc:
       case Expr::ForInitNoInc:
       case Expr::ForNoInitNoInc:
       case Expr::ForNoInitInc:
@@ -2572,151 +2565,137 @@ EmitExpr(FunctionCompiler& f, ExprType t
       case Expr::Continue:
         return EmitContinue(f, HasLabel(false));
       case Expr::ContinueLabel:
         return EmitContinue(f, HasLabel(true));
       case Expr::Break:
         return EmitBreak(f, HasLabel(false));
       case Expr::BreakLabel:
         return EmitBreak(f, HasLabel(true));
-      case Expr::Ret:
+      case Expr::Return:
         return EmitRet(f);
       case Expr::I32Expr:
         return EmitExpr(f, ExprType::I32, def);
       case Expr::F32Expr:
         return EmitExpr(f, ExprType::F32, def);
       case Expr::F64Expr:
         return EmitExpr(f, ExprType::F64, def);
       case Expr::I32X4Expr:
         return EmitExpr(f, ExprType::I32x4, def);
       case Expr::F32X4Expr:
         return EmitExpr(f, ExprType::F32x4, def);
       case Expr::B32X4Expr:
         return EmitExpr(f, ExprType::B32x4, def);
       case Expr::CallInternal:
-        return EmitInternalCall(f, ExprType::Void, def);
+        return EmitInternalCall(f, type, def);
       case Expr::CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::Void, def);
+        return EmitFuncPtrCall(f, type, def);
       case Expr::CallImport:
-        return EmitFFICall(f, ExprType::Void, def);
+        return EmitFFICall(f, type, def);
       case Expr::AtomicsFence:
         f.memoryBarrier(MembarFull);
         return true;
-      case Expr::Noop:
-        return true;
       case Expr::InterruptCheckHead:
         return EmitInterruptCheck(f);
       case Expr::InterruptCheckLoop:
         return EmitInterruptCheckLoop(f);
       // Common
       case Expr::GetLocal:
         return EmitGetLocal(f, type, def);
       case Expr::SetLocal:
         return EmitSetLocal(f, type, def);
       case Expr::LoadGlobal:
         return EmitLoadGlobal(f, type, def);
       case Expr::StoreGlobal:
         return EmitStoreGlobal(f, type, def);
       case Expr::Id:
         return EmitExpr(f, type, def);
       // I32
-      case Expr::I32Literal:
+      case Expr::I32Const:
         return EmitLiteral(f, ExprType::I32, def);
-      case Expr::I32CallInternal:
-        return EmitInternalCall(f, ExprType::I32, def);
-      case Expr::I32CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::I32, def);
-      case Expr::I32CallImport:
-        return EmitFFICall(f, ExprType::I32, def);
-      case Expr::I32Conditional:
-        return EmitConditional(f, ExprType::I32, def);
-      case Expr::I32Comma:
-        return EmitComma(f, ExprType::I32, def);
       case Expr::I32Add:
         return EmitAddOrSub(f, ExprType::I32, IsAdd(true), def);
       case Expr::I32Sub:
         return EmitAddOrSub(f, ExprType::I32, IsAdd(false), def);
       case Expr::I32Mul:
         return EmitMultiply(f, ExprType::I32, def);
-      case Expr::I32UDiv:
-      case Expr::I32SDiv:
-        return EmitDivOrMod(f, ExprType::I32, IsDiv(true), IsUnsigned(op == Expr::I32UDiv), def);
-      case Expr::I32UMod:
-      case Expr::I32SMod:
-        return EmitDivOrMod(f, ExprType::I32, IsDiv(false), IsUnsigned(op == Expr::I32UMod), def);
+      case Expr::I32DivS:
+      case Expr::I32DivU:
+        return EmitDivOrMod(f, ExprType::I32, IsDiv(true), IsUnsigned(op == Expr::I32DivU), def);
+      case Expr::I32RemS:
+      case Expr::I32RemU:
+        return EmitDivOrMod(f, ExprType::I32, IsDiv(false), IsUnsigned(op == Expr::I32RemU), def);
       case Expr::I32Min:
         return EmitMathMinMax(f, ExprType::I32, IsMax(false), def);
       case Expr::I32Max:
         return EmitMathMinMax(f, ExprType::I32, IsMax(true), def);
       case Expr::I32Not:
         return EmitUnary<MNot>(f, ExprType::I32, def);
-      case Expr::I32FromF32:
+      case Expr::I32SConvertF32:
         return EmitUnary<MTruncateToInt32>(f, ExprType::F32, def);
-      case Expr::I32FromF64:
+      case Expr::I32SConvertF64:
         return EmitUnary<MTruncateToInt32>(f, ExprType::F64, def);
       case Expr::I32Clz:
         return EmitUnary<MClz>(f, ExprType::I32, def);
       case Expr::I32Abs:
         return EmitUnaryMir<MAbs>(f, ExprType::I32, def);
       case Expr::I32Neg:
         return EmitUnaryMir<MAsmJSNeg>(f, ExprType::I32, def);
-      case Expr::I32BitOr:
+      case Expr::I32Ior:
         return EmitBitwise<MBitOr>(f, def);
-      case Expr::I32BitAnd:
+      case Expr::I32And:
         return EmitBitwise<MBitAnd>(f, def);
-      case Expr::I32BitXor:
+      case Expr::I32Xor:
         return EmitBitwise<MBitXor>(f, def);
-      case Expr::I32Lsh:
+      case Expr::I32Shl:
         return EmitBitwise<MLsh>(f, def);
-      case Expr::I32ArithRsh:
+      case Expr::I32ShrS:
         return EmitBitwise<MRsh>(f, def);
-      case Expr::I32LogicRsh:
+      case Expr::I32ShrU:
         return EmitBitwise<MUrsh>(f, def);
       case Expr::I32BitNot:
         return EmitBitwise<MBitNot>(f, def);
-      case Expr::I32SLoad8:
+      case Expr::I32LoadMem8S:
         return EmitLoadArray(f, Scalar::Int8, def);
-      case Expr::I32SLoad16:
-        return EmitLoadArray(f, Scalar::Int16, def);
-      case Expr::I32SLoad32:
-        return EmitLoadArray(f, Scalar::Int32, def);
-      case Expr::I32ULoad8:
+      case Expr::I32LoadMem8U:
         return EmitLoadArray(f, Scalar::Uint8, def);
-      case Expr::I32ULoad16:
+      case Expr::I32LoadMem16S:
+        return EmitLoadArray(f, Scalar::Int16, def);
+      case Expr::I32LoadMem16U:
         return EmitLoadArray(f, Scalar::Uint16, def);
-      case Expr::I32ULoad32:
-        return EmitLoadArray(f, Scalar::Uint32, def);
-      case Expr::I32Store8:
+      case Expr::I32LoadMem:
+        return EmitLoadArray(f, Scalar::Int32, def);
+      case Expr::I32StoreMem8:
         return EmitStore(f, Scalar::Int8, def);
-      case Expr::I32Store16:
+      case Expr::I32StoreMem16:
         return EmitStore(f, Scalar::Int16, def);
-      case Expr::I32Store32:
+      case Expr::I32StoreMem:
         return EmitStore(f, Scalar::Int32, def);
-      case Expr::I32EqI32:
-      case Expr::I32NeI32:
-      case Expr::I32SLtI32:
-      case Expr::I32SLeI32:
-      case Expr::I32SGtI32:
-      case Expr::I32SGeI32:
-      case Expr::I32ULtI32:
-      case Expr::I32ULeI32:
-      case Expr::I32UGtI32:
-      case Expr::I32UGeI32:
-      case Expr::I32EqF32:
-      case Expr::I32NeF32:
-      case Expr::I32LtF32:
-      case Expr::I32LeF32:
-      case Expr::I32GtF32:
-      case Expr::I32GeF32:
-      case Expr::I32EqF64:
-      case Expr::I32NeF64:
-      case Expr::I32LtF64:
-      case Expr::I32LeF64:
-      case Expr::I32GtF64:
-      case Expr::I32GeF64:
+      case Expr::I32Eq:
+      case Expr::I32Ne:
+      case Expr::I32LtS:
+      case Expr::I32LeS:
+      case Expr::I32GtS:
+      case Expr::I32GeS:
+      case Expr::I32LtU:
+      case Expr::I32LeU:
+      case Expr::I32GtU:
+      case Expr::I32GeU:
+      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 EmitComparison(f, op, def);
       case Expr::I32AtomicsCompareExchange:
         return EmitAtomicsCompareExchange(f, def);
       case Expr::I32AtomicsExchange:
         return EmitAtomicsExchange(f, def);
       case Expr::I32AtomicsLoad:
         return EmitAtomicsLoad(f, def);
       case Expr::I32AtomicsStore:
@@ -2727,28 +2706,18 @@ EmitExpr(FunctionCompiler& f, ExprType t
         return EmitExtractLane(f, ExprType::I32x4, def);
       case Expr::I32B32X4ExtractLane:
         return EmitExtractLane(f, ExprType::B32x4, def);
       case Expr::I32B32X4AllTrue:
         return EmitSimdAllTrue(f, ExprType::B32x4, def);
       case Expr::I32B32X4AnyTrue:
         return EmitSimdAnyTrue(f, ExprType::B32x4, def);
       // F32
-      case Expr::F32Literal:
+      case Expr::F32Const:
         return EmitLiteral(f, ExprType::F32, def);
-      case Expr::F32CallInternal:
-        return EmitInternalCall(f, ExprType::F32, def);
-      case Expr::F32CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::F32, def);
-      case Expr::F32CallImport:
-        return EmitFFICall(f, ExprType::F32, def);
-      case Expr::F32Conditional:
-        return EmitConditional(f, ExprType::F32, def);
-      case Expr::F32Comma:
-        return EmitComma(f, ExprType::F32, def);
       case Expr::F32Add:
         return EmitAddOrSub(f, ExprType::F32, IsAdd(true), def);
       case Expr::F32Sub:
         return EmitAddOrSub(f, ExprType::F32, IsAdd(false), def);
       case Expr::F32Mul:
         return EmitMultiply(f, ExprType::F32, def);
       case Expr::F32Div:
         return EmitDivOrMod(f, ExprType::F32, IsDiv(true), def);
@@ -2766,26 +2735,26 @@ EmitExpr(FunctionCompiler& f, ExprType t
       case Expr::F32Floor:
         return EmitF32MathBuiltinCall(f, op, def);
       case Expr::F32FromF64:
         return EmitUnary<MToFloat32>(f, ExprType::F64, def);
       case Expr::F32FromS32:
         return EmitUnary<MToFloat32>(f, ExprType::I32, def);
       case Expr::F32FromU32:
         return EmitUnary<MAsmJSUnsignedToFloat32>(f, ExprType::I32, def);
-      case Expr::F32Load:
+      case Expr::F32LoadMem:
         return EmitLoadArray(f, Scalar::Float32, def);
-      case Expr::F32StoreF32:
+      case Expr::F32StoreMem:
         return EmitStore(f, Scalar::Float32, def);
-      case Expr::F32StoreF64:
+      case Expr::F32StoreMemF64:
         return EmitStoreWithCoercion(f, Scalar::Float32, Scalar::Float64, def);
       case Expr::F32F32X4ExtractLane:
         return EmitExtractLane(f, ExprType::F32x4, def);
       // F64
-      case Expr::F64Literal:
+      case Expr::F64Const:
         return EmitLiteral(f, ExprType::F64, def);
       case Expr::F64Add:
         return EmitAddOrSub(f, ExprType::F64, IsAdd(true), def);
       case Expr::F64Sub:
         return EmitAddOrSub(f, ExprType::F64, IsAdd(false), def);
       case Expr::F64Mul:
         return EmitMultiply(f, ExprType::F64, def);
       case Expr::F64Div:
@@ -2816,44 +2785,24 @@ EmitExpr(FunctionCompiler& f, ExprType t
       case Expr::F64Atan2:
         return EmitF64MathBuiltinCall(f, op, def);
       case Expr::F64FromF32:
         return EmitUnary<MToDouble>(f, ExprType::F32, def);
       case Expr::F64FromS32:
         return EmitUnary<MToDouble>(f, ExprType::I32, def);
       case Expr::F64FromU32:
         return EmitUnary<MAsmJSUnsignedToDouble>(f, ExprType::I32, def);
-      case Expr::F64Load:
+      case Expr::F64LoadMem:
         return EmitLoadArray(f, Scalar::Float64, def);
-      case Expr::F64StoreF64:
+      case Expr::F64StoreMem:
         return EmitStore(f, Scalar::Float64, def);
-      case Expr::F64StoreF32:
+      case Expr::F64StoreMemF32:
         return EmitStoreWithCoercion(f, Scalar::Float64, Scalar::Float32, def);
-      case Expr::F64CallInternal:
-        return EmitInternalCall(f, ExprType::F64, def);
-      case Expr::F64CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::F64, def);
-      case Expr::F64CallImport:
-        return EmitFFICall(f, ExprType::F64, def);
-      case Expr::F64Conditional:
-        return EmitConditional(f, ExprType::F64, def);
-      case Expr::F64Comma:
-        return EmitComma(f, ExprType::F64, def);
       // I32x4
-      case Expr::I32X4Comma:
-        return EmitComma(f, ExprType::I32x4, def);
-      case Expr::I32X4Conditional:
-        return EmitConditional(f, ExprType::I32x4, def);
-      case Expr::I32X4CallInternal:
-        return EmitInternalCall(f, ExprType::I32x4, def);
-      case Expr::I32X4CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::I32x4, def);
-      case Expr::I32X4CallImport:
-        return EmitFFICall(f, ExprType::I32x4, def);
-      case Expr::I32X4Literal:
+      case Expr::I32X4Const:
         return EmitLiteral(f, ExprType::I32x4, def);
       case Expr::I32X4Ctor:
         return EmitSimdCtor(f, ExprType::I32x4, def);
       case Expr::I32X4Unary:
         return EmitSimdUnary(f, ExprType::I32x4, def);
       case Expr::I32X4Binary:
         return EmitSimdBinaryArith(f, ExprType::I32x4, def);
       case Expr::I32X4BinaryBitwise:
@@ -2874,27 +2823,17 @@ EmitExpr(FunctionCompiler& f, ExprType t
         return EmitSimdSelect(f, ExprType::I32x4, def);
       case Expr::I32X4Splat:
         return EmitSimdSplat(f, ExprType::I32x4, def);
       case Expr::I32X4Load:
         return EmitSimdLoad(f, def);
       case Expr::I32X4Store:
         return EmitSimdStore(f, ExprType::I32x4, def);
       // F32x4
-      case Expr::F32X4Comma:
-        return EmitComma(f, ExprType::F32x4, def);
-      case Expr::F32X4Conditional:
-        return EmitConditional(f, ExprType::F32x4, def);
-      case Expr::F32X4CallInternal:
-        return EmitInternalCall(f, ExprType::F32x4, def);
-      case Expr::F32X4CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::F32x4, def);
-      case Expr::F32X4CallImport:
-        return EmitFFICall(f, ExprType::F32x4, def);
-      case Expr::F32X4Literal:
+      case Expr::F32X4Const:
         return EmitLiteral(f, ExprType::F32x4, def);
       case Expr::F32X4Ctor:
         return EmitSimdCtor(f, ExprType::F32x4, def);
       case Expr::F32X4Unary:
         return EmitSimdUnary(f, ExprType::F32x4, def);
       case Expr::F32X4Binary:
         return EmitSimdBinaryArith(f, ExprType::F32x4, def);
       case Expr::F32X4ReplaceLane:
@@ -2911,27 +2850,17 @@ EmitExpr(FunctionCompiler& f, ExprType t
         return EmitSimdSelect(f, ExprType::F32x4, def);
       case Expr::F32X4Splat:
         return EmitSimdSplat(f, ExprType::F32x4, def);
       case Expr::F32X4Load:
         return EmitSimdLoad(f, def);
       case Expr::F32X4Store:
         return EmitSimdStore(f, ExprType::F32x4, def);
       // B32x4
-      case Expr::B32X4Comma:
-        return EmitComma(f, ExprType::B32x4, def);
-      case Expr::B32X4Conditional:
-        return EmitConditional(f, ExprType::B32x4, def);
-      case Expr::B32X4CallInternal:
-        return EmitInternalCall(f, ExprType::B32x4, def);
-      case Expr::B32X4CallIndirect:
-        return EmitFuncPtrCall(f, ExprType::B32x4, def);
-      case Expr::B32X4CallImport:
-        return EmitFFICall(f, ExprType::B32x4, def);
-      case Expr::B32X4Literal:
+      case Expr::B32X4Const:
         return EmitLiteral(f, ExprType::B32x4, def);
       case Expr::B32X4Ctor:
         return EmitSimdCtor(f, ExprType::B32x4, def);
       case Expr::B32X4Unary:
         return EmitSimdUnary(f, ExprType::B32x4, def);
       case Expr::B32X4Binary:
         return EmitSimdBinaryArith(f, ExprType::B32x4, def);
       case Expr::B32X4BinaryBitwise:
@@ -2939,21 +2868,57 @@ EmitExpr(FunctionCompiler& f, ExprType t
       case Expr::B32X4BinaryCompI32X4:
         return EmitSimdBinaryComp(f, ExprType::I32x4, def);
       case Expr::B32X4BinaryCompF32X4:
         return EmitSimdBinaryComp(f, ExprType::F32x4, def);
       case Expr::B32X4ReplaceLane:
         return EmitSimdReplaceLane(f, ExprType::B32x4, def);
       case Expr::B32X4Splat:
         return EmitSimdBooleanSplat(f, def);
+      case Expr::Loop:
+      case Expr::Select:
+      case Expr::Br:
+      case Expr::BrIf:
+      case Expr::I8Const:
+      case Expr::I32Ctz:
+      case Expr::I32Popcnt:
+      case Expr::F32CopySign:
+      case Expr::F32Trunc:
+      case Expr::F32NearestInt:
+      case Expr::F64CopySign:
+      case Expr::F64NearestInt:
+      case Expr::F64Trunc:
+      case Expr::I32UConvertF32:
+      case Expr::I32UConvertF64:
+      case Expr::I32ConvertI64:
+      case Expr::I64Const:
+      case Expr::I64SConvertI32:
+      case Expr::I64UConvertI32:
+      case Expr::I64SConvertF32:
+      case Expr::I64SConvertF64:
+      case Expr::I64UConvertF32:
+      case Expr::I64UConvertF64:
+      case Expr::I64LoadMem8S:
+      case Expr::I64LoadMem16S:
+      case Expr::I64LoadMem32S:
+      case Expr::I64LoadMem8U:
+      case Expr::I64LoadMem16U:
+      case Expr::I64LoadMem32U:
+      case Expr::I64LoadMem:
+      case Expr::I64StoreMem8:
+      case Expr::I64StoreMem16:
+      case Expr::I64StoreMem32:
+      case Expr::I64StoreMem:
+        MOZ_CRASH("NYI");
       case Expr::DebugCheckPoint:
-      case Expr::Bad:
+      case Expr::Unreachable:
         break;
     }
-    MOZ_CRASH("unexpected asm type");
+
+    MOZ_CRASH("unexpected wasm opcode");
 }
 
 static bool
 EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* maybeLabels)
 {
     return EmitExpr(f, type, f.readOpcode(), def, maybeLabels);
 }