mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset cfb447308e8a (bug 1241454) for bustage on a CLOSED TREE
This commit is contained in:
parent
0021043626
commit
0aef8e65b5
@ -1082,10 +1082,17 @@ class Type
|
|||||||
MOZ_IMPLICIT Type(Which w) : which_(w) {}
|
MOZ_IMPLICIT Type(Which w) : which_(w) {}
|
||||||
MOZ_IMPLICIT Type(SimdType type) {
|
MOZ_IMPLICIT Type(SimdType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SimdType::Int32x4: which_ = Int32x4; return;
|
case SimdType::Int32x4:
|
||||||
case SimdType::Float32x4: which_ = Float32x4; return;
|
which_ = Int32x4;
|
||||||
case SimdType::Bool32x4: which_ = Bool32x4; return;
|
return;
|
||||||
default: break;
|
case SimdType::Float32x4:
|
||||||
|
which_ = Float32x4;
|
||||||
|
return;
|
||||||
|
case SimdType::Bool32x4:
|
||||||
|
which_ = Bool32x4;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad SimdType");
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("bad SimdType");
|
||||||
}
|
}
|
||||||
@ -2294,18 +2301,6 @@ IsCallToGlobal(ModuleValidator& m, ParseNode* pn, const ModuleValidator::Global*
|
|||||||
return !!*global;
|
return !!*global;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValType
|
|
||||||
ToValType(SimdType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case SimdType::Int32x4: return ValType::I32x4;
|
|
||||||
case SimdType::Float32x4: return ValType::F32x4;
|
|
||||||
case SimdType::Bool32x4: return ValType::B32x4;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
MOZ_CRASH("unexpected SIMD type");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsCoercionCall(ModuleValidator& m, ParseNode* pn, ValType* coerceTo, ParseNode** coercedExpr)
|
IsCoercionCall(ModuleValidator& m, ParseNode* pn, ValType* coerceTo, ParseNode** coercedExpr)
|
||||||
{
|
{
|
||||||
@ -2325,8 +2320,19 @@ IsCoercionCall(ModuleValidator& m, ParseNode* pn, ValType* coerceTo, ParseNode**
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (global->isSimdOperation() && global->simdOperation() == SimdOperation::Fn_check) {
|
if (global->isSimdOperation() && global->simdOperation() == SimdOperation::Fn_check) {
|
||||||
*coerceTo = ToValType(global->simdOperationType());
|
switch (global->simdOperationType()) {
|
||||||
return true;
|
case SimdType::Int32x4:
|
||||||
|
*coerceTo = ValType::I32x4;
|
||||||
|
return true;
|
||||||
|
case SimdType::Float32x4:
|
||||||
|
*coerceTo = ValType::F32x4;
|
||||||
|
return true;
|
||||||
|
case SimdType::Bool32x4:
|
||||||
|
*coerceTo = ValType::B32x4;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("unexpected SIMD type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -2721,16 +2727,6 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||||||
bool writeOp(Expr op) {
|
bool writeOp(Expr op) {
|
||||||
return encoder().writeExpr(op);
|
return encoder().writeExpr(op);
|
||||||
}
|
}
|
||||||
MOZ_WARN_UNUSED_RESULT
|
|
||||||
bool writeExprType(ExprType type) {
|
|
||||||
return encoder().writeExprType(type);
|
|
||||||
}
|
|
||||||
MOZ_WARN_UNUSED_RESULT
|
|
||||||
bool writeSimdOp(SimdType simdType, SimdOperation op) {
|
|
||||||
return writeOp(Expr::SimdOp) &&
|
|
||||||
encoder().writeExprType(ToExprType(simdType)) &&
|
|
||||||
encoder().writeSimdOp(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_WARN_UNUSED_RESULT
|
MOZ_WARN_UNUSED_RESULT
|
||||||
bool writeDebugCheckPoint() {
|
bool writeDebugCheckPoint() {
|
||||||
@ -2773,15 +2769,12 @@ class MOZ_STACK_CLASS FunctionValidator
|
|||||||
case NumLit::Double:
|
case NumLit::Double:
|
||||||
return writeOp(Expr::F64Const) && encoder().writeF64(lit.toDouble());
|
return writeOp(Expr::F64Const) && encoder().writeF64(lit.toDouble());
|
||||||
case NumLit::Int32x4:
|
case NumLit::Int32x4:
|
||||||
return writeOp(Expr::SimdConst) && writeExprType(ExprType::I32x4) &&
|
return writeOp(Expr::I32X4Const) && encoder().writeI32X4(lit.simdValue().asInt32x4());
|
||||||
encoder().writeI32X4(lit.simdValue().asInt32x4());
|
|
||||||
case NumLit::Float32x4:
|
case NumLit::Float32x4:
|
||||||
return writeOp(Expr::SimdConst) && writeExprType(ExprType::F32x4) &&
|
return writeOp(Expr::F32X4Const) && encoder().writeF32X4(lit.simdValue().asFloat32x4());
|
||||||
encoder().writeF32X4(lit.simdValue().asFloat32x4());
|
|
||||||
case NumLit::Bool32x4:
|
case NumLit::Bool32x4:
|
||||||
// Boolean vectors use the Int32x4 memory representation.
|
// Boolean vectors use the Int32x4 memory representation.
|
||||||
return writeOp(Expr::SimdConst) && writeExprType(ExprType::B32x4) &&
|
return writeOp(Expr::B32X4Const) && encoder().writeI32X4(lit.simdValue().asInt32x4());
|
||||||
encoder().writeI32X4(lit.simdValue().asInt32x4());
|
|
||||||
case NumLit::OutOfRangeInt:
|
case NumLit::OutOfRangeInt:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4948,10 +4941,24 @@ class CheckSimdReplaceLaneArgs
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdUnary(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
SwitchPackOp(FunctionValidator& f, SimdType type, Expr i32x4, Expr f32x4, Expr b32x4)
|
||||||
Type* type)
|
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, op))
|
switch (type) {
|
||||||
|
case SimdType::Int32x4: return f.writeOp(i32x4);
|
||||||
|
case SimdType::Float32x4: return f.writeOp(f32x4);
|
||||||
|
case SimdType::Bool32x4: return f.writeOp(b32x4);
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
MOZ_CRASH("unexpected simd type");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckSimdUnary(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
|
MSimdUnaryArith::Operation op, Type* type)
|
||||||
|
{
|
||||||
|
if (!SwitchPackOp(f, opType, Expr::I32X4Unary, Expr::F32X4Unary, Expr::B32X4Unary))
|
||||||
|
return false;
|
||||||
|
if (!f.writeU8(uint8_t(op)))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
||||||
return false;
|
return false;
|
||||||
@ -4959,23 +4966,54 @@ CheckSimdUnary(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOpera
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
template<class OpKind>
|
||||||
CheckSimdBinaryShift(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
inline bool
|
||||||
Type *type)
|
CheckSimdBinaryGuts(FunctionValidator& f, ParseNode* call, SimdType opType, OpKind op,
|
||||||
|
Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, op))
|
if (!f.writeU8(uint8_t(op)))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(opType)))
|
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType)))
|
||||||
return false;
|
return false;
|
||||||
*type = Type::Int32x4;
|
*type = opType;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdBinaryComp(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
CheckSimdBinary(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
Type *type)
|
MSimdBinaryArith::Operation op, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, op))
|
return SwitchPackOp(f, opType, Expr::I32X4Binary, Expr::F32X4Binary, Expr::B32X4Binary) &&
|
||||||
|
CheckSimdBinaryGuts(f, call, opType, op, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckSimdBinary(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
|
MSimdBinaryBitwise::Operation op, Type* type)
|
||||||
|
{
|
||||||
|
return SwitchPackOp(f, opType, Expr::I32X4BinaryBitwise, Expr::Unreachable, Expr::B32X4BinaryBitwise) &&
|
||||||
|
CheckSimdBinaryGuts(f, call, opType, op, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CheckSimdBinary(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
|
MSimdBinaryComp::Operation op, Type* type)
|
||||||
|
{
|
||||||
|
switch (opType) {
|
||||||
|
case SimdType::Int32x4:
|
||||||
|
if (!f.writeOp(Expr::B32X4BinaryCompI32X4))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case SimdType::Float32x4:
|
||||||
|
if (!f.writeOp(Expr::B32X4BinaryCompF32X4))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case SimdType::Bool32x4:
|
||||||
|
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Can't compare boolean vectors");
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("unhandled SIMD type");
|
||||||
|
}
|
||||||
|
if (!f.writeU8(uint8_t(op)))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType)))
|
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType)))
|
||||||
return false;
|
return false;
|
||||||
@ -4984,27 +5022,38 @@ CheckSimdBinaryComp(FunctionValidator& f, ParseNode* call, SimdType opType, Simd
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdBinary(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
CheckSimdBinary(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
Type* type)
|
MSimdShift::Operation op, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, op))
|
if (!f.writeOp(Expr::I32X4BinaryShift) || !f.writeU8(uint8_t(op)))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(opType)))
|
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorScalarArgs(opType)))
|
||||||
return false;
|
return false;
|
||||||
*type = opType;
|
*type = Type::Int32x4;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdExtractLane(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdExtractLane(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_extractLane))
|
|
||||||
return false;
|
|
||||||
switch (opType) {
|
switch (opType) {
|
||||||
case SimdType::Int32x4: *type = Type::Signed; break;
|
case SimdType::Int32x4:
|
||||||
case SimdType::Float32x4: *type = Type::Float; break;
|
if (!f.writeOp(Expr::I32I32X4ExtractLane))
|
||||||
case SimdType::Bool32x4: *type = Type::Int; break;
|
return false;
|
||||||
default: MOZ_CRASH("unhandled simd type");
|
*type = Type::Signed;
|
||||||
|
break;
|
||||||
|
case SimdType::Float32x4:
|
||||||
|
if (!f.writeOp(Expr::F32F32X4ExtractLane))
|
||||||
|
return false;
|
||||||
|
*type = Type::Float;
|
||||||
|
break;
|
||||||
|
case SimdType::Bool32x4:
|
||||||
|
if (!f.writeOp(Expr::I32B32X4ExtractLane))
|
||||||
|
return false;
|
||||||
|
*type = Type::Int;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("unhandled simd type");
|
||||||
}
|
}
|
||||||
return CheckSimdCallArgs(f, call, 2, CheckSimdExtractLaneArgs(opType));
|
return CheckSimdCallArgs(f, call, 2, CheckSimdExtractLaneArgs(opType));
|
||||||
}
|
}
|
||||||
@ -5012,7 +5061,7 @@ CheckSimdExtractLane(FunctionValidator& f, ParseNode* call, SimdType opType, Typ
|
|||||||
static bool
|
static bool
|
||||||
CheckSimdReplaceLane(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdReplaceLane(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_replaceLane))
|
if (!SwitchPackOp(f, opType, Expr::I32X4ReplaceLane, Expr::F32X4ReplaceLane, Expr::B32X4ReplaceLane))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgsPatchable(f, call, 3, CheckSimdReplaceLaneArgs(opType)))
|
if (!CheckSimdCallArgsPatchable(f, call, 3, CheckSimdReplaceLaneArgs(opType)))
|
||||||
return false;
|
return false;
|
||||||
@ -5020,17 +5069,22 @@ CheckSimdReplaceLane(FunctionValidator& f, ParseNode* call, SimdType opType, Typ
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool Bitcast;
|
typedef bool IsBitCast;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Include CheckSimdCast in unnamed namespace to avoid MSVC name lookup bug (due to the use of Type).
|
// Include CheckSimdCast in unnamed namespace to avoid MSVC name lookup bug (due to the use of Type).
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdCast(FunctionValidator& f, ParseNode* call, SimdType fromType, SimdType toType,
|
CheckSimdCast(FunctionValidator& f, ParseNode* call, SimdType fromType, SimdType toType,
|
||||||
SimdOperation op, Type* type)
|
bool bitcast, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(toType, op))
|
if (!SwitchPackOp(f, toType,
|
||||||
|
bitcast ? Expr::I32X4FromF32X4Bits : Expr::I32X4FromF32X4,
|
||||||
|
bitcast ? Expr::F32X4FromI32X4Bits : Expr::F32X4FromI32X4,
|
||||||
|
Expr::Unreachable))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(fromType)))
|
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(fromType)))
|
||||||
return false;
|
return false;
|
||||||
*type = toType;
|
*type = toType;
|
||||||
@ -5060,7 +5114,7 @@ CheckSimdSwizzle(FunctionValidator& f, ParseNode* call, SimdType opType, Type* t
|
|||||||
if (numArgs != 5)
|
if (numArgs != 5)
|
||||||
return f.failf(call, "expected 5 arguments to SIMD swizzle, got %u", numArgs);
|
return f.failf(call, "expected 5 arguments to SIMD swizzle, got %u", numArgs);
|
||||||
|
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_swizzle))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Swizzle, Expr::F32X4Swizzle, Expr::Unreachable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type retType = opType;
|
Type retType = opType;
|
||||||
@ -5091,7 +5145,7 @@ CheckSimdShuffle(FunctionValidator& f, ParseNode* call, SimdType opType, Type* t
|
|||||||
if (numArgs != 6)
|
if (numArgs != 6)
|
||||||
return f.failf(call, "expected 6 arguments to SIMD shuffle, got %u", numArgs);
|
return f.failf(call, "expected 6 arguments to SIMD shuffle, got %u", numArgs);
|
||||||
|
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_shuffle))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Shuffle, Expr::F32X4Shuffle, Expr::Unreachable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type retType = opType;
|
Type retType = opType;
|
||||||
@ -5118,7 +5172,8 @@ CheckSimdShuffle(FunctionValidator& f, ParseNode* call, SimdType opType, Type* t
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdLoadStoreArgs(FunctionValidator& f, ParseNode* call)
|
CheckSimdLoadStoreArgs(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
|
Scalar::Type* viewType, NeedsBoundsCheck* needsBoundsCheck)
|
||||||
{
|
{
|
||||||
ParseNode* view = CallArgList(call);
|
ParseNode* view = CallArgList(call);
|
||||||
if (!view->isKind(PNK_NAME))
|
if (!view->isKind(PNK_NAME))
|
||||||
@ -5132,16 +5187,24 @@ CheckSimdLoadStoreArgs(FunctionValidator& f, ParseNode* call)
|
|||||||
return f.fail(view, "expected Uint8Array view as SIMD.*.load/store first argument");
|
return f.fail(view, "expected Uint8Array view as SIMD.*.load/store first argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*needsBoundsCheck = NEEDS_BOUNDS_CHECK;
|
||||||
|
|
||||||
|
switch (opType) {
|
||||||
|
case SimdType::Int32x4: *viewType = Scalar::Int32x4; break;
|
||||||
|
case SimdType::Float32x4: *viewType = Scalar::Float32x4; break;
|
||||||
|
case SimdType::Bool32x4: MOZ_CRASH("Cannot load/store boolean SIMD type");
|
||||||
|
default: MOZ_CRASH("unhandled SIMD type");
|
||||||
|
}
|
||||||
|
|
||||||
ParseNode* indexExpr = NextNode(view);
|
ParseNode* indexExpr = NextNode(view);
|
||||||
uint32_t indexLit;
|
uint32_t indexLit;
|
||||||
if (IsLiteralOrConstInt(f, indexExpr, &indexLit)) {
|
if (IsLiteralOrConstInt(f, indexExpr, &indexLit)) {
|
||||||
if (!f.m().tryConstantAccess(indexLit, Simd128DataSize))
|
if (!f.m().tryConstantAccess(indexLit, Simd128DataSize))
|
||||||
return f.fail(indexExpr, "constant index out of range");
|
return f.fail(indexExpr, "constant index out of range");
|
||||||
return f.writeU8(NO_BOUNDS_CHECK) && f.writeInt32Lit(indexLit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!f.writeU8(NEEDS_BOUNDS_CHECK))
|
*needsBoundsCheck = NO_BOUNDS_CHECK;
|
||||||
return false;
|
return f.writeInt32Lit(indexLit);
|
||||||
|
}
|
||||||
|
|
||||||
Type indexType;
|
Type indexType;
|
||||||
if (!CheckExpr(f, indexExpr, &indexType))
|
if (!CheckExpr(f, indexExpr, &indexType))
|
||||||
@ -5154,35 +5217,52 @@ CheckSimdLoadStoreArgs(FunctionValidator& f, ParseNode* call)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdLoad(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
CheckSimdLoad(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
Type* type)
|
unsigned numElems, Type* type)
|
||||||
{
|
{
|
||||||
unsigned numArgs = CallArgListLength(call);
|
unsigned numArgs = CallArgListLength(call);
|
||||||
if (numArgs != 2)
|
if (numArgs != 2)
|
||||||
return f.failf(call, "expected 2 arguments to SIMD load, got %u", numArgs);
|
return f.failf(call, "expected 2 arguments to SIMD load, got %u", numArgs);
|
||||||
|
|
||||||
if (!f.writeSimdOp(opType, op))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Load, Expr::F32X4Load, Expr::Unreachable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CheckSimdLoadStoreArgs(f, call))
|
size_t viewTypeAt;
|
||||||
|
size_t needsBoundsCheckAt;
|
||||||
|
if (!f.tempU8(&viewTypeAt) || !f.tempU8(&needsBoundsCheckAt) || !f.writeU8(numElems))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Scalar::Type viewType;
|
||||||
|
NeedsBoundsCheck needsBoundsCheck;
|
||||||
|
if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &needsBoundsCheck))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
f.patchU8(needsBoundsCheckAt, uint8_t(needsBoundsCheck));
|
||||||
|
f.patchU8(viewTypeAt, uint8_t(viewType));
|
||||||
|
|
||||||
*type = opType;
|
*type = opType;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckSimdStore(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOperation op,
|
CheckSimdStore(FunctionValidator& f, ParseNode* call, SimdType opType,
|
||||||
Type* type)
|
unsigned numElems, Type* type)
|
||||||
{
|
{
|
||||||
unsigned numArgs = CallArgListLength(call);
|
unsigned numArgs = CallArgListLength(call);
|
||||||
if (numArgs != 3)
|
if (numArgs != 3)
|
||||||
return f.failf(call, "expected 3 arguments to SIMD store, got %u", numArgs);
|
return f.failf(call, "expected 3 arguments to SIMD store, got %u", numArgs);
|
||||||
|
|
||||||
if (!f.writeSimdOp(opType, op))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Store, Expr::F32X4Store, Expr::Unreachable))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CheckSimdLoadStoreArgs(f, call))
|
size_t viewTypeAt;
|
||||||
|
size_t needsBoundsCheckAt;
|
||||||
|
if (!f.tempU8(&viewTypeAt) || !f.tempU8(&needsBoundsCheckAt) || !f.writeU8(numElems))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Scalar::Type viewType;
|
||||||
|
NeedsBoundsCheck needsBoundsCheck;
|
||||||
|
if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &needsBoundsCheck))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type retType = opType;
|
Type retType = opType;
|
||||||
@ -5190,10 +5270,12 @@ CheckSimdStore(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOpera
|
|||||||
Type vecType;
|
Type vecType;
|
||||||
if (!CheckExpr(f, vecExpr, &vecType))
|
if (!CheckExpr(f, vecExpr, &vecType))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!(vecType <= retType))
|
if (!(vecType <= retType))
|
||||||
return f.failf(vecExpr, "%s is not a subtype of %s", vecType.toChars(), retType.toChars());
|
return f.failf(vecExpr, "%s is not a subtype of %s", vecType.toChars(), retType.toChars());
|
||||||
|
|
||||||
|
f.patchU8(needsBoundsCheckAt, uint8_t(needsBoundsCheck));
|
||||||
|
f.patchU8(viewTypeAt, uint8_t(viewType));
|
||||||
|
|
||||||
*type = vecType;
|
*type = vecType;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5201,7 +5283,7 @@ CheckSimdStore(FunctionValidator& f, ParseNode* call, SimdType opType, SimdOpera
|
|||||||
static bool
|
static bool
|
||||||
CheckSimdSelect(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdSelect(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_select))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Select, Expr::F32X4Select, Expr::Unreachable))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(opType)))
|
if (!CheckSimdCallArgs(f, call, 3, CheckSimdSelectArgs(opType)))
|
||||||
return false;
|
return false;
|
||||||
@ -5212,8 +5294,17 @@ CheckSimdSelect(FunctionValidator& f, ParseNode* call, SimdType opType, Type* ty
|
|||||||
static bool
|
static bool
|
||||||
CheckSimdAllTrue(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdAllTrue(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_allTrue))
|
switch (opType) {
|
||||||
return false;
|
case SimdType::Bool32x4:
|
||||||
|
if (!f.writeOp(Expr::I32B32X4AllTrue))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case SimdType::Int32x4:
|
||||||
|
case SimdType::Float32x4:
|
||||||
|
MOZ_CRASH("allTrue is only defined on bool SIMD types");
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("unhandled SIMD type");
|
||||||
|
}
|
||||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
||||||
return false;
|
return false;
|
||||||
*type = Type::Int;
|
*type = Type::Int;
|
||||||
@ -5223,8 +5314,16 @@ CheckSimdAllTrue(FunctionValidator& f, ParseNode* call, SimdType opType, Type* t
|
|||||||
static bool
|
static bool
|
||||||
CheckSimdAnyTrue(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdAnyTrue(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_anyTrue))
|
switch (opType) {
|
||||||
return false;
|
case SimdType::Bool32x4:
|
||||||
|
if (!f.writeOp(Expr::I32B32X4AnyTrue))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case SimdType::Int32x4:
|
||||||
|
case SimdType::Float32x4:
|
||||||
|
MOZ_CRASH("anyTrue is only defined on bool SIMD types");
|
||||||
|
default: MOZ_CRASH("unhandled simd type");
|
||||||
|
}
|
||||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(opType)))
|
||||||
return false;
|
return false;
|
||||||
*type = Type::Int;
|
*type = Type::Int;
|
||||||
@ -5244,7 +5343,7 @@ CheckSimdCheck(FunctionValidator& f, ParseNode* call, SimdType opType, Type* typ
|
|||||||
static bool
|
static bool
|
||||||
CheckSimdSplat(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
CheckSimdSplat(FunctionValidator& f, ParseNode* call, SimdType opType, Type* type)
|
||||||
{
|
{
|
||||||
if (!f.writeSimdOp(opType, SimdOperation::Fn_splat))
|
if (!SwitchPackOp(f, opType, Expr::I32X4Splat, Expr::F32X4Splat, Expr::B32X4Splat))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckSimdCallArgsPatchable(f, call, 1, CheckSimdScalarArgs(opType)))
|
if (!CheckSimdCallArgsPatchable(f, call, 1, CheckSimdScalarArgs(opType)))
|
||||||
return false;
|
return false;
|
||||||
@ -5260,22 +5359,36 @@ CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValida
|
|||||||
|
|
||||||
SimdType opType = global->simdOperationType();
|
SimdType opType = global->simdOperationType();
|
||||||
|
|
||||||
switch (SimdOperation op = global->simdOperation()) {
|
switch (global->simdOperation()) {
|
||||||
case SimdOperation::Fn_check:
|
case SimdOperation::Fn_check:
|
||||||
return CheckSimdCheck(f, call, opType, type);
|
return CheckSimdCheck(f, call, opType, type);
|
||||||
|
|
||||||
#define _CASE(OP) case SimdOperation::Fn_##OP:
|
#define OP_CHECK_CASE_LIST_(OP) \
|
||||||
FOREACH_SHIFT_SIMD_OP(_CASE)
|
case SimdOperation::Fn_##OP: \
|
||||||
return CheckSimdBinaryShift(f, call, opType, op, type);
|
return CheckSimdBinary(f, call, opType, MSimdBinaryArith::Op_##OP, type);
|
||||||
|
FOREACH_NUMERIC_SIMD_BINOP(OP_CHECK_CASE_LIST_)
|
||||||
|
FOREACH_FLOAT_SIMD_BINOP(OP_CHECK_CASE_LIST_)
|
||||||
|
#undef OP_CHECK_CASE_LIST_
|
||||||
|
|
||||||
FOREACH_COMP_SIMD_OP(_CASE)
|
case SimdOperation::Fn_lessThan:
|
||||||
return CheckSimdBinaryComp(f, call, opType, op, type);
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThan, type);
|
||||||
|
case SimdOperation::Fn_lessThanOrEqual:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::lessThanOrEqual, type);
|
||||||
|
case SimdOperation::Fn_equal:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::equal, type);
|
||||||
|
case SimdOperation::Fn_notEqual:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::notEqual, type);
|
||||||
|
case SimdOperation::Fn_greaterThan:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::greaterThan, type);
|
||||||
|
case SimdOperation::Fn_greaterThanOrEqual:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryComp::greaterThanOrEqual, type);
|
||||||
|
|
||||||
FOREACH_NUMERIC_SIMD_BINOP(_CASE)
|
case SimdOperation::Fn_and:
|
||||||
FOREACH_FLOAT_SIMD_BINOP(_CASE)
|
return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::and_, type);
|
||||||
FOREACH_BITWISE_SIMD_BINOP(_CASE)
|
case SimdOperation::Fn_or:
|
||||||
return CheckSimdBinary(f, call, opType, op, type);
|
return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::or_, type);
|
||||||
#undef _CASE
|
case SimdOperation::Fn_xor:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdBinaryBitwise::xor_, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_extractLane:
|
case SimdOperation::Fn_extractLane:
|
||||||
return CheckSimdExtractLane(f, call, opType, type);
|
return CheckSimdExtractLane(f, call, opType, type);
|
||||||
@ -5283,19 +5396,37 @@ CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValida
|
|||||||
return CheckSimdReplaceLane(f, call, opType, type);
|
return CheckSimdReplaceLane(f, call, opType, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_fromInt32x4:
|
case SimdOperation::Fn_fromInt32x4:
|
||||||
case SimdOperation::Fn_fromInt32x4Bits:
|
return CheckSimdCast(f, call, SimdType::Int32x4, opType, IsBitCast(false), type);
|
||||||
return CheckSimdCast(f, call, SimdType::Int32x4, opType, op, type);
|
|
||||||
case SimdOperation::Fn_fromFloat32x4:
|
case SimdOperation::Fn_fromFloat32x4:
|
||||||
|
return CheckSimdCast(f, call, SimdType::Float32x4, opType, IsBitCast(false), type);
|
||||||
|
case SimdOperation::Fn_fromInt32x4Bits:
|
||||||
|
return CheckSimdCast(f, call, SimdType::Int32x4, opType, IsBitCast(true), type);
|
||||||
case SimdOperation::Fn_fromFloat32x4Bits:
|
case SimdOperation::Fn_fromFloat32x4Bits:
|
||||||
return CheckSimdCast(f, call, SimdType::Float32x4, opType, op, type);
|
return CheckSimdCast(f, call, SimdType::Float32x4, opType, IsBitCast(true), type);
|
||||||
|
|
||||||
|
case SimdOperation::Fn_shiftLeftByScalar:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdShift::lsh, type);
|
||||||
|
case SimdOperation::Fn_shiftRightByScalar:
|
||||||
|
return CheckSimdBinary(f, call, opType,
|
||||||
|
IsSignedIntSimdType(opType) ? MSimdShift::rsh : MSimdShift::ursh,
|
||||||
|
type);
|
||||||
|
case SimdOperation::Fn_shiftRightArithmeticByScalar:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdShift::rsh, type);
|
||||||
|
case SimdOperation::Fn_shiftRightLogicalByScalar:
|
||||||
|
return CheckSimdBinary(f, call, opType, MSimdShift::ursh, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_abs:
|
case SimdOperation::Fn_abs:
|
||||||
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::abs, type);
|
||||||
case SimdOperation::Fn_neg:
|
case SimdOperation::Fn_neg:
|
||||||
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::neg, type);
|
||||||
case SimdOperation::Fn_not:
|
case SimdOperation::Fn_not:
|
||||||
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::not_, type);
|
||||||
case SimdOperation::Fn_sqrt:
|
case SimdOperation::Fn_sqrt:
|
||||||
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::sqrt, type);
|
||||||
case SimdOperation::Fn_reciprocalApproximation:
|
case SimdOperation::Fn_reciprocalApproximation:
|
||||||
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::reciprocalApproximation, type);
|
||||||
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
||||||
return CheckSimdUnary(f, call, opType, op, type);
|
return CheckSimdUnary(f, call, opType, MSimdUnaryArith::reciprocalSqrtApproximation, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_swizzle:
|
case SimdOperation::Fn_swizzle:
|
||||||
return CheckSimdSwizzle(f, call, opType, type);
|
return CheckSimdSwizzle(f, call, opType, type);
|
||||||
@ -5303,15 +5434,21 @@ CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValida
|
|||||||
return CheckSimdShuffle(f, call, opType, type);
|
return CheckSimdShuffle(f, call, opType, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_load:
|
case SimdOperation::Fn_load:
|
||||||
|
return CheckSimdLoad(f, call, opType, 4, type);
|
||||||
case SimdOperation::Fn_load1:
|
case SimdOperation::Fn_load1:
|
||||||
|
return CheckSimdLoad(f, call, opType, 1, type);
|
||||||
case SimdOperation::Fn_load2:
|
case SimdOperation::Fn_load2:
|
||||||
|
return CheckSimdLoad(f, call, opType, 2, type);
|
||||||
case SimdOperation::Fn_load3:
|
case SimdOperation::Fn_load3:
|
||||||
return CheckSimdLoad(f, call, opType, op, type);
|
return CheckSimdLoad(f, call, opType, 3, type);
|
||||||
case SimdOperation::Fn_store:
|
case SimdOperation::Fn_store:
|
||||||
|
return CheckSimdStore(f, call, opType, 4, type);
|
||||||
case SimdOperation::Fn_store1:
|
case SimdOperation::Fn_store1:
|
||||||
|
return CheckSimdStore(f, call, opType, 1, type);
|
||||||
case SimdOperation::Fn_store2:
|
case SimdOperation::Fn_store2:
|
||||||
|
return CheckSimdStore(f, call, opType, 2, type);
|
||||||
case SimdOperation::Fn_store3:
|
case SimdOperation::Fn_store3:
|
||||||
return CheckSimdStore(f, call, opType, op, type);
|
return CheckSimdStore(f, call, opType, 3, type);
|
||||||
|
|
||||||
case SimdOperation::Fn_select:
|
case SimdOperation::Fn_select:
|
||||||
return CheckSimdSelect(f, call, opType, type);
|
return CheckSimdSelect(f, call, opType, type);
|
||||||
@ -5325,7 +5462,7 @@ CheckSimdOperationCall(FunctionValidator& f, ParseNode* call, const ModuleValida
|
|||||||
return CheckSimdAnyTrue(f, call, opType, type);
|
return CheckSimdAnyTrue(f, call, opType, type);
|
||||||
|
|
||||||
case SimdOperation::Constructor:
|
case SimdOperation::Constructor:
|
||||||
MOZ_CRASH("constructors are handled in CheckSimdCtorCall");
|
MOZ_CRASH("constructors are handled elsewhere");
|
||||||
case SimdOperation::Fn_fromUint32x4:
|
case SimdOperation::Fn_fromUint32x4:
|
||||||
case SimdOperation::Fn_fromInt8x16Bits:
|
case SimdOperation::Fn_fromInt8x16Bits:
|
||||||
case SimdOperation::Fn_fromInt16x8Bits:
|
case SimdOperation::Fn_fromInt16x8Bits:
|
||||||
@ -5345,7 +5482,7 @@ CheckSimdCtorCall(FunctionValidator& f, ParseNode* call, const ModuleValidator::
|
|||||||
MOZ_ASSERT(call->isKind(PNK_CALL));
|
MOZ_ASSERT(call->isKind(PNK_CALL));
|
||||||
|
|
||||||
SimdType simdType = global->simdCtorType();
|
SimdType simdType = global->simdCtorType();
|
||||||
if (!f.writeSimdOp(simdType, SimdOperation::Constructor))
|
if (!SwitchPackOp(f, simdType, Expr::I32X4Ctor, Expr::F32X4Ctor, Expr::B32X4Ctor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned length = SimdTypeToLength(simdType);
|
unsigned length = SimdTypeToLength(simdType);
|
||||||
|
@ -25,8 +25,6 @@ namespace js {
|
|||||||
|
|
||||||
class PropertyName;
|
class PropertyName;
|
||||||
|
|
||||||
enum class SimdOperation : uint8_t;
|
|
||||||
|
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
// Module header constants
|
// Module header constants
|
||||||
@ -221,8 +219,53 @@ enum class Expr : uint8_t
|
|||||||
I32AtomicsBinOp,
|
I32AtomicsBinOp,
|
||||||
|
|
||||||
// SIMD
|
// SIMD
|
||||||
SimdConst,
|
I32X4Const,
|
||||||
SimdOp,
|
B32X4Const,
|
||||||
|
F32X4Const,
|
||||||
|
|
||||||
|
I32I32X4ExtractLane,
|
||||||
|
I32B32X4ExtractLane,
|
||||||
|
I32B32X4AllTrue,
|
||||||
|
I32B32X4AnyTrue,
|
||||||
|
|
||||||
|
F32F32X4ExtractLane,
|
||||||
|
|
||||||
|
I32X4Ctor,
|
||||||
|
I32X4Unary,
|
||||||
|
I32X4Binary,
|
||||||
|
I32X4BinaryBitwise,
|
||||||
|
I32X4BinaryShift,
|
||||||
|
I32X4ReplaceLane,
|
||||||
|
I32X4FromF32X4,
|
||||||
|
I32X4FromF32X4Bits,
|
||||||
|
I32X4Swizzle,
|
||||||
|
I32X4Shuffle,
|
||||||
|
I32X4Select,
|
||||||
|
I32X4Splat,
|
||||||
|
I32X4Load,
|
||||||
|
I32X4Store,
|
||||||
|
|
||||||
|
F32X4Ctor,
|
||||||
|
F32X4Unary,
|
||||||
|
F32X4Binary,
|
||||||
|
F32X4ReplaceLane,
|
||||||
|
F32X4FromI32X4,
|
||||||
|
F32X4FromI32X4Bits,
|
||||||
|
F32X4Swizzle,
|
||||||
|
F32X4Shuffle,
|
||||||
|
F32X4Select,
|
||||||
|
F32X4Splat,
|
||||||
|
F32X4Load,
|
||||||
|
F32X4Store,
|
||||||
|
|
||||||
|
B32X4Ctor,
|
||||||
|
B32X4Unary,
|
||||||
|
B32X4Binary,
|
||||||
|
B32X4BinaryCompI32X4,
|
||||||
|
B32X4BinaryCompF32X4,
|
||||||
|
B32X4BinaryBitwise,
|
||||||
|
B32X4ReplaceLane,
|
||||||
|
B32X4Splat,
|
||||||
|
|
||||||
// I32 asm.js opcodes
|
// I32 asm.js opcodes
|
||||||
I32Not,
|
I32Not,
|
||||||
@ -340,8 +383,6 @@ class Encoder
|
|||||||
writeValType(ValType type, size_t* offset = nullptr) { return writeEnum(type, offset); }
|
writeValType(ValType type, size_t* offset = nullptr) { return writeEnum(type, offset); }
|
||||||
MOZ_WARN_UNUSED_RESULT bool
|
MOZ_WARN_UNUSED_RESULT bool
|
||||||
writeExprType(ExprType type, size_t* offset = nullptr) { return writeEnum(type, offset); }
|
writeExprType(ExprType type, size_t* offset = nullptr) { return writeEnum(type, offset); }
|
||||||
MOZ_WARN_UNUSED_RESULT bool
|
|
||||||
writeSimdOp(SimdOperation op, size_t* offset = nullptr) { return writeEnum(op, offset); }
|
|
||||||
|
|
||||||
MOZ_WARN_UNUSED_RESULT bool
|
MOZ_WARN_UNUSED_RESULT bool
|
||||||
writeU8(uint8_t i, size_t* offset = nullptr) { return write<uint8_t>(i, offset); }
|
writeU8(uint8_t i, size_t* offset = nullptr) { return write<uint8_t>(i, offset); }
|
||||||
@ -566,9 +607,6 @@ class Decoder
|
|||||||
MOZ_WARN_UNUSED_RESULT bool readExprType(ExprType* type = nullptr) {
|
MOZ_WARN_UNUSED_RESULT bool readExprType(ExprType* type = nullptr) {
|
||||||
return readEnum(type);
|
return readEnum(type);
|
||||||
}
|
}
|
||||||
MOZ_WARN_UNUSED_RESULT bool readSimdOp(SimdOperation* op = nullptr) {
|
|
||||||
return readEnum(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_WARN_UNUSED_RESULT bool readCString(const char** cstr = nullptr) {
|
MOZ_WARN_UNUSED_RESULT bool readCString(const char** cstr = nullptr) {
|
||||||
if (cstr)
|
if (cstr)
|
||||||
@ -658,12 +696,6 @@ class Decoder
|
|||||||
Expr uncheckedReadExpr() {
|
Expr uncheckedReadExpr() {
|
||||||
return uncheckedReadEnum<Expr>();
|
return uncheckedReadEnum<Expr>();
|
||||||
}
|
}
|
||||||
ExprType uncheckedReadExprType() {
|
|
||||||
return uncheckedReadEnum<ExprType>();
|
|
||||||
}
|
|
||||||
SimdOperation uncheckedReadSimdOp() {
|
|
||||||
return uncheckedReadEnum<SimdOperation>();
|
|
||||||
}
|
|
||||||
Expr uncheckedPeekExpr() const {
|
Expr uncheckedPeekExpr() const {
|
||||||
return uncheckedPeekEnum<Expr>();
|
return uncheckedPeekEnum<Expr>();
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,7 @@ class FunctionCompiler
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool needsBoundsCheck = chk == NEEDS_BOUNDS_CHECK;
|
bool needsBoundsCheck = chk == NEEDS_BOUNDS_CHECK;
|
||||||
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD stores should use storeSimdHeap");
|
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD stores should use loadSimdHeap");
|
||||||
MAsmJSStoreHeap* store = MAsmJSStoreHeap::New(alloc(), accessType, ptr, v, needsBoundsCheck);
|
MAsmJSStoreHeap* store = MAsmJSStoreHeap::New(alloc(), accessType, ptr, v, needsBoundsCheck);
|
||||||
curBlock_->add(store);
|
curBlock_->add(store);
|
||||||
}
|
}
|
||||||
@ -1175,18 +1175,16 @@ class FunctionCompiler
|
|||||||
|
|
||||||
/************************************************************ DECODING ***/
|
/************************************************************ DECODING ***/
|
||||||
|
|
||||||
uint8_t readU8() { return decoder_.uncheckedReadU8(); }
|
uint8_t readU8() { return decoder_.uncheckedReadU8(); }
|
||||||
uint32_t readU32() { return decoder_.uncheckedReadU32(); }
|
uint32_t readU32() { return decoder_.uncheckedReadU32(); }
|
||||||
uint32_t readVarU32() { return decoder_.uncheckedReadVarU32(); }
|
uint32_t readVarU32() { return decoder_.uncheckedReadVarU32(); }
|
||||||
int32_t readI32() { return decoder_.uncheckedReadI32(); }
|
int32_t readI32() { return decoder_.uncheckedReadI32(); }
|
||||||
float readF32() { return decoder_.uncheckedReadF32(); }
|
float readF32() { return decoder_.uncheckedReadF32(); }
|
||||||
double readF64() { return decoder_.uncheckedReadF64(); }
|
double readF64() { return decoder_.uncheckedReadF64(); }
|
||||||
SimdConstant readI32X4() { return decoder_.uncheckedReadI32X4(); }
|
SimdConstant readI32X4() { return decoder_.uncheckedReadI32X4(); }
|
||||||
SimdConstant readF32X4() { return decoder_.uncheckedReadF32X4(); }
|
SimdConstant readF32X4() { return decoder_.uncheckedReadF32X4(); }
|
||||||
Expr readOpcode() { return decoder_.uncheckedReadExpr(); }
|
Expr readOpcode() { return decoder_.uncheckedReadExpr(); }
|
||||||
ExprType readExprType() { return decoder_.uncheckedReadExprType(); }
|
Expr peekOpcode() { return decoder_.uncheckedPeekExpr(); }
|
||||||
SimdOperation readSimdOp() { return decoder_.uncheckedReadSimdOp(); }
|
|
||||||
Expr peekOpcode() { return decoder_.uncheckedPeekExpr(); }
|
|
||||||
|
|
||||||
void readCallLineCol(uint32_t* line, uint32_t* column) {
|
void readCallLineCol(uint32_t* line, uint32_t* column) {
|
||||||
const SourceCoords& sc = func_.sourceCoords(lastReadCallSite_++);
|
const SourceCoords& sc = func_.sourceCoords(lastReadCallSite_++);
|
||||||
@ -1378,6 +1376,7 @@ EmitLoadGlobal(FunctionCompiler& f, MaybeType type, MDefinition** def)
|
|||||||
|
|
||||||
static bool EmitExpr(FunctionCompiler&, MaybeType, MDefinition**, LabelVector* = nullptr);
|
static bool EmitExpr(FunctionCompiler&, MaybeType, MDefinition**, LabelVector* = nullptr);
|
||||||
static bool EmitExprStmt(FunctionCompiler&, MDefinition**, LabelVector* = nullptr);
|
static bool EmitExprStmt(FunctionCompiler&, MDefinition**, LabelVector* = nullptr);
|
||||||
|
static bool EmitSimdBooleanLaneExpr(FunctionCompiler& f, MDefinition** def);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitLoadArray(FunctionCompiler& f, Scalar::Type scalarType, MDefinition** def)
|
EmitLoadArray(FunctionCompiler& f, Scalar::Type scalarType, MDefinition** def)
|
||||||
@ -1723,31 +1722,9 @@ EmitF64MathBuiltinCall(FunctionCompiler& f, Expr f64, MDefinition** def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdUnary(FunctionCompiler& f, ExprType type, SimdOperation simdOp, MDefinition** def)
|
EmitSimdUnary(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
{
|
{
|
||||||
MSimdUnaryArith::Operation op;
|
MSimdUnaryArith::Operation op = MSimdUnaryArith::Operation(f.readU8());
|
||||||
switch (simdOp) {
|
|
||||||
case SimdOperation::Fn_abs:
|
|
||||||
op = MSimdUnaryArith::abs;
|
|
||||||
break;
|
|
||||||
case SimdOperation::Fn_neg:
|
|
||||||
op = MSimdUnaryArith::neg;
|
|
||||||
break;
|
|
||||||
case SimdOperation::Fn_not:
|
|
||||||
op = MSimdUnaryArith::not_;
|
|
||||||
break;
|
|
||||||
case SimdOperation::Fn_sqrt:
|
|
||||||
op = MSimdUnaryArith::sqrt;
|
|
||||||
break;
|
|
||||||
case SimdOperation::Fn_reciprocalApproximation:
|
|
||||||
op = MSimdUnaryArith::reciprocalApproximation;
|
|
||||||
break;
|
|
||||||
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
|
||||||
op = MSimdUnaryArith::reciprocalSqrtApproximation;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("not a simd unary arithmetic operation");
|
|
||||||
}
|
|
||||||
MDefinition* in;
|
MDefinition* in;
|
||||||
if (!EmitExpr(f, type, &in))
|
if (!EmitExpr(f, type, &in))
|
||||||
return false;
|
return false;
|
||||||
@ -1757,7 +1734,7 @@ EmitSimdUnary(FunctionCompiler& f, ExprType type, SimdOperation simdOp, MDefinit
|
|||||||
|
|
||||||
template<class OpKind>
|
template<class OpKind>
|
||||||
inline bool
|
inline bool
|
||||||
EmitSimdBinary(FunctionCompiler& f, ExprType type, OpKind op, MDefinition** def)
|
EmitBinarySimdGuts(FunctionCompiler& f, ExprType type, OpKind op, MDefinition** def)
|
||||||
{
|
{
|
||||||
MDefinition* lhs;
|
MDefinition* lhs;
|
||||||
if (!EmitExpr(f, type, &lhs))
|
if (!EmitExpr(f, type, &lhs))
|
||||||
@ -1770,9 +1747,23 @@ EmitSimdBinary(FunctionCompiler& f, ExprType type, OpKind op, MDefinition** def)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdBinaryComp(FunctionCompiler& f, ExprType type, MSimdBinaryComp::Operation op,
|
EmitSimdBinaryArith(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
MDefinition** def)
|
|
||||||
{
|
{
|
||||||
|
MSimdBinaryArith::Operation op = MSimdBinaryArith::Operation(f.readU8());
|
||||||
|
return EmitBinarySimdGuts(f, type, op, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitSimdBinaryBitwise(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
|
{
|
||||||
|
MSimdBinaryBitwise::Operation op = MSimdBinaryBitwise::Operation(f.readU8());
|
||||||
|
return EmitBinarySimdGuts(f, type, op, def);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitSimdBinaryComp(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
|
{
|
||||||
|
MSimdBinaryComp::Operation op = MSimdBinaryComp::Operation(f.readU8());
|
||||||
MDefinition* lhs;
|
MDefinition* lhs;
|
||||||
if (!EmitExpr(f, type, &lhs))
|
if (!EmitExpr(f, type, &lhs))
|
||||||
return false;
|
return false;
|
||||||
@ -1784,10 +1775,11 @@ EmitSimdBinaryComp(FunctionCompiler& f, ExprType type, MSimdBinaryComp::Operatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdShift(FunctionCompiler& f, ExprType type, MSimdShift::Operation op, MDefinition** def)
|
EmitSimdBinaryShift(FunctionCompiler& f, MDefinition** def)
|
||||||
{
|
{
|
||||||
|
MSimdShift::Operation op = MSimdShift::Operation(f.readU8());
|
||||||
MDefinition* lhs;
|
MDefinition* lhs;
|
||||||
if (!EmitExpr(f, type, &lhs))
|
if (!EmitExpr(f, ExprType::I32x4, &lhs))
|
||||||
return false;
|
return false;
|
||||||
MDefinition* rhs;
|
MDefinition* rhs;
|
||||||
if (!EmitExpr(f, ExprType::I32, &rhs))
|
if (!EmitExpr(f, ExprType::I32, &rhs))
|
||||||
@ -1837,19 +1829,6 @@ EmitExtractLane(FunctionCompiler& f, ExprType type, MDefinition** def)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit an I32 expression and then convert it to a boolean SIMD lane value, i.e. -1 or 0.
|
|
||||||
static bool
|
|
||||||
EmitSimdBooleanLaneExpr(FunctionCompiler& f, MDefinition** def)
|
|
||||||
{
|
|
||||||
MDefinition* i32;
|
|
||||||
if (!EmitExpr(f, ExprType::I32, &i32))
|
|
||||||
return false;
|
|
||||||
// Now compute !i32 - 1 to force the value range into {0, -1}.
|
|
||||||
MDefinition* noti32 = f.unary<MNot>(i32);
|
|
||||||
*def = f.binary<MSub>(noti32, f.constant(Int32Value(1), MIRType_Int32), MIRType_Int32);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdReplaceLane(FunctionCompiler& f, ExprType simdType, MDefinition** def)
|
EmitSimdReplaceLane(FunctionCompiler& f, ExprType simdType, MDefinition** def)
|
||||||
{
|
{
|
||||||
@ -1927,27 +1906,12 @@ EmitSimdShuffle(FunctionCompiler& f, ExprType type, MDefinition** def)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Scalar::Type
|
|
||||||
SimdExprTypeToViewType(ExprType type, unsigned* defaultNumElems)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ExprType::I32x4: *defaultNumElems = 4; return Scalar::Int32x4;
|
|
||||||
case ExprType::F32x4: *defaultNumElems = 4; return Scalar::Float32x4;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
MOZ_CRASH("type not handled in SimdExprTypeToViewType");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdLoad(FunctionCompiler& f, ExprType type, unsigned numElems, MDefinition** def)
|
EmitSimdLoad(FunctionCompiler& f, MDefinition** def)
|
||||||
{
|
{
|
||||||
unsigned defaultNumElems;
|
Scalar::Type viewType = Scalar::Type(f.readU8());
|
||||||
Scalar::Type viewType = SimdExprTypeToViewType(type, &defaultNumElems);
|
|
||||||
|
|
||||||
if (!numElems)
|
|
||||||
numElems = defaultNumElems;
|
|
||||||
|
|
||||||
NeedsBoundsCheck needsBoundsCheck = NeedsBoundsCheck(f.readU8());
|
NeedsBoundsCheck needsBoundsCheck = NeedsBoundsCheck(f.readU8());
|
||||||
|
uint8_t numElems = f.readU8();
|
||||||
|
|
||||||
MDefinition* index;
|
MDefinition* index;
|
||||||
if (!EmitExpr(f, ExprType::I32, &index))
|
if (!EmitExpr(f, ExprType::I32, &index))
|
||||||
@ -1958,15 +1922,11 @@ EmitSimdLoad(FunctionCompiler& f, ExprType type, unsigned numElems, MDefinition*
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdStore(FunctionCompiler& f, ExprType type, unsigned numElems, MDefinition** def)
|
EmitSimdStore(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
{
|
{
|
||||||
unsigned defaultNumElems;
|
Scalar::Type viewType = Scalar::Type(f.readU8());
|
||||||
Scalar::Type viewType = SimdExprTypeToViewType(type, &defaultNumElems);
|
|
||||||
|
|
||||||
if (!numElems)
|
|
||||||
numElems = defaultNumElems;
|
|
||||||
|
|
||||||
NeedsBoundsCheck needsBoundsCheck = NeedsBoundsCheck(f.readU8());
|
NeedsBoundsCheck needsBoundsCheck = NeedsBoundsCheck(f.readU8());
|
||||||
|
uint8_t numElems = f.readU8();
|
||||||
|
|
||||||
MDefinition* index;
|
MDefinition* index;
|
||||||
if (!EmitExpr(f, ExprType::I32, &index))
|
if (!EmitExpr(f, ExprType::I32, &index))
|
||||||
@ -2021,16 +1981,22 @@ static bool
|
|||||||
EmitSimdSplat(FunctionCompiler& f, ExprType type, MDefinition** def)
|
EmitSimdSplat(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
{
|
{
|
||||||
MDefinition* in;
|
MDefinition* in;
|
||||||
if (IsSimdBoolType(type)) {
|
if (!EmitExpr(f, SimdToLaneType(type), &in))
|
||||||
if (!EmitSimdBooleanLaneExpr(f, &in))
|
|
||||||
return false;
|
|
||||||
} else if (!EmitExpr(f, SimdToLaneType(type), &in)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
*def = f.splatSimd(in, ToMIRType(type));
|
*def = f.splatSimd(in, ToMIRType(type));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitSimdBooleanSplat(FunctionCompiler& f, MDefinition** def)
|
||||||
|
{
|
||||||
|
MDefinition* in;
|
||||||
|
if (!EmitSimdBooleanLaneExpr(f, &in))
|
||||||
|
return false;
|
||||||
|
*def = f.splatSimd(in, MIRType_Bool32x4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitSimdCtor(FunctionCompiler& f, ExprType type, MDefinition** def)
|
EmitSimdCtor(FunctionCompiler& f, ExprType type, MDefinition** def)
|
||||||
{
|
{
|
||||||
@ -2307,99 +2273,17 @@ EmitBitwise<MBitNot>(FunctionCompiler& f, MDefinition** def)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit an I32 expression and then convert it to a boolean SIMD lane value, i.e. -1 or 0.
|
||||||
static bool
|
static bool
|
||||||
EmitSimdOp(FunctionCompiler& f, MDefinition** def)
|
EmitSimdBooleanLaneExpr(FunctionCompiler& f, MDefinition** def)
|
||||||
{
|
{
|
||||||
ExprType type = f.readExprType();
|
MDefinition* i32;
|
||||||
switch (SimdOperation op = f.readSimdOp()) {
|
if (!EmitExpr(f, ExprType::I32, &i32))
|
||||||
case SimdOperation::Constructor:
|
return false;
|
||||||
return EmitSimdCtor(f, type, def);
|
// Now compute !i32 - 1 to force the value range into {0, -1}.
|
||||||
case SimdOperation::Fn_extractLane:
|
MDefinition* noti32 = f.unary<MNot>(i32);
|
||||||
return EmitExtractLane(f, type, def);
|
*def = f.binary<MSub>(noti32, f.constant(Int32Value(1), MIRType_Int32), MIRType_Int32);
|
||||||
case SimdOperation::Fn_replaceLane:
|
return true;
|
||||||
return EmitSimdReplaceLane(f, type, def);
|
|
||||||
case SimdOperation::Fn_check:
|
|
||||||
MOZ_CRASH("only used in asm.js' type system");
|
|
||||||
case SimdOperation::Fn_splat:
|
|
||||||
return EmitSimdSplat(f, type, def);
|
|
||||||
case SimdOperation::Fn_select:
|
|
||||||
return EmitSimdSelect(f, type, def);
|
|
||||||
case SimdOperation::Fn_swizzle:
|
|
||||||
return EmitSimdSwizzle(f, type, def);
|
|
||||||
case SimdOperation::Fn_shuffle:
|
|
||||||
return EmitSimdShuffle(f, type, def);
|
|
||||||
case SimdOperation::Fn_load:
|
|
||||||
return EmitSimdLoad(f, type, 0, def);
|
|
||||||
case SimdOperation::Fn_load1:
|
|
||||||
return EmitSimdLoad(f, type, 1, def);
|
|
||||||
case SimdOperation::Fn_load2:
|
|
||||||
return EmitSimdLoad(f, type, 2, def);
|
|
||||||
case SimdOperation::Fn_load3:
|
|
||||||
return EmitSimdLoad(f, type, 3, def);
|
|
||||||
case SimdOperation::Fn_store:
|
|
||||||
return EmitSimdStore(f, type, 0, def);
|
|
||||||
case SimdOperation::Fn_store1:
|
|
||||||
return EmitSimdStore(f, type, 1, def);
|
|
||||||
case SimdOperation::Fn_store2:
|
|
||||||
return EmitSimdStore(f, type, 2, def);
|
|
||||||
case SimdOperation::Fn_store3:
|
|
||||||
return EmitSimdStore(f, type, 3, def);
|
|
||||||
case SimdOperation::Fn_allTrue:
|
|
||||||
return EmitSimdAllTrue(f, type, def);
|
|
||||||
case SimdOperation::Fn_anyTrue:
|
|
||||||
return EmitSimdAnyTrue(f, type, def);
|
|
||||||
case SimdOperation::Fn_abs:
|
|
||||||
case SimdOperation::Fn_neg:
|
|
||||||
case SimdOperation::Fn_not:
|
|
||||||
case SimdOperation::Fn_sqrt:
|
|
||||||
case SimdOperation::Fn_reciprocalApproximation:
|
|
||||||
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
|
||||||
return EmitSimdUnary(f, type, op, def);
|
|
||||||
case SimdOperation::Fn_shiftLeftByScalar:
|
|
||||||
return EmitSimdShift(f, type, MSimdShift::lsh, def);
|
|
||||||
case SimdOperation::Fn_shiftRightByScalar:
|
|
||||||
return EmitSimdShift(f, type,
|
|
||||||
type == ExprType::I32x4 ? MSimdShift::rsh : MSimdShift::ursh,
|
|
||||||
def);
|
|
||||||
case SimdOperation::Fn_shiftRightArithmeticByScalar:
|
|
||||||
return EmitSimdShift(f, type, MSimdShift::rsh, def);
|
|
||||||
case SimdOperation::Fn_shiftRightLogicalByScalar:
|
|
||||||
return EmitSimdShift(f, type, MSimdShift::ursh, def);
|
|
||||||
#define _CASE(OP) \
|
|
||||||
case SimdOperation::Fn_##OP: \
|
|
||||||
return EmitSimdBinaryComp(f, type, MSimdBinaryComp::OP, def);
|
|
||||||
FOREACH_COMP_SIMD_OP(_CASE)
|
|
||||||
#undef _CASE
|
|
||||||
case SimdOperation::Fn_and:
|
|
||||||
return EmitSimdBinary(f, type, MSimdBinaryBitwise::and_, def);
|
|
||||||
case SimdOperation::Fn_or:
|
|
||||||
return EmitSimdBinary(f, type, MSimdBinaryBitwise::or_, def);
|
|
||||||
case SimdOperation::Fn_xor:
|
|
||||||
return EmitSimdBinary(f, type, MSimdBinaryBitwise::xor_, def);
|
|
||||||
#define _CASE(OP) \
|
|
||||||
case SimdOperation::Fn_##OP: \
|
|
||||||
return EmitSimdBinary(f, type, MSimdBinaryArith::Op_##OP, def);
|
|
||||||
FOREACH_NUMERIC_SIMD_BINOP(_CASE)
|
|
||||||
FOREACH_FLOAT_SIMD_BINOP(_CASE)
|
|
||||||
#undef _CASE
|
|
||||||
case SimdOperation::Fn_fromFloat32x4:
|
|
||||||
return EmitSimdCast<MSimdConvert>(f, ExprType::F32x4, type, def);
|
|
||||||
case SimdOperation::Fn_fromInt32x4:
|
|
||||||
return EmitSimdCast<MSimdConvert>(f, ExprType::I32x4, type, def);
|
|
||||||
case SimdOperation::Fn_fromInt32x4Bits:
|
|
||||||
return EmitSimdCast<MSimdReinterpretCast>(f, ExprType::I32x4, type, def);
|
|
||||||
case SimdOperation::Fn_fromFloat32x4Bits:
|
|
||||||
return EmitSimdCast<MSimdReinterpretCast>(f, ExprType::F32x4, type, def);
|
|
||||||
case SimdOperation::Fn_fromUint32x4:
|
|
||||||
case SimdOperation::Fn_fromInt8x16Bits:
|
|
||||||
case SimdOperation::Fn_fromInt16x8Bits:
|
|
||||||
case SimdOperation::Fn_fromUint8x16Bits:
|
|
||||||
case SimdOperation::Fn_fromUint16x8Bits:
|
|
||||||
case SimdOperation::Fn_fromUint32x4Bits:
|
|
||||||
case SimdOperation::Fn_fromFloat64x2Bits:
|
|
||||||
MOZ_CRASH("NYI");
|
|
||||||
}
|
|
||||||
MOZ_CRASH("unexpected opcode");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -2839,6 +2723,14 @@ EmitExpr(FunctionCompiler& f, MaybeType type, MDefinition** def, LabelVector* ma
|
|||||||
return EmitAtomicsStore(f, def);
|
return EmitAtomicsStore(f, def);
|
||||||
case Expr::I32AtomicsBinOp:
|
case Expr::I32AtomicsBinOp:
|
||||||
return EmitAtomicsBinOp(f, def);
|
return EmitAtomicsBinOp(f, def);
|
||||||
|
case Expr::I32I32X4ExtractLane:
|
||||||
|
return EmitExtractLane(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32B32X4ExtractLane:
|
||||||
|
return EmitExtractLane(f, ExprType::B32x4, def);
|
||||||
|
case Expr::I32B32X4AllTrue:
|
||||||
|
return EmitSimdAllTrue(f, ExprType::B32x4, def);
|
||||||
|
case Expr::I32B32X4AnyTrue:
|
||||||
|
return EmitSimdAnyTrue(f, ExprType::B32x4, def);
|
||||||
// F32
|
// F32
|
||||||
case Expr::F32Const:
|
case Expr::F32Const:
|
||||||
return EmitLiteral(f, ExprType::F32, def);
|
return EmitLiteral(f, ExprType::F32, def);
|
||||||
@ -2875,6 +2767,8 @@ EmitExpr(FunctionCompiler& f, MaybeType type, MDefinition** def, LabelVector* ma
|
|||||||
return EmitStore(f, Scalar::Float32, def);
|
return EmitStore(f, Scalar::Float32, def);
|
||||||
case Expr::F32StoreMemF64:
|
case Expr::F32StoreMemF64:
|
||||||
return EmitStoreWithCoercion(f, Scalar::Float32, Scalar::Float64, def);
|
return EmitStoreWithCoercion(f, Scalar::Float32, Scalar::Float64, def);
|
||||||
|
case Expr::F32F32X4ExtractLane:
|
||||||
|
return EmitExtractLane(f, ExprType::F32x4, def);
|
||||||
// F64
|
// F64
|
||||||
case Expr::F64Const:
|
case Expr::F64Const:
|
||||||
return EmitLiteral(f, ExprType::F64, def);
|
return EmitLiteral(f, ExprType::F64, def);
|
||||||
@ -2923,11 +2817,83 @@ EmitExpr(FunctionCompiler& f, MaybeType type, MDefinition** def, LabelVector* ma
|
|||||||
return EmitStore(f, Scalar::Float64, def);
|
return EmitStore(f, Scalar::Float64, def);
|
||||||
case Expr::F64StoreMemF32:
|
case Expr::F64StoreMemF32:
|
||||||
return EmitStoreWithCoercion(f, Scalar::Float64, Scalar::Float32, def);
|
return EmitStoreWithCoercion(f, Scalar::Float64, Scalar::Float32, def);
|
||||||
// SIMD
|
// I32x4
|
||||||
case Expr::SimdConst:
|
case Expr::I32X4Const:
|
||||||
return EmitLiteral(f, f.readExprType(), def);
|
return EmitLiteral(f, ExprType::I32x4, def);
|
||||||
case Expr::SimdOp:
|
case Expr::I32X4Ctor:
|
||||||
return EmitSimdOp(f, def);
|
return EmitSimdCtor(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Unary:
|
||||||
|
return EmitSimdUnary(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Binary:
|
||||||
|
return EmitSimdBinaryArith(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4BinaryBitwise:
|
||||||
|
return EmitSimdBinaryBitwise(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4BinaryShift:
|
||||||
|
return EmitSimdBinaryShift(f, def);
|
||||||
|
case Expr::I32X4ReplaceLane:
|
||||||
|
return EmitSimdReplaceLane(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4FromF32X4:
|
||||||
|
return EmitSimdCast<MSimdConvert>(f, ExprType::F32x4, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4FromF32X4Bits:
|
||||||
|
return EmitSimdCast<MSimdReinterpretCast>(f, ExprType::F32x4, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Swizzle:
|
||||||
|
return EmitSimdSwizzle(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Shuffle:
|
||||||
|
return EmitSimdShuffle(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Select:
|
||||||
|
return EmitSimdSelect(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Splat:
|
||||||
|
return EmitSimdSplat(f, ExprType::I32x4, def);
|
||||||
|
case Expr::I32X4Load:
|
||||||
|
return EmitSimdLoad(f, def);
|
||||||
|
case Expr::I32X4Store:
|
||||||
|
return EmitSimdStore(f, ExprType::I32x4, def);
|
||||||
|
// F32x4
|
||||||
|
case Expr::F32X4Const:
|
||||||
|
return EmitLiteral(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Ctor:
|
||||||
|
return EmitSimdCtor(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Unary:
|
||||||
|
return EmitSimdUnary(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Binary:
|
||||||
|
return EmitSimdBinaryArith(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4ReplaceLane:
|
||||||
|
return EmitSimdReplaceLane(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4FromI32X4:
|
||||||
|
return EmitSimdCast<MSimdConvert>(f, ExprType::I32x4, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4FromI32X4Bits:
|
||||||
|
return EmitSimdCast<MSimdReinterpretCast>(f, ExprType::I32x4, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Swizzle:
|
||||||
|
return EmitSimdSwizzle(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Shuffle:
|
||||||
|
return EmitSimdShuffle(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Select:
|
||||||
|
return EmitSimdSelect(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Splat:
|
||||||
|
return EmitSimdSplat(f, ExprType::F32x4, def);
|
||||||
|
case Expr::F32X4Load:
|
||||||
|
return EmitSimdLoad(f, def);
|
||||||
|
case Expr::F32X4Store:
|
||||||
|
return EmitSimdStore(f, ExprType::F32x4, def);
|
||||||
|
// B32x4
|
||||||
|
case Expr::B32X4Const:
|
||||||
|
return EmitLiteral(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4Ctor:
|
||||||
|
return EmitSimdCtor(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4Unary:
|
||||||
|
return EmitSimdUnary(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4Binary:
|
||||||
|
return EmitSimdBinaryArith(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4BinaryBitwise:
|
||||||
|
return EmitSimdBinaryBitwise(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4BinaryCompI32X4:
|
||||||
|
return EmitSimdBinaryComp(f, ExprType::I32x4, def);
|
||||||
|
case Expr::B32X4BinaryCompF32X4:
|
||||||
|
return EmitSimdBinaryComp(f, ExprType::F32x4, def);
|
||||||
|
case Expr::B32X4ReplaceLane:
|
||||||
|
return EmitSimdReplaceLane(f, ExprType::B32x4, def);
|
||||||
|
case Expr::B32X4Splat:
|
||||||
|
return EmitSimdBooleanSplat(f, def);
|
||||||
case Expr::Loop:
|
case Expr::Loop:
|
||||||
case Expr::Select:
|
case Expr::Select:
|
||||||
case Expr::Br:
|
case Expr::Br:
|
||||||
|
Loading…
Reference in New Issue
Block a user