Bug 1316651 - Baldr: change decoding of enumerated values (r=sunfish)
authorLuke Wagner <luke@mozilla.com>
Fri, 11 Nov 2016 13:52:10 -0600
changeset 322186 8a0300ec29c9e7523c62263eb9e98d89c23739b1
parent 322185 a3fbd5543a77e9a3ba8b2aa86fe16034b8fad340
child 322187 52a2f468a31c73eed841e91a4a68fcb35ae645c5
push id83805
push userlwagner@mozilla.com
push dateFri, 11 Nov 2016 19:56:52 +0000
treeherdermozilla-inbound@52a2f468a31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1316651
milestone52.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 1316651 - Baldr: change decoding of enumerated values (r=sunfish) MozReview-Commit-ID: AUGzgO2rqyQ
js/src/wasm/WasmBaselineCompile.cpp
js/src/wasm/WasmBinaryConstants.h
js/src/wasm/WasmBinaryFormat.cpp
js/src/wasm/WasmBinaryFormat.h
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/WasmTypes.h
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -6579,540 +6579,540 @@ BaseCompiler::emitBody()
             CHECK(stk_.reserve(stk_.length() + overhead * 2));
         }
 
         overhead--;
 
         if (done())
             return true;
 
-        Expr expr;
+        uint16_t expr;
         CHECK(iter_.readExpr(&expr));
 
         switch (expr) {
           // Control opcodes
-          case Expr::Nop:
+          case uint16_t(Expr::Nop):
             CHECK(iter_.readNop());
             NEXT();
-          case Expr::Drop:
+          case uint16_t(Expr::Drop):
             CHECK_NEXT(emitDrop());
-          case Expr::Block:
+          case uint16_t(Expr::Block):
             CHECK_NEXT(emitBlock());
-          case Expr::Loop:
+          case uint16_t(Expr::Loop):
             CHECK_NEXT(emitLoop());
-          case Expr::If:
+          case uint16_t(Expr::If):
             CHECK_NEXT(emitIf());
-          case Expr::Else:
+          case uint16_t(Expr::Else):
             CHECK_NEXT(emitElse());
-          case Expr::End:
+          case uint16_t(Expr::End):
             CHECK_NEXT(emitEnd());
-          case Expr::Br:
+          case uint16_t(Expr::Br):
             CHECK_NEXT(emitBr());
-          case Expr::BrIf:
+          case uint16_t(Expr::BrIf):
             CHECK_NEXT(emitBrIf());
-          case Expr::BrTable:
+          case uint16_t(Expr::BrTable):
             CHECK_NEXT(emitBrTable());
-          case Expr::Return:
+          case uint16_t(Expr::Return):
             CHECK_NEXT(emitReturn());
-          case Expr::Unreachable:
+          case uint16_t(Expr::Unreachable):
             CHECK(iter_.readUnreachable());
             if (!deadCode_) {
                 unreachableTrap();
                 deadCode_ = true;
                 popValueStackTo(ctl_.back().stackSize);
             }
             NEXT();
 
           // Calls
-          case Expr::Call:
+          case uint16_t(Expr::Call):
             CHECK_NEXT(emitCall());
-          case Expr::CallIndirect:
+          case uint16_t(Expr::CallIndirect):
             CHECK_NEXT(emitCallIndirect(/* oldStyle = */ false));
-          case Expr::OldCallIndirect:
+          case uint16_t(Expr::OldCallIndirect):
             CHECK_NEXT(emitCallIndirect(/* oldStyle = */ true));
 
           // Locals and globals
-          case Expr::GetLocal:
+          case uint16_t(Expr::GetLocal):
             CHECK_NEXT(emitGetLocal());
-          case Expr::SetLocal:
+          case uint16_t(Expr::SetLocal):
             CHECK_NEXT(emitSetLocal());
-          case Expr::TeeLocal:
+          case uint16_t(Expr::TeeLocal):
             CHECK_NEXT(emitTeeLocal());
-          case Expr::GetGlobal:
+          case uint16_t(Expr::GetGlobal):
             CHECK_NEXT(emitGetGlobal());
-          case Expr::SetGlobal:
+          case uint16_t(Expr::SetGlobal):
             CHECK_NEXT(emitSetGlobal());
-          case Expr::TeeGlobal:
+          case uint16_t(Expr::TeeGlobal):
             CHECK_NEXT(emitTeeGlobal());
 
           // Select
-          case Expr::Select:
+          case uint16_t(Expr::Select):
             CHECK_NEXT(emitSelect());
 
           // I32
-          case Expr::I32Const: {
+          case uint16_t(Expr::I32Const): {
             int32_t i32;
             CHECK(iter_.readI32Const(&i32));
             if (!deadCode_)
                 pushI32(i32);
             NEXT();
           }
-          case Expr::I32Add:
+          case uint16_t(Expr::I32Add):
             CHECK_NEXT(emitBinary(emitAddI32, ValType::I32));
-          case Expr::I32Sub:
+          case uint16_t(Expr::I32Sub):
             CHECK_NEXT(emitBinary(emitSubtractI32, ValType::I32));
-          case Expr::I32Mul:
+          case uint16_t(Expr::I32Mul):
             CHECK_NEXT(emitBinary(emitMultiplyI32, ValType::I32));
-          case Expr::I32DivS:
+          case uint16_t(Expr::I32DivS):
             CHECK_NEXT(emitBinary(emitQuotientI32, ValType::I32));
-          case Expr::I32DivU:
+          case uint16_t(Expr::I32DivU):
             CHECK_NEXT(emitBinary(emitQuotientU32, ValType::I32));
-          case Expr::I32RemS:
+          case uint16_t(Expr::I32RemS):
             CHECK_NEXT(emitBinary(emitRemainderI32, ValType::I32));
-          case Expr::I32RemU:
+          case uint16_t(Expr::I32RemU):
             CHECK_NEXT(emitBinary(emitRemainderU32, ValType::I32));
-          case Expr::I32Min:
+          case uint16_t(Expr::I32Min):
             CHECK_NEXT(emitBinary(emitMinI32, ValType::I32));
-          case Expr::I32Max:
+          case uint16_t(Expr::I32Max):
             CHECK_NEXT(emitBinary(emitMaxI32, ValType::I32));
-          case Expr::I32Eqz:
+          case uint16_t(Expr::I32Eqz):
             CHECK_NEXT(emitConversion(emitEqzI32, ValType::I32, ValType::I32));
-          case Expr::I32TruncSF32:
+          case uint16_t(Expr::I32TruncSF32):
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<false>, ValType::F32, ValType::I32));
-          case Expr::I32TruncUF32:
+          case uint16_t(Expr::I32TruncUF32):
             CHECK_NEXT(emitConversionOOM(emitTruncateF32ToI32<true>, ValType::F32, ValType::I32));
-          case Expr::I32TruncSF64:
+          case uint16_t(Expr::I32TruncSF64):
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<false>, ValType::F64, ValType::I32));
-          case Expr::I32TruncUF64:
+          case uint16_t(Expr::I32TruncUF64):
             CHECK_NEXT(emitConversionOOM(emitTruncateF64ToI32<true>, ValType::F64, ValType::I32));
-          case Expr::I32WrapI64:
+          case uint16_t(Expr::I32WrapI64):
             CHECK_NEXT(emitConversion(emitWrapI64ToI32, ValType::I64, ValType::I32));
-          case Expr::I32ReinterpretF32:
+          case uint16_t(Expr::I32ReinterpretF32):
             CHECK_NEXT(emitConversion(emitReinterpretF32AsI32, ValType::F32, ValType::I32));
-          case Expr::I32Clz:
+          case uint16_t(Expr::I32Clz):
             CHECK_NEXT(emitUnary(emitClzI32, ValType::I32));
-          case Expr::I32Ctz:
+          case uint16_t(Expr::I32Ctz):
             CHECK_NEXT(emitUnary(emitCtzI32, ValType::I32));
-          case Expr::I32Popcnt:
+          case uint16_t(Expr::I32Popcnt):
             CHECK_NEXT(emitUnary(emitPopcntI32, ValType::I32));
-          case Expr::I32Abs:
+          case uint16_t(Expr::I32Abs):
             CHECK_NEXT(emitUnary(emitAbsI32, ValType::I32));
-          case Expr::I32Neg:
+          case uint16_t(Expr::I32Neg):
             CHECK_NEXT(emitUnary(emitNegateI32, ValType::I32));
-          case Expr::I32Or:
+          case uint16_t(Expr::I32Or):
             CHECK_NEXT(emitBinary(emitOrI32, ValType::I32));
-          case Expr::I32And:
+          case uint16_t(Expr::I32And):
             CHECK_NEXT(emitBinary(emitAndI32, ValType::I32));
-          case Expr::I32Xor:
+          case uint16_t(Expr::I32Xor):
             CHECK_NEXT(emitBinary(emitXorI32, ValType::I32));
-          case Expr::I32Shl:
+          case uint16_t(Expr::I32Shl):
             CHECK_NEXT(emitBinary(emitShlI32, ValType::I32));
-          case Expr::I32ShrS:
+          case uint16_t(Expr::I32ShrS):
             CHECK_NEXT(emitBinary(emitShrI32, ValType::I32));
-          case Expr::I32ShrU:
+          case uint16_t(Expr::I32ShrU):
             CHECK_NEXT(emitBinary(emitShrU32, ValType::I32));
-          case Expr::I32BitNot:
+          case uint16_t(Expr::I32BitNot):
             CHECK_NEXT(emitUnary(emitBitNotI32, ValType::I32));
-          case Expr::I32Load8S:
+          case uint16_t(Expr::I32Load8S):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int8));
-          case Expr::I32Load8U:
+          case uint16_t(Expr::I32Load8U):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint8));
-          case Expr::I32Load16S:
+          case uint16_t(Expr::I32Load16S):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int16));
-          case Expr::I32Load16U:
+          case uint16_t(Expr::I32Load16U):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Uint16));
-          case Expr::I32Load:
+          case uint16_t(Expr::I32Load):
             CHECK_NEXT(emitLoad(ValType::I32, Scalar::Int32));
-          case Expr::I32Store8:
+          case uint16_t(Expr::I32Store8):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int8));
-          case Expr::I32TeeStore8:
+          case uint16_t(Expr::I32TeeStore8):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int8));
-          case Expr::I32Store16:
+          case uint16_t(Expr::I32Store16):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int16));
-          case Expr::I32TeeStore16:
+          case uint16_t(Expr::I32TeeStore16):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int16));
-          case Expr::I32Store:
+          case uint16_t(Expr::I32Store):
             CHECK_NEXT(emitStore(ValType::I32, Scalar::Int32));
-          case Expr::I32TeeStore:
+          case uint16_t(Expr::I32TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::I32, Scalar::Int32));
-          case Expr::I32Rotr:
+          case uint16_t(Expr::I32Rotr):
             CHECK_NEXT(emitBinary(emitRotrI32, ValType::I32));
-          case Expr::I32Rotl:
+          case uint16_t(Expr::I32Rotl):
             CHECK_NEXT(emitBinary(emitRotlI32, ValType::I32));
 
           // I64
-          case Expr::I64Const: {
+          case uint16_t(Expr::I64Const): {
             int64_t i64;
             CHECK(iter_.readI64Const(&i64));
             if (!deadCode_)
                 pushI64(i64);
             NEXT();
           }
-          case Expr::I64Add:
+          case uint16_t(Expr::I64Add):
             CHECK_NEXT(emitBinary(emitAddI64, ValType::I64));
-          case Expr::I64Sub:
+          case uint16_t(Expr::I64Sub):
             CHECK_NEXT(emitBinary(emitSubtractI64, ValType::I64));
-          case Expr::I64Mul:
+          case uint16_t(Expr::I64Mul):
             CHECK_NEXT(emitBinary(emitMultiplyI64, ValType::I64));
-          case Expr::I64DivS:
+          case uint16_t(Expr::I64DivS):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::DivI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitQuotientI64, ValType::I64));
 #endif
-          case Expr::I64DivU:
+          case uint16_t(Expr::I64DivU):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UDivI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitQuotientU64, ValType::I64));
 #endif
-          case Expr::I64RemS:
+          case uint16_t(Expr::I64RemS):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::ModI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitRemainderI64, ValType::I64));
 #endif
-          case Expr::I64RemU:
+          case uint16_t(Expr::I64RemU):
 #ifdef INT_DIV_I64_CALLOUT
             CHECK_NEXT(emitDivOrModI64BuiltinCall(SymbolicAddress::UModI64, ValType::I64));
 #else
             CHECK_NEXT(emitBinary(emitRemainderU64, ValType::I64));
 #endif
-          case Expr::I64TruncSF32:
+          case uint16_t(Expr::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 Expr::I64TruncUF32:
+          case uint16_t(Expr::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 Expr::I64TruncSF64:
+          case uint16_t(Expr::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 Expr::I64TruncUF64:
+          case uint16_t(Expr::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 Expr::I64ExtendSI32:
+          case uint16_t(Expr::I64ExtendSI32):
             CHECK_NEXT(emitConversion(emitExtendI32ToI64, ValType::I32, ValType::I64));
-          case Expr::I64ExtendUI32:
+          case uint16_t(Expr::I64ExtendUI32):
             CHECK_NEXT(emitConversion(emitExtendU32ToI64, ValType::I32, ValType::I64));
-          case Expr::I64ReinterpretF64:
+          case uint16_t(Expr::I64ReinterpretF64):
             CHECK_NEXT(emitConversion(emitReinterpretF64AsI64, ValType::F64, ValType::I64));
-          case Expr::I64Or:
+          case uint16_t(Expr::I64Or):
             CHECK_NEXT(emitBinary(emitOrI64, ValType::I64));
-          case Expr::I64And:
+          case uint16_t(Expr::I64And):
             CHECK_NEXT(emitBinary(emitAndI64, ValType::I64));
-          case Expr::I64Xor:
+          case uint16_t(Expr::I64Xor):
             CHECK_NEXT(emitBinary(emitXorI64, ValType::I64));
-          case Expr::I64Shl:
+          case uint16_t(Expr::I64Shl):
             CHECK_NEXT(emitBinary(emitShlI64, ValType::I64));
-          case Expr::I64ShrS:
+          case uint16_t(Expr::I64ShrS):
             CHECK_NEXT(emitBinary(emitShrI64, ValType::I64));
-          case Expr::I64ShrU:
+          case uint16_t(Expr::I64ShrU):
             CHECK_NEXT(emitBinary(emitShrU64, ValType::I64));
-          case Expr::I64Rotr:
+          case uint16_t(Expr::I64Rotr):
             CHECK_NEXT(emitBinary(emitRotrI64, ValType::I64));
-          case Expr::I64Rotl:
+          case uint16_t(Expr::I64Rotl):
             CHECK_NEXT(emitBinary(emitRotlI64, ValType::I64));
-          case Expr::I64Clz:
+          case uint16_t(Expr::I64Clz):
             CHECK_NEXT(emitUnary(emitClzI64, ValType::I64));
-          case Expr::I64Ctz:
+          case uint16_t(Expr::I64Ctz):
             CHECK_NEXT(emitUnary(emitCtzI64, ValType::I64));
-          case Expr::I64Popcnt:
+          case uint16_t(Expr::I64Popcnt):
             CHECK_NEXT(emitUnary(emitPopcntI64, ValType::I64));
-          case Expr::I64Eqz:
+          case uint16_t(Expr::I64Eqz):
             CHECK_NEXT(emitConversion(emitEqzI64, ValType::I64, ValType::I32));
-          case Expr::I64Load8S:
+          case uint16_t(Expr::I64Load8S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int8));
-          case Expr::I64Load16S:
+          case uint16_t(Expr::I64Load16S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int16));
-          case Expr::I64Load32S:
+          case uint16_t(Expr::I64Load32S):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int32));
-          case Expr::I64Load8U:
+          case uint16_t(Expr::I64Load8U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint8));
-          case Expr::I64Load16U:
+          case uint16_t(Expr::I64Load16U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint16));
-          case Expr::I64Load32U:
+          case uint16_t(Expr::I64Load32U):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Uint32));
-          case Expr::I64Load:
+          case uint16_t(Expr::I64Load):
             CHECK_NEXT(emitLoad(ValType::I64, Scalar::Int64));
-          case Expr::I64Store8:
+          case uint16_t(Expr::I64Store8):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int8));
-          case Expr::I64TeeStore8:
+          case uint16_t(Expr::I64TeeStore8):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int8));
-          case Expr::I64Store16:
+          case uint16_t(Expr::I64Store16):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int16));
-          case Expr::I64TeeStore16:
+          case uint16_t(Expr::I64TeeStore16):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int16));
-          case Expr::I64Store32:
+          case uint16_t(Expr::I64Store32):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int32));
-          case Expr::I64TeeStore32:
+          case uint16_t(Expr::I64TeeStore32):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int32));
-          case Expr::I64Store:
+          case uint16_t(Expr::I64Store):
             CHECK_NEXT(emitStore(ValType::I64, Scalar::Int64));
-          case Expr::I64TeeStore:
+          case uint16_t(Expr::I64TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::I64, Scalar::Int64));
 
           // F32
-          case Expr::F32Const: {
+          case uint16_t(Expr::F32Const): {
             RawF32 f32;
             CHECK(iter_.readF32Const(&f32));
             if (!deadCode_)
                 pushF32(f32);
             NEXT();
           }
-          case Expr::F32Add:
+          case uint16_t(Expr::F32Add):
             CHECK_NEXT(emitBinary(emitAddF32, ValType::F32));
-          case Expr::F32Sub:
+          case uint16_t(Expr::F32Sub):
             CHECK_NEXT(emitBinary(emitSubtractF32, ValType::F32));
-          case Expr::F32Mul:
+          case uint16_t(Expr::F32Mul):
             CHECK_NEXT(emitBinary(emitMultiplyF32, ValType::F32));
-          case Expr::F32Div:
+          case uint16_t(Expr::F32Div):
             CHECK_NEXT(emitBinary(emitDivideF32, ValType::F32));
-          case Expr::F32Min:
+          case uint16_t(Expr::F32Min):
             CHECK_NEXT(emitBinary(emitMinF32, ValType::F32));
-          case Expr::F32Max:
+          case uint16_t(Expr::F32Max):
             CHECK_NEXT(emitBinary(emitMaxF32, ValType::F32));
-          case Expr::F32Neg:
+          case uint16_t(Expr::F32Neg):
             CHECK_NEXT(emitUnary(emitNegateF32, ValType::F32));
-          case Expr::F32Abs:
+          case uint16_t(Expr::F32Abs):
             CHECK_NEXT(emitUnary(emitAbsF32, ValType::F32));
-          case Expr::F32Sqrt:
+          case uint16_t(Expr::F32Sqrt):
             CHECK_NEXT(emitUnary(emitSqrtF32, ValType::F32));
-          case Expr::F32Ceil:
+          case uint16_t(Expr::F32Ceil):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilF, ValType::F32));
-          case Expr::F32Floor:
+          case uint16_t(Expr::F32Floor):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorF, ValType::F32));
-          case Expr::F32DemoteF64:
+          case uint16_t(Expr::F32DemoteF64):
             CHECK_NEXT(emitConversion(emitConvertF64ToF32, ValType::F64, ValType::F32));
-          case Expr::F32ConvertSI32:
+          case uint16_t(Expr::F32ConvertSI32):
             CHECK_NEXT(emitConversion(emitConvertI32ToF32, ValType::I32, ValType::F32));
-          case Expr::F32ConvertUI32:
+          case uint16_t(Expr::F32ConvertUI32):
             CHECK_NEXT(emitConversion(emitConvertU32ToF32, ValType::I32, ValType::F32));
-          case Expr::F32ConvertSI64:
+          case uint16_t(Expr::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 Expr::F32ConvertUI64:
+          case uint16_t(Expr::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 Expr::F32ReinterpretI32:
+          case uint16_t(Expr::F32ReinterpretI32):
             CHECK_NEXT(emitConversion(emitReinterpretI32AsF32, ValType::I32, ValType::F32));
-          case Expr::F32Load:
+          case uint16_t(Expr::F32Load):
             CHECK_NEXT(emitLoad(ValType::F32, Scalar::Float32));
-          case Expr::F32Store:
+          case uint16_t(Expr::F32Store):
             CHECK_NEXT(emitStore(ValType::F32, Scalar::Float32));
-          case Expr::F32TeeStore:
+          case uint16_t(Expr::F32TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::F32, Scalar::Float32));
-          case Expr::F32TeeStoreF64:
+          case uint16_t(Expr::F32TeeStoreF64):
             CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F32, Scalar::Float64));
-          case Expr::F32CopySign:
+          case uint16_t(Expr::F32CopySign):
             CHECK_NEXT(emitBinary(emitCopysignF32, ValType::F32));
-          case Expr::F32Nearest:
+          case uint16_t(Expr::F32Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntF, ValType::F32));
-          case Expr::F32Trunc:
+          case uint16_t(Expr::F32Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncF, ValType::F32));
 
           // F64
-          case Expr::F64Const: {
+          case uint16_t(Expr::F64Const): {
             RawF64 f64;
             CHECK(iter_.readF64Const(&f64));
             if (!deadCode_)
                 pushF64(f64);
             NEXT();
           }
-          case Expr::F64Add:
+          case uint16_t(Expr::F64Add):
             CHECK_NEXT(emitBinary(emitAddF64, ValType::F64));
-          case Expr::F64Sub:
+          case uint16_t(Expr::F64Sub):
             CHECK_NEXT(emitBinary(emitSubtractF64, ValType::F64));
-          case Expr::F64Mul:
+          case uint16_t(Expr::F64Mul):
             CHECK_NEXT(emitBinary(emitMultiplyF64, ValType::F64));
-          case Expr::F64Div:
+          case uint16_t(Expr::F64Div):
             CHECK_NEXT(emitBinary(emitDivideF64, ValType::F64));
-          case Expr::F64Mod:
+          case uint16_t(Expr::F64Mod):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ModD, ValType::F64));
-          case Expr::F64Min:
+          case uint16_t(Expr::F64Min):
             CHECK_NEXT(emitBinary(emitMinF64, ValType::F64));
-          case Expr::F64Max:
+          case uint16_t(Expr::F64Max):
             CHECK_NEXT(emitBinary(emitMaxF64, ValType::F64));
-          case Expr::F64Neg:
+          case uint16_t(Expr::F64Neg):
             CHECK_NEXT(emitUnary(emitNegateF64, ValType::F64));
-          case Expr::F64Abs:
+          case uint16_t(Expr::F64Abs):
             CHECK_NEXT(emitUnary(emitAbsF64, ValType::F64));
-          case Expr::F64Sqrt:
+          case uint16_t(Expr::F64Sqrt):
             CHECK_NEXT(emitUnary(emitSqrtF64, ValType::F64));
-          case Expr::F64Ceil:
+          case uint16_t(Expr::F64Ceil):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CeilD, ValType::F64));
-          case Expr::F64Floor:
+          case uint16_t(Expr::F64Floor):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::FloorD, ValType::F64));
-          case Expr::F64Sin:
+          case uint16_t(Expr::F64Sin):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::SinD, ValType::F64));
-          case Expr::F64Cos:
+          case uint16_t(Expr::F64Cos):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::CosD, ValType::F64));
-          case Expr::F64Tan:
+          case uint16_t(Expr::F64Tan):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TanD, ValType::F64));
-          case Expr::F64Asin:
+          case uint16_t(Expr::F64Asin):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ASinD, ValType::F64));
-          case Expr::F64Acos:
+          case uint16_t(Expr::F64Acos):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ACosD, ValType::F64));
-          case Expr::F64Atan:
+          case uint16_t(Expr::F64Atan):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ATanD, ValType::F64));
-          case Expr::F64Exp:
+          case uint16_t(Expr::F64Exp):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::ExpD, ValType::F64));
-          case Expr::F64Log:
+          case uint16_t(Expr::F64Log):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::LogD, ValType::F64));
-          case Expr::F64Pow:
+          case uint16_t(Expr::F64Pow):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::PowD, ValType::F64));
-          case Expr::F64Atan2:
+          case uint16_t(Expr::F64Atan2):
             CHECK_NEXT(emitBinaryMathBuiltinCall(SymbolicAddress::ATan2D, ValType::F64));
-          case Expr::F64PromoteF32:
+          case uint16_t(Expr::F64PromoteF32):
             CHECK_NEXT(emitConversion(emitConvertF32ToF64, ValType::F32, ValType::F64));
-          case Expr::F64ConvertSI32:
+          case uint16_t(Expr::F64ConvertSI32):
             CHECK_NEXT(emitConversion(emitConvertI32ToF64, ValType::I32, ValType::F64));
-          case Expr::F64ConvertUI32:
+          case uint16_t(Expr::F64ConvertUI32):
             CHECK_NEXT(emitConversion(emitConvertU32ToF64, ValType::I32, ValType::F64));
-          case Expr::F64ConvertSI64:
+          case uint16_t(Expr::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 Expr::F64ConvertUI64:
+          case uint16_t(Expr::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 Expr::F64Load:
+          case uint16_t(Expr::F64Load):
             CHECK_NEXT(emitLoad(ValType::F64, Scalar::Float64));
-          case Expr::F64Store:
+          case uint16_t(Expr::F64Store):
             CHECK_NEXT(emitStore(ValType::F64, Scalar::Float64));
-          case Expr::F64TeeStore:
+          case uint16_t(Expr::F64TeeStore):
             CHECK_NEXT(emitTeeStore(ValType::F64, Scalar::Float64));
-          case Expr::F64TeeStoreF32:
+          case uint16_t(Expr::F64TeeStoreF32):
             CHECK_NEXT(emitTeeStoreWithCoercion(ValType::F64, Scalar::Float32));
-          case Expr::F64ReinterpretI64:
+          case uint16_t(Expr::F64ReinterpretI64):
             CHECK_NEXT(emitConversion(emitReinterpretI64AsF64, ValType::I64, ValType::F64));
-          case Expr::F64CopySign:
+          case uint16_t(Expr::F64CopySign):
             CHECK_NEXT(emitBinary(emitCopysignF64, ValType::F64));
-          case Expr::F64Nearest:
+          case uint16_t(Expr::F64Nearest):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::NearbyIntD, ValType::F64));
-          case Expr::F64Trunc:
+          case uint16_t(Expr::F64Trunc):
             CHECK_NEXT(emitUnaryMathBuiltinCall(SymbolicAddress::TruncD, ValType::F64));
 
           // Comparisons
-          case Expr::I32Eq:
+          case uint16_t(Expr::I32Eq):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_EQ, MCompare::Compare_Int32));
-          case Expr::I32Ne:
+          case uint16_t(Expr::I32Ne):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_NE, MCompare::Compare_Int32));
-          case Expr::I32LtS:
+          case uint16_t(Expr::I32LtS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_Int32));
-          case Expr::I32LeS:
+          case uint16_t(Expr::I32LeS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_Int32));
-          case Expr::I32GtS:
+          case uint16_t(Expr::I32GtS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_Int32));
-          case Expr::I32GeS:
+          case uint16_t(Expr::I32GeS):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_Int32));
-          case Expr::I32LtU:
+          case uint16_t(Expr::I32LtU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LT, MCompare::Compare_UInt32));
-          case Expr::I32LeU:
+          case uint16_t(Expr::I32LeU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_LE, MCompare::Compare_UInt32));
-          case Expr::I32GtU:
+          case uint16_t(Expr::I32GtU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GT, MCompare::Compare_UInt32));
-          case Expr::I32GeU:
+          case uint16_t(Expr::I32GeU):
             CHECK_NEXT(emitComparison(emitCompareI32, ValType::I32, JSOP_GE, MCompare::Compare_UInt32));
-          case Expr::I64Eq:
+          case uint16_t(Expr::I64Eq):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_EQ, MCompare::Compare_Int64));
-          case Expr::I64Ne:
+          case uint16_t(Expr::I64Ne):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_NE, MCompare::Compare_Int64));
-          case Expr::I64LtS:
+          case uint16_t(Expr::I64LtS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_Int64));
-          case Expr::I64LeS:
+          case uint16_t(Expr::I64LeS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_Int64));
-          case Expr::I64GtS:
+          case uint16_t(Expr::I64GtS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_Int64));
-          case Expr::I64GeS:
+          case uint16_t(Expr::I64GeS):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_Int64));
-          case Expr::I64LtU:
+          case uint16_t(Expr::I64LtU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LT, MCompare::Compare_UInt64));
-          case Expr::I64LeU:
+          case uint16_t(Expr::I64LeU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_LE, MCompare::Compare_UInt64));
-          case Expr::I64GtU:
+          case uint16_t(Expr::I64GtU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GT, MCompare::Compare_UInt64));
-          case Expr::I64GeU:
+          case uint16_t(Expr::I64GeU):
             CHECK_NEXT(emitComparison(emitCompareI64, ValType::I64, JSOP_GE, MCompare::Compare_UInt64));
-          case Expr::F32Eq:
+          case uint16_t(Expr::F32Eq):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_EQ, MCompare::Compare_Float32));
-          case Expr::F32Ne:
+          case uint16_t(Expr::F32Ne):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_NE, MCompare::Compare_Float32));
-          case Expr::F32Lt:
+          case uint16_t(Expr::F32Lt):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LT, MCompare::Compare_Float32));
-          case Expr::F32Le:
+          case uint16_t(Expr::F32Le):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_LE, MCompare::Compare_Float32));
-          case Expr::F32Gt:
+          case uint16_t(Expr::F32Gt):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GT, MCompare::Compare_Float32));
-          case Expr::F32Ge:
+          case uint16_t(Expr::F32Ge):
             CHECK_NEXT(emitComparison(emitCompareF32, ValType::F32, JSOP_GE, MCompare::Compare_Float32));
-          case Expr::F64Eq:
+          case uint16_t(Expr::F64Eq):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_EQ, MCompare::Compare_Double));
-          case Expr::F64Ne:
+          case uint16_t(Expr::F64Ne):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_NE, MCompare::Compare_Double));
-          case Expr::F64Lt:
+          case uint16_t(Expr::F64Lt):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LT, MCompare::Compare_Double));
-          case Expr::F64Le:
+          case uint16_t(Expr::F64Le):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_LE, MCompare::Compare_Double));
-          case Expr::F64Gt:
+          case uint16_t(Expr::F64Gt):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GT, MCompare::Compare_Double));
-          case Expr::F64Ge:
+          case uint16_t(Expr::F64Ge):
             CHECK_NEXT(emitComparison(emitCompareF64, ValType::F64, JSOP_GE, MCompare::Compare_Double));
 
           // SIMD
 #define CASE(TYPE, OP, SIGN) \
-          case Expr::TYPE##OP: \
+          case uint16_t(Expr::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 Expr::TYPE##Constructor: \
+          case uint16_t(Expr::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,62 +7123,60 @@ BaseCompiler::emitBody()
 #undef I16x8CASE
 #undef I32x4CASE
 #undef F32x4CASE
 #undef B8x16CASE
 #undef B16x8CASE
 #undef B32x4CASE
 #undef ENUMERATE
 
-          case Expr::I8x16Const:
-          case Expr::I16x8Const:
-          case Expr::I32x4Const:
-          case Expr::F32x4Const:
-          case Expr::B8x16Const:
-          case Expr::B16x8Const:
-          case Expr::B32x4Const:
-          case Expr::I32x4shiftRightByScalarU:
-          case Expr::I8x16addSaturateU:
-          case Expr::I8x16subSaturateU:
-          case Expr::I8x16shiftRightByScalarU:
-          case Expr::I8x16lessThanU:
-          case Expr::I8x16lessThanOrEqualU:
-          case Expr::I8x16greaterThanU:
-          case Expr::I8x16greaterThanOrEqualU:
-          case Expr::I8x16extractLaneU:
-          case Expr::I16x8addSaturateU:
-          case Expr::I16x8subSaturateU:
-          case Expr::I16x8shiftRightByScalarU:
-          case Expr::I16x8lessThanU:
-          case Expr::I16x8lessThanOrEqualU:
-          case Expr::I16x8greaterThanU:
-          case Expr::I16x8greaterThanOrEqualU:
-          case Expr::I16x8extractLaneU:
-          case Expr::I32x4lessThanU:
-          case Expr::I32x4lessThanOrEqualU:
-          case Expr::I32x4greaterThanU:
-          case Expr::I32x4greaterThanOrEqualU:
-          case Expr::I32x4fromFloat32x4U:
+          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):
             MOZ_CRASH("Unimplemented SIMD");
 
           // Atomics
-          case Expr::I32AtomicsLoad:
-          case Expr::I32AtomicsStore:
-          case Expr::I32AtomicsBinOp:
-          case Expr::I32AtomicsCompareExchange:
-          case Expr::I32AtomicsExchange:
+          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):
             MOZ_CRASH("Unimplemented Atomics");
 
           // Memory Related
-          case Expr::GrowMemory:
+          case uint16_t(Expr::GrowMemory):
             CHECK_NEXT(emitGrowMemory());
-          case Expr::CurrentMemory:
+          case uint16_t(Expr::CurrentMemory):
             CHECK_NEXT(emitCurrentMemory());
-
-          case Expr::Limit:;
         }
 
         MOZ_CRASH("unexpected wasm opcode");
 
 #undef CHECK
 #undef NEXT
 #undef CHECK_NEXT
 #undef emitBinary
@@ -7451,17 +7449,17 @@ js::wasm::BaselineCompileFunction(IonCom
 
     Decoder d(func.bytes());
 
     // Build the local types vector.
 
     ValTypeVector locals;
     if (!locals.appendAll(func.sig().args()))
         return false;
-    if (!DecodeLocalEntries(d, &locals))
+    if (!DecodeLocalEntries(d, task->mg().kind, &locals))
         return false;
 
     // The MacroAssembler will sometimes access the jitContext.
 
     JitContext jitContext(&results.alloc());
 
     // One-pass baseline compilation.
 
--- a/js/src/wasm/WasmBinaryConstants.h
+++ b/js/src/wasm/WasmBinaryConstants.h
@@ -64,22 +64,20 @@ enum class TypeCode
     AnyFunc                              = 0x70,  // SLEB128(-0x10)
 
     // Type constructor for function types
     Func                                 = 0x60,  // SLEB128(-0x20)
 
     // Special code representing the block signature ()->()
     BlockVoid                            = 0x40,  // SLEB128(-0x40)
 
-    // Type codes currently always fit in a single byte
-    Max                                  = 0x7f,
     Limit                                = 0x80
 };
 
-enum class ValType : uint32_t // fix type so we can cast from any u8 in decoder
+enum class ValType
 {
     I32                                  = uint8_t(TypeCode::I32),
     I64                                  = uint8_t(TypeCode::I64),
     F32                                  = uint8_t(TypeCode::F32),
     F64                                  = uint8_t(TypeCode::F64),
 
     // ------------------------------------------------------------------------
     // The rest of these types are currently only emitted internally when
@@ -110,17 +108,17 @@ enum class GlobalFlags
     AllowedMask                          = 0x1
 };
 
 enum class MemoryTableFlags
 {
     Default                              = 0x0
 };
 
-enum class Expr : uint32_t // fix type so we can cast from any u16 in decoder
+enum class Expr
 {
     // 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
@@ -38,31 +38,44 @@ wasm::DecodePreamble(Decoder& d)
 
     if (!d.readFixedU32(&u32) || u32 != EncodingVersion)
         return d.fail("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32,
                       u32, EncodingVersion);
 
     return true;
 }
 
-bool
-wasm::CheckValType(Decoder& d, ValType type)
+static bool
+DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
 {
-    switch (type) {
-      case ValType::I32:
-      case ValType::F32:
-      case ValType::F64:
-      case ValType::I64:
+    uint8_t unchecked;
+    if (!d.readValType(&unchecked))
+        return false;
+
+    switch (unchecked) {
+      case uint8_t(ValType::I32):
+      case uint8_t(ValType::F32):
+      case uint8_t(ValType::F64):
+      case uint8_t(ValType::I64):
+        *type = ValType(unchecked);
+        return true;
+      case uint8_t(ValType::I8x16):
+      case uint8_t(ValType::I16x8):
+      case uint8_t(ValType::I32x4):
+      case uint8_t(ValType::F32x4):
+      case uint8_t(ValType::B8x16):
+      case uint8_t(ValType::B16x8):
+      case uint8_t(ValType::B32x4):
+        if (kind != ModuleKind::AsmJS)
+            return d.fail("bad type");
+        *type = ValType(unchecked);
         return true;
       default:
-        // Note: it's important not to remove this default since readValType()
-        // can return ValType values for which there is no enumerator.
         break;
     }
-
     return d.fail("bad type");
 }
 
 bool
 wasm::DecodeTypeSection(Decoder& d, SigWithIdVector* sigs)
 {
     uint32_t sectionStart, sectionSize;
     if (!d.startSection(SectionId::Type, &sectionStart, &sectionSize, "type"))
@@ -92,38 +105,32 @@ wasm::DecodeTypeSection(Decoder& d, SigW
         if (numArgs > MaxArgsPerFunc)
             return d.fail("too many arguments in signature");
 
         ValTypeVector args;
         if (!args.resize(numArgs))
             return false;
 
         for (uint32_t i = 0; i < numArgs; i++) {
-            if (!d.readValType(&args[i]))
-                return d.fail("bad value type");
-
-            if (!CheckValType(d, args[i]))
+            if (!DecodeValType(d, ModuleKind::Wasm, &args[i]))
                 return false;
         }
 
         uint32_t numRets;
         if (!d.readVarU32(&numRets))
             return d.fail("bad number of function returns");
 
         if (numRets > 1)
             return d.fail("too many returns in signature");
 
         ExprType result = ExprType::Void;
 
         if (numRets == 1) {
             ValType type;
-            if (!d.readValType(&type))
-                return d.fail("bad expression type");
-
-            if (!CheckValType(d, type))
+            if (!DecodeValType(d, ModuleKind::Wasm, &type))
                 return false;
 
             result = ToExprType(type);
         }
 
         (*sigs)[sigIndex] = Sig(Move(args), result);
     }
 
@@ -362,96 +369,96 @@ wasm::EncodeLocalEntries(Encoder& e, con
         if (!e.writeValType(prev))
             return false;
     }
 
     return true;
 }
 
 bool
-wasm::DecodeLocalEntries(Decoder& d, ValTypeVector* locals)
+wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals)
 {
     uint32_t numLocalEntries;
     if (!d.readVarU32(&numLocalEntries))
-        return false;
+        return d.fail("failed to read number of local entries");
 
     for (uint32_t i = 0; i < numLocalEntries; i++) {
         uint32_t count;
         if (!d.readVarU32(&count))
-            return false;
+            return d.fail("failed to read local entry count");
 
         if (MaxLocals - locals->length() < count)
-            return false;
+            return d.fail("too many locals");
 
         ValType type;
-        if (!d.readValType(&type))
+        if (!DecodeValType(d, kind, &type))
             return false;
 
         if (!locals->appendN(type, count))
             return false;
     }
 
     return true;
 }
 
 bool
 wasm::DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable)
 {
-    if (!d.readValType(type))
-        return d.fail("bad global type");
+    if (!DecodeValType(d, ModuleKind::Wasm, type))
+        return false;
 
     uint32_t flags;
     if (!d.readVarU32(&flags))
         return d.fail("expected global flags");
 
     if (flags & ~uint32_t(GlobalFlags::AllowedMask))
         return d.fail("unexpected bits set in global flags");
 
     *isMutable = flags & uint32_t(GlobalFlags::IsMutable);
     return true;
 }
 
 bool
 wasm::DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
                                   InitExpr* init)
 {
-    Expr expr;
+    uint16_t expr;
     if (!d.readExpr(&expr))
         return d.fail("failed to read initializer type");
 
     switch (expr) {
-      case Expr::I32Const: {
+      case uint16_t(Expr::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 Expr::I64Const: {
+      case uint16_t(Expr::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 Expr::F32Const: {
+      case uint16_t(Expr::F32Const): {
         RawF32 f32;
         if (!d.readFixedF32(&f32))
             return d.fail("failed to read initializer f32 expression");
         *init = InitExpr(Val(f32));
         break;
       }
-      case Expr::F64Const: {
+      case uint16_t(Expr::F64Const): {
         RawF64 f64;
         if (!d.readFixedF64(&f64))
             return d.fail("failed to read initializer f64 expression");
         *init = InitExpr(Val(f64));
         break;
       }
-      case Expr::GetGlobal: {
+      case uint16_t(Expr::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());
@@ -460,18 +467,18 @@ wasm::DecodeInitializerExpression(Decode
       default: {
         return d.fail("unexpected initializer expression");
       }
     }
 
     if (expected != init->type())
         return d.fail("type mismatch: initializer type and expected type don't match");
 
-    Expr end;
-    if (!d.readExpr(&end) || end != Expr::End)
+    uint16_t end;
+    if (!d.readExpr(&end) || end != uint16_t(Expr::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
@@ -93,18 +93,16 @@ class Encoder
 
     uint32_t varU32ByteLength(size_t offset) const {
         size_t start = offset;
         while (bytes_[offset] & 0x80)
             offset++;
         return offset - start + 1;
     }
 
-    static const size_t ExprLimit = 2 * UINT8_MAX - 1;
-
   public:
     explicit Encoder(Bytes& bytes)
       : bytes_(bytes)
     {
         MOZ_ASSERT(empty());
     }
 
     size_t currentOffset() const { return bytes_.length(); }
@@ -152,27 +150,28 @@ class Encoder
     }
     MOZ_MUST_USE bool writeVarU64(uint64_t i) {
         return writeVarU<uint64_t>(i);
     }
     MOZ_MUST_USE bool writeVarS64(int64_t i) {
         return writeVarS<int64_t>(i);
     }
     MOZ_MUST_USE bool writeValType(ValType type) {
-        static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
-        MOZ_ASSERT(size_t(type) <= size_t(TypeCode::Max));
+        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 writeBlockType(ExprType type) {
-        static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
-        MOZ_ASSERT(size_t(type) <= size_t(TypeCode::Max));
+        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) <= ExprLimit, "fits");
+        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));
         return writeFixedU8(UINT8_MAX) &&
                writeFixedU8(size_t(expr) - UINT8_MAX);
     }
 
     // Fixed-length encodings that allow back-patching.
 
@@ -303,18 +302,16 @@ class Decoder
             return false;
         uint8_t mask = 0x7f & (uint8_t(-1) << remainderBits);
         if ((byte & mask) != ((byte & (1 << (remainderBits - 1))) ? mask : 0))
             return false;
         *out = s | SInt(byte) << shift;
         return true;
     }
 
-    static const size_t ExprLimit = 2 * UINT8_MAX - 1;
-
   public:
     Decoder(const uint8_t* begin, const uint8_t* end, UniqueChars* error)
       : beg_(begin),
         end_(end),
         cur_(begin),
         error_(error)
     {
         MOZ_ASSERT(begin <= end);
@@ -397,46 +394,36 @@ class Decoder
         return readVarS<int32_t>(out);
     }
     MOZ_MUST_USE bool readVarU64(uint64_t* out) {
         return readVarU<uint64_t>(out);
     }
     MOZ_MUST_USE bool readVarS64(int64_t* out) {
         return readVarS<int64_t>(out);
     }
-    MOZ_MUST_USE bool readValType(ValType* type) {
-        static_assert(uint8_t(TypeCode::Max) <= INT8_MAX, "fits");
+    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");
         uint8_t u8;
         if (!readFixedU8(&u8))
             return false;
-        *type = (ValType)u8;
-        return true;
-    }
-    MOZ_MUST_USE bool readBlockType(ExprType* type) {
-        static_assert(size_t(TypeCode::Max) <= INT8_MAX, "fits");
-        uint8_t u8;
-        if (!readFixedU8(&u8))
-            return false;
-        *type = (ExprType)u8;
-        return true;
-    }
-    MOZ_MUST_USE bool readExpr(Expr* expr) {
-        static_assert(size_t(Expr::Limit) <= ExprLimit, "fits");
-        uint8_t u8;
-        if (!readFixedU8(&u8))
-            return false;
-        if (u8 != UINT8_MAX) {
-            *expr = Expr(u8);
+        if (MOZ_LIKELY(u8 != UINT8_MAX)) {
+            *expr = u8;
             return true;
         }
         if (!readFixedU8(&u8))
             return false;
-        if (u8 == UINT8_MAX)
-            return false;
-        *expr = Expr(uint16_t(u8) + UINT8_MAX);
+        *expr = 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_;
@@ -598,17 +585,17 @@ class Decoder
         int64_t i64 = 0;
         MOZ_ALWAYS_TRUE(readVarS64(&i64));
         return i64;
     }
     ValType uncheckedReadValType() {
         return (ValType)uncheckedReadFixedU8();
     }
     Expr uncheckedReadExpr() {
-        static_assert(size_t(Expr::Limit) <= ExprLimit, "fits");
+        static_assert(size_t(Expr::Limit) <= 2 * UINT8_MAX, "fits");
         uint8_t u8 = uncheckedReadFixedU8();
         return u8 != UINT8_MAX
                ? Expr(u8)
                : Expr(uncheckedReadFixedU8() + UINT8_MAX);
     }
     void uncheckedReadFixedI8x16(I8x16* i8x16) {
         struct T { I8x16 v; };
         T t = uncheckedRead<T>();
@@ -632,33 +619,30 @@ class Decoder
 };
 
 // Reusable macro encoding/decoding functions reused by both the two
 // encoders (AsmJS/WasmTextToBinary) and all the decoders
 // (WasmCompile/WasmIonCompile/WasmBaselineCompile/WasmBinaryToText).
 
 // Misc helpers.
 
-MOZ_MUST_USE bool
-CheckValType(Decoder& d, ValType type);
-
 UniqueChars
 DecodeName(Decoder& d);
 
 MOZ_MUST_USE bool
 DecodeTableLimits(Decoder& d, TableDescVector* tables);
 
 MOZ_MUST_USE bool
 GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable);
 
 MOZ_MUST_USE bool
 EncodeLocalEntries(Encoder& d, const ValTypeVector& locals);
 
 MOZ_MUST_USE bool
-DecodeLocalEntries(Decoder& d, ValTypeVector* locals);
+DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals);
 
 MOZ_MUST_USE bool
 DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable);
 
 MOZ_MUST_USE bool
 DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
                             InitExpr* init);
 
--- a/js/src/wasm/WasmBinaryIterator.h
+++ b/js/src/wasm/WasmBinaryIterator.h
@@ -521,25 +521,25 @@ class MOZ_STACK_CLASS ExprIter : private
 
     // Report a general failure.
     MOZ_MUST_USE bool fail(const char* msg) MOZ_COLD;
 
     // Report an unimplemented feature.
     MOZ_MUST_USE bool notYetImplemented(const char* what) MOZ_COLD;
 
     // Report an unrecognized opcode.
-    MOZ_MUST_USE bool unrecognizedOpcode(Expr expr) MOZ_COLD;
+    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(Expr* expr);
+    MOZ_MUST_USE bool readExpr(uint16_t* expr);
     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);
@@ -708,19 +708,19 @@ ExprIter<Policy>::notYetImplemented(cons
     if (!error)
         return false;
 
     return fail(error.get());
 }
 
 template <typename Policy>
 bool
-ExprIter<Policy>::unrecognizedOpcode(Expr expr)
+ExprIter<Policy>::unrecognizedOpcode(uint32_t expr)
 {
-    UniqueChars error(JS_smprintf("unrecognized opcode: %x", uint32_t(expr)));
+    UniqueChars error(JS_smprintf("unrecognized opcode: %x", expr));
     if (!error)
         return false;
 
     return fail(error.get());
 }
 
 template <typename Policy>
 bool
@@ -807,56 +807,58 @@ ExprIter<Policy>::popControl(LabelKind* 
 
     return true;
 }
 
 template <typename Policy>
 inline bool
 ExprIter<Policy>::readBlockType(ExprType* type)
 {
-    if (!d_.readBlockType(type))
+    uint8_t unchecked;
+    if (!d_.readBlockType(&unchecked))
         return fail("unable to read block signature");
 
     if (Validate) {
-        switch (*type) {
-          case ExprType::Void:
-          case ExprType::I32:
-          case ExprType::I64:
-          case ExprType::F32:
-          case ExprType::F64:
-          case ExprType::I8x16:
-          case ExprType::I16x8:
-          case ExprType::I32x4:
-          case ExprType::F32x4:
-          case ExprType::B8x16:
-          case ExprType::B16x8:
-          case ExprType::B32x4:
+        switch (unchecked) {
+          case uint8_t(ExprType::Void):
+          case uint8_t(ExprType::I32):
+          case uint8_t(ExprType::I64):
+          case uint8_t(ExprType::F32):
+          case uint8_t(ExprType::F64):
+          case uint8_t(ExprType::I8x16):
+          case uint8_t(ExprType::I16x8):
+          case uint8_t(ExprType::I32x4):
+          case uint8_t(ExprType::F32x4):
+          case uint8_t(ExprType::B8x16):
+          case uint8_t(ExprType::B16x8):
+          case uint8_t(ExprType::B32x4):
             break;
           default:
             return fail("invalid inline block type");
         }
     }
 
+    *type = ExprType(unchecked);
     return true;
 }
 
 template <typename Policy>
 inline bool
-ExprIter<Policy>::readExpr(Expr* expr)
+ExprIter<Policy>::readExpr(uint16_t* expr)
 {
     offsetOfExpr_ = d_.currentOffset();
 
     if (Validate) {
         if (MOZ_UNLIKELY(!d_.readExpr(expr)))
             return fail("unable to read opcode");
     } else {
-        *expr = d_.uncheckedReadExpr();
+        *expr = uint16_t(d_.uncheckedReadExpr());
     }
 
-    expr_ = *expr;
+    expr_ = Expr(*expr);  // debug-only
 
     return true;
 }
 
 template <typename Policy>
 inline bool
 ExprIter<Policy>::readFunctionStart(ExprType ret)
 {
--- a/js/src/wasm/WasmBinaryToAST.cpp
+++ b/js/src/wasm/WasmBinaryToAST.cpp
@@ -1009,421 +1009,419 @@ AstDecodeReturn(AstDecodeContext& c)
 
     return true;
 }
 
 static bool
 AstDecodeExpr(AstDecodeContext& c)
 {
     uint32_t exprOffset = c.iter().currentOffset();
-    Expr expr;
+    uint16_t expr;
     if (!c.iter().readExpr(&expr))
         return false;
 
     AstExpr* tmp;
     switch (expr) {
-      case Expr::Nop:
+      case uint16_t(Expr::Nop):
         if (!AstDecodeNop(c))
             return false;
         break;
-      case Expr::Drop:
+      case uint16_t(Expr::Drop):
         if (!AstDecodeDrop(c))
             return false;
         break;
-      case Expr::Call:
+      case uint16_t(Expr::Call):
         if (!AstDecodeCall(c))
             return false;
         break;
-      case Expr::CallIndirect:
+      case uint16_t(Expr::CallIndirect):
         if (!AstDecodeCallIndirect(c))
             return false;
         break;
-      case Expr::I32Const:
+      case uint16_t(Expr::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 Expr::I64Const:
+      case uint16_t(Expr::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 Expr::F32Const: {
+      case uint16_t(Expr::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 Expr::F64Const: {
+      case uint16_t(Expr::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 Expr::GetLocal:
+      case uint16_t(Expr::GetLocal):
         if (!AstDecodeGetLocal(c))
             return false;
         break;
-      case Expr::SetLocal:
+      case uint16_t(Expr::SetLocal):
         if (!AstDecodeSetLocal(c))
             return false;
         break;
-      case Expr::TeeLocal:
+      case uint16_t(Expr::TeeLocal):
         if (!AstDecodeTeeLocal(c))
             return false;
         break;
-      case Expr::Select:
+      case uint16_t(Expr::Select):
         if (!AstDecodeSelect(c))
             return false;
         break;
-      case Expr::Block:
-      case Expr::Loop:
-        if (!AstDecodeBlock(c, expr))
+      case uint16_t(Expr::Block):
+      case uint16_t(Expr::Loop):
+        if (!AstDecodeBlock(c, Expr(expr)))
             return false;
         break;
-      case Expr::If:
+      case uint16_t(Expr::If):
         if (!AstDecodeIf(c))
             return false;
         break;
-      case Expr::Else:
+      case uint16_t(Expr::Else):
         if (!AstDecodeElse(c))
             return false;
         break;
-      case Expr::End:
+      case uint16_t(Expr::End):
         if (!AstDecodeEnd(c))
             return false;
         break;
-      case Expr::I32Clz:
-      case Expr::I32Ctz:
-      case Expr::I32Popcnt:
-        if (!AstDecodeUnary(c, ValType::I32, expr))
+      case uint16_t(Expr::I32Clz):
+      case uint16_t(Expr::I32Ctz):
+      case uint16_t(Expr::I32Popcnt):
+        if (!AstDecodeUnary(c, ValType::I32, Expr(expr)))
             return false;
         break;
-      case Expr::I64Clz:
-      case Expr::I64Ctz:
-      case Expr::I64Popcnt:
-        if (!AstDecodeUnary(c, ValType::I64, expr))
+      case uint16_t(Expr::I64Clz):
+      case uint16_t(Expr::I64Ctz):
+      case uint16_t(Expr::I64Popcnt):
+        if (!AstDecodeUnary(c, ValType::I64, Expr(expr)))
             return false;
         break;
-      case Expr::F32Abs:
-      case Expr::F32Neg:
-      case Expr::F32Ceil:
-      case Expr::F32Floor:
-      case Expr::F32Sqrt:
-      case Expr::F32Trunc:
-      case Expr::F32Nearest:
-        if (!AstDecodeUnary(c, ValType::F32, expr))
+      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)))
             return false;
         break;
-      case Expr::F64Abs:
-      case Expr::F64Neg:
-      case Expr::F64Ceil:
-      case Expr::F64Floor:
-      case Expr::F64Sqrt:
-      case Expr::F64Trunc:
-      case Expr::F64Nearest:
-        if (!AstDecodeUnary(c, ValType::F64, expr))
+      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)))
             return false;
         break;
-      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:
-        if (!AstDecodeBinary(c, ValType::I32, expr))
+      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)))
             return false;
         break;
-      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:
-        if (!AstDecodeBinary(c, ValType::I64, expr))
+      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)))
             return false;
         break;
-      case Expr::F32Add:
-      case Expr::F32Sub:
-      case Expr::F32Mul:
-      case Expr::F32Div:
-      case Expr::F32Min:
-      case Expr::F32Max:
-      case Expr::F32CopySign:
-        if (!AstDecodeBinary(c, ValType::F32, expr))
+      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)))
             return false;
         break;
-      case Expr::F64Add:
-      case Expr::F64Sub:
-      case Expr::F64Mul:
-      case Expr::F64Div:
-      case Expr::F64Min:
-      case Expr::F64Max:
-      case Expr::F64CopySign:
-        if (!AstDecodeBinary(c, ValType::F64, expr))
+      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)))
             return false;
         break;
-      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:
-        if (!AstDecodeComparison(c, ValType::I32, expr))
+      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)))
             return false;
         break;
-      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:
-        if (!AstDecodeComparison(c, ValType::I64, expr))
+      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)))
             return false;
         break;
-      case Expr::F32Eq:
-      case Expr::F32Ne:
-      case Expr::F32Lt:
-      case Expr::F32Le:
-      case Expr::F32Gt:
-      case Expr::F32Ge:
-        if (!AstDecodeComparison(c, ValType::F32, expr))
+      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)))
             return false;
         break;
-      case Expr::F64Eq:
-      case Expr::F64Ne:
-      case Expr::F64Lt:
-      case Expr::F64Le:
-      case Expr::F64Gt:
-      case Expr::F64Ge:
-        if (!AstDecodeComparison(c, ValType::F64, expr))
+      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)))
             return false;
         break;
-      case Expr::I32Eqz:
-        if (!AstDecodeConversion(c, ValType::I32, ValType::I32, expr))
+      case uint16_t(Expr::I32Eqz):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::I32, Expr(expr)))
             return false;
         break;
-      case Expr::I64Eqz:
-      case Expr::I32WrapI64:
-        if (!AstDecodeConversion(c, ValType::I64, ValType::I32, expr))
+      case uint16_t(Expr::I64Eqz):
+      case uint16_t(Expr::I32WrapI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::I32, Expr(expr)))
             return false;
         break;
-      case Expr::I32TruncSF32:
-      case Expr::I32TruncUF32:
-      case Expr::I32ReinterpretF32:
-        if (!AstDecodeConversion(c, ValType::F32, ValType::I32, expr))
+      case uint16_t(Expr::I32TruncSF32):
+      case uint16_t(Expr::I32TruncUF32):
+      case uint16_t(Expr::I32ReinterpretF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::I32, Expr(expr)))
             return false;
         break;
-      case Expr::I32TruncSF64:
-      case Expr::I32TruncUF64:
-        if (!AstDecodeConversion(c, ValType::F64, ValType::I32, expr))
+      case uint16_t(Expr::I32TruncSF64):
+      case uint16_t(Expr::I32TruncUF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::I32, Expr(expr)))
             return false;
         break;
-      case Expr::I64ExtendSI32:
-      case Expr::I64ExtendUI32:
-        if (!AstDecodeConversion(c, ValType::I32, ValType::I64, expr))
+      case uint16_t(Expr::I64ExtendSI32):
+      case uint16_t(Expr::I64ExtendUI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::I64, Expr(expr)))
             return false;
         break;
-      case Expr::I64TruncSF32:
-      case Expr::I64TruncUF32:
-        if (!AstDecodeConversion(c, ValType::F32, ValType::I64, expr))
+      case uint16_t(Expr::I64TruncSF32):
+      case uint16_t(Expr::I64TruncUF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::I64, Expr(expr)))
             return false;
         break;
-      case Expr::I64TruncSF64:
-      case Expr::I64TruncUF64:
-      case Expr::I64ReinterpretF64:
-        if (!AstDecodeConversion(c, ValType::F64, ValType::I64, expr))
+      case uint16_t(Expr::I64TruncSF64):
+      case uint16_t(Expr::I64TruncUF64):
+      case uint16_t(Expr::I64ReinterpretF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::I64, Expr(expr)))
             return false;
         break;
-      case Expr::F32ConvertSI32:
-      case Expr::F32ConvertUI32:
-      case Expr::F32ReinterpretI32:
-        if (!AstDecodeConversion(c, ValType::I32, ValType::F32, expr))
+      case uint16_t(Expr::F32ConvertSI32):
+      case uint16_t(Expr::F32ConvertUI32):
+      case uint16_t(Expr::F32ReinterpretI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::F32, Expr(expr)))
             return false;
         break;
-      case Expr::F32ConvertSI64:
-      case Expr::F32ConvertUI64:
-        if (!AstDecodeConversion(c, ValType::I64, ValType::F32, expr))
+      case uint16_t(Expr::F32ConvertSI64):
+      case uint16_t(Expr::F32ConvertUI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::F32, Expr(expr)))
             return false;
         break;
-      case Expr::F32DemoteF64:
-        if (!AstDecodeConversion(c, ValType::F64, ValType::F32, expr))
+      case uint16_t(Expr::F32DemoteF64):
+        if (!AstDecodeConversion(c, ValType::F64, ValType::F32, Expr(expr)))
             return false;
         break;
-      case Expr::F64ConvertSI32:
-      case Expr::F64ConvertUI32:
-        if (!AstDecodeConversion(c, ValType::I32, ValType::F64, expr))
+      case uint16_t(Expr::F64ConvertSI32):
+      case uint16_t(Expr::F64ConvertUI32):
+        if (!AstDecodeConversion(c, ValType::I32, ValType::F64, Expr(expr)))
             return false;
         break;
-      case Expr::F64ConvertSI64:
-      case Expr::F64ConvertUI64:
-      case Expr::F64ReinterpretI64:
-        if (!AstDecodeConversion(c, ValType::I64, ValType::F64, expr))
+      case uint16_t(Expr::F64ConvertSI64):
+      case uint16_t(Expr::F64ConvertUI64):
+      case uint16_t(Expr::F64ReinterpretI64):
+        if (!AstDecodeConversion(c, ValType::I64, ValType::F64, Expr(expr)))
             return false;
         break;
-      case Expr::F64PromoteF32:
-        if (!AstDecodeConversion(c, ValType::F32, ValType::F64, expr))
+      case uint16_t(Expr::F64PromoteF32):
+        if (!AstDecodeConversion(c, ValType::F32, ValType::F64, Expr(expr)))
             return false;
         break;
-      case Expr::I32Load8S:
-      case Expr::I32Load8U:
-        if (!AstDecodeLoad(c, ValType::I32, 1, expr))
+      case uint16_t(Expr::I32Load8S):
+      case uint16_t(Expr::I32Load8U):
+        if (!AstDecodeLoad(c, ValType::I32, 1, Expr(expr)))
             return false;
         break;
-      case Expr::I32Load16S:
-      case Expr::I32Load16U:
-        if (!AstDecodeLoad(c, ValType::I32, 2, expr))
+      case uint16_t(Expr::I32Load16S):
+      case uint16_t(Expr::I32Load16U):
+        if (!AstDecodeLoad(c, ValType::I32, 2, Expr(expr)))
             return false;
         break;
-      case Expr::I32Load:
-        if (!AstDecodeLoad(c, ValType::I32, 4, expr))
+      case uint16_t(Expr::I32Load):
+        if (!AstDecodeLoad(c, ValType::I32, 4, Expr(expr)))
             return false;
         break;
-      case Expr::I64Load8S:
-      case Expr::I64Load8U:
-        if (!AstDecodeLoad(c, ValType::I64, 1, expr))
+      case uint16_t(Expr::I64Load8S):
+      case uint16_t(Expr::I64Load8U):
+        if (!AstDecodeLoad(c, ValType::I64, 1, Expr(expr)))
             return false;
         break;
-      case Expr::I64Load16S:
-      case Expr::I64Load16U:
-        if (!AstDecodeLoad(c, ValType::I64, 2, expr))
+      case uint16_t(Expr::I64Load16S):
+      case uint16_t(Expr::I64Load16U):
+        if (!AstDecodeLoad(c, ValType::I64, 2, Expr(expr)))
             return false;
         break;
-      case Expr::I64Load32S:
-      case Expr::I64Load32U:
-        if (!AstDecodeLoad(c, ValType::I64, 4, expr))
+      case uint16_t(Expr::I64Load32S):
+      case uint16_t(Expr::I64Load32U):
+        if (!AstDecodeLoad(c, ValType::I64, 4, Expr(expr)))
             return false;
         break;
-      case Expr::I64Load:
-        if (!AstDecodeLoad(c, ValType::I64, 8, expr))
+      case uint16_t(Expr::I64Load):
+        if (!AstDecodeLoad(c, ValType::I64, 8, Expr(expr)))
             return false;
         break;
-      case Expr::F32Load:
-        if (!AstDecodeLoad(c, ValType::F32, 4, expr))
+      case uint16_t(Expr::F32Load):
+        if (!AstDecodeLoad(c, ValType::F32, 4, Expr(expr)))
             return false;
         break;
-      case Expr::F64Load:
-        if (!AstDecodeLoad(c, ValType::F64, 8, expr))
+      case uint16_t(Expr::F64Load):
+        if (!AstDecodeLoad(c, ValType::F64, 8, Expr(expr)))
             return false;
         break;
-      case Expr::I32Store8:
-        if (!AstDecodeStore(c, ValType::I32, 1, expr))
+      case uint16_t(Expr::I32Store8):
+        if (!AstDecodeStore(c, ValType::I32, 1, Expr(expr)))
             return false;
         break;
-      case Expr::I32Store16:
-        if (!AstDecodeStore(c, ValType::I32, 2, expr))
+      case uint16_t(Expr::I32Store16):
+        if (!AstDecodeStore(c, ValType::I32, 2, Expr(expr)))
             return false;
         break;
-      case Expr::I32Store:
-        if (!AstDecodeStore(c, ValType::I32, 4, expr))
+      case uint16_t(Expr::I32Store):
+        if (!AstDecodeStore(c, ValType::I32, 4, Expr(expr)))
             return false;
         break;
-      case Expr::I64Store8:
-        if (!AstDecodeStore(c, ValType::I64, 1, expr))
+      case uint16_t(Expr::I64Store8):
+        if (!AstDecodeStore(c, ValType::I64, 1, Expr(expr)))
             return false;
         break;
-      case Expr::I64Store16:
-        if (!AstDecodeStore(c, ValType::I64, 2, expr))
+      case uint16_t(Expr::I64Store16):
+        if (!AstDecodeStore(c, ValType::I64, 2, Expr(expr)))
             return false;
         break;
-      case Expr::I64Store32:
-        if (!AstDecodeStore(c, ValType::I64, 4, expr))
+      case uint16_t(Expr::I64Store32):
+        if (!AstDecodeStore(c, ValType::I64, 4, Expr(expr)))
             return false;
         break;
-      case Expr::I64Store:
-        if (!AstDecodeStore(c, ValType::I64, 8, expr))
+      case uint16_t(Expr::I64Store):
+        if (!AstDecodeStore(c, ValType::I64, 8, Expr(expr)))
             return false;
         break;
-      case Expr::F32Store:
-        if (!AstDecodeStore(c, ValType::F32, 4, expr))
+      case uint16_t(Expr::F32Store):
+        if (!AstDecodeStore(c, ValType::F32, 4, Expr(expr)))
             return false;
         break;
-      case Expr::F64Store:
-        if (!AstDecodeStore(c, ValType::F64, 8, expr))
+      case uint16_t(Expr::F64Store):
+        if (!AstDecodeStore(c, ValType::F64, 8, Expr(expr)))
             return false;
         break;
-      case Expr::CurrentMemory:
+      case uint16_t(Expr::CurrentMemory):
         if (!AstDecodeCurrentMemory(c))
             return false;
         break;
-      case Expr::GrowMemory:
+      case uint16_t(Expr::GrowMemory):
         if (!AstDecodeGrowMemory(c))
             return false;
         break;
-      case Expr::SetGlobal:
+      case uint16_t(Expr::SetGlobal):
         if (!AstDecodeSetGlobal(c))
             return false;
         break;
-      case Expr::GetGlobal:
+      case uint16_t(Expr::GetGlobal):
         if (!AstDecodeGetGlobal(c))
             return false;
         break;
-      case Expr::Br:
-      case Expr::BrIf:
-        if (!AstDecodeBranch(c, expr))
+      case uint16_t(Expr::Br):
+      case uint16_t(Expr::BrIf):
+        if (!AstDecodeBranch(c, Expr(expr)))
             return false;
         break;
-      case Expr::BrTable:
+      case uint16_t(Expr::BrTable):
         if (!AstDecodeBrTable(c))
             return false;
         break;
-      case Expr::Return:
+      case uint16_t(Expr::Return):
         if (!AstDecodeReturn(c))
             return false;
         break;
-      case Expr::Unreachable:
+      case uint16_t(Expr::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:
-        // Note: it's important not to remove this default since readExpr()
-        // can return Expr values for which there is no enumerator.
         return c.iter().unrecognizedOpcode(expr);
     }
 
     AstExpr* lastExpr = c.top().expr;
     if (lastExpr)
         lastExpr->setOffset(exprOffset);
     return true;
 }
@@ -1802,17 +1800,17 @@ AstDecodeFunctionBody(AstDecodeContext &
     AstValTypeVector vars(c.lifo);
     AstNameVector localsNames(c.lifo);
     AstExprVector body(c.lifo);
 
     ValTypeVector locals;
     if (!locals.appendAll(sig->args()))
         return false;
 
-    if (!DecodeLocalEntries(c.d, &locals))
+    if (!DecodeLocalEntries(c.d, ModuleKind::Wasm, &locals))
         return c.d.fail("failed decoding local entries");
 
     c.startFunction(&iter, &locals, sig->ret());
 
     AstName funcName;
     if (!GenerateName(c, AstName(u"func"), c.module().numFuncImports() + funcDefIndex, &funcName))
         return false;
 
--- a/js/src/wasm/WasmBinaryToExperimentalText.cpp
+++ b/js/src/wasm/WasmBinaryToExperimentalText.cpp
@@ -502,16 +502,51 @@ PrintTeeLocal(WasmPrintContext& c, AstTe
             return false;
     }
 
     c.currentPrecedence = lastPrecedence;
     return true;
 }
 
 static bool
+PrintGetGlobal(WasmPrintContext& c, AstGetGlobal& gg)
+{
+    return PrintRef(c, gg.global());
+}
+
+static bool
+PrintSetGlobal(WasmPrintContext& c, AstSetGlobal& sg)
+{
+    PrintOperatorPrecedence lastPrecedence = c.currentPrecedence;
+
+    if (!c.f.reduceParens || lastPrecedence > AssignmentPrecedence) {
+        if (!c.buffer.append("("))
+            return false;
+    }
+
+    if (!PrintRef(c, sg.global()))
+        return false;
+    if (!c.buffer.append(" = "))
+        return false;
+
+    c.currentPrecedence = AssignmentPrecedence;
+
+    if (!PrintExpr(c, sg.value()))
+        return false;
+
+    if (!c.f.reduceParens || lastPrecedence > AssignmentPrecedence) {
+        if (!c.buffer.append(")"))
+            return false;
+    }
+
+    c.currentPrecedence = lastPrecedence;
+    return true;
+}
+
+static bool
 PrintExprList(WasmPrintContext& c, const AstExprVector& exprs, uint32_t startFrom = 0)
 {
     for (uint32_t i = startFrom; i < exprs.length(); i++) {
         if (!PrintBlockLevelExpr(c, *exprs[i], i + 1 == exprs.length()))
             return false;
     }
     return true;
 }
@@ -1396,16 +1431,20 @@ PrintExpr(WasmPrintContext& c, AstExpr& 
       case AstExprKind::Const:
         return PrintConst(c, expr.as<AstConst>());
       case AstExprKind::GetLocal:
         return PrintGetLocal(c, expr.as<AstGetLocal>());
       case AstExprKind::SetLocal:
         return PrintSetLocal(c, expr.as<AstSetLocal>());
       case AstExprKind::TeeLocal:
         return PrintTeeLocal(c, expr.as<AstTeeLocal>());
+      case AstExprKind::GetGlobal:
+        return PrintGetGlobal(c, expr.as<AstGetGlobal>());
+      case AstExprKind::SetGlobal:
+        return PrintSetGlobal(c, expr.as<AstSetGlobal>());
       case AstExprKind::Block:
         return PrintBlock(c, expr.as<AstBlock>());
       case AstExprKind::If:
         return PrintIf(c, expr.as<AstIf>());
       case AstExprKind::UnaryOperator:
         return PrintUnaryOperator(c, expr.as<AstUnaryOperator>());
       case AstExprKind::BinaryOperator:
         return PrintBinaryOperator(c, expr.as<AstBinaryOperator>());
@@ -1426,23 +1465,21 @@ PrintExpr(WasmPrintContext& c, AstExpr& 
       case AstExprKind::Return:
         return PrintReturn(c, expr.as<AstReturn>());
       case AstExprKind::First:
         return PrintFirst(c, expr.as<AstFirst>());
       case AstExprKind::CurrentMemory:
         return PrintCurrentMemory(c, expr.as<AstCurrentMemory>());
       case AstExprKind::GrowMemory:
         return PrintGrowMemory(c, expr.as<AstGrowMemory>());
-      default:
-        // Note: it's important not to remove this default since readExpr()
-        // can return Expr values for which there is no enumerator.
-        break;
+      case AstExprKind::Pop:
+        return true;
     }
 
-    return false;
+    MOZ_CRASH("Bad AstExprKind");
 }
 
 static bool
 PrintSignature(WasmPrintContext& c, const AstSig& sig, const AstNameVector* maybeLocals = nullptr)
 {
     uint32_t paramsNum = sig.args().length();
 
     if (!c.buffer.append("("))
--- a/js/src/wasm/WasmBinaryToText.cpp
+++ b/js/src/wasm/WasmBinaryToText.cpp
@@ -1122,19 +1122,17 @@ RenderExpr(WasmRenderContext& c, AstExpr
         if (!RenderCurrentMemory(c, expr.as<AstCurrentMemory>()))
             return false;
         break;
       case AstExprKind::GrowMemory:
         if (!RenderGrowMemory(c, expr.as<AstGrowMemory>()))
             return false;
         break;
       default:
-        // Note: it's important not to remove this default since readExpr()
-        // can return Expr values for which there is no enumerator.
-        return Fail(c, "unexpected expression kind");
+        MOZ_CRASH("Bad AstExprKind");
     }
 
     return !newLine || c.buffer.append("\n");
 }
 
 static bool
 RenderSignature(WasmRenderContext& c, const AstSig& sig, const AstNameVector* maybeLocals = nullptr)
 {
--- a/js/src/wasm/WasmCompile.cpp
+++ b/js/src/wasm/WasmCompile.cpp
@@ -145,265 +145,265 @@ DecodeBrTable(FunctionDecoder& f)
 }
 
 static bool
 DecodeFunctionBodyExprs(FunctionDecoder& f)
 {
 #define CHECK(c) if (!(c)) return false; break
 
     while (true) {
-        Expr expr;
+        uint16_t expr;
         if (!f.iter().readExpr(&expr))
             return false;
 
         switch (expr) {
-          case Expr::End:
+          case uint16_t(Expr::End):
             if (!f.iter().readEnd(nullptr, nullptr, nullptr))
                 return false;
             if (f.iter().controlStackEmpty())
                 return true;
             break;
-          case Expr::Nop:
+          case uint16_t(Expr::Nop):
             CHECK(f.iter().readNop());
-          case Expr::Drop:
+          case uint16_t(Expr::Drop):
             CHECK(f.iter().readDrop());
-          case Expr::Call:
+          case uint16_t(Expr::Call):
             CHECK(DecodeCall(f));
-          case Expr::CallIndirect:
+          case uint16_t(Expr::CallIndirect):
             CHECK(DecodeCallIndirect(f));
-          case Expr::I32Const:
+          case uint16_t(Expr::I32Const):
             CHECK(f.iter().readI32Const(nullptr));
-          case Expr::I64Const:
+          case uint16_t(Expr::I64Const):
             CHECK(f.iter().readI64Const(nullptr));
-          case Expr::F32Const:
+          case uint16_t(Expr::F32Const):
             CHECK(f.iter().readF32Const(nullptr));
-          case Expr::F64Const:
+          case uint16_t(Expr::F64Const):
             CHECK(f.iter().readF64Const(nullptr));
-          case Expr::GetLocal:
+          case uint16_t(Expr::GetLocal):
             CHECK(f.iter().readGetLocal(f.locals(), nullptr));
-          case Expr::SetLocal:
+          case uint16_t(Expr::SetLocal):
             CHECK(f.iter().readSetLocal(f.locals(), nullptr, nullptr));
-          case Expr::TeeLocal:
+          case uint16_t(Expr::TeeLocal):
             CHECK(f.iter().readTeeLocal(f.locals(), nullptr, nullptr));
-          case Expr::GetGlobal:
+          case uint16_t(Expr::GetGlobal):
             CHECK(f.iter().readGetGlobal(f.mg().globals(), nullptr));
-          case Expr::SetGlobal:
+          case uint16_t(Expr::SetGlobal):
             CHECK(f.iter().readSetGlobal(f.mg().globals(), nullptr, nullptr));
-          case Expr::Select:
+          case uint16_t(Expr::Select):
             CHECK(f.iter().readSelect(nullptr, nullptr, nullptr, nullptr));
-          case Expr::Block:
+          case uint16_t(Expr::Block):
             CHECK(f.iter().readBlock());
-          case Expr::Loop:
+          case uint16_t(Expr::Loop):
             CHECK(f.iter().readLoop());
-          case Expr::If:
+          case uint16_t(Expr::If):
             CHECK(f.iter().readIf(nullptr));
-          case Expr::Else:
+          case uint16_t(Expr::Else):
             CHECK(f.iter().readElse(nullptr, nullptr));
-          case Expr::I32Clz:
-          case Expr::I32Ctz:
-          case Expr::I32Popcnt:
+          case uint16_t(Expr::I32Clz):
+          case uint16_t(Expr::I32Ctz):
+          case uint16_t(Expr::I32Popcnt):
             CHECK(f.iter().readUnary(ValType::I32, nullptr));
-          case Expr::I64Clz:
-          case Expr::I64Ctz:
-          case Expr::I64Popcnt:
+          case uint16_t(Expr::I64Clz):
+          case uint16_t(Expr::I64Ctz):
+          case uint16_t(Expr::I64Popcnt):
             CHECK(f.iter().readUnary(ValType::I64, nullptr));
-          case Expr::F32Abs:
-          case Expr::F32Neg:
-          case Expr::F32Ceil:
-          case Expr::F32Floor:
-          case Expr::F32Sqrt:
-          case Expr::F32Trunc:
-          case Expr::F32Nearest:
+          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):
             CHECK(f.iter().readUnary(ValType::F32, nullptr));
-          case Expr::F64Abs:
-          case Expr::F64Neg:
-          case Expr::F64Ceil:
-          case Expr::F64Floor:
-          case Expr::F64Sqrt:
-          case Expr::F64Trunc:
-          case Expr::F64Nearest:
+          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):
             CHECK(f.iter().readUnary(ValType::F64, nullptr));
-          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 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):
             CHECK(f.iter().readBinary(ValType::I32, nullptr, nullptr));
-          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 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):
             CHECK(f.iter().readBinary(ValType::I64, nullptr, nullptr));
-          case Expr::F32Add:
-          case Expr::F32Sub:
-          case Expr::F32Mul:
-          case Expr::F32Div:
-          case Expr::F32Min:
-          case Expr::F32Max:
-          case Expr::F32CopySign:
+          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):
             CHECK(f.iter().readBinary(ValType::F32, nullptr, nullptr));
-          case Expr::F64Add:
-          case Expr::F64Sub:
-          case Expr::F64Mul:
-          case Expr::F64Div:
-          case Expr::F64Min:
-          case Expr::F64Max:
-          case Expr::F64CopySign:
+          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):
             CHECK(f.iter().readBinary(ValType::F64, nullptr, nullptr));
-          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 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):
             CHECK(f.iter().readComparison(ValType::I32, nullptr, nullptr));
-          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 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):
             CHECK(f.iter().readComparison(ValType::I64, nullptr, nullptr));
-          case Expr::F32Eq:
-          case Expr::F32Ne:
-          case Expr::F32Lt:
-          case Expr::F32Le:
-          case Expr::F32Gt:
-          case Expr::F32Ge:
+          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):
             CHECK(f.iter().readComparison(ValType::F32, nullptr, nullptr));
-          case Expr::F64Eq:
-          case Expr::F64Ne:
-          case Expr::F64Lt:
-          case Expr::F64Le:
-          case Expr::F64Gt:
-          case Expr::F64Ge:
+          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):
             CHECK(f.iter().readComparison(ValType::F64, nullptr, nullptr));
-          case Expr::I32Eqz:
+          case uint16_t(Expr::I32Eqz):
             CHECK(f.iter().readConversion(ValType::I32, ValType::I32, nullptr));
-          case Expr::I64Eqz:
-          case Expr::I32WrapI64:
+          case uint16_t(Expr::I64Eqz):
+          case uint16_t(Expr::I32WrapI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::I32, nullptr));
-          case Expr::I32TruncSF32:
-          case Expr::I32TruncUF32:
-          case Expr::I32ReinterpretF32:
+          case uint16_t(Expr::I32TruncSF32):
+          case uint16_t(Expr::I32TruncUF32):
+          case uint16_t(Expr::I32ReinterpretF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::I32, nullptr));
-          case Expr::I32TruncSF64:
-          case Expr::I32TruncUF64:
+          case uint16_t(Expr::I32TruncSF64):
+          case uint16_t(Expr::I32TruncUF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::I32, nullptr));
-          case Expr::I64ExtendSI32:
-          case Expr::I64ExtendUI32:
+          case uint16_t(Expr::I64ExtendSI32):
+          case uint16_t(Expr::I64ExtendUI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::I64, nullptr));
-          case Expr::I64TruncSF32:
-          case Expr::I64TruncUF32:
+          case uint16_t(Expr::I64TruncSF32):
+          case uint16_t(Expr::I64TruncUF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::I64, nullptr));
-          case Expr::I64TruncSF64:
-          case Expr::I64TruncUF64:
-          case Expr::I64ReinterpretF64:
+          case uint16_t(Expr::I64TruncSF64):
+          case uint16_t(Expr::I64TruncUF64):
+          case uint16_t(Expr::I64ReinterpretF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::I64, nullptr));
-          case Expr::F32ConvertSI32:
-          case Expr::F32ConvertUI32:
-          case Expr::F32ReinterpretI32:
+          case uint16_t(Expr::F32ConvertSI32):
+          case uint16_t(Expr::F32ConvertUI32):
+          case uint16_t(Expr::F32ReinterpretI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::F32, nullptr));
-          case Expr::F32ConvertSI64:
-          case Expr::F32ConvertUI64:
+          case uint16_t(Expr::F32ConvertSI64):
+          case uint16_t(Expr::F32ConvertUI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::F32, nullptr));
-          case Expr::F32DemoteF64:
+          case uint16_t(Expr::F32DemoteF64):
             CHECK(f.iter().readConversion(ValType::F64, ValType::F32, nullptr));
-          case Expr::F64ConvertSI32:
-          case Expr::F64ConvertUI32:
+          case uint16_t(Expr::F64ConvertSI32):
+          case uint16_t(Expr::F64ConvertUI32):
             CHECK(f.iter().readConversion(ValType::I32, ValType::F64, nullptr));
-          case Expr::F64ConvertSI64:
-          case Expr::F64ConvertUI64:
-          case Expr::F64ReinterpretI64:
+          case uint16_t(Expr::F64ConvertSI64):
+          case uint16_t(Expr::F64ConvertUI64):
+          case uint16_t(Expr::F64ReinterpretI64):
             CHECK(f.iter().readConversion(ValType::I64, ValType::F64, nullptr));
-          case Expr::F64PromoteF32:
+          case uint16_t(Expr::F64PromoteF32):
             CHECK(f.iter().readConversion(ValType::F32, ValType::F64, nullptr));
-          case Expr::I32Load8S:
-          case Expr::I32Load8U:
+          case uint16_t(Expr::I32Load8S):
+          case uint16_t(Expr::I32Load8U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 1, nullptr));
-          case Expr::I32Load16S:
-          case Expr::I32Load16U:
+          case uint16_t(Expr::I32Load16S):
+          case uint16_t(Expr::I32Load16U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 2, nullptr));
-          case Expr::I32Load:
+          case uint16_t(Expr::I32Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I32, 4, nullptr));
-          case Expr::I64Load8S:
-          case Expr::I64Load8U:
+          case uint16_t(Expr::I64Load8S):
+          case uint16_t(Expr::I64Load8U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 1, nullptr));
-          case Expr::I64Load16S:
-          case Expr::I64Load16U:
+          case uint16_t(Expr::I64Load16S):
+          case uint16_t(Expr::I64Load16U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 2, nullptr));
-          case Expr::I64Load32S:
-          case Expr::I64Load32U:
+          case uint16_t(Expr::I64Load32S):
+          case uint16_t(Expr::I64Load32U):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 4, nullptr));
-          case Expr::I64Load:
+          case uint16_t(Expr::I64Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::I64, 8, nullptr));
-          case Expr::F32Load:
+          case uint16_t(Expr::F32Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::F32, 4, nullptr));
-          case Expr::F64Load:
+          case uint16_t(Expr::F64Load):
             CHECK(f.checkHasMemory() && f.iter().readLoad(ValType::F64, 8, nullptr));
-          case Expr::I32Store8:
+          case uint16_t(Expr::I32Store8):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 1, nullptr, nullptr));
-          case Expr::I32Store16:
+          case uint16_t(Expr::I32Store16):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 2, nullptr, nullptr));
-          case Expr::I32Store:
+          case uint16_t(Expr::I32Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I32, 4, nullptr, nullptr));
-          case Expr::I64Store8:
+          case uint16_t(Expr::I64Store8):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 1, nullptr, nullptr));
-          case Expr::I64Store16:
+          case uint16_t(Expr::I64Store16):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 2, nullptr, nullptr));
-          case Expr::I64Store32:
+          case uint16_t(Expr::I64Store32):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 4, nullptr, nullptr));
-          case Expr::I64Store:
+          case uint16_t(Expr::I64Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::I64, 8, nullptr, nullptr));
-          case Expr::F32Store:
+          case uint16_t(Expr::F32Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::F32, 4, nullptr, nullptr));
-          case Expr::F64Store:
+          case uint16_t(Expr::F64Store):
             CHECK(f.checkHasMemory() && f.iter().readStore(ValType::F64, 8, nullptr, nullptr));
-          case Expr::GrowMemory:
+          case uint16_t(Expr::GrowMemory):
             CHECK(f.checkHasMemory() && f.iter().readGrowMemory(nullptr));
-          case Expr::CurrentMemory:
+          case uint16_t(Expr::CurrentMemory):
             CHECK(f.checkHasMemory() && f.iter().readCurrentMemory());
-          case Expr::Br:
+          case uint16_t(Expr::Br):
             CHECK(f.iter().readBr(nullptr, nullptr, nullptr));
-          case Expr::BrIf:
+          case uint16_t(Expr::BrIf):
             CHECK(f.iter().readBrIf(nullptr, nullptr, nullptr, nullptr));
-          case Expr::BrTable:
+          case uint16_t(Expr::BrTable):
             CHECK(DecodeBrTable(f));
-          case Expr::Return:
+          case uint16_t(Expr::Return):
             CHECK(f.iter().readReturn(nullptr));
-          case Expr::Unreachable:
+          case uint16_t(Expr::Unreachable):
             CHECK(f.iter().readUnreachable());
           default:
             return f.iter().unrecognizedOpcode(expr);
         }
     }
 
     MOZ_CRASH("unreachable");
 
@@ -665,23 +665,18 @@ DecodeFunctionBody(Decoder& d, ModuleGen
     if (!mg.startFuncDef(offsetInModule, &fg))
         return false;
 
     ValTypeVector locals;
     const Sig& sig = mg.funcSig(funcIndex);
     if (!locals.appendAll(sig.args()))
         return false;
 
-    if (!DecodeLocalEntries(d, &locals))
-        return d.fail("failed decoding local entries");
-
-    for (ValType type : locals) {
-        if (!CheckValType(d, type))
-            return false;
-    }
+    if (!DecodeLocalEntries(d, ModuleKind::Wasm, &locals))
+        return false;
 
     FunctionDecoder f(mg, locals, d);
 
     if (!f.iter().readFunctionStart(sig.ret()))
         return false;
 
     if (!DecodeFunctionBodyExprs(f))
         return false;
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -3095,19 +3095,19 @@ EmitCurrentMemory(FunctionCompiler& f)
 }
 
 static bool
 EmitExpr(FunctionCompiler& f)
 {
     if (!f.mirGen().ensureBallast())
         return false;
 
-    Expr expr;
-    if (!f.iter().readExpr(&expr))
-        return false;
+    uint16_t u16;
+    MOZ_ALWAYS_TRUE(f.iter().readExpr(&u16));
+    Expr expr = Expr(u16);
 
     switch (expr) {
       // Control opcodes
       case Expr::Nop:
         return f.iter().readNop();
       case Expr::Drop:
         return f.iter().readDrop();
       case Expr::Block:
@@ -3706,17 +3706,17 @@ wasm::IonCompileFunction(IonCompileTask*
 
     Decoder d(func.bytes());
 
     // Build the local types vector.
 
     ValTypeVector locals;
     if (!locals.appendAll(func.sig().args()))
         return false;
-    if (!DecodeLocalEntries(d, &locals))
+    if (!DecodeLocalEntries(d, task->mg().kind, &locals))
         return false;
 
     // Set up for Ion compilation.
 
     JitContext jitContext(&results.alloc());
     const JitCompileOptions options;
     MIRGraph graph(&results.alloc());
     CompileInfo compileInfo(locals.length());
--- a/js/src/wasm/WasmTypes.h
+++ b/js/src/wasm/WasmTypes.h
@@ -254,17 +254,17 @@ ToMIRType(ValType vt)
     MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad type");
 }
 
 // The ExprType enum represents the type of a WebAssembly expression or return
 // value and may either be a value type or void. Soon, expression types will be
 // generalized to a list of ValType and this enum will go away, replaced,
 // wherever it is used, by a varU32 + list of ValType.
 
-enum class ExprType : uint32_t // fix type so we can cast from any u8 in decoder
+enum class ExprType
 {
     Void  = uint8_t(TypeCode::BlockVoid),
 
     I32   = uint8_t(TypeCode::I32),
     I64   = uint8_t(TypeCode::I64),
     F32   = uint8_t(TypeCode::F32),
     F64   = uint8_t(TypeCode::F64),