Bug 1316651 - Baldr: change decoding of enumerated values (r=sunfish)
authorLuke Wagner <luke@mozilla.com>
Fri, 11 Nov 2016 13:52:10 -0600
changeset 352329 8a0300ec29c9e7523c62263eb9e98d89c23739b1
parent 352328 a3fbd5543a77e9a3ba8b2aa86fe16034b8fad340
child 352330 52a2f468a31c73eed841e91a4a68fcb35ae645c5
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1316651
milestone52.0a1
Bug 1316651 - Baldr: 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),