mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1067502: Be less coercive for float32x4 ctor and splat inputs; r=luke
This commit is contained in:
parent
7a9c9c16a1
commit
7b449eb079
@ -4766,43 +4766,21 @@ CheckSimdCallArgs(FunctionCompiler &f, ParseNode *call, unsigned expectedArity,
|
||||
Type argType;
|
||||
if (!CheckExpr(f, arg, &argDefs[i], &argType))
|
||||
return false;
|
||||
if (!checkArg(f, arg, i, argType, &argDefs[i]))
|
||||
if (!checkArg(f, arg, i, argType))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class CheckSimdScalarArgs
|
||||
class CheckArgIsSubtypeOf
|
||||
{
|
||||
Type formalType_;
|
||||
|
||||
public:
|
||||
explicit CheckSimdScalarArgs(Type t) : formalType_(t.simdToCoercedScalarType()) {}
|
||||
explicit CheckArgIsSubtypeOf(Type t) : formalType_(t) {}
|
||||
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
{
|
||||
if (formalType_ == Type::Floatish)
|
||||
return CheckFloatCoercionArg(f, arg, actualType, *argDef, argDef);
|
||||
|
||||
if (!(actualType <= formalType_)) {
|
||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
||||
formalType_.toChars());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CheckSimdVectorArgs
|
||||
{
|
||||
Type formalType_;
|
||||
|
||||
public:
|
||||
explicit CheckSimdVectorArgs(Type t) : formalType_(t) {}
|
||||
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType) const
|
||||
{
|
||||
if (!(actualType <= formalType_)) {
|
||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
||||
@ -4819,8 +4797,7 @@ class CheckSimdSelectArgs
|
||||
public:
|
||||
explicit CheckSimdSelectArgs(Type t) : formalType_(t) {}
|
||||
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType,
|
||||
MDefinition **argDef) const
|
||||
bool operator()(FunctionCompiler &f, ParseNode *arg, unsigned argIndex, Type actualType) const
|
||||
{
|
||||
if (argIndex == 0) {
|
||||
// First argument of select is an int32x4 mask.
|
||||
@ -4845,7 +4822,7 @@ CheckSimdBinary(FunctionCompiler &f, ParseNode *call, Type retType, OpEnum op, M
|
||||
Type *type)
|
||||
{
|
||||
DefinitionVector argDefs;
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs))
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs))
|
||||
return false;
|
||||
*def = f.binarySimd(argDefs[0], argDefs[1], op, retType.toMIRType());
|
||||
*type = retType;
|
||||
@ -4859,7 +4836,7 @@ CheckSimdBinary<MSimdBinaryComp::Operation>(FunctionCompiler &f, ParseNode *call
|
||||
Type *type)
|
||||
{
|
||||
DefinitionVector argDefs;
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckSimdVectorArgs(retType), &argDefs))
|
||||
if (!CheckSimdCallArgs(f, call, 2, CheckArgIsSubtypeOf(retType), &argDefs))
|
||||
return false;
|
||||
*def = f.binarySimd(argDefs[0], argDefs[1], op);
|
||||
*type = Type::Int32x4;
|
||||
@ -4906,7 +4883,8 @@ CheckSimdOperationCall(FunctionCompiler &f, ParseNode *call, const ModuleCompile
|
||||
|
||||
case AsmJSSimdOperation_splat: {
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, 1, CheckSimdScalarArgs(retType), &defs))
|
||||
Type formalType = retType.simdToCoercedScalarType();
|
||||
if (!CheckSimdCallArgs(f, call, 1, CheckArgIsSubtypeOf(formalType), &defs))
|
||||
return false;
|
||||
*def = f.splatSimd(defs[0], retType.toMIRType());
|
||||
*type = retType;
|
||||
@ -4938,11 +4916,11 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl
|
||||
return CheckCoercionArg(f, argNode, coercion, def, type);
|
||||
|
||||
AsmJSSimdType simdType = global->simdCtorType();
|
||||
unsigned length = SimdTypeToLength(simdType);
|
||||
Type retType = simdType;
|
||||
|
||||
unsigned length = SimdTypeToLength(simdType);
|
||||
Type formalType = retType.simdToCoercedScalarType();
|
||||
DefinitionVector defs;
|
||||
if (!CheckSimdCallArgs(f, call, length, CheckSimdScalarArgs(retType), &defs))
|
||||
if (!CheckSimdCallArgs(f, call, length, CheckArgIsSubtypeOf(formalType), &defs))
|
||||
return false;
|
||||
|
||||
// This code will need to be generalized when we handle float64x2
|
||||
@ -5094,11 +5072,65 @@ CheckCoercedSimdCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckCoercedNumericLiteral(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **def,
|
||||
Type *type)
|
||||
{
|
||||
if (retType == RetType::Void) {
|
||||
*def = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
AsmJSNumLit literal = ExtractNumericLiteral(f.m(), call);
|
||||
switch (literal.which()) {
|
||||
case AsmJSNumLit::Fixnum:
|
||||
case AsmJSNumLit::NegativeInt:
|
||||
case AsmJSNumLit::BigUnsigned:
|
||||
case AsmJSNumLit::Double:
|
||||
case AsmJSNumLit::OutOfRangeInt:
|
||||
MOZ_CRASH("unexpected numeric literal calls");
|
||||
|
||||
case AsmJSNumLit::Float:
|
||||
switch (retType.which()) {
|
||||
case RetType::Int32x4:
|
||||
case RetType::Float32x4:
|
||||
return f.fail(call, "float literal is not a vector type");
|
||||
case RetType::Double:
|
||||
literal = AsmJSNumLit::Create(AsmJSNumLit::Double, DoubleValue(literal.toFloat()));
|
||||
break;
|
||||
case RetType::Float:
|
||||
break;
|
||||
case RetType::Signed:
|
||||
return f.fail(call, "float literal used as signed");
|
||||
case RetType::Void:
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("case handled before");
|
||||
}
|
||||
break;
|
||||
|
||||
case AsmJSNumLit::Int32x4:
|
||||
if (retType != RetType::Int32x4)
|
||||
return f.failf(call, "int32x4 literal used as %s", retType.toType().toChars());
|
||||
break;
|
||||
|
||||
case AsmJSNumLit::Float32x4:
|
||||
if (retType != RetType::Float32x4)
|
||||
return f.failf(call, "float32x4 literal used as %s", retType.toType().toChars());
|
||||
break;
|
||||
}
|
||||
|
||||
*def = f.constant(literal);
|
||||
*type = Type::Of(literal);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckCoercedCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **def, Type *type)
|
||||
{
|
||||
JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
|
||||
|
||||
if (IsNumericLiteral(f.m(), call))
|
||||
return CheckCoercedNumericLiteral(f, call, retType, def, type);
|
||||
|
||||
ParseNode *callee = CallCallee(call);
|
||||
|
||||
if (callee->isKind(PNK_ELEM))
|
||||
|
@ -129,16 +129,29 @@ assertAsmTypeFail('glob', USE_ASM + I32 + "function f(i) {var x=i4(1,2,3,i4(4,5,
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=i4(1,2,3,f4(4,5,6,7))} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=f4(1,2,3,i4(4,5,6,7))} return f");
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return +i4(1,2,3,4)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4)|0} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {return f32(i4(1,2,3,4))} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f() {return f4(i4(1,2,3,4))} return f");
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return +f4(1,2,3,4)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4)|0} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + "function f() {return f32(f4(1,2,3,4))} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f() {return i4(f4(1,2,3,4))} return f");
|
||||
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(i4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(f4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {i4(1,2,3,4);} return f"), this)(), undefined);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {f4(1,2,3,4);} return f"), this)(), undefined);
|
||||
|
||||
// Int32x4 ctor should accept int?
|
||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return i4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]);
|
||||
// Float32x4 ctor should accept floatish, i.e. float || float? || floatish
|
||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + "var f32=new glob.Float32Array(heap); function f(i) {i=i|0; return f4(f4(f32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "var f32=glob.Math.fround; function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return f4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + "function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
||||
|
||||
// 1.3.2 Reading values out of lanes
|
||||
assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return x.y | 0;} return f");
|
||||
@ -172,9 +185,9 @@ assertAsmTypeFail('glob', USE_ASM + FROUND + "function f() {var x=f32(42.); retu
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(1,2,3,4); return x.signMask | 0 } return f'), this)(), 0b0000);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(0,-1, ' + INT32_MAX + ',' + INT32_MIN + '); return x.signMask | 0 } return f'), this)(), 0b1010);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(1, -13.37, 42, -Infinity); return x.signMask | 0 } return f'), this)(), 0b1010);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(-1, 0, -0.000001, Infinity); return x.signMask | 0 } return f'), this)(), 0b0101);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(-1, NaN, 3., 4.); return x.signMask | 0 } return f'), this)(), 0b0001);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(1), f32(-13.37), f32(42), f32(-Infinity)); return x.signMask | 0 } return f'), this)(), 0b1010);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(0), f32(-0.000001), f32(Infinity)); return x.signMask | 0 } return f'), this)(), 0b0101);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(NaN), f32(3.), f32(4.)); return x.signMask | 0 } return f'), this)(), 0b0001);
|
||||
|
||||
// 1.3.3. Variable assignments
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4();} return f");
|
||||
@ -197,9 +210,13 @@ CheckI4('', 'var x=i4(1,2,3,4); x=i4(5,6,7,8)', [5, 6, 7, 8]);
|
||||
CheckI4('', 'var x=i4(1,2,3,4); var c=6; x=i4(5,c|0,7,8)', [5, 6, 7, 8]);
|
||||
CheckI4('', 'var x=i4(8,7,6,5); x=i4(x.w|0,x.z|0,x.y|0,x.x|0)', [5, 6, 7, 8]);
|
||||
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(5,6,y,8)', [5, 6, 7, 8]);
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),6.,7.,8.)', [5, 6, 7, 8]);
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),6,7,8)', [5, 6, 7, 8]);
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1,2,3,c);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4; x=f4(1.,2.,3.,c);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1,2,3,c);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); var c=4.; x=f4(1.,2.,3.,c);} return f");
|
||||
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); var y=f32(7.); x=f4(f32(5),f32(6),y,f32(8))', [5, 6, 7, 8]);
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5),f32(6),f32(7),f32(8))', [5, 6, 7, 8]);
|
||||
CheckF4(FROUND, 'var x=f4(1,2,3,4); x=f4(f32(5.),f32(6.),f32(7.),f32(8.))', [5, 6, 7, 8]);
|
||||
CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(5.,6.,7.,8.)', [5, 6, 7, 8]);
|
||||
CheckF4('', 'var x=f4(1.,2.,3.,4.); x=f4(1,2,3,4)', [1, 2, 3, 4]);
|
||||
@ -228,6 +245,11 @@ assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4();} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(1,2,3,4);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x,y) {x=i4(y);y=+y} return f");
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return +i4(1,2,3,4)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return 0|i4(1,2,3,4)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f(x) {return f32(i4(1,2,3,4))} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(x) {return f4(i4(1,2,3,4))} return f");
|
||||
|
||||
var i32x4 = SIMD.int32x4(1, 3, 3, 7);
|
||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=i4(x)} return f"), this)(i32x4), undefined);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=i4(x); return i4(x);} return f"), this)(i32x4), [1,3,3,7]);
|
||||
@ -561,7 +583,7 @@ assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f
|
||||
const I32SPLAT = 'var splat=i4.splat;'
|
||||
const F32SPLAT = 'var splat=f4.splat;'
|
||||
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(1);} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); var p=f4(1.,2.,3.,4.); p=splat(f32(1));} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1, 2)} return f");
|
||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat()} return f");
|
||||
|
||||
@ -572,9 +594,8 @@ assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SPLAT + 'function f(){return i4(splat(42));} return f'), this)(), [42, 42, 42, 42]);
|
||||
|
||||
const l33t = Math.fround(13.37);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1));} return f'), this)(), [1, 1, 1, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1 >>> 0));} return f'), this)(), [1, 1, 1, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]);
|
||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||
|
||||
var i32view = new Int32Array(heap);
|
||||
|
Loading…
Reference in New Issue
Block a user